update sqlalchemy
This commit is contained in:
parent
6c6c3e68c6
commit
a4267212e4
192 changed files with 17429 additions and 9601 deletions
|
|
@ -1,5 +1,5 @@
|
|||
# sql/dml.py
|
||||
# Copyright (C) 2009-2014 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2009-2016 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
|
@ -10,7 +10,8 @@ Provide :class:`.Insert`, :class:`.Update` and :class:`.Delete`.
|
|||
"""
|
||||
|
||||
from .base import Executable, _generative, _from_objects, DialectKWArgs
|
||||
from .elements import ClauseElement, _literal_as_text, Null, and_, _clone
|
||||
from .elements import ClauseElement, _literal_as_text, Null, and_, _clone, \
|
||||
_column_as_key
|
||||
from .selectable import _interpret_as_from, _interpret_as_select, HasPrefixes
|
||||
from .. import util
|
||||
from .. import exc
|
||||
|
|
@ -26,6 +27,7 @@ class UpdateBase(DialectKWArgs, HasPrefixes, Executable, ClauseElement):
|
|||
_execution_options = \
|
||||
Executable._execution_options.union({'autocommit': True})
|
||||
_hints = util.immutabledict()
|
||||
_parameter_ordering = None
|
||||
_prefixes = ()
|
||||
|
||||
def _process_colparams(self, parameters):
|
||||
|
|
@ -38,6 +40,16 @@ class UpdateBase(DialectKWArgs, HasPrefixes, Executable, ClauseElement):
|
|||
else:
|
||||
return p
|
||||
|
||||
if self._preserve_parameter_order and parameters is not None:
|
||||
if not isinstance(parameters, list) or \
|
||||
(parameters and not isinstance(parameters[0], tuple)):
|
||||
raise ValueError(
|
||||
"When preserve_parameter_order is True, "
|
||||
"values() only accepts a list of 2-tuples")
|
||||
self._parameter_ordering = [key for key, value in parameters]
|
||||
|
||||
return dict(parameters), False
|
||||
|
||||
if (isinstance(parameters, (list, tuple)) and parameters and
|
||||
isinstance(parameters[0], (list, tuple, dict))):
|
||||
|
||||
|
|
@ -177,6 +189,7 @@ class ValuesBase(UpdateBase):
|
|||
|
||||
_supports_multi_parameters = False
|
||||
_has_multi_parameters = False
|
||||
_preserve_parameter_order = False
|
||||
select = None
|
||||
|
||||
def __init__(self, table, values, prefixes):
|
||||
|
|
@ -213,23 +226,32 @@ class ValuesBase(UpdateBase):
|
|||
|
||||
users.update().where(users.c.id==5).values(name="some name")
|
||||
|
||||
:param \*args: Alternatively, a dictionary, tuple or list
|
||||
of dictionaries or tuples can be passed as a single positional
|
||||
argument in order to form the VALUES or
|
||||
SET clause of the statement. The single dictionary form
|
||||
works the same as the kwargs form::
|
||||
:param \*args: As an alternative to passing key/value parameters,
|
||||
a dictionary, tuple, or list of dictionaries or tuples can be passed
|
||||
as a single positional argument in order to form the VALUES or
|
||||
SET clause of the statement. The forms that are accepted vary
|
||||
based on whether this is an :class:`.Insert` or an :class:`.Update`
|
||||
construct.
|
||||
|
||||
For either an :class:`.Insert` or :class:`.Update` construct, a
|
||||
single dictionary can be passed, which works the same as that of
|
||||
the kwargs form::
|
||||
|
||||
users.insert().values({"name": "some name"})
|
||||
|
||||
If a tuple is passed, the tuple should contain the same number
|
||||
of columns as the target :class:`.Table`::
|
||||
users.update().values({"name": "some new name"})
|
||||
|
||||
Also for either form but more typically for the :class:`.Insert`
|
||||
construct, a tuple that contains an entry for every column in the
|
||||
table is also accepted::
|
||||
|
||||
users.insert().values((5, "some name"))
|
||||
|
||||
The :class:`.Insert` construct also supports multiply-rendered VALUES
|
||||
construct, for those backends which support this SQL syntax
|
||||
(SQLite, Postgresql, MySQL). This mode is indicated by passing a
|
||||
list of one or more dictionaries/tuples::
|
||||
The :class:`.Insert` construct also supports being passed a list
|
||||
of dictionaries or full-table-tuples, which on the server will
|
||||
render the less common SQL syntax of "multiple values" - this
|
||||
syntax is supported on backends such as SQLite, Postgresql, MySQL,
|
||||
but not necessarily others::
|
||||
|
||||
users.insert().values([
|
||||
{"name": "some name"},
|
||||
|
|
@ -237,38 +259,61 @@ class ValuesBase(UpdateBase):
|
|||
{"name": "yet another name"},
|
||||
])
|
||||
|
||||
In the case of an :class:`.Update`
|
||||
construct, only the single dictionary/tuple form is accepted,
|
||||
else an exception is raised. It is also an exception case to
|
||||
attempt to mix the single-/multiple- value styles together,
|
||||
either through multiple :meth:`.ValuesBase.values` calls
|
||||
or by sending a list + kwargs at the same time.
|
||||
The above form would render a multiple VALUES statement similar to::
|
||||
|
||||
.. note::
|
||||
INSERT INTO users (name) VALUES
|
||||
(:name_1),
|
||||
(:name_2),
|
||||
(:name_3)
|
||||
|
||||
Passing a multiple values list is *not* the same
|
||||
as passing a multiple values list to the
|
||||
:meth:`.Connection.execute` method. Passing a list of parameter
|
||||
sets to :meth:`.ValuesBase.values` produces a construct of this
|
||||
form::
|
||||
It is essential to note that **passing multiple values is
|
||||
NOT the same as using traditional executemany() form**. The above
|
||||
syntax is a **special** syntax not typically used. To emit an
|
||||
INSERT statement against multiple rows, the normal method is
|
||||
to pass a multiple values list to the :meth:`.Connection.execute`
|
||||
method, which is supported by all database backends and is generally
|
||||
more efficient for a very large number of parameters.
|
||||
|
||||
INSERT INTO table (col1, col2, col3) VALUES
|
||||
(col1_0, col2_0, col3_0),
|
||||
(col1_1, col2_1, col3_1),
|
||||
...
|
||||
.. seealso::
|
||||
|
||||
whereas a multiple list passed to :meth:`.Connection.execute`
|
||||
has the effect of using the DBAPI
|
||||
`executemany() <http://www.python.org/dev/peps/pep-0249/#id18>`_
|
||||
method, which provides a high-performance system of invoking
|
||||
a single-row INSERT statement many times against a series
|
||||
of parameter sets. The "executemany" style is supported by
|
||||
all database backends, as it does not depend on a special SQL
|
||||
syntax.
|
||||
:ref:`execute_multiple` - an introduction to
|
||||
the traditional Core method of multiple parameter set
|
||||
invocation for INSERTs and other statements.
|
||||
|
||||
.. 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.
|
||||
|
||||
.. versionchanged:: 1.0.0 A multiple-VALUES INSERT now supports
|
||||
columns with Python side default values and callables in the
|
||||
same way as that of an "executemany" style of invocation; the
|
||||
callable is invoked for each row. See :ref:`bug_3288`
|
||||
for other details.
|
||||
|
||||
The :class:`.Update` construct supports a special form which is a
|
||||
list of 2-tuples, which when provided must be passed in conjunction
|
||||
with the
|
||||
:paramref:`~sqlalchemy.sql.expression.update.preserve_parameter_order`
|
||||
parameter.
|
||||
This form causes the UPDATE statement to render the SET clauses
|
||||
using the order of parameters given to :meth:`.Update.values`, rather
|
||||
than the ordering of columns given in the :class:`.Table`.
|
||||
|
||||
.. versionadded:: 1.0.10 - added support for parameter-ordered
|
||||
UPDATE statements via the
|
||||
:paramref:`~sqlalchemy.sql.expression.update.preserve_parameter_order`
|
||||
flag.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`updates_order_parameters` - full example of the
|
||||
:paramref:`~sqlalchemy.sql.expression.update.preserve_parameter_order`
|
||||
flag
|
||||
|
||||
.. seealso::
|
||||
|
||||
|
|
@ -358,7 +403,7 @@ class ValuesBase(UpdateBase):
|
|||
SELECT, multi-valued VALUES clause),
|
||||
:meth:`.ValuesBase.return_defaults` is intended only for an
|
||||
"ORM-style" single-row INSERT/UPDATE statement. The row returned
|
||||
by the statement is also consumed implcitly when
|
||||
by the statement is also consumed implicitly when
|
||||
:meth:`.ValuesBase.return_defaults` is used. By contrast,
|
||||
:meth:`.UpdateBase.returning` leaves the RETURNING result-set
|
||||
intact with a collection of any number of rows.
|
||||
|
|
@ -380,7 +425,7 @@ class ValuesBase(UpdateBase):
|
|||
:func:`.mapper`.
|
||||
|
||||
:param cols: optional list of column key names or :class:`.Column`
|
||||
objects. If omitted, all column expressions evaulated on the server
|
||||
objects. If omitted, all column expressions evaluated on the server
|
||||
are added to the returning list.
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
|
|
@ -434,8 +479,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
|
||||
|
|
@ -463,6 +513,7 @@ class Insert(ValuesBase):
|
|||
ValuesBase.__init__(self, table, values, prefixes)
|
||||
self._bind = bind
|
||||
self.select = self.select_names = None
|
||||
self.include_insert_from_select_defaults = False
|
||||
self.inline = inline
|
||||
self._returning = returning
|
||||
self._validate_dialect_kwargs(dialect_kw)
|
||||
|
|
@ -475,7 +526,7 @@ class Insert(ValuesBase):
|
|||
return ()
|
||||
|
||||
@_generative
|
||||
def from_select(self, names, select):
|
||||
def from_select(self, names, select, include_defaults=True):
|
||||
"""Return a new :class:`.Insert` construct which represents
|
||||
an ``INSERT...FROM SELECT`` statement.
|
||||
|
||||
|
|
@ -494,25 +545,28 @@ class Insert(ValuesBase):
|
|||
is not checked before passing along to the database, the database
|
||||
would normally raise an exception if these column lists don't
|
||||
correspond.
|
||||
:param include_defaults: if True, non-server default values and
|
||||
SQL expressions as specified on :class:`.Column` objects
|
||||
(as documented in :ref:`metadata_defaults_toplevel`) not
|
||||
otherwise specified in the list of names will be rendered
|
||||
into the INSERT and SELECT statements, so that these values are also
|
||||
included in the data to be inserted.
|
||||
|
||||
.. note::
|
||||
.. note:: A Python-side default that uses a Python callable function
|
||||
will only be invoked **once** for the whole statement, and **not
|
||||
per row**.
|
||||
|
||||
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::
|
||||
.. versionadded:: 1.0.0 - :meth:`.Insert.from_select` now renders
|
||||
Python-side and SQL expression column defaults into the
|
||||
SELECT statement for columns otherwise not included in the
|
||||
list of column names.
|
||||
|
||||
sel = select([table1.c.a, table1.c.b]).where(table1.c.c > 5)
|
||||
ins = table2.insert(inline=True).from_select(['a', 'b'], sel)
|
||||
|
||||
.. note::
|
||||
|
||||
A SELECT..INSERT construct in SQL has no VALUES clause. Therefore
|
||||
:class:`.Column` objects which utilize Python-side defaults
|
||||
(e.g. as described at :ref:`metadata_defaults_toplevel`)
|
||||
will **not** take effect when using :meth:`.Insert.from_select`.
|
||||
.. 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.
|
||||
|
||||
.. versionadded:: 0.8.3
|
||||
|
||||
|
|
@ -522,9 +576,12 @@ class Insert(ValuesBase):
|
|||
"This construct already inserts value expressions")
|
||||
|
||||
self.parameters, self._has_multi_parameters = \
|
||||
self._process_colparams(dict((n, Null()) for n in names))
|
||||
self._process_colparams(
|
||||
dict((_column_as_key(n), Null()) for n in names))
|
||||
|
||||
self.select_names = names
|
||||
self.inline = True
|
||||
self.include_insert_from_select_defaults = include_defaults
|
||||
self.select = _interpret_as_select(select)
|
||||
|
||||
def _copy_internals(self, clone=_clone, **kw):
|
||||
|
|
@ -552,6 +609,7 @@ class Update(ValuesBase):
|
|||
prefixes=None,
|
||||
returning=None,
|
||||
return_defaults=False,
|
||||
preserve_parameter_order=False,
|
||||
**dialect_kw):
|
||||
"""Construct an :class:`.Update` object.
|
||||
|
||||
|
|
@ -614,6 +672,19 @@ class Update(ValuesBase):
|
|||
be available in the dictionary returned from
|
||||
:meth:`.ResultProxy.last_updated_params`.
|
||||
|
||||
:param preserve_parameter_order: if True, the update statement is
|
||||
expected to receive parameters **only** via the :meth:`.Update.values`
|
||||
method, and they must be passed as a Python ``list`` of 2-tuples.
|
||||
The rendered UPDATE statement will emit the SET clause for each
|
||||
referenced column maintaining this order.
|
||||
|
||||
.. versionadded:: 1.0.10
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`updates_order_parameters` - full example of the
|
||||
:paramref:`~sqlalchemy.sql.expression.update.preserve_parameter_order` flag
|
||||
|
||||
If both ``values`` and compile-time bind parameters are present, the
|
||||
compile-time bind parameters override the information specified
|
||||
within ``values`` on a per-key basis.
|
||||
|
|
@ -655,6 +726,7 @@ class Update(ValuesBase):
|
|||
|
||||
|
||||
"""
|
||||
self._preserve_parameter_order = preserve_parameter_order
|
||||
ValuesBase.__init__(self, table, values, prefixes)
|
||||
self._bind = bind
|
||||
self._returning = returning
|
||||
|
|
@ -728,10 +800,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::
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue