Permalink
Browse files

Allow Database#get to take an array to return multiple values, simila…

…r to map/select_map

This is very similar to the map/select_map change made some time
go.  For array arguments, we need to make sure we have a valid
alias for each array element, then we just use values_at to
retrieve the resulting values.

This could potentially cause backwards compat issues when using
a conditions specifier:

  DB.get([[:a, 1], [:b, 2]])

That type of code now needs to be updated:

  DB.get(Sequel.expr([[:a, 1], [:b, 2]]))

The same was true of the map/select_map change, but I didn't
realize the backwards compat issues back then.  However, as
nobody reported problems, it's unlikely anyone was relying
on the old behavior.
  • Loading branch information...
jeremyevans committed Dec 13, 2012
1 parent 1c82ae2 commit a0d5ffa6245d6f31050de000c7ce2b53ea65f7d7
Showing with 62 additions and 3 deletions.
  1. +3 −1 CHANGELOG
  2. +25 −2 lib/sequel/dataset/actions.rb
  3. +34 −0 spec/core/dataset_spec.rb
View
@@ -1,6 +1,8 @@
=== HEAD
-* Default :prefetch_rows to 100 in the Oracle adapter (andrewhr)
+* Allow Database#get to take an array to return multiple values, similar to map/select_map (jeremyevans)
+
+* Default :prefetch_rows to 100 in the Oracle adapter (andrewhr) (#592)
=== 3.42.0 (2012-12-03)
@@ -225,12 +225,35 @@ def first(*args, &block)
#
# ds.get{sum(id)} # SELECT sum(id) FROM table LIMIT 1
# # => 6
+ #
+ # You can pass an array of arguments to return multiple arguments,
+ # but you must make sure each element in the array has an alias that
+ # Sequel can determine:
+ #
+ # DB[:table].get([:id, :name]) # SELECT id, name FROM table LIMIT 1
+ # # => [3, 'foo']
+ #
+ # DB[:table].get{[sum(id).as(sum), name]} # SELECT sum(id) AS sum, name FROM table LIMIT 1
+ # # => [6, 'foo']
def get(column=(no_arg=true; nil), &block)
+ ds = naked
if block
raise(Error, ARG_BLOCK_ERROR_MSG) unless no_arg
- select(&block).single_value
+ ds = ds.select(&block)
+ column = ds.opts[:select]
+ column = nil if column.is_a?(Array) && column.length < 2
+ else
+ ds = if column.is_a?(Array)
+ ds.select(*column)
+ else
+ ds.select(column)
+ end
+ end
+
+ if column.is_a?(Array)
+ ds.single_record.values_at(*column.map{|c| hash_key_symbol(c)})
else
- select(column).single_value
+ ds.single_value
end
end
View
@@ -2686,6 +2686,40 @@ def d.to_s; "adsf" end
@d.get(false).should == "SELECT 'f' FROM test LIMIT 1"
@d.get(nil).should == "SELECT NULL FROM test LIMIT 1"
end
+
+ specify "should support an array of expressions to get an array of results" do
+ @d._fetch = {:name=>1, :abc=>2}
+ @d.get([:name, :abc]).should == [1, 2]
+ @d.db.sqls.should == ['SELECT name, abc FROM test LIMIT 1']
+ end
+
+ specify "should support an array with a single expression" do
+ @d.get([:name]).should == ['SELECT name FROM test LIMIT 1']
+ end
+
+ specify "should handle an array with aliases" do
+ @d._fetch = {:name=>1, :abc=>2}
+ @d.get([:n___name, Sequel.as(:a, :abc)]).should == [1, 2]
+ @d.db.sqls.should == ['SELECT n AS name, a AS abc FROM test LIMIT 1']
+ end
+
+ specify "should raise an Error if an alias cannot be determined" do
+ @d._fetch = {:name=>1, :abc=>2}
+ proc{@d.get([Sequel.+(:a, 1), :a])}.should raise_error(Sequel::Error)
+ end
+
+ specify "should support an array of expressions in a virtual row" do
+ @d._fetch = {:name=>1, :abc=>2}
+ @d.get{[name, n__abc]}.should == [1, 2]
+ @d.db.sqls.should == ['SELECT name, n.abc FROM test LIMIT 1']
+ end
+
+ specify "should work with static SQL" do
+ @d.with_sql('SELECT foo').get(:name).should == "SELECT foo"
+ @d._fetch = {:name=>1, :abc=>2}
+ @d.with_sql('SELECT foo').get{[name, n__abc]}.should == [1, 2]
+ @d.db.sqls.should == ['SELECT foo'] * 2
+ end
end
describe "Dataset#set_row_proc" do

0 comments on commit a0d5ffa

Please sign in to comment.