summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Kirtland <jek@discorporate.us>2008-03-07 16:56:37 +0000
committerJason Kirtland <jek@discorporate.us>2008-03-07 16:56:37 +0000
commitaa033afeeedd4d41493819312d652041017abf72 (patch)
tree2950637d74d991a2892d6cf58bc005691494f209
parent90a7553b5be6abada946edb2cfbe6b4ee5e3b18c (diff)
downloadsqlalchemy-aa033afeeedd4d41493819312d652041017abf72.tar.gz
Added support for vendor-extended INSERT syntax like INSERT DELAYED INTO
-rw-r--r--CHANGES4
-rw-r--r--lib/sqlalchemy/sql/compiler.py5
-rw-r--r--lib/sqlalchemy/sql/expression.py22
-rw-r--r--test/sql/generative.py45
4 files changed, 74 insertions, 2 deletions
diff --git a/CHANGES b/CHANGES
index 0fe58815f..b176db4ac 100644
--- 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 -
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index 8a2a5f2dd..bb9cc7597 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -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]),
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py
index 8e2a13e7c..316cbd7c1 100644
--- a/lib/sqlalchemy/sql/expression.py
+++ b/lib/sqlalchemy/sql/expression.py
@@ -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
diff --git a/test/sql/generative.py b/test/sql/generative.py
index 5e6b3b7e6..3d7c88972 100644
--- a/test/sql/generative.py
+++ b/test/sql/generative.py
@@ -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()