]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Added support for vendor-extended INSERT syntax like INSERT DELAYED INTO
authorJason Kirtland <jek@discorporate.us>
Fri, 7 Mar 2008 16:56:37 +0000 (16:56 +0000)
committerJason Kirtland <jek@discorporate.us>
Fri, 7 Mar 2008 16:56:37 +0000 (16:56 +0000)
CHANGES
lib/sqlalchemy/sql/compiler.py
lib/sqlalchemy/sql/expression.py
test/sql/generative.py

diff --git a/CHANGES b/CHANGES
index 0fe58815fb638b00d0b23427c02680769e860af9..b176db4ac927c9584e41546ada935210f39d2fb8 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -27,6 +27,10 @@ CHANGES
       delete() and DDL(). The .bind property is now assignable
       on those statements as well as on select().
 
+    - Insert statements can now be compiled with extra "prefix"
+      words between INSERT and INTO, for vendor extensions like
+      MySQL's INSERT IGNORE INTO table.
+
 - orm
     - any(), has(), contains(), ~contains(), attribute level ==
       and != now work properly with self-referential relations -
index 8a2a5f2ddb42a1ec1819f795d57a00e429300837..bb9cc7597a34351614061daf2d68cd38daa3e6eb 100644 (file)
@@ -626,7 +626,10 @@ class DefaultCompiler(engine.Compiled):
         colparams = self._get_colparams(insert_stmt)
         preparer = self.preparer
 
-        return ("INSERT INTO %s (%s) VALUES (%s)" %
+        insert = ' '.join(["INSERT"] +
+                          [self.process(x) for x in insert_stmt._prefixes])
+
+        return (insert + " INTO %s (%s) VALUES (%s)" %
                 (preparer.format_table(insert_stmt.table),
                  ', '.join([preparer.quote(c[0], c[0].name)
                             for c in colparams]),
index 8e2a13e7cebc34bbff371ebba7b6e9703fdd95aa..316cbd7c196f49c0349985a109a258a0521bc716 100644 (file)
@@ -274,6 +274,10 @@ def insert(table, values=None, inline=False, **kwargs):
       column specifications will be generated from the full list of
       table columns.
 
+    prefixes
+      A list of modifier keywords to be inserted between INSERT and INTO,
+      see ``Insert.prefix_with``.
+
     inline
       if True, SQL defaults will be compiled 'inline' into the statement
       and not pre-executed.
@@ -3475,11 +3479,16 @@ class _UpdateBase(ClauseElement):
     bind = property(bind, _set_bind)
 
 class Insert(_UpdateBase):
-    def __init__(self, table, values=None, inline=False, bind=None, **kwargs):
+    def __init__(self, table, values=None, inline=False, bind=None, prefixes=None, **kwargs):
         self._bind = bind
         self.table = table
         self.select = None
         self.inline=inline
+        if prefixes:
+            self._prefixes = [_literal_as_text(p) for p in prefixes]
+        else:
+            self._prefixes = []
+
         self.parameters = self._process_colparams(values)
 
         self.kwargs = kwargs
@@ -3504,6 +3513,17 @@ class Insert(_UpdateBase):
             u.parameters.update(u._process_colparams(v))
         return u
 
+    def prefix_with(self, clause):
+        """Add a word or expression between INSERT and INTO. Generative.
+
+        If multiple prefixes are supplied, they will be separated with
+        spaces.
+        """
+        gen = self._clone()
+        clause = _literal_as_text(clause)
+        gen._prefixes = self._prefixes + [clause]
+        return gen
+
 class Update(_UpdateBase):
     def __init__(self, table, whereclause, values=None, inline=False, bind=None, **kwargs):
         self._bind = bind
index 5e6b3b7e6c4c62a477034acb3640fb3c565f6ecf..3d7c88972e8dd694469e7cf7c7003db9222bf2fd 100644 (file)
@@ -510,5 +510,50 @@ class SelectTest(TestBase, AssertsCompiledSQL):
         self.assert_compile(select_copy, "SELECT FOOBER table1.col1, table1.col2, table1.col3 FROM table1")
         self.assert_compile(s, "SELECT table1.col1, table1.col2, table1.col3 FROM table1")
 
+
+class InsertTest(TestBase, AssertsCompiledSQL):
+    """Tests the generative capability of Insert"""
+
+    # fixme: consolidate converage from elsewhere here and expand
+
+    def setUpAll(self):
+        global t1, t2
+        t1 = table("table1",
+            column("col1"),
+            column("col2"),
+            column("col3"),
+            )
+        t2 = table("table2",
+            column("col1"),
+            column("col2"),
+            column("col3"),
+            )
+
+    def test_prefixes(self):
+        i = t1.insert()
+        self.assert_compile(i,
+                            "INSERT INTO table1 (col1, col2, col3) "
+                            "VALUES (:col1, :col2, :col3)")
+
+        gen = i.prefix_with("foober")
+        self.assert_compile(gen,
+                            "INSERT foober INTO table1 (col1, col2, col3) "
+                            "VALUES (:col1, :col2, :col3)")
+
+        self.assert_compile(i,
+                            "INSERT INTO table1 (col1, col2, col3) "
+                            "VALUES (:col1, :col2, :col3)")
+
+        i2 = t1.insert(prefixes=['squiznart'])
+        self.assert_compile(i2,
+                            "INSERT squiznart INTO table1 (col1, col2, col3) "
+                            "VALUES (:col1, :col2, :col3)")
+
+        gen2 = i2.prefix_with("quux")
+        self.assert_compile(gen2,
+                            "INSERT squiznart quux INTO "
+                            "table1 (col1, col2, col3) "
+                            "VALUES (:col1, :col2, :col3)")
+
 if __name__ == '__main__':
     testenv.main()