From d768ec2c266ec462a8ff0b782516c494c451f2db Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Fri, 15 Aug 2014 14:27:12 -0400 Subject: - don't add the parent attach event within _on_table_attach if we already have a table; this prevents reentrant calls and we aren't supporting columns/etc being moved around between different parents --- lib/sqlalchemy/sql/schema.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/sqlalchemy/sql') diff --git a/lib/sqlalchemy/sql/schema.py b/lib/sqlalchemy/sql/schema.py index 8099dca75..c8e815d24 100644 --- a/lib/sqlalchemy/sql/schema.py +++ b/lib/sqlalchemy/sql/schema.py @@ -1269,7 +1269,8 @@ class Column(SchemaItem, ColumnClause): def _on_table_attach(self, fn): if self.table is not None: fn(self, self.table) - event.listen(self, 'after_parent_attach', fn) + else: + event.listen(self, 'after_parent_attach', fn) def copy(self, **kw): """Create a copy of this ``Column``, unitialized. -- cgit v1.2.1 From 71ca494f518658676b532afaf84a4cc93025dbbb Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Wed, 20 Aug 2014 20:14:20 -0400 Subject: - The INSERT...FROM SELECT construct now implies ``inline=True`` on :class:`.Insert`. This helps to fix a bug where an INSERT...FROM SELECT construct would inadvertently be compiled as "implicit returning" on supporting backends, which would cause breakage in the case of an INSERT that inserts zero rows (as implicit returning expects a row), as well as arbitrary return data in the case of an INSERT that inserts multiple rows (e.g. only the first row of many). A similar change is also applied to an INSERT..VALUES with multiple parameter sets; implicit RETURNING will no longer emit for this statement either. As both of these constructs deal with varible numbers of rows, the :attr:`.ResultProxy.inserted_primary_key` accessor does not apply. Previously, there was a documentation note that one may prefer ``inline=True`` with INSERT..FROM SELECT as some databases don't support returning and therefore can't do "implicit" returning, but there's no reason an INSERT...FROM SELECT needs implicit returning in any case. Regular explicit :meth:`.Insert.returning` should be used to return variable numbers of result rows if inserted data is needed. fixes #3169 --- lib/sqlalchemy/sql/compiler.py | 4 +++- lib/sqlalchemy/sql/dml.py | 34 +++++++++++++++++++++------------- 2 files changed, 24 insertions(+), 14 deletions(-) (limited to 'lib/sqlalchemy/sql') diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index e45510aa4..fac4980b0 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -1981,11 +1981,13 @@ class SQLCompiler(Compiled): need_pks = self.isinsert and \ not self.inline and \ - not stmt._returning + not stmt._returning and \ + not stmt._has_multi_parameters implicit_returning = need_pks and \ self.dialect.implicit_returning and \ stmt.table.implicit_returning + if self.isinsert: implicit_return_defaults = (implicit_returning and stmt._return_defaults) diff --git a/lib/sqlalchemy/sql/dml.py b/lib/sqlalchemy/sql/dml.py index f7e033d85..72dd92c99 100644 --- a/lib/sqlalchemy/sql/dml.py +++ b/lib/sqlalchemy/sql/dml.py @@ -269,6 +269,13 @@ class ValuesBase(UpdateBase): .. versionadded:: 0.8 Support for multiple-VALUES INSERT statements. + .. versionchanged:: 1.0.0 an INSERT that uses a multiple-VALUES + clause, even a list of length one, + implies that the :paramref:`.Insert.inline` flag is set to + True, indicating that the statement will not attempt to fetch + the "last inserted primary key" or other defaults. The statement + deals with an arbitrary number of rows, so the + :attr:`.ResultProxy.inserted_primary_key` accessor does not apply. .. seealso:: @@ -434,8 +441,13 @@ class Insert(ValuesBase): dynamically render the VALUES clause at execution time based on the parameters passed to :meth:`.Connection.execute`. - :param inline: if True, SQL defaults will be compiled 'inline' into - the statement and not pre-executed. + :param inline: if True, no attempt will be made to retrieve the + SQL-generated default values to be provided within the statement; + in particular, + this allows SQL expressions to be rendered 'inline' within the + statement without the need to pre-execute them beforehand; for + backends that support "returning", this turns off the "implicit + returning" feature for the statement. If both `values` and compile-time bind parameters are present, the compile-time bind parameters override the information specified @@ -495,17 +507,12 @@ class Insert(ValuesBase): would normally raise an exception if these column lists don't correspond. - .. note:: - - Depending on backend, it may be necessary for the :class:`.Insert` - statement to be constructed using the ``inline=True`` flag; this - flag will prevent the implicit usage of ``RETURNING`` when the - ``INSERT`` statement is rendered, which isn't supported on a - backend such as Oracle in conjunction with an ``INSERT..SELECT`` - combination:: - - sel = select([table1.c.a, table1.c.b]).where(table1.c.c > 5) - ins = table2.insert(inline=True).from_select(['a', 'b'], sel) + .. versionchanged:: 1.0.0 an INSERT that uses FROM SELECT + implies that the :paramref:`.Insert.inline` flag is set to + True, indicating that the statement will not attempt to fetch + the "last inserted primary key" or other defaults. The statement + deals with an arbitrary number of rows, so the + :attr:`.ResultProxy.inserted_primary_key` accessor does not apply. .. note:: @@ -525,6 +532,7 @@ class Insert(ValuesBase): self._process_colparams(dict((n, Null()) for n in names)) self.select_names = names + self.inline = True self.select = _interpret_as_select(select) def _copy_internals(self, clone=_clone, **kw): -- cgit v1.2.1 From 374173e89d4e21a75bfabd8a655d17c247b6f1fc Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Thu, 21 Aug 2014 10:29:21 -0400 Subject: - fix link --- lib/sqlalchemy/sql/dml.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/sqlalchemy/sql') diff --git a/lib/sqlalchemy/sql/dml.py b/lib/sqlalchemy/sql/dml.py index 72dd92c99..06c50981d 100644 --- a/lib/sqlalchemy/sql/dml.py +++ b/lib/sqlalchemy/sql/dml.py @@ -508,7 +508,7 @@ class Insert(ValuesBase): correspond. .. versionchanged:: 1.0.0 an INSERT that uses FROM SELECT - implies that the :paramref:`.Insert.inline` flag is set to + implies that the :paramref:`.insert.inline` flag is set to True, indicating that the statement will not attempt to fetch the "last inserted primary key" or other defaults. The statement deals with an arbitrary number of rows, so the -- cgit v1.2.1 From 7c4d0a4d6611fd891fb7afda6db277e9fbf83e70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gunnlaugur=20=C3=9E=C3=B3r=20Briem?= Date: Thu, 31 Jul 2014 23:23:56 +0000 Subject: Fix copy-paste error in Delete doc --- lib/sqlalchemy/sql/dml.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/sqlalchemy/sql') diff --git a/lib/sqlalchemy/sql/dml.py b/lib/sqlalchemy/sql/dml.py index 06c50981d..1934d0776 100644 --- a/lib/sqlalchemy/sql/dml.py +++ b/lib/sqlalchemy/sql/dml.py @@ -736,10 +736,10 @@ class Delete(UpdateBase): :meth:`~.TableClause.delete` method on :class:`~.schema.Table`. - :param table: The table to be updated. + :param table: The table to delete rows from. :param whereclause: A :class:`.ClauseElement` describing the ``WHERE`` - condition of the ``UPDATE`` statement. Note that the + condition of the ``DELETE`` statement. Note that the :meth:`~Delete.where()` generative method may be used instead. .. seealso:: -- cgit v1.2.1