sql-maker 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/CHANGELOG.md +3 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +23 -0
  7. data/Rakefile +14 -0
  8. data/lib/sql-maker.rb +5 -0
  9. data/lib/sql/maker.rb +676 -0
  10. data/lib/sql/maker/condition.rb +378 -0
  11. data/lib/sql/maker/error.rb +3 -0
  12. data/lib/sql/maker/helper.rb +22 -0
  13. data/lib/sql/maker/quoting.rb +138 -0
  14. data/lib/sql/maker/select.rb +544 -0
  15. data/lib/sql/maker/select/oracle.rb +30 -0
  16. data/lib/sql/maker/select_set.rb +194 -0
  17. data/lib/sql/maker/util.rb +54 -0
  18. data/lib/sql/query_maker.rb +429 -0
  19. data/scripts/perl2ruby.rb +34 -0
  20. data/spec/maker/bind_param_spec.rb +62 -0
  21. data/spec/maker/condition/add_raw_spec.rb +29 -0
  22. data/spec/maker/condition/compose_empty_spec.rb +72 -0
  23. data/spec/maker/condition/empty_values_spec.rb +25 -0
  24. data/spec/maker/condition/make_term_spec.rb +38 -0
  25. data/spec/maker/condition/where_spec.rb +35 -0
  26. data/spec/maker/delete_spec.rb +116 -0
  27. data/spec/maker/insert_empty_spec.rb +23 -0
  28. data/spec/maker/insert_spec.rb +61 -0
  29. data/spec/maker/new_line_spec.rb +9 -0
  30. data/spec/maker/select/oracle/oracle_spec.rb +16 -0
  31. data/spec/maker/select/pod_select_spec.rb +34 -0
  32. data/spec/maker/select/statement_spec.rb +805 -0
  33. data/spec/maker/select_set_spec.rb +294 -0
  34. data/spec/maker/select_spec.rb +470 -0
  35. data/spec/maker/simple_spec.rb +54 -0
  36. data/spec/maker/strict_spec.rb +45 -0
  37. data/spec/maker/subquery_spec.rb +77 -0
  38. data/spec/maker/update_spec.rb +138 -0
  39. data/spec/maker/util_spec.rb +6 -0
  40. data/spec/maker/where_spec.rb +28 -0
  41. data/spec/query_maker/and_using_hash_spec.rb +13 -0
  42. data/spec/query_maker/cheatsheet_spec.rb +32 -0
  43. data/spec/query_maker/column_bind_spec.rb +55 -0
  44. data/spec/query_maker/refs_in_bind_spec.rb +19 -0
  45. data/spec/spec_helper.rb +15 -0
  46. data/sql-maker.gemspec +25 -0
  47. metadata +185 -0
