diff options
author | mike bayer <mike_mp@zzzcomputing.com> | 2021-04-14 17:21:36 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@ci3.zzzcomputing.com> | 2021-04-14 17:21:36 +0000 |
commit | ccff3a14db356ba435d77f2958e87ca8013f6ce4 (patch) | |
tree | 04b9c5be595f3ae7a2d47eb6a8fd633471a7fe2f /lib/sqlalchemy | |
parent | b26cf96462b195a4c12ccdf8283ef028f91eb872 (diff) | |
parent | 94a1c523984e2082bb16d784cf8615061ba9d49a (diff) | |
download | sqlalchemy-ccff3a14db356ba435d77f2958e87ca8013f6ce4.tar.gz |
Merge "Support DEFAULT VALUES and VALUES(DEFAULT) individually"
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r-- | lib/sqlalchemy/dialects/mysql/base.py | 5 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/oracle/base.py | 4 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/postgresql/base.py | 3 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/sqlite/base.py | 5 | ||||
-rw-r--r-- | lib/sqlalchemy/engine/default.py | 10 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/compiler.py | 1 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/crud.py | 6 | ||||
-rw-r--r-- | lib/sqlalchemy/testing/assertions.py | 3 | ||||
-rw-r--r-- | lib/sqlalchemy/testing/assertsql.py | 6 | ||||
-rw-r--r-- | lib/sqlalchemy/testing/requirements.py | 10 | ||||
-rw-r--r-- | lib/sqlalchemy/testing/suite/test_insert.py | 15 |
11 files changed, 64 insertions, 4 deletions
diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py index f45d5ec91..c5113b054 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -2534,6 +2534,11 @@ class MySQLDialect(default.DefaultDialect): supports_for_update_of = False # default for MySQL ... # ... may be updated to True for MySQL 8+ in initialize() + # MySQL doesn't support "DEFAULT VALUES" but *does* support + # "VALUES (DEFAULT)" + supports_default_values = False + supports_default_metavalue = True + supports_sane_rowcount = True supports_sane_multi_rowcount = False supports_multivalues_insert = True diff --git a/lib/sqlalchemy/dialects/oracle/base.py b/lib/sqlalchemy/dialects/oracle/base.py index 6496c4f71..3e1f50fc8 100644 --- a/lib/sqlalchemy/dialects/oracle/base.py +++ b/lib/sqlalchemy/dialects/oracle/base.py @@ -1453,7 +1453,11 @@ class OracleDialect(default.DefaultDialect): requires_name_normalize = True supports_comments = True + + # Oracle supports these syntaxes but I'm not able to get them + # to work with RETURNING which we usually need supports_default_values = False + supports_default_metavalue = True supports_empty_insert = False statement_compiler = OracleCompiler diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py index 3b419ed16..0e9968031 100644 --- a/lib/sqlalchemy/dialects/postgresql/base.py +++ b/lib/sqlalchemy/dialects/postgresql/base.py @@ -3079,6 +3079,9 @@ class PGDialect(default.DefaultDialect): supports_comments = True supports_default_values = True + + supports_default_metavalue = True + supports_empty_insert = False supports_multivalues_insert = True default_paramstyle = "pyformat" diff --git a/lib/sqlalchemy/dialects/sqlite/base.py b/lib/sqlalchemy/dialects/sqlite/base.py index 28901d028..0075b3876 100644 --- a/lib/sqlalchemy/dialects/sqlite/base.py +++ b/lib/sqlalchemy/dialects/sqlite/base.py @@ -1791,7 +1791,12 @@ class SQLiteDialect(default.DefaultDialect): supports_alter = False supports_unicode_statements = True supports_unicode_binds = True + + # SQlite supports "DEFAULT VALUES" but *does not* support + # "VALUES (DEFAULT)" supports_default_values = True + supports_default_metavalue = False + supports_empty_insert = False supports_cast = True supports_multivalues_insert = True diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py index 375a93a48..a917228ad 100644 --- a/lib/sqlalchemy/engine/default.py +++ b/lib/sqlalchemy/engine/default.py @@ -141,8 +141,18 @@ class DefaultDialect(interfaces.Dialect): supports_sane_multi_rowcount = True colspecs = {} default_paramstyle = "named" + supports_default_values = False + """dialect supports INSERT... DEFAULT VALUES syntax""" + + supports_default_metavalue = False + """dialect supports INSERT... VALUES (DEFAULT) syntax""" + + # not sure if this is a real thing but the compiler will deliver it + # if this is the only flag enabled. supports_empty_insert = True + """dialect supports INSERT () VALUES ()""" + supports_multivalues_insert = False supports_is_distinct_from = True diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index 8eefa10d1..0c701cb52 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -3480,6 +3480,7 @@ class SQLCompiler(Compiled): if ( not crud_params and not self.dialect.supports_default_values + and not self.dialect.supports_default_metavalue and not self.dialect.supports_empty_insert ): raise exc.CompileError( diff --git a/lib/sqlalchemy/sql/crud.py b/lib/sqlalchemy/sql/crud.py index 174a1c131..5fa82bcd0 100644 --- a/lib/sqlalchemy/sql/crud.py +++ b/lib/sqlalchemy/sql/crud.py @@ -174,7 +174,11 @@ def _get_crud_params(compiler, stmt, compile_state, **kw): values = _extend_values_for_multiparams( compiler, stmt, compile_state, values, kw ) - elif not values and compiler.for_executemany: + elif ( + not values + and compiler.for_executemany + and compiler.dialect.supports_default_metavalue + ): # convert an "INSERT DEFAULT VALUES" # into INSERT (firstcol) VALUES (DEFAULT) which can be turned # into an in-place multi values. This supports diff --git a/lib/sqlalchemy/testing/assertions.py b/lib/sqlalchemy/testing/assertions.py index 02137474b..9ff2f76eb 100644 --- a/lib/sqlalchemy/testing/assertions.py +++ b/lib/sqlalchemy/testing/assertions.py @@ -400,6 +400,7 @@ class AssertsCompiledSQL(object): use_default_dialect=False, allow_dialect_select=False, supports_default_values=True, + supports_default_metavalue=True, literal_binds=False, render_postcompile=False, schema_translate_map=None, @@ -410,6 +411,7 @@ class AssertsCompiledSQL(object): if use_default_dialect: dialect = default.DefaultDialect() dialect.supports_default_values = supports_default_values + dialect.supports_default_metavalue = supports_default_metavalue elif allow_dialect_select: dialect = None else: @@ -421,6 +423,7 @@ class AssertsCompiledSQL(object): elif dialect == "default": dialect = default.DefaultDialect() dialect.supports_default_values = supports_default_values + dialect.supports_default_metavalue = supports_default_metavalue elif dialect == "default_enhanced": dialect = default.StrCompileDialect() elif isinstance(dialect, util.string_types): diff --git a/lib/sqlalchemy/testing/assertsql.py b/lib/sqlalchemy/testing/assertsql.py index 1bdd11585..98261a374 100644 --- a/lib/sqlalchemy/testing/assertsql.py +++ b/lib/sqlalchemy/testing/assertsql.py @@ -76,7 +76,11 @@ class CompiledSQL(SQLMatchRule): def _compile_dialect(self, execute_observed): if self.dialect == "default": - return DefaultDialect() + dialect = DefaultDialect() + # this is currently what tests are expecting + # dialect.supports_default_values = True + dialect.supports_default_metavalue = True + return dialect else: # ugh if self.dialect == "postgresql": diff --git a/lib/sqlalchemy/testing/requirements.py b/lib/sqlalchemy/testing/requirements.py index f82d5f065..8a70cc692 100644 --- a/lib/sqlalchemy/testing/requirements.py +++ b/lib/sqlalchemy/testing/requirements.py @@ -335,11 +335,19 @@ class SuiteRequirements(Requirements): return exclusions.only_if( lambda config: config.db.dialect.supports_empty_insert - or config.db.dialect.supports_default_values, + or config.db.dialect.supports_default_values + or config.db.dialect.supports_default_metavalue, "empty inserts not supported", ) @property + def empty_inserts_executemany(self): + """target platform supports INSERT with no values, i.e. + INSERT DEFAULT VALUES or equivalent, within executemany()""" + + return self.empty_inserts + + @property def insert_from_select(self): """target platform supports INSERT from a SELECT.""" diff --git a/lib/sqlalchemy/testing/suite/test_insert.py b/lib/sqlalchemy/testing/suite/test_insert.py index 35f3315c7..3c033a774 100644 --- a/lib/sqlalchemy/testing/suite/test_insert.py +++ b/lib/sqlalchemy/testing/suite/test_insert.py @@ -167,8 +167,21 @@ class InsertBehaviorTest(fixtures.TablesTest): self.tables.autoinc_pk.c.id != None ) ) + eq_(len(r.all()), 1) - assert len(r.fetchall()) + @requirements.empty_inserts_executemany + def test_empty_insert_multiple(self, connection): + r = connection.execute(self.tables.autoinc_pk.insert(), [{}, {}, {}]) + assert r._soft_closed + assert not r.closed + + r = connection.execute( + self.tables.autoinc_pk.select().where( + self.tables.autoinc_pk.c.id != None + ) + ) + + eq_(len(r.all()), 3) @requirements.insert_from_select def test_insert_from_select_autoinc(self, connection): |