From f0bf091b842fb2dea17ddcd6da87ae39e5ffa805 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Mon, 27 Oct 2008 11:14:53 -0700 Subject: [PATCH] Add Array#sql_array to handle ruby arrays of all two pairs as SQL arrays (Fixes #245) Previously, this wasn't possible, as ruby arrays of all two pairs were interpreted as conditions (sort of like an ordered hash). This allows you to do things like: DB[:foo].filter([:a,:b] => [[1,2],[3,4]].sql_array) # => SELECT * FROM foo WHERE ((a, b) IN ((1, 2), (3, 4))) --- CHANGELOG | 2 ++ lib/sequel_core/core_sql.rb | 7 +++++++ lib/sequel_core/dataset/sql.rb | 7 ++++++- lib/sequel_core/sql.rb | 16 ++++++++++++++++ spec/sequel_core/core_sql_spec.rb | 11 +++++++++++ 5 files changed, 42 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index ceafa362ce..f2c9695da3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ === HEAD +* Add Array#sql_array to handle ruby arrays of all two pairs as SQL arrays (jeremyevans) (#245) + * Add ComplexExpression#== and #eql?, for checking equality (rubymage) (#244) * Allow full text search on PostgreSQL to include rows where a search column is NULL (jeremyevans) diff --git a/lib/sequel_core/core_sql.rb b/lib/sequel_core/core_sql.rb index aae237e953..0252235591 100644 --- a/lib/sequel_core/core_sql.rb +++ b/lib/sequel_core/core_sql.rb @@ -11,6 +11,13 @@ def case(default, expression = nil) ::Sequel::SQL::CaseExpression.new(self, default, expression) end + # Return a Sequel::SQL::Array created from this array. Used if this array contains + # all two pairs and you want it treated as an SQL array instead of a ordered hash-like + # conditions. + def sql_array + ::Sequel::SQL::SQLArray.new(self) + end + # Return a Sequel::SQL::BooleanExpression created from this array, matching all of the # conditions. def sql_expr diff --git a/lib/sequel_core/dataset/sql.rb b/lib/sequel_core/dataset/sql.rb index 7e335d50b5..6478611fae 100644 --- a/lib/sequel_core/dataset/sql.rb +++ b/lib/sequel_core/dataset/sql.rb @@ -29,6 +29,11 @@ def aliased_expression_sql(ae) as_sql(literal(ae.expression), ae.aliaz) end + # SQL fragment for the SQL array. + def array_sql(a) + a.empty? ? '(NULL)' : "(#{expression_list(a)})" + end + # SQL fragment for specifying given CaseExpression. def case_expression_sql(ce) sql = '(CASE ' @@ -470,7 +475,7 @@ def literal(v) when ::Sequel::SQL::Expression v.to_s(self) when Array - v.all_two_pairs? ? literal(v.sql_expr) : (v.empty? ? '(NULL)' : "(#{expression_list(v)})") + v.all_two_pairs? ? literal(v.sql_expr) : array_sql(v) when Hash literal(v.sql_expr) when Time, DateTime diff --git a/lib/sequel_core/sql.rb b/lib/sequel_core/sql.rb index d0504507a3..438874d683 100644 --- a/lib/sequel_core/sql.rb +++ b/lib/sequel_core/sql.rb @@ -407,6 +407,22 @@ def to_s(ds) end end + # Represents an SQL array. Added so it is possible to deal with a + # ruby array of all two pairs as an SQL array instead of an ordered + # hash-like conditions specifier. + class SQLArray < Expression + # Create an object with the given array. + def initialize(array) + @array = array + end + + # Delegate the creation of the resulting SQL to the given dataset, + # since it may be database dependent. + def to_s(ds) + ds.array_sql(@array) + end + end + # Blob is used to represent binary data in the Ruby environment that is # stored as a blob type in the database. In PostgreSQL, the blob type is # called bytea. Sequel represents binary data as a Blob object because diff --git a/spec/sequel_core/core_sql_spec.rb b/spec/sequel_core/core_sql_spec.rb index 4550266b81..ed94c685cc 100644 --- a/spec/sequel_core/core_sql_spec.rb +++ b/spec/sequel_core/core_sql_spec.rb @@ -51,6 +51,17 @@ end end +context "Array#sql_array" do + setup do + @d = Sequel::Dataset.new(nil) + end + + specify "should treat the array as an SQL array instead of conditions" do + @d.literal([[:x, 1], [:y, 2]]).should == '((x = 1) AND (y = 2))' + @d.literal([[:x, 1], [:y, 2]].sql_array).should == '((x, 1), (y, 2))' + end +end + context "Array#to_sql" do specify "should concatenate multiple lines into a single string" do "SELECT * \r\nFROM items\r\n WHERE a = 1".split.to_sql. \