@@ -0,0 +1,34 @@
1
+ filename = ARGV.first
2
+ body = File.read(filename)
3
+
4
+ body.gsub!(/ eq /, ' == ')
5
+ body.gsub!(/\$([_A-Za-z]\w*)->\{([_A-Za-z]\w*)\}/, '\1.\2') # $self->{var} => self.var
6
+ body.gsub!(/\$([_A-Za-z]\w*)->([_A-Za-z]\w*)/, '\1.\2') # $self->var => self.var
7
+ body.gsub!(/\$([_A-Za-z]\w*)/, '\1') # $var => var
8
+ body.gsub!(/\@([_A-Za-z]\w*)/, '\1') # @var => var
9
+ body.gsub!(/ \. /, ' + ') # str . str => str + str
10
+ body.gsub!(/join\('([^']+)', ([^)]+)\)/, '\2.join(\'\1\')') # join(', ', foo) => foo.join(', ')
11
+ body.gsub!(/subtest '([^']+)' => sub {/, 'it \'\1\' do') # subtest '[]' => sub { => it '[]' do
12
+ body.gsub!(/sub ([_A-Za-z]\w*) {/, 'def \1') # sub sql_op { => def sql_op
13
+ body.gsub!(/([_A-Za-z]\w*) => /, ':\1 => ') # x => [] to :x => []
14
+ body.gsub!(/ +};$/, 'end') # }; => end
15
+ body.gsub!(/}$/, 'end') # } => end
16
+ body.gsub!(/my /, '') # remove my
17
+ body.gsub!(/->/, '.') # foo->var => foo.var
18
+ body.gsub!(/;$/, '')
19
+ body.gsub!(/\\'$/, "'") # \' => '
20
+ body.gsub!(/\\\[$/, "[") # \[ => [
21
+ body.gsub!(/qq{/, '%Q{')
22
+ #body.gsub!(/\[ qw\/([^/]+)\/ \]/, '%w/\1/')
23
+ body.gsub!(/ordered_hashref\(([^)]+)\)/, '{\1}')
24
+ body.gsub!(/use strict/, '')
25
+ body.gsub!(/\(sql, bind\)/, 'sql, bind')
26
+ body.gsub!(/use warnings/, '')
27
+ body.gsub!(/use Test::More/, "require_relative '../spec_helper'")
28
+ body.gsub!(/use SQL::Maker/, "require 'sql/maker'")
29
+ body.gsub!(/use SQL::QueryMaker/, "require 'sql/query_maker'")
30
+ body.gsub!(/done_testing/, '')
31
+ body.gsub!(/is ([^,]+), (.+)$/, 'expect(\1).to be == \2')
32
+ body.gsub!(/is\(([^,]+), (.+)\)$/, 'expect(\1).to be == \2')
33
+ body.gsub!(/is ([^(]+\([^)]+\)), (.+)$/, 'expect(\1).to be == \2') # is foo.join(', '), '1'
34
+ puts body.strip
@@ -0,0 +1,62 @@
1
+ require_relative '../spec_helper'
2
+ require 'sql/maker'
3
+
4
+ describe 'SQL::Maker' do
5
+ context 'auto bind' do
6
+ let(:builder) { SQL::Maker.new(:driver => 'mysql', :auto_bind => true) }
7
+
8
+ it 'delete' do
9
+ sql = builder.delete('foo', {:bar => "t' OR 't' = 't"})
10
+ expect(sql).to be == %q{DELETE FROM `foo` WHERE (`bar` = 't'' OR ''t'' = ''t')}
11
+ end
12
+
13
+ it 'insert' do
14
+ sql = builder.insert('foo', {:bar => "t' OR 't' = 't"})
15
+ expect(sql).to be == %Q{INSERT INTO `foo`\n(`bar`)\nVALUES ('t'' OR ''t'' = ''t')}
16
+ end
17
+
18
+ it 'select' do
19
+ sql = builder.select('foo', ['foo'], { :bar => "t' OR 't' = 't" })
20
+ expect(sql).to be == %Q{SELECT `foo`\nFROM `foo`\nWHERE (`bar` = 't'' OR ''t'' = ''t')}
21
+ end
22
+
23
+ it 'update' do
24
+ sql = builder.update('foo', {:bar => "t' OR 't' = 't"})
25
+ expect(sql).to be == %Q{UPDATE `foo` SET `bar` = 't'' OR ''t'' = ''t'}
26
+ end
27
+ end
28
+
29
+ context '#bind_param' do
30
+ let(:builder) { SQL::Maker.new(:driver => 'mysql', :auto_bind => false) }
31
+
32
+ it 'delete' do
33
+ sql, bind = builder.delete('foo', {:bar => "t' OR 't' = 't"})
34
+ sql = builder.bind_param(sql, bind)
35
+ expect(sql).to be == %q{DELETE FROM `foo` WHERE (`bar` = 't'' OR ''t'' = ''t')}
36
+ end
37
+ end
38
+
39
+ context 'hash arguments' do
40
+ let(:builder) { SQL::Maker.new(:driver => 'mysql', :auto_bind => true) }
41
+
42
+ it 'delete' do
43
+ sql = builder.delete(table: 'foo', where: {:bar => "t' OR 't' = 't"})
44
+ expect(sql).to be == %q{DELETE FROM `foo` WHERE (`bar` = 't'' OR ''t'' = ''t')}
45
+ end
46
+
47
+ it 'insert' do
48
+ sql = builder.insert(table: 'foo', values: {:bar => "t' OR 't' = 't"})
49
+ expect(sql).to be == %Q{INSERT INTO `foo`\n(`bar`)\nVALUES ('t'' OR ''t'' = ''t')}
50
+ end
51
+
52
+ it 'select' do
53
+ sql = builder.select(table: 'foo', fields: ['foo'], where: { :bar => "t' OR 't' = 't" })
54
+ expect(sql).to be == %Q{SELECT `foo`\nFROM `foo`\nWHERE (`bar` = 't'' OR ''t'' = ''t')}
55
+ end
56
+
57
+ it 'update' do
58
+ sql = builder.update(table: 'foo', set: {:bar => "t' OR 't' = 't"})
59
+ expect(sql).to be == %Q{UPDATE `foo` SET `bar` = 't'' OR ''t'' = ''t'}
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,29 @@
1
+ require_relative '../../spec_helper'
2
+ require 'sql/maker/condition'
3
+
4
+ describe 'SQL::Maker::Condition' do
5
+ it 'with values' do
6
+ w1 = SQL::Maker::Condition.new()
7
+ w1.add_raw( 'a = ?' => 1 )
8
+ w1.add_raw( 'b = ?' => 2 )
9
+
10
+ expect(w1.as_sql).to be == '(a = ?) AND (b = ?)'
11
+ expect(w1.bind.join(',')).to be == '1,2'
12
+
13
+ w2 = SQL::Maker::Condition.new()
14
+ w2.add_raw( 'b = IF(c > 0, ?, ?)' => [0, 1] )
15
+ w2.add_raw( 'd = ?' => [2])
16
+
17
+ expect(w2.as_sql).to be == '(b = IF(c > 0, ?, ?)) AND (d = ?)'
18
+ expect(w2.bind.join(',')).to be == '0,1,2'
19
+ end
20
+
21
+ it 'without values' do
22
+ w = SQL::Maker::Condition.new()
23
+ w.add_raw( 'a IS NOT NULL' )
24
+ w.add_raw( 'b IS NULL' )
25
+
26
+ expect(w.as_sql).to be == '(a IS NOT NULL) AND (b IS NULL)'
27
+ expect(w.bind.join(',')).to be == ''
28
+ end
29
+ end
@@ -0,0 +1,72 @@
1
+ require_relative '../../spec_helper'
2
+ require 'sql/maker/condition'
3
+
4
+ describe 'SQL::Maker::Condition' do
5
+ let(:w1) do
6
+ w1 = SQL::Maker::Condition.new()
7
+ w1.add(:x => 1)
8
+ w1.add(:y => 2)
9
+ end
10
+ let(:w2) { SQL::Maker::Condition.new() }
11
+ let(:w3) { SQL::Maker::Condition.new() }
12
+
13
+ it 'and_before' do
14
+ w = (w1 & w2)
15
+ expect(w.as_sql).to be == '((x = ?) AND (y = ?))'
16
+ expect(w.bind.join(', ')).to be == '1, 2'
17
+
18
+ w.add(:z => 99)
19
+ expect(w.as_sql).to be == '((x = ?) AND (y = ?)) AND (z = ?)'
20
+ expect(w.bind.join(', ')).to be == '1, 2, 99'
21
+ end
22
+
23
+ it 'and_after' do
24
+ w = (w2 & w1)
25
+ expect(w.as_sql).to be == '((x = ?) AND (y = ?))'
26
+ expect(w.bind.join(', ')).to be == '1, 2'
27
+
28
+ w.add(:z => 99)
29
+ expect(w.as_sql).to be == '((x = ?) AND (y = ?)) AND (z = ?)'
30
+ expect(w.bind.join(', ')).to be == '1, 2, 99'
31
+ end
32
+
33
+ it 'or_before' do
34
+ w = (w1 | w2)
35
+ expect(w.as_sql).to be == '((x = ?) AND (y = ?))'
36
+ expect(w.bind.join(', ')).to be == '1, 2'
37
+
38
+ w.add(:z => 99)
39
+ expect(w.as_sql).to be == '((x = ?) AND (y = ?)) AND (z = ?)'
40
+ expect(w.bind.join(', ')).to be == '1, 2, 99'
41
+ end
42
+
43
+ it 'or_after' do
44
+ w = (w2 | w1)
45
+ expect(w.as_sql).to be == '((x = ?) AND (y = ?))'
46
+ expect(w.bind.join(', ')).to be == '1, 2'
47
+
48
+ w.add(:z => 99)
49
+ expect(w.as_sql).to be == '((x = ?) AND (y = ?)) AND (z = ?)'
50
+ expect(w.bind.join(', ')).to be == '1, 2, 99'
51
+ end
52
+
53
+ it 'and_both' do
54
+ w = (w2 & w3)
55
+ expect(w.as_sql).to be == ''
56
+ expect(w.bind.join(', ')).to be == ''
57
+
58
+ w.add(:z => 99)
59
+ expect(w.as_sql).to be == '(z = ?)'
60
+ expect(w.bind.join(', ')).to be == '99'
61
+ end
62
+
63
+ it 'or_both' do
64
+ w = (w2 | w3)
65
+ expect(w.as_sql).to be == ''
66
+ expect(w.bind.join(', ')).to be == ''
67
+
68
+ w.add(:z => 99)
69
+ expect(w.as_sql).to be == '(z = ?)'
70
+ expect(w.bind.join(', ')).to be == '99'
71
+ end
72
+ end
@@ -0,0 +1,25 @@
1
+ require_relative '../../spec_helper'
2
+ require 'sql/maker/condition'
3
+
4
+ describe SQL::Maker::Condition do
5
+ it '[]' do
6
+ w = SQL::Maker::Condition.new()
7
+ w.add(:x => [])
8
+ expect(w.as_sql).to be == '(0=1)'
9
+ expect(w.bind.join(', ')).to be == ''
10
+ end
11
+
12
+ it 'in' do
13
+ w = SQL::Maker::Condition.new()
14
+ w.add(:x => { 'IN' => [] })
15
+ expect(w.as_sql).to be == '(0=1)'
16
+ expect(w.bind.join(', ')).to be == ''
17
+ end
18
+
19
+ it 'not in' do
20
+ w2 = SQL::Maker::Condition.new()
21
+ w2.add(:x => { 'NOT IN' => [] })
22
+ expect(w2.as_sql).to be == '(1=1)'
23
+ expect(w2.bind.join(', ')).to be == ''
24
+ end
25
+ end
@@ -0,0 +1,38 @@
1
+ require_relative '../../spec_helper'
2
+ require 'sql/maker/condition'
3
+ require 'sql/maker/helper'
4
+
5
+ include SQL::Maker::Helper
6
+
7
+ def test(input, expected_term, expected_bind)
8
+ describe 'SQL::Maker::Condition' do
9
+ it input do
10
+ source = eval(input, binding)
11
+ cond = SQL::Maker::Condition.new(
12
+ :quote_char => '`',
13
+ :name_sep => '.',
14
+ )
15
+ cond.add(source)
16
+ sql = cond.as_sql
17
+ sql = sql.gsub(/^\(/, '').gsub(/\)$/, '')
18
+ expect(sql).to be == expected_term
19
+ expect(cond.bind).to be == expected_bind
20
+ end
21
+ end
22
+ end
23
+
24
+ begin
25
+ file = File.open("#{ROOT}/lib/sql/maker/condition.rb")
26
+ while line = file.gets
27
+ break if line =~ /=head1 CONDITION CHEAT SHEET/
28
+ end
29
+ while line = file.gets
30
+ next if line =~ /^#/
31
+ src = $1 if line =~ /IN:\s*(.+)\s*$/
32
+ query = eval($1, binding) if line =~ /OUT QUERY:(.+)/
33
+ if line =~ /OUT BIND:(.+)/
34
+ bind = eval($1, binding)
35
+ test(src, query, bind)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,35 @@
1
+ require_relative '../../spec_helper'
2
+ require 'sql/maker/condition'
3
+
4
+ describe SQL::Maker::Condition do
5
+ let(:w1) do
6
+ w1 = SQL::Maker::Condition.new()
7
+ w1.add(:x => 1)
8
+ w1.add(:y => 2)
9
+ end
10
+ let(:w2) do
11
+ w2 = SQL::Maker::Condition.new()
12
+ w2.add(:a => 3)
13
+ w2.add(:b => 4)
14
+ end
15
+
16
+ it 'and' do
17
+ w = (w1 & w2)
18
+ expect(w.as_sql).to be == '((x = ?) AND (y = ?)) AND ((a = ?) AND (b = ?))'
19
+ expect(w.bind.join(', ')).to be == '1, 2, 3, 4'
20
+
21
+ w.add(:z => 99)
22
+ expect(w.as_sql).to be == '((x = ?) AND (y = ?)) AND ((a = ?) AND (b = ?)) AND (z = ?)'
23
+ expect(w.bind.join(', ')).to be == '1, 2, 3, 4, 99'
24
+ end
25
+
26
+ it 'or' do
27
+ w = (w1 | w2)
28
+ expect(w.as_sql).to be == '(((x = ?) AND (y = ?)) OR ((a = ?) AND (b = ?)))'
29
+ expect(w.bind.join(', ')).to be == '1, 2, 3, 4'
30
+
31
+ w.add(:z => 99)
32
+ expect(w.as_sql).to be == '(((x = ?) AND (y = ?)) OR ((a = ?) AND (b = ?))) AND (z = ?)'
33
+ expect(w.bind.join(', ')).to be == '1, 2, 3, 4, 99'
34
+ end
35
+ end
@@ -0,0 +1,116 @@
1
+ require_relative '../spec_helper'
2
+ require 'sql/maker'
3
+
4
+ describe 'SQL::Maker' do
5
+ context 'driver sqlite' do
6
+ it 'simple where_as_hashref' do
7
+ builder = SQL::Maker.new(:driver => 'sqlite')
8
+ sql, bind = builder.delete('foo', {:bar => 'baz', :john => 'man'})
9
+ expect(sql).to be == %q{DELETE FROM "foo" WHERE ("bar" = ?) AND ("john" = ?)}
10
+ expect(bind.join(',')).to be == 'baz,man'
11
+ end
12
+
13
+ # it 'simple where_as_arrayref' do
14
+
15
+ it 'simple where_as_condition' do
16
+ builder = SQL::Maker.new(:driver => 'sqlite')
17
+ cond = builder.new_condition
18
+ cond.add(:bar => 'baz')
19
+ cond.add(:john => 'man')
20
+ sql, bind = builder.delete('foo', cond)
21
+ expect(sql).to be == %q{DELETE FROM "foo" WHERE ("bar" = ?) AND ("john" = ?)}
22
+ expect(bind.join(',')).to be == 'baz,man'
23
+ end
24
+
25
+ it 'delete all' do
26
+ builder = SQL::Maker.new(:driver => 'sqlite')
27
+ sql, bind = builder.delete('foo')
28
+ expect(sql).to be == %q{DELETE FROM "foo"}
29
+ expect(bind.join(',')).to be == ''
30
+ end
31
+ end
32
+
33
+ context 'driver mysql' do
34
+ it 'simple where_as_hashref' do
35
+ builder = SQL::Maker.new(:driver => 'mysql')
36
+ sql, bind = builder.delete('foo', {:bar => 'baz', :john => 'man'})
37
+ expect(sql).to be == %q{DELETE FROM `foo` WHERE (`bar` = ?) AND (`john` = ?)}
38
+ expect(bind.join(',')).to be == 'baz,man'
39
+ end
40
+
41
+ # it 'simple where_as_arrayref' do
42
+
43
+ it 'simple where_as_condition' do
44
+ builder = SQL::Maker.new(:driver => 'mysql')
45
+ cond = builder.new_condition
46
+ cond.add(:bar => 'baz')
47
+ cond.add(:john => 'man')
48
+ sql, bind = builder.delete('foo', cond)
49
+ expect(sql).to be == %q{DELETE FROM `foo` WHERE (`bar` = ?) AND (`john` = ?)}
50
+ expect(bind.join(',')).to be == 'baz,man'
51
+ end
52
+
53
+ it 'delete all' do
54
+ builder = SQL::Maker.new(:driver => 'mysql')
55
+ sql, bind = builder.delete('foo')
56
+ expect(sql).to be == %q{DELETE FROM `foo`}
57
+ expect(bind.join(',')).to be == ''
58
+ end
59
+
60
+ it 'delete using where_as_hashref' do
61
+ builder = SQL::Maker.new(:driver => 'mysql')
62
+ sql, bind = builder.delete('foo', {:bar => 'baz', :john => 'man'}, {:using => 'bar'})
63
+ expect(sql).to be == %q{DELETE FROM `foo` USING `bar` WHERE (`bar` = ?) AND (`john` = ?)}
64
+ expect(bind.join(',')).to be == 'baz,man'
65
+ end
66
+
67
+ it 'delete using array where_as_hashref' do
68
+ builder = SQL::Maker.new(:driver => 'mysql')
69
+ sql, bind = builder.delete('foo', {:bar => 'baz', :john => 'man'}, {:using => ['bar', 'qux']})
70
+ expect(sql).to be == %q{DELETE FROM `foo` USING `bar`, `qux` WHERE (`bar` = ?) AND (`john` = ?)}
71
+ expect(bind.join(',')).to be == 'baz,man'
72
+ end
73
+ end
74
+
75
+ context 'driver mysql, quote_char: "", new_line: " "' do
76
+ it 'simple where_as_hashref' do
77
+ builder = SQL::Maker.new(:driver => 'mysql', :quote_char => '', :new_line => ' ')
78
+ sql, bind = builder.delete('foo', {:bar => 'baz', :john => 'man'})
79
+ expect(sql).to be == %q{DELETE FROM foo WHERE (bar = ?) AND (john = ?)}
80
+ expect(bind.join(',')).to be == 'baz,man'
81
+ end
82
+
83
+ # it 'simple where_as_arrayref' do
84
+
85
+ it 'simple where_as_condition' do
86
+ builder = SQL::Maker.new(:driver => 'mysql', :quote_char => '', :new_line => ' ')
87
+ cond = builder.new_condition
88
+ cond.add(:bar => 'baz')
89
+ cond.add(:john => 'man')
90
+ sql, bind = builder.delete('foo', cond)
91
+ expect(sql).to be == %q{DELETE FROM foo WHERE (bar = ?) AND (john = ?)}
92
+ expect(bind.join(',')).to be == 'baz,man'
93
+ end
94
+
95
+ it 'delete all' do
96
+ builder = SQL::Maker.new(:driver => 'mysql', :quote_char => '', :new_line => ' ')
97
+ sql, bind = builder.delete('foo')
98
+ expect(sql).to be == %q{DELETE FROM foo}
99
+ expect(bind.join(',')).to be == ''
100
+ end
101
+
102
+ it 'delete using where_as_hashref' do
103
+ builder = SQL::Maker.new(:driver => 'mysql', :quote_char => '', :new_line => ' ')
104
+ sql, bind = builder.delete('foo', {:bar => 'baz', :john => 'man'}, {:using => 'bar'})
105
+ expect(sql).to be == %q{DELETE FROM foo USING bar WHERE (bar = ?) AND (john = ?)}
106
+ expect(bind.join(',')).to be == 'baz,man'
107
+ end
108
+
109
+ it 'delete using array where_as_hashref' do
110
+ builder = SQL::Maker.new(:driver => 'mysql', :quote_char => '', :new_line => ' ')
111
+ sql, bind = builder.delete('foo', {:bar => 'baz', :john => 'man'}, {:using => ['bar', 'qux']})
112
+ expect(sql).to be == %q{DELETE FROM foo USING bar, qux WHERE (bar = ?) AND (john = ?)}
113
+ expect(bind.join(',')).to be == 'baz,man'
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,23 @@
1
+ require_relative '../spec_helper'
2
+ require 'sql/maker'
3
+
4
+ describe 'SQL::Maker#insert' do
5
+ def normalize(sql)
6
+ sql.gsub(/\n/, ' ')
7
+ end
8
+
9
+ # see https://github.com/tokuhirom/SQL-Maker/issues/11
10
+ it 'sqlite' do
11
+ maker = SQL::Maker.new(:driver => 'SQLite')
12
+ sql, bind = maker.insert('foo', {})
13
+ expect(normalize(sql)).to be == 'INSERT INTO "foo" DEFAULT VALUES'
14
+ expect(bind.size).to be == 0
15
+ end
16
+
17
+ it 'mysql' do
18
+ maker = SQL::Maker.new(:driver => 'mysql')
19
+ sql, bind = maker.insert('foo', {})
20
+ expect(normalize(sql)).to be == 'INSERT INTO `foo` () VALUES ()'
21
+ expect(bind.size).to be == 0
22
+ end
23
+ end