Merge lp:~wgrant/storm/bulk-insert into lp:storm

Proposed by William Grant
Status: Merged
Approved by: Free Ekanayaka
Approved revision: 434
Merge reported by: Free Ekanayaka
Merged at revision: not available
Proposed branch: lp:~wgrant/storm/bulk-insert
Merge into: lp:storm
Diff against target: 108 lines (+46/-6)
3 files modified
NEWS (+3/-0)
storm/expr.py (+19/-6)
tests/expr.py (+24/-0)
To merge this branch: bzr merge lp:~wgrant/storm/bulk-insert
Reviewer Review Type Date Requested Status
Free Ekanayaka (community) Approve
Robert Collins (community) Approve
Review via email: mp+93527@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Robert Collins (lifeless) wrote :

The first hunk is at best confusing. Marking them up as object references @Column or whatever would help. Other than that it looks fine to me.

review: Approve
Revision history for this message
Free Ekanayaka (free.ekanayaka) wrote :

Nice addition, looks good to me! +1.

Maybe changing the name of the new parameter from "expr" to "values" would be a touch more meaningful.

review: Approve
lp:~wgrant/storm/bulk-insert updated
435. By William Grant

Insert's expr param is now values.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'NEWS'
2--- NEWS 2012-03-05 20:12:44 +0000
3+++ NEWS 2012-03-08 10:12:18 +0000
4@@ -23,6 +23,9 @@
5 There are also disconnection tests that simulate sudden termination
6 of pgbouncer <http://pgfoundry.org/projects/pgbouncer/>.
7
8+- Insert expressions now support multi-row and subquery INSERT
9+ statements.
10+
11 Bug fixes
12 ---------
13
14
15=== modified file 'storm/expr.py'
16--- storm/expr.py 2011-09-15 13:07:55 +0000
17+++ storm/expr.py 2012-03-08 10:12:18 +0000
18@@ -700,7 +700,8 @@
19 class Insert(Expr):
20 """Expression representing an insert statement.
21
22- @ivar map: Dictionary mapping columns to values.
23+ @ivar map: Dictionary mapping columns to values, or a sequence of columns
24+ for a bulk insert.
25 @ivar table: Table where the row should be inserted.
26 @ivar default_table: Table to use if no table is explicitly provided, and
27 no tables may be inferred from provided columns.
28@@ -710,17 +711,21 @@
29 @ivar primary_variables: Tuple of variables with values for the primary
30 key of the table where the row will be inserted. This is a hint used
31 by backends to process the insertion of rows.
32+ @ivar values: Expression or sequence of tuples of values for bulk
33+ insertion.
34 """
35 __slots__ = ("map", "table", "default_table", "primary_columns",
36- "primary_variables")
37+ "primary_variables", "values")
38
39 def __init__(self, map, table=Undef, default_table=Undef,
40- primary_columns=Undef, primary_variables=Undef):
41+ primary_columns=Undef, primary_variables=Undef,
42+ values=Undef):
43 self.map = map
44 self.table = table
45 self.default_table = default_table
46 self.primary_columns = primary_columns
47 self.primary_variables = primary_variables
48+ self.values = values
49
50 @compile.when(Insert)
51 def compile_insert(compile, insert, state):
52@@ -729,10 +734,18 @@
53 state.context = TABLE
54 table = build_tables(compile, insert.table, insert.default_table, state)
55 state.context = EXPR
56- values = compile(tuple(insert.map.itervalues()), state)
57+ values = insert.values
58+ if values is Undef:
59+ values = [tuple(insert.map.itervalues())]
60+ if isinstance(values, Expr):
61+ compiled_values = compile(values, state)
62+ else:
63+ compiled_values = (
64+ "VALUES (%s)" %
65+ "), (".join(compile(value, state) for value in values))
66 state.pop()
67- return "".join(["INSERT INTO ", table, " (", columns,
68- ") VALUES (", values, ")"])
69+ return "".join(
70+ ["INSERT INTO ", table, " (", columns, ") ", compiled_values])
71
72
73 class Update(Expr):
74
75=== modified file 'tests/expr.py'
76--- tests/expr.py 2011-09-14 15:27:52 +0000
77+++ tests/expr.py 2012-03-08 10:12:18 +0000
78@@ -879,6 +879,30 @@
79 self.assertEquals(value.context, EXPR)
80 self.assertEquals(table.context, TABLE)
81
82+ def test_insert_bulk(self):
83+ expr = Insert((Column(column1, table1), Column(column2, table1)),
84+ values=[(elem1, elem2), (elem3, elem4)])
85+ state = State()
86+ statement = compile(expr, state)
87+ self.assertEquals(
88+ statement,
89+ 'INSERT INTO "table 1" (column1, column2) '
90+ 'VALUES (elem1, elem2), (elem3, elem4)')
91+ self.assertEquals(state.parameters, [])
92+
93+ def test_insert_select(self):
94+ expr = Insert((Column(column1, table1), Column(column2, table1)),
95+ values=Select(
96+ (Column(column3, table3), Column(column4, table4))))
97+ state = State()
98+ statement = compile(expr, state)
99+ self.assertEquals(
100+ statement,
101+ 'INSERT INTO "table 1" (column1, column2) '
102+ 'SELECT "table 3".column3, "table 4".column4 '
103+ 'FROM "table 3", "table 4"')
104+ self.assertEquals(state.parameters, [])
105+
106 def test_update(self):
107 expr = Update({column1: elem1, Func1(): Func2()}, table=Func1())
108 state = State()

Subscribers

People subscribed via source and target branches

to status/vote changes: