diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2017-09-08 21:34:39 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2017-09-08 21:41:13 -0400 |
commit | 70be7312f10a2241cde3e6472af15ef5a9ae222a (patch) | |
tree | 7e7e28baf1a5fc7d2d07c6249b2b177abe770ef8 | |
parent | 5ae984b946f87cc485c29c4c947a8649d4c4c422 (diff) | |
download | sqlalchemy-70be7312f10a2241cde3e6472af15ef5a9ae222a.tar.gz |
Rename MySQL dml.insert().values to .inserted
Changed the name of the ``.values`` attribute of the new MySQL
INSERT..ON DUPLICATE KEY UPDATE construct to ``.inserted``, as
:class:`.Insert` already has a method called :meth:`.Insert.values`.
The ``.inserted`` attribute ultimately renders the MySQL ``VALUES()``
function.
Change-Id: I8da8e30a3077698385a4b77e2c2032e2d1ff10b2
Fixes: #4072
-rw-r--r-- | doc/build/changelog/migration_12.rst | 2 | ||||
-rw-r--r-- | doc/build/changelog/unreleased_12/4072.rst | 9 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/mysql/base.py | 14 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/mysql/dml.py | 23 | ||||
-rw-r--r-- | test/dialect/mysql/test_compiler.py | 14 | ||||
-rw-r--r-- | test/dialect/mysql/test_on_duplicate.py | 13 |
6 files changed, 43 insertions, 32 deletions
diff --git a/doc/build/changelog/migration_12.rst b/doc/build/changelog/migration_12.rst index 4cfaf38c4..87c08dc21 100644 --- a/doc/build/changelog/migration_12.rst +++ b/doc/build/changelog/migration_12.rst @@ -1336,7 +1336,7 @@ This :class:`~.expression.Insert` subclass adds a new method values(id='some_id', data='some data to insert') on_conflict_stmt = insert_stmt.on_duplicate_key_update( - data=stmt.values.data, + data=stmt.inserted.data, status='U' ) diff --git a/doc/build/changelog/unreleased_12/4072.rst b/doc/build/changelog/unreleased_12/4072.rst new file mode 100644 index 000000000..3e5e83f24 --- /dev/null +++ b/doc/build/changelog/unreleased_12/4072.rst @@ -0,0 +1,9 @@ +.. change:: + :tags: bug, mysql + :tickets: 4072 + + Changed the name of the ``.values`` attribute of the new MySQL + INSERT..ON DUPLICATE KEY UPDATE construct to ``.inserted``, as + :class:`.Insert` already has a method called :meth:`.Insert.values`. + The ``.inserted`` attribute ultimately renders the MySQL ``VALUES()`` + function.
\ No newline at end of file diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py index 976ff367b..b1b249001 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -332,8 +332,8 @@ INSERT...ON DUPLICATE KEY UPDATE (Upsert) MySQL allows "upserts" (update or insert) of rows into a table via the ``ON DUPLICATE KEY UPDATE`` clause of the ``INSERT`` statement. A candidate row will only be inserted if that row does -not match an existing primary or unique key in the table; otherwise, an UPDATE will -be performed. The statement allows for separate specification of the +not match an existing primary or unique key in the table; otherwise, an UPDATE +will be performed. The statement allows for separate specification of the values to INSERT versus the values for UPDATE. SQLAlchemy provides ``ON DUPLICATE KEY UPDATE`` support via the MySQL-specific @@ -347,7 +347,7 @@ the generative method :meth:`~.mysql.dml.Insert.on_duplicate_key_update`:: data='inserted value') on_duplicate_key_stmt = insert_stmt.on_duplicate_key_update( - data=insert_stmt.values.data, + data=insert_stmt.inserted.data, status='U' ) @@ -381,7 +381,7 @@ as values:: unless they are manually specified explicitly in the parameters. In order to refer to the proposed insertion row, the special alias -:attr:`~.mysql.dml.Insert.values` is available as an attribute on +:attr:`~.mysql.dml.Insert.inserted` is available as an attribute on the :class:`.mysql.dml.Insert` object; this object is a :class:`.ColumnCollection` which contains all columns of the target table:: @@ -394,11 +394,11 @@ table:: author='jlh') do_update_stmt = stmt.on_duplicate_key_update( data="updated value", - author=stmt.values.author + author=stmt.inserted.author ) conn.execute(do_update_stmt) -When rendered, the "values" namespace will produce the expression +When rendered, the "inserted" namespace will produce the expression ``VALUES(<columnname>)``. .. versionadded:: 1.2 Added support for MySQL ON DUPLICATE KEY UPDATE clause @@ -921,7 +921,7 @@ class MySQLCompiler(compiler.SQLCompiler): val.type = column.type value_text = self.process(val.self_group(), use_schema=False) elif isinstance(val, elements.ColumnClause) \ - and val.table is on_duplicate.values_alias: + and val.table is on_duplicate.inserted_alias: value_text = 'VALUES(' + self.preparer.quote(column.name) + ')' else: value_text = self.process(val.self_group(), use_schema=False) diff --git a/lib/sqlalchemy/dialects/mysql/dml.py b/lib/sqlalchemy/dialects/mysql/dml.py index 743510317..217dc7a2a 100644 --- a/lib/sqlalchemy/dialects/mysql/dml.py +++ b/lib/sqlalchemy/dialects/mysql/dml.py @@ -18,26 +18,27 @@ class Insert(StandardInsert): """ @property - def values(self): - """Provide the ``values`` namespace for an ON DUPLICATE KEY UPDATE statement + def inserted(self): + """Provide the "inserted" namespace for an ON DUPLICATE KEY UPDATE statement MySQL's ON DUPLICATE KEY UPDATE clause allows reference to the row that would be inserted, via a special function called ``VALUES()``. This attribute provides all columns in this row to be referenaceable such that they will render within a ``VALUES()`` function inside the - ON DUPLICATE KEY UPDATE clause. + ON DUPLICATE KEY UPDATE clause. The attribute is named ``.inserted`` + so as not to conflict with the existing :meth:`.Insert.values` method. .. seealso:: :ref:`mysql_insert_on_duplicate_key_update` - example of how - to use :attr:`.Insert.values` + to use :attr:`.Insert.inserted` """ - return self.values_alias.columns + return self.inserted_alias.columns @util.memoized_property - def values_alias(self): - return alias(self.table, name='values') + def inserted_alias(self): + return alias(self.table, name='inserted') @_generative def on_duplicate_key_update(self, **kw): @@ -61,8 +62,8 @@ class Insert(StandardInsert): :ref:`mysql_insert_on_duplicate_key_update` """ - values_alias = getattr(self, 'values_alias', None) - self._post_values_clause = OnDuplicateClause(values_alias, kw) + inserted_alias = getattr(self, 'inserted_alias', None) + self._post_values_clause = OnDuplicateClause(inserted_alias, kw) return self @@ -72,8 +73,8 @@ insert = public_factory(Insert, '.dialects.mysql.insert') class OnDuplicateClause(ClauseElement): __visit_name__ = 'on_duplicate_key_update' - def __init__(self, values_alias, update): - self.values_alias = values_alias + def __init__(self, inserted_alias, update): + self.inserted_alias = inserted_alias if not update or not isinstance(update, dict): raise ValueError('update parameter must be a non-empty dictionary') self.update = update diff --git a/test/dialect/mysql/test_compiler.py b/test/dialect/mysql/test_compiler.py index 3663a4800..e8731e532 100644 --- a/test/dialect/mysql/test_compiler.py +++ b/test/dialect/mysql/test_compiler.py @@ -704,10 +704,10 @@ class InsertOnDuplicateTest(fixtures.TestBase, AssertsCompiledSQL): ) def test_from_values(self): - stmt = insert( - self.table, [{'id': 1, 'bar': 'ab'}, {'id': 2, 'bar': 'b'}]) + stmt = insert(self.table).values( + [{'id': 1, 'bar': 'ab'}, {'id': 2, 'bar': 'b'}]) stmt = stmt.on_duplicate_key_update( - bar=stmt.values.bar, baz=stmt.values.baz) + bar=stmt.inserted.bar, baz=stmt.inserted.baz) expected_sql = ( 'INSERT INTO foos (id, bar) VALUES (%s, %s), (%s, %s) ' 'ON DUPLICATE KEY UPDATE bar = VALUES(bar), baz = VALUES(baz)' @@ -715,8 +715,8 @@ class InsertOnDuplicateTest(fixtures.TestBase, AssertsCompiledSQL): self.assert_compile(stmt, expected_sql) def test_from_literal(self): - stmt = insert( - self.table, [{'id': 1, 'bar': 'ab'}, {'id': 2, 'bar': 'b'}]) + stmt = insert(self.table).values( + [{'id': 1, 'bar': 'ab'}, {'id': 2, 'bar': 'b'}]) stmt = stmt.on_duplicate_key_update(bar=literal_column('bb')) expected_sql = ( 'INSERT INTO foos (id, bar) VALUES (%s, %s), (%s, %s) ' @@ -725,8 +725,8 @@ class InsertOnDuplicateTest(fixtures.TestBase, AssertsCompiledSQL): self.assert_compile(stmt, expected_sql) def test_python_values(self): - stmt = insert( - self.table, [{'id': 1, 'bar': 'ab'}, {'id': 2, 'bar': 'b'}]) + stmt = insert(self.table).values( + [{'id': 1, 'bar': 'ab'}, {'id': 2, 'bar': 'b'}]) stmt = stmt.on_duplicate_key_update(bar="foobar") expected_sql = ( 'INSERT INTO foos (id, bar) VALUES (%s, %s), (%s, %s) ' diff --git a/test/dialect/mysql/test_on_duplicate.py b/test/dialect/mysql/test_on_duplicate.py index 2ff4a58cc..9a026f9ed 100644 --- a/test/dialect/mysql/test_on_duplicate.py +++ b/test/dialect/mysql/test_on_duplicate.py @@ -29,8 +29,9 @@ class OnDuplicateTest(fixtures.TablesTest): foos = self.tables.foos with testing.db.connect() as conn: conn.execute(insert(foos, dict(id=1, bar='b', baz='bz'))) - stmt = insert(foos, [dict(id=1, bar='ab'), dict(id=2, bar='b')]) - stmt = stmt.on_duplicate_key_update(bar=stmt.values.bar) + stmt = insert(foos).values( + [dict(id=1, bar='ab'), dict(id=2, bar='b')]) + stmt = stmt.on_duplicate_key_update(bar=stmt.inserted.bar) result = conn.execute(stmt) eq_(result.inserted_primary_key, [2]) eq_( @@ -41,17 +42,17 @@ class OnDuplicateTest(fixtures.TablesTest): def test_last_inserted_id(self): foos = self.tables.foos with testing.db.connect() as conn: - stmt = insert(foos, {"bar": "b", "baz": "bz"}) + stmt = insert(foos).values({"bar": "b", "baz": "bz"}) result = conn.execute( stmt.on_duplicate_key_update( - bar=stmt.values.bar, baz="newbz") + bar=stmt.inserted.bar, baz="newbz") ) eq_(result.inserted_primary_key, [1]) - stmt = insert(foos, {"id": 1, "bar": "b", "baz": "bz"}) + stmt = insert(foos).values({"id": 1, "bar": "b", "baz": "bz"}) result = conn.execute( stmt.on_duplicate_key_update( - bar=stmt.values.bar, baz="newbz") + bar=stmt.inserted.bar, baz="newbz") ) eq_(result.inserted_primary_key, [1]) |