From aef0c7a903464f4e05496c69ff4e78d41239c220 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 20 Aug 2012 17:04:25 -0400 Subject: - [feature] The Core oeprator system now includes the `getitem` operator, i.e. the bracket operator in Python. This is used at first to provide index and slice behavior to the Postgresql ARRAY type, and also provides a hook for end-user definition of custom __getitem__ schemes which can be applied at the type level as well as within ORM-level custom operator schemes. Note that this change has the effect that descriptor-based __getitem__ schemes used by the ORM in conjunction with synonym() or other "descriptor-wrapped" schemes will need to start using a custom comparator in order to maintain this behavior. - [feature] postgresql.ARRAY now supports indexing and slicing. The Python [] operator is available on all SQL expressions that are of type ARRAY; integer or simple slices can be passed. The slices can also be used on the assignment side in the SET clause of an UPDATE statement by passing them into Update.values(); see the docs for examples. - [feature] Added new "array literal" construct postgresql.array(). Basically a "tuple" that renders as ARRAY[1,2,3]. --- lib/sqlalchemy/sql/compiler.py | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) (limited to 'lib/sqlalchemy/sql/compiler.py') diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index 5d842f3d6..c56b7fc37 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -411,7 +411,8 @@ class SQLCompiler(engine.Compiled): within_columns_clause=False, **kw) - def visit_column(self, column, add_to_result_map=None, **kwargs): + def visit_column(self, column, add_to_result_map=None, + include_table=True, **kwargs): name = orig_name = column.name if name is None: raise exc.CompileError("Cannot compile Column object until " @@ -438,7 +439,7 @@ class SQLCompiler(engine.Compiled): name = self.preparer.quote(name, column.quote) table = column.table - if table is None or not table.named_with_column: + if table is None or not include_table or not table.named_with_column: return name else: if table.schema: @@ -1329,16 +1330,13 @@ class SQLCompiler(engine.Compiled): text += table_text text += ' SET ' - if extra_froms and self.render_table_with_column_in_update_from: - text += ', '.join( - self.visit_column(c[0]) + - '=' + c[1] for c in colparams - ) - else: - text += ', '.join( - self.preparer.quote(c[0].name, c[0].quote) + + include_table = extra_froms and \ + self.render_table_with_column_in_update_from + text += ', '.join( + c[0]._compiler_dispatch(self, + include_table=include_table) + '=' + c[1] for c in colparams - ) + ) if update_stmt._returning: self.returning = update_stmt._returning @@ -1414,12 +1412,25 @@ class SQLCompiler(engine.Compiled): if not stmt.parameters or key not in stmt.parameters) + # create a list of column assignment clauses as tuples + values = [] + if stmt.parameters is not None: for k, v in stmt.parameters.iteritems(): - parameters.setdefault(sql._column_as_key(k), v) + colkey = sql._column_as_key(k) + if colkey is not None: + parameters.setdefault(colkey, v) + else: + # a non-Column expression on the left side; + # add it to values() in an "as-is" state, + # coercing right side to bound param + if sql._is_literal(v): + v = self.process(sql.bindparam(None, v, type_=k.type)) + else: + v = self.process(v.self_group()) + + values.append((k, v)) - # create a list of column assignment clauses as tuples - values = [] need_pks = self.isinsert and \ not self.inline and \ -- cgit v1.2.1