Permalink
Browse files

Have prepared statements work correctly with datasets with static sql…

… and placeholders
  • Loading branch information...
1 parent 2d4084e commit 35bd9acd9087c6b7791e576e20836e941710405b @jeremyevans committed Dec 3, 2008
@@ -277,7 +277,7 @@ def execute_dui(sql, opts={}, &block)
# DB.fetch('SELECT * FROM items WHERE name = ?', my_name).print
def fetch(sql, *args, &block)
ds = dataset
- ds.opts[:sql] = ds.literal(Sequel::SQL::PlaceholderLiteralString.new(sql, args))
+ ds.opts[:sql] = Sequel::SQL::PlaceholderLiteralString.new(sql, args)
ds.each(&block) if block
ds
end
@@ -81,9 +81,7 @@ def count
def delete_sql(opts = nil)
opts = opts ? @opts.merge(opts) : @opts
- if sql = opts[:sql]
- return sql
- end
+ return static_sql(opts[:sql]) if opts[:sql]
if opts[:group]
raise Error::InvalidOperation, "Grouped datasets cannot be deleted from"
@@ -271,9 +269,7 @@ def insert_multiple(array, &block)
# dataset.insert_sql(:a => 1, :b => 2) #=>
# 'INSERT INTO items (a, b) VALUES (1, 2)'
def insert_sql(*values)
- if sql = @opts[:sql]
- return sql
- end
+ return static_sql(@opts[:sql]) if @opts[:sql]
from = source_list(@opts[:from])
case values.size
@@ -641,7 +637,7 @@ def select_more(*columns)
# options.
def select_sql(opts = nil)
opts = opts ? @opts.merge(opts) : @opts
- return opts[:sql] if opts[:sql]
+ return static_sql(opts[:sql]) if opts[:sql]
sql = 'SELECT'
select_clause_order.each{|x| send("select_#{x}_sql", sql, opts)}
sql
@@ -710,9 +706,7 @@ def unordered
def update_sql(values = {}, opts = nil)
opts = opts ? @opts.merge(opts) : @opts
- if sql = opts[:sql]
- return sql
- end
+ return static_sql(opts[:sql]) if opts[:sql]
if opts[:group]
raise Error::InvalidOperation, "A grouped dataset cannot be updated"
@@ -973,6 +967,13 @@ def split_symbol(sym)
end
end
+ # SQL to use if this dataset uses static SQL. Since static SQL
+ # can be a PlaceholderLiteralString in addition to a String,
+ # we literalize nonstrings.
+ def static_sql(sql)
+ sql.is_a?(String) ? sql : literal(sql)
+ end
+
# SQL fragment for a subselect using the given database's SQL.
def subselect_sql(ds)
ds.sql
@@ -28,6 +28,10 @@
@ds.filter("number = ?", @ds.ba(:$n)).call(:select, :n=>10).should == [{:id=>1, :number=>10}]
end
+ specify "should support datasets with static sql and placeholders" do
+ INTEGRATION_DB["SELECT * FROM items WHERE number = ?", @ds.ba(:$n)].call(:select, :n=>10).should == [{:id=>1, :number=>10}]
+ end
+
specify "should support subselects" do
@ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>@ds.ba(:$n))).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
end
@@ -36,6 +40,10 @@
@ds.filter(:id=>:$i, :number=>@ds.select(:number).filter("number = ?", @ds.ba(:$n))).call(:select, :n=>10, :i=>1).should == [{:id=>1, :number=>10}]
end
+ specify "should support subselects with static sql and placeholders" do
+ @ds.filter(:id=>:$i, :number=>INTEGRATION_DB["SELECT number FROM items WHERE number = ?", @ds.ba(:$n)]).call(:select, :n=>10, :i=>1).should == [{:id=>1, :number=>10}]
+ end
+
specify "should support subselects of subselects" do
@ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>@ds.select(:number).filter(:number=>@ds.ba(:$n)))).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
end
@@ -3088,10 +3088,14 @@ def fetch_rows(sql, &block)
def @db.execute(sql, opts={})
@sqls << sql
end
- @ds = @db[:items]
- def @ds.fetch_rows(sql, &block)
- execute(sql)
+ def @db.dataset
+ ds = super()
+ def ds.fetch_rows(sql, &block)
+ execute(sql)
+ end
+ ds
end
+ @ds = @db[:items]
end
specify "#call should take a type and bind hash and interpolate it" do
@@ -3138,6 +3142,11 @@ def @ds.fetch_rows(sql, &block)
@db.sqls.should == ['SELECT * FROM items WHERE (num = 1)']
end
+ specify "should handle datasets using static sql and placeholders" do
+ @db["SELECT * FROM items WHERE (num = ?)", :$n].call(:select, :n=>1)
+ @db.sqls.should == ['SELECT * FROM items WHERE (num = 1)']
+ end
+
specify "should handle subselects" do
@ds.filter(:$b).filter(:num=>@ds.select(:num).filter(:num=>:$n)).filter(:$c).call(:select, :n=>1, :b=>0, :c=>2)
@db.sqls.should == ['SELECT * FROM items WHERE ((0 AND (num IN (SELECT num FROM items WHERE (num = 1)))) AND 2)']
@@ -3152,6 +3161,11 @@ def @ds.fetch_rows(sql, &block)
@ds.filter(:$b).filter(:num=>@ds.select(:num).filter("num = ?", :$n)).call(:select, :n=>1, :b=>0)
@db.sqls.should == ['SELECT * FROM items WHERE (0 AND (num IN (SELECT num FROM items WHERE (num = 1))))']
end
+
+ specify "should handle subselects with static sql and placeholders" do
+ @ds.filter(:$b).filter(:num=>@db["SELECT num FROM items WHERE (num = ?)", :$n]).call(:select, :n=>1, :b=>0)
+ @db.sqls.should == ['SELECT * FROM items WHERE (0 AND (num IN (SELECT num FROM items WHERE (num = 1))))']
+ end
end
context Sequel::Dataset::UnnumberedArgumentMapper do

0 comments on commit 35bd9ac

Please sign in to comment.