require 'rubygems' require 'parse_tree' require 'ruby2ruby' require 'sequel' require 'dataset_expressions' class Sequel::Dataset include Sequel::Dataset::Sequelizer def filter(*args, &block) if block filter(block.to_sql(self)) else super(*args) end end end require 'sequel/postgres' DB = Sequel("postgres://postgres:postgres@localhost:5432/reality_development") DS = DB[:items] class Proc def to_sql DS.translate_expr(self) end end context "Proc#to_sql" do specify "should support " do proc {:x > 100}.to_sql.should == 'x > 100' proc {:x < 100}.to_sql.should == 'x < 100' proc {:x >= 100}.to_sql.should == 'x >= 100' proc {:x <= 100}.to_sql.should == 'x <= 100' proc {:x == 100}.to_sql.should == 'x = 100' end specify "should support number literals" do proc {:x > 123.45}.to_sql.should == 'x > 123.45' proc {:x > -30_000}.to_sql.should == 'x > -30000' end specify "should support string literals" do proc {:x == 'abc'}.to_sql.should == "x = 'abc'" proc {:y == "ab'cd"}.to_sql.should == "y = 'ab''cd'" end specify "should support boolean literals" do proc {:x == false}.to_sql.should == "x = 'f'" proc {:x == true}.to_sql.should == "x = 't'" end specify "should support nil literal and nil?" do proc {:x == nil}.to_sql.should == "x IS NULL" proc {:x.nil?}.to_sql.should == "x IS NULL" end specify "should support local vars or method references" do proc {proc {:x == a}.to_sql}.should raise_error(NameError) b = 123 proc {:x == b}.to_sql.should == "x = 123" def xyz; 321; end proc {:x == xyz}.to_sql.should == "x = 321" proc {:x == xyz.to_s}.to_sql.should == "x = '321'" end specify "should support constants" do ZZZ = 444 proc {:x == ZZZ}.to_sql.should == "x = 444" CCC = Module.new CCC::DDD = 'hi' proc {:x == CCC::DDD}.to_sql.should == "x = 'hi'" end specify "should support instance attributes" do @abc = 123 proc {:x == @abc}.to_sql.should == "x = 123" end specify "should support class attributes" do @@abc = 321 proc {:x == @@abc}.to_sql.should == "x = 321" end specify "should support like? pattern" do proc {:x.like? '%abc'}.to_sql.should == "x LIKE '%abc'" end specify "should support =~ operator" do # stock SQL version does not know about regexps proc {:x =~ '123'}.to_sql.should == "x = '123'" end specify "should support != operator" do proc {:x != 100}.to_sql.should == "NOT (x = 100)" end specify "should support !~ operator" do proc {:x !~ '123'}.to_sql.should == "NOT (x = '123')" end specify "should support ! operator" do proc {!:x}.to_sql.should == "x = 'f'" proc {!(:x > 100)}.to_sql.should == "NOT (x > 100)" end specify "should support && operator" do proc {1 && 2}.to_sql.should == "(1) AND (2)" proc {:x > 100 && :y < 100}.to_sql.should == "(x > 100) AND (y < 100)" proc {:x && :y && :z}.to_sql.should == "(x) AND ((y) AND (z))" end specify "should concatenate separate statements using AND" do proc {:x == 20; :y == 30}.to_sql.should == "(x = 20) AND (y = 30)" proc do :x != 1 :y != 2 :z != 3 end.to_sql.should == "(NOT (x = 1)) AND (NOT (y = 2)) AND (NOT (z = 3))" end specify "should support || operator" do proc {1 || 2}.to_sql.should == "(1) OR (2)" proc {:x > 100 || :y < 100}.to_sql.should == "(x > 100) OR (y < 100)" proc {:x || :y || :z}.to_sql.should == "(x) OR ((y) OR (z))" end specify "should support operator combinations" do proc {(:x > 1 || :y > 2) && (:z > 3)}.to_sql.should == "((x > 1) OR (y > 2)) AND (z > 3)" proc {(1 && 2) || (3 || 4)}.to_sql.should == "((1) AND (2)) OR ((3) OR (4))" proc {(:x != 2) || (:y == 3) || !(:z == 4)}.to_sql.should == "(NOT (x = 2)) OR ((y = 3) OR (NOT (z = 4)))" end specify "should support late bound column references" do def abc; :tttt; end proc {abc > 2}.to_sql.should == "tttt > 2" end specify "should support qualified column references" do proc {:x__y > 3}.to_sql.should == "x.y > 3" end specify "should support functions on columns" do proc {:x.MAX > 100}.to_sql.should == "max(x) > 100" proc {:x.COUNT > 100}.to_sql.should == "count(x) > 100" end specify "should do stuff like..." do proc {:price < 100 || :category != 'ruby'}.to_sql.should == \ "(price < 100) OR (NOT (category = 'ruby'))" t = Time.now proc {:node_id == 1 && :stamp < t}.to_sql.should == \ "(node_id = 1) AND (stamp < #{DS.literal(t)})" proc {1 < :x}.to_sql.should == "1 < x" end specify "should complain if someone is crazy" do proc {proc {def x; 1; end}.to_sql}.should raise_error(SequelError) a = 1 proc {proc {a = 1}.to_sql}.should raise_error(SequelError) end end