[Sqlalchemy-commits] [3426] sqlalchemy/branches/inline_insert: work in progress
Brought to you by:
zzzeek
From: <co...@sq...> - 2007-08-30 03:30:09
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><style type="text/css"><!-- #msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; } #msg dt { float: left; width: 6em; font-weight: bold; } #msg dt:after { content:':';} #msg dl, #msg dt, #msg ul, #msg li, #header, #footer { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; } #msg dl a { font-weight: bold} #msg dl a:link { color:#fc3; } #msg dl a:active { color:#ff0; } #msg dl a:visited { color:#cc6; } h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; } #msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; } #msg ul, pre { overflow: auto; } #header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; } #patch { width: 100%; } #patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;} #patch .propset h4, #patch .binary h4 {margin:0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;} #patch .propset .diff, #patch .binary .diff {padding:10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;} #patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;} #patch .lines, .info {color:#888;background:#fff;} --></style> <title>[3426] sqlalchemy/branches/inline_insert: work in progress</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>3426</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2007-08-29 23:29:58 -0400 (Wed, 29 Aug 2007)</dd> </dl> <h3>Log Message</h3> <pre>work in progress</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemybranchesinline_insertlibsqlalchemysqlcompilerpy">sqlalchemy/branches/inline_insert/lib/sqlalchemy/sql/compiler.py</a></li> <li><a href="#sqlalchemybranchesinline_insertlibsqlalchemysqlexpressionpy">sqlalchemy/branches/inline_insert/lib/sqlalchemy/sql/expression.py</a></li> <li><a href="#sqlalchemybranchesinline_inserttestsqldefaultspy">sqlalchemy/branches/inline_insert/test/sql/defaults.py</a></li> <li><a href="#sqlalchemybranchesinline_inserttestsqlselectpy">sqlalchemy/branches/inline_insert/test/sql/select.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemybranchesinline_insertlibsqlalchemysqlcompilerpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/inline_insert/lib/sqlalchemy/sql/compiler.py (3425 => 3426)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/inline_insert/lib/sqlalchemy/sql/compiler.py 2007-08-30 00:22:17 UTC (rev 3425) +++ sqlalchemy/branches/inline_insert/lib/sqlalchemy/sql/compiler.py 2007-08-30 03:29:58 UTC (rev 3426) </span><span class="lines">@@ -90,7 +90,7 @@ </span><span class="cx"> </span><span class="cx"> operators = OPERATORS </span><span class="cx"> </span><del>- def __init__(self, dialect, statement, parameters=None, inline=False): </del><ins>+ def __init__(self, dialect, statement, parameters=None, inline=False, **kwargs): </ins><span class="cx"> """Construct a new ``DefaultCompiler`` object. </span><span class="cx"> </span><span class="cx"> dialect </span><span class="lines">@@ -622,41 +622,10 @@ </span><span class="cx"> def visit_sequence(self, seq): </span><span class="cx"> raise NotImplementedError() </span><span class="cx"> </span><del>- def visit_column_onupdate(self, onupdate): - if isinstance(onupdate.arg, expression.ClauseElement): - return self.exec_default_sql(onupdate) - elif callable(onupdate.arg): - return onupdate.arg(self.context) - else: - return onupdate.arg - - def visit_column_default(self, default): - if isinstance(default.arg, expression.ClauseElement): - return self.exec_default_sql(default) - elif callable(default.arg): - return default.arg(self.context) - else: - return default.arg - </del><span class="cx"> def visit_insert(self, insert_stmt): </span><span class="cx"> </span><del>- # search for columns who will be required to have an explicit bound value. - # for inserts, this includes Python-side defaults, columns with sequences for dialects - # that support sequences, and primary key columns for dialects that explicitly insert - # pre-generated primary key values - required_cols = [ - c for c in insert_stmt.table.c - if \ - isinstance(c, schema.SchemaItem) and \ - (self.parameters is None or self.parameters.get(c.key, None) is None) and \ - ( - ((c.primary_key or isinstance(c.default, schema.Sequence)) and self.uses_sequences_for_inserts()) or - isinstance(c.default, schema.ColumnDefault) - ) - ] - </del><span class="cx"> self.isinsert = True </span><del>- colparams = self._get_colparams(insert_stmt, required_cols) </del><ins>+ colparams = self._get_colparams(insert_stmt) </ins><span class="cx"> </span><span class="cx"> return ("INSERT INTO " + self.preparer.format_table(insert_stmt.table) + " (" + string.join([self.preparer.format_column(c[0]) for c in colparams], ', ') + ")" + </span><span class="cx"> " VALUES (" + string.join([c[1] for c in colparams], ', ') + ")") </span><span class="lines">@@ -664,17 +633,8 @@ </span><span class="cx"> def visit_update(self, update_stmt): </span><span class="cx"> self.stack.append({'from':util.Set([update_stmt.table])}) </span><span class="cx"> </span><del>- # search for columns who will be required to have an explicit bound value. - # for updates, this includes Python-side "onupdate" defaults. - required_cols = [c for c in update_stmt.table.c - if - isinstance(c, schema.SchemaItem) and \ - (self.parameters is None or self.parameters.get(c.key, None) is None) and - isinstance(c.onupdate, schema.ColumnDefault) - ] - </del><span class="cx"> self.isupdate = True </span><del>- colparams = self._get_colparams(update_stmt, required_cols) </del><ins>+ colparams = self._get_colparams(update_stmt) </ins><span class="cx"> </span><span class="cx"> text = "UPDATE " + self.preparer.format_table(update_stmt.table) + " SET " + string.join(["%s=%s" % (self.preparer.format_column(c[0]), c[1]) for c in colparams], ', ') </span><span class="cx"> </span><span class="lines">@@ -685,7 +645,7 @@ </span><span class="cx"> </span><span class="cx"> return text </span><span class="cx"> </span><del>- def _get_colparams(self, stmt, required_cols): </del><ins>+ def _get_colparams(self, stmt): </ins><span class="cx"> """create a set of tuples representing column/string pairs for use </span><span class="cx"> in an INSERT or UPDATE statement. </span><span class="cx"> </span><span class="lines">@@ -723,23 +683,35 @@ </span><span class="cx"> for k, v in stmt.parameters.iteritems(): </span><span class="cx"> parameters.setdefault(getattr(k, 'key', k), v) </span><span class="cx"> </span><del>- for col in required_cols: - parameters.setdefault(col.key, None) - </del><span class="cx"> # create a list of column assignment clauses as tuples </span><span class="cx"> values = [] </span><span class="cx"> for c in stmt.table.columns: </span><span class="cx"> if c.key in parameters: </span><span class="cx"> value = parameters[c.key] </span><ins>+ if sql._is_literal(value): + value = create_bind_param(c, value) + else: + self.inline_params.add(c) + value = self.process(value.self_group()) + values.append((c, value)) </ins><span class="cx"> else: </span><del>- continue - if sql._is_literal(value): - value = create_bind_param(c, value) - else: - self.inline_params.add(c) - value = self.process(value.self_group()) - values.append((c, value)) - </del><ins>+ if self.isinsert: + if (c.primary_key or isinstance(c.default, schema.Sequence)) and self.uses_sequences_for_inserts(): + if self.inline: + values.append((c, self.process(c.default))) + else: + values.append((c, create_bind_param(c, None))) + elif isinstance(c.default, schema.ColumnDefault) and isinstance(c.default.arg, sql.ClauseElement): + if self.inline: + values.append((c, self.process(c.default.arg))) + else: + values.append((c, create_bind_param(c, None))) + elif self.isupdate: + if isinstance(c.onupdate, schema.ColumnDefault) and isinstance(c.onupdate.arg, sql.ClauseElement): + if self.inline: + values.append((c, self.process(c.onupdate.arg))) + else: + values.append((c, create_bind_param(c, None))) </ins><span class="cx"> return values </span><span class="cx"> </span><span class="cx"> def visit_delete(self, delete_stmt): </span></span></pre></div> <a id="sqlalchemybranchesinline_insertlibsqlalchemysqlexpressionpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/inline_insert/lib/sqlalchemy/sql/expression.py (3425 => 3426)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/inline_insert/lib/sqlalchemy/sql/expression.py 2007-08-30 00:22:17 UTC (rev 3425) +++ sqlalchemy/branches/inline_insert/lib/sqlalchemy/sql/expression.py 2007-08-30 03:29:58 UTC (rev 3426) </span><span class="lines">@@ -249,7 +249,7 @@ </span><span class="cx"> </span><span class="cx"> return Select(*args, **kwargs).alias(alias) </span><span class="cx"> </span><del>-def insert(table, values = None, **kwargs): </del><ins>+def insert(table, values=None, inline=False): </ins><span class="cx"> """Return an [sqlalchemy.sql#Insert] clause element. </span><span class="cx"> </span><span class="cx"> Similar functionality is available via the ``insert()`` method on </span><span class="lines">@@ -266,6 +266,10 @@ </span><span class="cx"> bind parameters also are None during the compile phase, then the </span><span class="cx"> column specifications will be generated from the full list of </span><span class="cx"> table columns. </span><ins>+ + inline + if True, SQL defaults will be compiled 'inline' into the statement + and not pre-executed. </ins><span class="cx"> </span><span class="cx"> If both `values` and compile-time bind parameters are present, the </span><span class="cx"> compile-time bind parameters override the information specified </span><span class="lines">@@ -283,9 +287,9 @@ </span><span class="cx"> against the ``INSERT`` statement. </span><span class="cx"> """ </span><span class="cx"> </span><del>- return Insert(table, values, **kwargs) </del><ins>+ return Insert(table, values, inline=inline) </ins><span class="cx"> </span><del>-def update(table, whereclause = None, values = None, **kwargs): </del><ins>+def update(table, whereclause=None, values=None, inline=False): </ins><span class="cx"> """Return an [sqlalchemy.sql#Update] clause element. </span><span class="cx"> </span><span class="cx"> Similar functionality is available via the ``update()`` method on </span><span class="lines">@@ -307,6 +311,11 @@ </span><span class="cx"> ``SET`` conditions will be generated from the full list of table </span><span class="cx"> columns. </span><span class="cx"> </span><ins>+ inline + if True, SQL defaults will be compiled 'inline' into the statement + and not pre-executed. + + </ins><span class="cx"> If both `values` and compile-time bind parameters are present, the </span><span class="cx"> compile-time bind parameters override the information specified </span><span class="cx"> within `values` on a per-key basis. </span><span class="lines">@@ -323,7 +332,7 @@ </span><span class="cx"> against the ``UPDATE`` statement. </span><span class="cx"> """ </span><span class="cx"> </span><del>- return Update(table, whereclause, values, **kwargs) </del><ins>+ return Update(table, whereclause=whereclause, values=values, inline=inline) </ins><span class="cx"> </span><span class="cx"> def delete(table, whereclause = None, **kwargs): </span><span class="cx"> """Return a [sqlalchemy.sql#Delete] clause element. </span><span class="lines">@@ -1004,7 +1013,7 @@ </span><span class="cx"> if compiler is None: </span><span class="cx"> from sqlalchemy.engine.default import DefaultDialect </span><span class="cx"> dialect = DefaultDialect() </span><del>- compiler = dialect.statement_compiler(dialect, self, parameters=parameters, inilne=inline) </del><ins>+ compiler = dialect.statement_compiler(dialect, self, parameters=parameters, inline=inline) </ins><span class="cx"> compiler.compile() </span><span class="cx"> return compiler </span><span class="cx"> </span><span class="lines">@@ -2705,13 +2714,13 @@ </span><span class="cx"> def select(self, whereclause = None, **params): </span><span class="cx"> return select([self], whereclause, **params) </span><span class="cx"> </span><del>- def insert(self, values = None): - return insert(self, values=values) </del><ins>+ def insert(self, values=None, inline=False): + return insert(self, values=values, inline=inline) </ins><span class="cx"> </span><del>- def update(self, whereclause = None, values = None): - return update(self, whereclause, values) </del><ins>+ def update(self, whereclause=None, values=None, inline=False): + return update(self, whereclause=whereclause, values=values, inline=inline) </ins><span class="cx"> </span><del>- def delete(self, whereclause = None): </del><ins>+ def delete(self, whereclause=None): </ins><span class="cx"> return delete(self, whereclause) </span><span class="cx"> </span><span class="cx"> def _get_from_objects(self, **modifiers): </span><span class="lines">@@ -3229,9 +3238,10 @@ </span><span class="cx"> return self.table.bind </span><span class="cx"> </span><span class="cx"> class Insert(_UpdateBase): </span><del>- def __init__(self, table, values=None): </del><ins>+ def __init__(self, table, values=None, inline=False): </ins><span class="cx"> self.table = table </span><span class="cx"> self.select = None </span><ins>+ self.inline=inline </ins><span class="cx"> self.parameters = self._process_colparams(values) </span><span class="cx"> </span><span class="cx"> def get_children(self, **kwargs): </span><span class="lines">@@ -3255,9 +3265,10 @@ </span><span class="cx"> return u </span><span class="cx"> </span><span class="cx"> class Update(_UpdateBase): </span><del>- def __init__(self, table, whereclause, values=None): </del><ins>+ def __init__(self, table, whereclause, values=None, inline=False): </ins><span class="cx"> self.table = table </span><span class="cx"> self._whereclause = whereclause </span><ins>+ self.inline = inline </ins><span class="cx"> self.parameters = self._process_colparams(values) </span><span class="cx"> </span><span class="cx"> def get_children(self, **kwargs): </span></span></pre></div> <a id="sqlalchemybranchesinline_inserttestsqldefaultspy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/inline_insert/test/sql/defaults.py (3425 => 3426)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/inline_insert/test/sql/defaults.py 2007-08-30 00:22:17 UTC (rev 3425) +++ sqlalchemy/branches/inline_insert/test/sql/defaults.py 2007-08-30 03:29:58 UTC (rev 3426) </span><span class="lines">@@ -180,7 +180,6 @@ </span><span class="cx"> pk = r.last_inserted_ids()[0] </span><span class="cx"> t.update(t.c.col1==pk).execute(col4=None, col5=None) </span><span class="cx"> ctexec = currenttime.scalar() </span><del>- print "Currenttime "+ repr(ctexec) </del><span class="cx"> l = t.select(t.c.col1==pk).execute() </span><span class="cx"> l = l.fetchone() </span><span class="cx"> self.assert_(l == (pk, 'im the update', f2, None, None, ctexec, True, False, 13, datetime.date.today())) </span><span class="lines">@@ -253,6 +252,8 @@ </span><span class="cx"> try: </span><span class="cx"> table.insert().execute(data='row 1') </span><span class="cx"> table.insert().execute(data='row 2') </span><ins>+ table.insert().execute({'data':'row 3'}, {'data':'row 4'}) + assert table.select().fetchall() == [(1, "row 1"), (2, "row 2"), (3, "row 3"), (4, "row 4")] </ins><span class="cx"> finally: </span><span class="cx"> table.drop() </span><span class="cx"> </span></span></pre></div> <a id="sqlalchemybranchesinline_inserttestsqlselectpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/inline_insert/test/sql/select.py (3425 => 3426)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/inline_insert/test/sql/select.py 2007-08-30 00:22:17 UTC (rev 3425) +++ sqlalchemy/branches/inline_insert/test/sql/select.py 2007-08-30 03:29:58 UTC (rev 3426) </span><span class="lines">@@ -1125,7 +1125,14 @@ </span><span class="cx"> "INSERT INTO mytable (myid, name) VALUES (:userid, :username)" </span><span class="cx"> ) </span><span class="cx"> </span><del>- </del><ins>+ def testinlineinsert(self): + metadata = MetaData() + table = Table('sometable', metadata, + Column('id', Integer, primary_key=True), + Column('foo', Integer, default=func.foobar())) + self.assert_compile(table.insert(values={}, inline=True), "INSERT INTO sometable (foo) VALUES (foobar())") + self.assert_compile(table.insert(inline=True), "INSERT INTO sometable (foo) VALUES (foobar())", params={}) + </ins><span class="cx"> def testinsertexpression(self): </span><span class="cx"> self.assert_compile(insert(table1), "INSERT INTO mytable (myid) VALUES (lala())", params=dict(myid=func.lala())) </span><span class="cx"> </span></span></pre> </div> </div> </body> </html> |