]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Modifications to allow the backends to control the behavior of an empty insert. ...
authorMichael Trier <mtrier@gmail.com>
Mon, 20 Oct 2008 15:21:00 +0000 (15:21 +0000)
committerMichael Trier <mtrier@gmail.com>
Mon, 20 Oct 2008 15:21:00 +0000 (15:21 +0000)
lib/sqlalchemy/databases/mssql.py
lib/sqlalchemy/databases/postgres.py
lib/sqlalchemy/databases/sqlite.py
lib/sqlalchemy/engine/default.py
lib/sqlalchemy/sql/compiler.py
test/sql/defaults.py

index 1ff482cf56c5d1b10ed28ae867a29b2e6c350956..4bbc2caf770a006b75fd0cab787e03b014d2f6b7 100644 (file)
@@ -361,6 +361,8 @@ class MSSQLExecutionContext_pyodbc (MSSQLExecutionContext):
 
 class MSSQLDialect(default.DefaultDialect):
     name = 'mssql'
+    supports_default_values = True
+    supports_empty_insert = False
 
     colspecs = {
         sqltypes.Unicode : MSNVarchar,
index 1c410af5388becfa358041da9a2d537f579ca3f3..c8abeb6db7bdf8e5a0f27887a25af189d49f8325 100644 (file)
@@ -302,6 +302,8 @@ class PGDialect(default.DefaultDialect):
     preexecute_pk_sequences = True
     supports_pk_autoincrement = False
     default_paramstyle = 'pyformat'
+    supports_default_values = True
+    supports_empty_insert = False
 
     def __init__(self, server_side_cursors=False, **kwargs):
         default.DefaultDialect.__init__(self, **kwargs)
index 70c3f74ecb14adaefd74928ed7a06ac00364fcab..b3de98100ccce1a80c0a72a6468eab907ca07572 100644 (file)
@@ -242,6 +242,8 @@ class SQLiteDialect(default.DefaultDialect):
     supports_alter = False
     supports_unicode_statements = True
     default_paramstyle = 'qmark'
+    supports_default_values = True
+    supports_empty_insert = False
 
     def __init__(self, **kwargs):
         default.DefaultDialect.__init__(self, **kwargs)
@@ -465,25 +467,6 @@ class SQLiteCompiler(compiler.DefaultCompiler):
         # sqlite has no "FOR UPDATE" AFAICT
         return ''
 
-    def visit_insert(self, insert_stmt):
-        self.isinsert = True
-        colparams = self._get_colparams(insert_stmt)
-        preparer = self.preparer
-
-        if not colparams:
-            if not self.dialect.supports_default_values:
-                raise exc.NotSupportedError(
-                    "The version of SQLite you are using, %s, does not support DEFAULT VALUES." % (self.dialect.dbapi.sqlite_version))
-
-            return ("INSERT INTO %s DEFAULT VALUES" % (
-                (preparer.format_table(insert_stmt.table),)))
-        else:
-            return ("INSERT INTO %s (%s) VALUES (%s)" %
-                    (preparer.format_table(insert_stmt.table),
-                     ', '.join([preparer.format_column(c[0])
-                                for c in colparams]),
-                     ', '.join([c[1] for c in colparams])))
-
 
 class SQLiteSchemaGenerator(compiler.SchemaGenerator):
 
index a90142702939813fff2311cb7e19635c1a3d8b10..96dadd0455d9fa4c15048b7c28b6d52c858e0b73 100644 (file)
@@ -39,7 +39,8 @@ class DefaultDialect(base.Dialect):
     supports_pk_autoincrement = True
     dbapi_type_map = {}
     default_paramstyle = 'named'
-    supports_default_values = True
+    supports_default_values = False 
+    supports_empty_insert = True
 
     def __init__(self, convert_unicode=False, assert_unicode=False, encoding='utf-8', paramstyle=None, dbapi=None, **kwargs):
         self.convert_unicode = convert_unicode
index 0117b96ff2c65829538799d83c9a0507d96b290b..2072d5a272d90f8823d491ca95f05e65f822c2de 100644 (file)
@@ -570,11 +570,18 @@ class DefaultCompiler(engine.Compiled):
         insert = ' '.join(["INSERT"] +
                           [self.process(x) for x in insert_stmt._prefixes])
 
-        return (insert + " INTO %s (%s) VALUES (%s)" %
+        if not colparams and not self.dialect.supports_default_values and not self.dialect.supports_empty_insert:
+            raise exc.NotSupportedError(
+                "The version of %s you are using does not support empty inserts." % self.dialect.name)
+        elif not colparams and self.dialect.supports_default_values:
+            return (insert + " INTO %s DEFAULT VALUES" % (
+                (preparer.format_table(insert_stmt.table),)))
+        else: 
+            return (insert + " INTO %s (%s) VALUES (%s)" %
                 (preparer.format_table(insert_stmt.table),
-                 ', '.join(preparer.quote(c[0].name, c[0].quote)
-                           for c in colparams),
-                 ', '.join(c[1] for c in colparams)))
+                 ', '.join([preparer.format_column(c[0])
+                           for c in colparams]),
+                 ', '.join([c[1] for c in colparams])))
 
     def visit_update(self, update_stmt):
         self.stack.append({'from': set([update_stmt.table])})
index 4f0f929f1791ffb6adba7ebed2038fbf79eb9a8f..169d60c670fe345e68a56ddba95a37107362b197 100644 (file)
@@ -1,8 +1,9 @@
 import testenv; testenv.configure_for_tests()
 import datetime
 from sqlalchemy import Sequence, Column, func
+from sqlalchemy.sql import select, text
 from testlib import sa, testing
-from testlib.sa import MetaData, Table, Integer, String, ForeignKey
+from testlib.sa import MetaData, Table, Integer, String, ForeignKey, Boolean
 from testlib.testing import eq_
 from sql import _base
 
@@ -472,6 +473,21 @@ class PKIncrementTest(_base.TablesTest):
             con.close()
 
 
+class EmptyInsertTest(testing.TestBase):
+    @testing.exclude('sqlite', '<', (3, 3, 8), 'no empty insert support')
+    def test_empty_insert(self):
+        metadata = MetaData(testing.db)
+        t1 = Table('t1', metadata,
+                Column('is_true', Boolean, server_default=('1')))
+        metadata.create_all()
+        
+        try:
+            result = t1.insert().execute()
+            self.assertEquals(1, select([func.count(text('*'))], from_obj=t1).scalar())
+            self.assertEquals(True, t1.select().scalar())
+        finally:
+            metadata.drop_all()
+
 class AutoIncrementTest(_base.TablesTest):
     __requires__ = ('identity',)
     run_define_tables = 'each'