From 793b7c2e6b177a9f6653dc36600f1e5bea051a96 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Tue, 4 Mar 2008 20:57:32 +0000 Subject: [PATCH] - added "bind" keyword argument to insert(), update(), delete(); .bind property is settable on those as well as select(). --- CHANGES | 3 +++ doc/build/content/sqlexpression.txt | 10 ++++------ lib/sqlalchemy/sql/expression.py | 26 +++++++++++++++++++------- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/CHANGES b/CHANGES index ff99249b9b..2c6c4bc731 100644 --- a/CHANGES +++ b/CHANGES @@ -23,6 +23,9 @@ CHANGES - fixed bug which was preventing UNIONS from being cloneable, [ticket:986] + - added "bind" keyword argument to insert(), update(), delete(); + .bind property is settable on those as well as select(). + - orm - any(), has(), contains(), ~contains(), attribute level == and != now work properly with self-referential relations - diff --git a/doc/build/content/sqlexpression.txt b/doc/build/content/sqlexpression.txt index 3d1e5ed1ef..ec7e92c245 100644 --- a/doc/build/content/sqlexpression.txt +++ b/doc/build/content/sqlexpression.txt @@ -117,9 +117,8 @@ The `Connection` object represents an actively checked out DBAPI connection reso So the INSERT statement was now issued to the database. Although we got positional "qmark" bind parameters instead of "named" bind parameters in the output. How come ? Because when executed, the `Connection` used the SQLite **dialect** to help generate the statement; when we use the `str()` function, the statement isn't aware of this dialect, and falls back onto a default which uses named parameters. We can view this manually as follows: {python} - >>> from sqlalchemy.databases.sqlite import SQLiteDialect - >>> compiled = ins.compile(dialect=SQLiteDialect()) - >>> str(compiled) + >>> ins.bind = engine + >>> str(ins) 'INSERT INTO users (name, fullname) VALUES (?, ?)' What about the `result` variable we got when we called `execute()` ? As the SQLAlchemy `Connection` object references a DBAPI connection, the result, known as a `ResultProxy` object, is analogous to the DBAPI cursor object. In the case of an INSERT, we can get important information from it, such as the primary key values which were generated from our statement: @@ -365,11 +364,10 @@ Interestingly, the type of the `Column` is important ! If we use `+` with two s Where `||` is the string concatenation operator used on most databases. But not all of them. MySQL users, fear not: {python} - >>> from sqlalchemy.databases.mysql import MySQLDialect - >>> print (users.c.name + users.c.fullname).compile(dialect=MySQLDialect()) + >>> print (users.c.name + users.c.fullname).compile(bind=create_engine('mysql://')) concat(users.name, users.fullname) -The above illustrates the SQL that's generated for an `Engine` that's connected to a MySQL database (note that the `Dialect` is normally created behind the scenes; we created one above just to illustrate without using an engine). +The above illustrates the SQL that's generated for an `Engine` that's connected to a MySQL database; the `||` operator now compiles as MySQL's `concat()` function. If you have come across an operator which really isn't available, you can always use the `op()` method; this generates whatever operator you need: diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py index 812c70c2d8..9fb0e596ae 100644 --- a/lib/sqlalchemy/sql/expression.py +++ b/lib/sqlalchemy/sql/expression.py @@ -2981,13 +2981,17 @@ class CompoundSelect(_SelectBaseMixin, FromClause): yield t def bind(self): + if self._bind: + return self._bind for s in self.selects: e = s.bind if e: return e else: return None - bind = property(bind) + def _set_bind(self, bind): + self._bind = bind + bind = property(bind, _set_bind) class Select(_SelectBaseMixin, FromClause): """Represents a ``SELECT`` statement. @@ -3437,7 +3441,9 @@ class Select(_SelectBaseMixin, FromClause): self._bind = e return e return None - bind = property(bind) + def _set_bind(self, bind): + self._bind = bind + bind = property(bind, _set_bind) class _UpdateBase(ClauseElement): """Form the base for ``INSERT``, ``UPDATE``, and ``DELETE`` statements.""" @@ -3462,11 +3468,15 @@ class _UpdateBase(ClauseElement): return parameters def bind(self): - return self.table.bind - bind = property(bind) + return self._bind or self.table.bind + + def _set_bind(self, bind): + self._bind = bind + bind = property(bind, _set_bind) class Insert(_UpdateBase): - def __init__(self, table, values=None, inline=False, **kwargs): + def __init__(self, table, values=None, inline=False, bind=None, **kwargs): + self._bind = bind self.table = table self.select = None self.inline=inline @@ -3495,7 +3505,8 @@ class Insert(_UpdateBase): return u class Update(_UpdateBase): - def __init__(self, table, whereclause, values=None, inline=False, **kwargs): + def __init__(self, table, whereclause, values=None, inline=False, bind=None, **kwargs): + self._bind = bind self.table = table if whereclause: self._whereclause = _literal_as_text(whereclause) @@ -3539,7 +3550,8 @@ class Update(_UpdateBase): return u class Delete(_UpdateBase): - def __init__(self, table, whereclause): + def __init__(self, table, whereclause, bind=None): + self._bind = bind self.table = table if whereclause: self._whereclause = _literal_as_text(whereclause) -- 2.47.3