Skip to content

Commit

Permalink
Allow Database#get to take an array to return multiple values, simila…
Browse files Browse the repository at this point in the history
…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 a0d5ffa
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 3 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG
Original file line number Original file line Diff line number Diff line change
@@ -1,6 +1,8 @@
=== HEAD === 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) === 3.42.0 (2012-12-03)


Expand Down
27 changes: 25 additions & 2 deletions lib/sequel/dataset/actions.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -225,12 +225,35 @@ def first(*args, &block)
# #
# ds.get{sum(id)} # SELECT sum(id) FROM table LIMIT 1 # ds.get{sum(id)} # SELECT sum(id) FROM table LIMIT 1
# # => 6 # # => 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) def get(column=(no_arg=true; nil), &block)
ds = naked
if block if block
raise(Error, ARG_BLOCK_ERROR_MSG) unless no_arg 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 else
select(column).single_value ds.single_value
end end
end end


Expand Down
34 changes: 34 additions & 0 deletions spec/core/dataset_spec.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -2686,6 +2686,40 @@ def d.to_s; "adsf" end
@d.get(false).should == "SELECT 'f' FROM test LIMIT 1" @d.get(false).should == "SELECT 'f' FROM test LIMIT 1"
@d.get(nil).should == "SELECT NULL FROM test LIMIT 1" @d.get(nil).should == "SELECT NULL FROM test LIMIT 1"
end 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 end


describe "Dataset#set_row_proc" do describe "Dataset#set_row_proc" do
Expand Down

0 comments on commit a0d5ffa

Please sign in to comment.