summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2005-10-23 20:40:22 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2005-10-23 20:40:22 +0000
commit9a2a2dfc7ac91770227fd2c420b126e745c5d3f1 (patch)
tree612cabdaa4561f64f978e178ff3c3e1a4e3ce7ad /lib/sqlalchemy
parentf56d75c3ad9fbe7ff85b5b65698cd5696d12ee28 (diff)
downloadsqlalchemy-9a2a2dfc7ac91770227fd2c420b126e745c5d3f1.tar.gz
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/ansisql.py8
-rw-r--r--lib/sqlalchemy/databases/oracle.py4
-rw-r--r--lib/sqlalchemy/databases/postgres.py4
-rw-r--r--lib/sqlalchemy/databases/sqlite.py4
-rw-r--r--lib/sqlalchemy/engine.py54
-rw-r--r--lib/sqlalchemy/sql.py4
6 files changed, 60 insertions, 18 deletions
diff --git a/lib/sqlalchemy/ansisql.py b/lib/sqlalchemy/ansisql.py
index 0b0aeca44..963e52a1f 100644
--- a/lib/sqlalchemy/ansisql.py
+++ b/lib/sqlalchemy/ansisql.py
@@ -48,13 +48,13 @@ class ANSISQLEngine(sqlalchemy.engine.SQLEngine):
class ANSICompiler(sql.Compiled):
- def __init__(self, engine, statement, bindparams):
+ def __init__(self, engine, statement, bindparams, typemap=None, **kwargs):
sql.Compiled.__init__(self, engine, statement, bindparams)
self.binds = {}
self.froms = {}
self.wheres = {}
self.strings = {}
- self.typemap = {}
+ self.typemap = typemap or {}
self.isinsert = False
def get_from_text(self, obj):
@@ -157,9 +157,9 @@ class ANSICompiler(sql.Compiled):
for co in c.columns:
inner_columns.append(co)
if select.use_labels:
- self.typemap[co.label] = co.type
+ self.typemap.setdefault(co.label, co.type)
else:
- self.typemap[co.key] = co.type
+ self.typemap.setdefault(co.key, co.type)
if select.use_labels:
collist = string.join(["%s AS %s" % (c.fullname, c.label) for c in inner_columns], ', ')
diff --git a/lib/sqlalchemy/databases/oracle.py b/lib/sqlalchemy/databases/oracle.py
index 0ef64d480..ff5178a0f 100644
--- a/lib/sqlalchemy/databases/oracle.py
+++ b/lib/sqlalchemy/databases/oracle.py
@@ -93,8 +93,8 @@ class OracleSQLEngine(ansisql.ANSISQLEngine):
def rowid_column_name(self):
return "rowid"
- def compiler(self, statement, bindparams):
- return OracleCompiler(self, statement, bindparams)
+ def compiler(self, statement, bindparams, **kwargs):
+ return OracleCompiler(self, statement, bindparams, **kwargs)
def schemagenerator(self, proxy, **params):
return OracleSchemaGenerator(proxy, **params)
diff --git a/lib/sqlalchemy/databases/postgres.py b/lib/sqlalchemy/databases/postgres.py
index f3648e69c..000f403f1 100644
--- a/lib/sqlalchemy/databases/postgres.py
+++ b/lib/sqlalchemy/databases/postgres.py
@@ -90,8 +90,8 @@ class PGSQLEngine(ansisql.ANSISQLEngine):
def last_inserted_ids(self):
return self.context.last_inserted_ids
- def compiler(self, statement, bindparams):
- return PGCompiler(self, statement, bindparams)
+ def compiler(self, statement, bindparams, **kwargs):
+ return PGCompiler(self, statement, bindparams, **kwargs)
def schemagenerator(self, proxy, **params):
return PGSchemaGenerator(proxy, **params)
diff --git a/lib/sqlalchemy/databases/sqlite.py b/lib/sqlalchemy/databases/sqlite.py
index d613728cb..660763f49 100644
--- a/lib/sqlalchemy/databases/sqlite.py
+++ b/lib/sqlalchemy/databases/sqlite.py
@@ -96,8 +96,8 @@ class SQLiteSQLEngine(ansisql.ANSISQLEngine):
def connect_args(self):
return ([self.filename], self.opts)
- def compiler(self, statement, bindparams):
- return SQLiteCompiler(self, statement, bindparams)
+ def compiler(self, statement, bindparams, **kwargs):
+ return SQLiteCompiler(self, statement, bindparams, **kwargs)
def dbapi(self):
return sqlite
diff --git a/lib/sqlalchemy/engine.py b/lib/sqlalchemy/engine.py
index c910916d1..37fb952e7 100644
--- a/lib/sqlalchemy/engine.py
+++ b/lib/sqlalchemy/engine.py
@@ -88,8 +88,8 @@ class SQLEngine(schema.SchemaEngine):
def drop(self, table, **params):
table.accept_visitor(self.schemadropper(self.proxy(), **params))
- def compile(self, statement, bindparams):
- compiler = self.compiler(statement, bindparams)
+ def compile(self, statement, bindparams, **kwargs):
+ compiler = self.compiler(statement, bindparams, **kwargs)
statement.accept_visitor(compiler)
return compiler
@@ -103,14 +103,19 @@ class SQLEngine(schema.SchemaEngine):
return sql.ColumnSelectable(column)
def last_inserted_ids(self):
- """returns a thread-local map of the generated primary keys corresponding to the most recent
- insert statement. keys are the names of columns."""
+ """returns a thread-local list of the primary keys for the last insert statement executed.
+ This does not apply to straight textual clauses; only to sql.Insert objects compiled against
+ a schema.Table object, which are executed via statement.execute(). The order of items in the list
+ is the same as that of the Table's 'primary_keys' attribute."""
raise NotImplementedError()
def connect_args(self):
+ """subclasses override this method to provide a two-item tuple containing the *args and **kwargs used
+ to establish a connection."""
raise NotImplementedError()
def dbapi(self):
+ """subclasses override this method to provide the DBAPI module used to establish connections."""
raise NotImplementedError()
def do_begin(self, connection):
@@ -123,10 +128,11 @@ class SQLEngine(schema.SchemaEngine):
"""implementations might want to put logic here for turning autocommit on/off, etc."""
connection.commit()
- def proxy(self):
- return lambda s, p = None: self.execute(s, p)
+ def proxy(self, **kwargs):
+ return lambda s, p = None: self.execute(s, p, **kwargs)
def connection(self):
+ """returns a managed DBAPI connection from this SQLEngine's connection pool."""
return self._pool.connect()
def multi_transaction(self, tables, func):
@@ -189,6 +195,28 @@ class SQLEngine(schema.SchemaEngine):
pass
def execute(self, statement, parameters, connection = None, echo = None, typemap = None, commit=False, **kwargs):
+ """executes the given string-based SQL statement with the given parameters. This is a direct interface to a
+ DBAPI connection object. The parameters may be a dictionary, or an array of dictionaries. If an array
+ of dictionaries is sent, executemany will be performed on the cursor instead of execute.
+
+ If the current thread has specified a transaction begin() for this engine, the statement will be executed
+ in the context of the current transactional connection. Otherwise, a commit() will be performed immediately
+ after execution, since the local pooled connection is returned to the pool after execution without a transaction
+ set up.
+
+ In all error cases, a rollback() is immediately performed on the connection before propigating the
+ exception outwards.
+
+ Other options include:
+
+ connection - a DBAPI connection to use for the execute. If None, a connection is pulled from this
+ engine's connection pool.
+ echo - enables echo for this execution, which causes all SQL and parameters to be dumped to the
+ engine's logging output before execution.
+ typemap - a map of column names mapped to sqlalchemy.types.TypeEngine objects. These will be
+ passed to the created ResultProxy to perform post-processing on result-set values.
+ commit - if True, will automatically commit the statement after completion.
+ """
if parameters is None:
parameters = {}
@@ -225,10 +253,21 @@ class SQLEngine(schema.SchemaEngine):
self.context.rowcount = c.rowcount
def log(self, msg):
+ """logs a message using this SQLEngine's logger stream."""
self.logger.write(msg + "\n")
class ResultProxy:
+ """wraps a DBAPI cursor object to provide access to row columns based on integer position, case-insensitive column name,
+ or by schema.Column object. e.g.:
+
+ row = fetchone()
+ col1 = row[0] # access via integer position
+ col2 = row['col2'] # access via name
+ col3 = row[mytable.c.mycol] # access via Column object.
+ #the Column's 'label', 'key', and 'name' properties are searched in that order.
+
+ """
def __init__(self, cursor, engine, typemap = None):
self.cursor = cursor
self.echo = engine.echo
@@ -262,6 +301,7 @@ class ResultProxy:
return rec[0].convert_result_value(row[rec[1]])
def fetchall(self):
+ """fetches all rows, just like DBAPI cursor.fetchall()."""
l = []
while True:
v = self.fetchone()
@@ -270,6 +310,7 @@ class ResultProxy:
l.append(v)
def fetchone(self):
+ """fetches one row, just like DBAPI cursor.fetchone()."""
row = self.cursor.fetchone()
if row is not None:
if self.echo: print repr(row)
@@ -278,6 +319,7 @@ class ResultProxy:
return None
class RowProxy:
+ """proxies a single cursor row for a parent ResultProxy."""
def __init__(self, parent, row):
self.parent = parent
self.row = row
diff --git a/lib/sqlalchemy/sql.py b/lib/sqlalchemy/sql.py
index a5a97a9e8..fa2baf06d 100644
--- a/lib/sqlalchemy/sql.py
+++ b/lib/sqlalchemy/sql.py
@@ -225,7 +225,7 @@ class ClauseElement(object):
return self
- def compile(self, engine = None, bindparams = None):
+ def compile(self, engine = None, bindparams = None, typemap=None):
"""compiles this SQL expression using its underlying SQLEngine to produce
a Compiled object. If no engine can be found, an ansisql engine is used.
bindparams is a dictionary representing the default bind parameters to be used with
@@ -239,7 +239,7 @@ class ClauseElement(object):
engine = ansisql.engine()
#raise "no engine supplied, and no engine could be located within the clauses!"
- return engine.compile(self, bindparams = bindparams)
+ return engine.compile(self, bindparams = bindparams, typemap=typemap)
def __str__(self):
return str(self.compile())