/SQLDSL

Fork of Jay Fields' SQLDSL

Primary LanguageRuby

= SQL DSL

SQL DSL is a library for creating SQL statements using ruby code.

by Jay[http://blog.jayfields.com] Fields[http://blog.jayfields.com]

== Download and Installation

You can download SQL DSL from here[http://rubyforge.org/projects/sqldsl] or install it with the following command.

 $ gem install sqldsl

== License
 	
You may use, copy and redistribute this library under the same terms as Ruby itself (see http://www.ruby-lang.org/en/LICENSE.txt).

== Examples

See the tests for more examples

=== Test Helper

    require 'test/unit'
    require File.dirname(__FILE__) + '/../lib/sqldsl'
    unless File.directory? File.dirname(__FILE__) + '/../vendor/mocha-0.4.0/'
      raise "mocha 4.0 is required to run the test suite. create the 'vendor' directory as a sibling of test and 'gem unpack mocha' in 'vendor'"
    end
    $:.unshift File.dirname(__FILE__) + '/../vendor/mocha-0.4.0/lib/'
    require File.dirname(__FILE__) + '/../vendor/mocha-0.4.0/lib/mocha'


=== Insert Example

    require File.dirname(__FILE__) + '/test_helper'
    
    class InsertAcceptanceTest < Test::Unit::TestCase
      def test_insert_select
        statement = Insert.into[:table1][:column1, :column2, :column3].values do
          Select[1]
        end
        assert_equal 'insert into table1 (column1, column2, column3) select 1', statement.to_sql
      end
      
      def test_insert_with_values
        statement = Insert.into[:table1][:column1, :column2, :column3].values(10, 'book', :column4)
        assert_equal "insert into table1 (column1, column2, column3) values (10, 'book', column4)", statement.to_sql
      end
    end

=== Update Example

    require File.dirname(__FILE__) + '/test_helper'
    
    class UpdateAcceptanceTest < Test::Unit::TestCase
      def test_insert_select
        statement = Update[:table1].set[:column1=>10, :column2=>'book'].where do
          not_exists(Select[1].from[:table2])
        end
        assert_equal "update table1 set column1=10, column2='book' where not exists (select 1 from table2)", statement.to_sql
      end
    end

=== Delete Example

    require File.dirname(__FILE__) + '/test_helper'
    
    class DeleteAcceptanceTest < Test::Unit::TestCase
      def test_insert_select
        statement = Delete.from[:table1].where do
          exists(Select[1].from[:table2])
        end
        assert_equal "delete from table1 where exists (select 1 from table2)", statement.to_sql
      end
    end

=== Select Example

    require File.dirname(__FILE__) + '/test_helper'
    
    class SelectAcceptanceTest < Test::Unit::TestCase
      def test_select_with_where_methods
        statement = Select[:column1, 'book', 10].from[:table1, :table2].where do
          equal :column1, 99
          not_equal :column1, 100
          less_than :column2, 'foo'
          less_than_or_equal :column3, :column4
          greater_than :column1, 0
          greater_than_or_equal :column2, 'bar'
          like :column1, 'any'
          is_not_null :column1
          is_in :column1, [1,2]
          is_not_in :column2, [3, 4]
          exists 0
          not_exists 0
        end
        expected = "select column1, 'book', 10 from table1, table2
                      where column1 = 99 and column1 <> 100 and column2 < 'foo' 
                      and column3 <= column4 and column1 > 0 and column2 >= 'bar' and column1 like 'any' 
                      and column1 is not null and column1 in (1, 2) and column2 not in (3, 4) 
                      and exists (0) and not exists (0)"
        assert_equal expected.delete("\n").squeeze(" "), statement.to_sql
      end
      
      def test_select_with_receive_any_objects_and_operators
        statement = Select[:column1, 'book', 10].from[:table1, :table2].where do
          column1 == 99
          column1 <=> 100
          column2 < 'foo'
          column3 <= column4
          column1 > 0
          column2 >= 'bar'
          column1 =~ 'any'
          column1 ^ nil
          column1 >> [1,2]
          column2 << [3, 4]
        end
        expected = "select column1, 'book', 10 from table1, table2
                      where column1 = 99 and column1 <> 100 and column2 < 'foo' 
                      and column3 <= column4 and column1 > 0 and column2 >= 'bar' and column1 like 'any'
                      and column1 is not null and column1 in (1, 2) and column2 not in (3, 4)"
        assert_equal expected.delete("\n").squeeze(" "), statement.to_sql
      end
      
      def test_select_with_receive_any_objects_and_method_calls
        statement = Select[:column1, 'book', 10].from[:table1, :table2].where do
          column1.equal 99
          column1.not_equal 100
          column2.less_than 'foo'
          column3.less_than_or_equal column4
          column1.greater_than 0
          column2.greater_than_or_equal 'bar'
          column1.like 'any'
          column1.is_not_null
          column1.is_in [1,2]
          column2.is_not_in [3, 4]
        end
        expected = "select column1, 'book', 10 from table1, table2
                      where column1 = 99 and column1 <> 100 and column2 < 'foo' 
                      and column3 <= column4 and column1 > 0 and column2 >= 'bar' and column1 like 'any'
                      and column1 is not null and column1 in (1, 2) and column2 not in (3, 4)"
        assert_equal expected.delete("\n").squeeze(" "), statement.to_sql
      end
      
      def test_add_clause
        statement = Select[:column1].from[:table1].where do
          like :column1, "any"
          add_clause "(c2 = 'foo')"
        end
        assert_equal "select column1 from table1 where column1 like 'any' and (c2 = 'foo')", statement.to_sql
      end
      
      
      def test_select_with_receive_any_objects_and_method_calls
        statement = Select[:column1, 'book', 10].from[:table1, :table2].where do
          column1.equal 0
        end.or do
          column1 > 100
        end.and do
          column2 == 15
        end
        expected = "select column1, 'book', 10 from table1, table2 where column1 = 0 or (column1 > 100) and (column2 = 15)"
        assert_equal expected, statement.to_sql
      end
      
      def test_select_with_inner_join
        expected = "select * from t1 a inner join t2 b, t3 c on a.id = b.id and b.id2 = c.id where c.attr1 = 'foo' and b.attr1 = 'foo2'"
        statement = Select.all.from[:t1.as(:a)].inner_join[:t2.as(:b), :t3.as(:c)].on do
          a.id == b.id
          b.id2 == c.id
        end.where do
          c.attr1 == 'foo'
          b.attr1 == 'foo2'
        end
        assert_equal expected, statement.to_sql
      end
      
      def test_columns_in_inner_where_are_validated_against_outer_tables
        statement = Select.all.from[:table].where do
          exists(Select.all.from[:inner_table.as(:aliased)].where do
            table.column1 == aliased.column1
          end)
        end
        assert_equal 'select * from table where exists (select * from inner_table aliased where table.column1 = aliased.column1)', statement.to_sql
      end
    
      def test_columns_in_where_are_validated_against_tables
        assert_raises ArgumentError do
          Select.all.from[:table].where do
            not_table.cat = 12
          end
        end
      end
    
      def test_columns_in_inner_where_are_validated_against_outer_and_inner_tables
        assert_raises ArgumentError do
          Select.all.from[:table].where do
            exists(Select.all.from[:inner_table].where do
              table.column1 = not_table.cat
            end)
          end
        end
      end
    end

=== Contributors
Matt[http://www.theagiledeveloper.com] Deiters[http://www.theagiledeveloper.com]

Sergio[http://spejman-on-rails.blogspot.com/] Espeja[http://spejman-on-rails.blogspot.com/]

Pat Farley (who contributed by being sqldsl's biggest skeptic)

Clint Bishop

Shane Harvie