sql_helper 0.1.0

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.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sql_helper.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Junegunn Choi
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # SQLHelper
2
+
3
+ A simplistic SQL generator extracted from [jdbc-helper](https://github.com/junegunn/jdbc-helper) gem.
4
+ This gem is not intended to be used independently outside the context of jdbc-helper.
5
+
6
+ ## Example
7
+
8
+ ```ruby
9
+ SQLHelper.select(
10
+ prepared: true,
11
+ table: 'mytable',
12
+ project: %w[a b c d e],
13
+ where: [
14
+ 'z <> 100',
15
+ ['y = ?', 200],
16
+ {
17
+ a: "hello 'world'",
18
+ b: (1..10),
19
+ c: (1...10),
20
+ d: ['abc', "'def'"],
21
+ e: { sql: 'sysdate' },
22
+ f: { not: nil },
23
+ g: { gt: 100 },
24
+ h: { lt: 100 },
25
+ i: { like: 'ABC%' },
26
+ j: { not: { like: 'ABC%' } },
27
+ k: { le: { sql: 'sysdate' } },
28
+ l: { ge: 100, le: 200 },
29
+ m: { not: [ 150, { ge: 100, le: 200 } ] },
30
+ n: nil,
31
+ o: { not: (1..10) },
32
+ p: { or: [{ gt: 100 }, { lt: 50 }] },
33
+ q: { like: ['ABC%', 'DEF%'] },
34
+ r: { or: [{ like: ['ABC%', 'DEF%'] }, { not: { like: 'XYZ%' } }] }
35
+ }
36
+ ],
37
+ order: 'a desc',
38
+ limit: 10
39
+ )
40
+ ```
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+ Rake::TestTask.new(:test) do |test|
4
+ test.libs << 'lib' << 'test'
5
+ test.pattern = 'test/**/test_*.rb'
6
+ test.verbose = true
7
+ end
@@ -0,0 +1,3 @@
1
+ module SQLHelper
2
+ VERSION = "0.1.0"
3
+ end
data/lib/sql_helper.rb ADDED
@@ -0,0 +1,348 @@
1
+ require "sql_helper/version"
2
+ require 'set'
3
+ require 'bigdecimal'
4
+
5
+ module SQLHelper
6
+ class << self
7
+ def escape arg
8
+ arg.to_s.gsub("'", "''")
9
+ end
10
+
11
+ # A naive check
12
+ def check expr
13
+ expr = expr.to_s
14
+ test = expr.to_s.gsub(/(['`"]).*?\1/, '').
15
+ gsub(%r{/\*.*?\*/}, '').
16
+ strip
17
+ raise SyntaxError.new("cannot contain unquoted semi-colons: #{expr}") if test.include?(';')
18
+ raise SyntaxError.new("cannot contain unquoted comments: #{expr}") if test.match(%r{--|/\*|\*/})
19
+ raise SyntaxError.new("unclosed quotation mark: #{expr}") if test.match(/['"`]/)
20
+ raise SyntaxError.new("empty expression") if expr.strip.empty?
21
+ expr
22
+ end
23
+
24
+ def quote arg
25
+ case arg
26
+ when String, Symbol
27
+ "'#{arg.to_s.gsub "'", "''"}'"
28
+ when BigDecimal
29
+ arg.to_s('F')
30
+ when nil
31
+ 'null'
32
+ else
33
+ if expr?(arg)
34
+ arg.values.first
35
+ else
36
+ arg.to_s
37
+ end
38
+ end
39
+ end
40
+
41
+ def insert arg
42
+ insert_internal 'insert into', arg
43
+ end
44
+
45
+ def insert_ignore arg
46
+ insert_internal 'insert ignore into', arg
47
+ end
48
+
49
+ def replace arg
50
+ insert_internal 'replace into', arg
51
+ end
52
+
53
+ def delete args
54
+ check_keys args, Set[:table, :where, :prepared]
55
+
56
+ wc, *wp = where_internal args[:prepared], args[:where]
57
+ sql = "delete from #{args.fetch :table} #{wc}".strip
58
+ if args[:prepared]
59
+ [sql, *wp]
60
+ else
61
+ sql
62
+ end
63
+ end
64
+
65
+ def update args
66
+ check_keys args, Set[:prepared, :where, :table, :data]
67
+ table = args.fetch(:table)
68
+ data = args.fetch(:data)
69
+ prepared = args[:prepared]
70
+ where,
71
+ *wbind = where_internal(args[:prepared], args[:where])
72
+ bind = []
73
+ vals = data.map { |k, v|
74
+ if prepared
75
+ if expr?(v)
76
+ [k, v.values.first].join(' = ')
77
+ else
78
+ bind << v
79
+ "#{k} = ?"
80
+ end
81
+ else
82
+ [k, quote(v)].join(' = ')
83
+ end
84
+ }
85
+ sql = "update #{check table} set #{vals.join ', '} #{where}".strip
86
+ if prepared
87
+ [sql] + bind + wbind
88
+ else
89
+ sql
90
+ end
91
+ end
92
+
93
+ def count args
94
+ check_keys args, Set[:prepared, :where, :table]
95
+ select args.merge(:project => 'count(*)')
96
+ end
97
+
98
+ def select args
99
+ check_keys args, Set[:prepared, :project, :where, :order, :limit, :top, :table]
100
+
101
+ top = args[:top] ? "top #{args[:top]}" : ''
102
+ project = project(*args[:project])
103
+ where,
104
+ *params = args[:where] ? where_internal(args[:prepared], args[:where]) : ['']
105
+ order = order(*args[:order])
106
+ limit = limit(*args[:limit])
107
+
108
+ sql = ['select', top, project, 'from', args.fetch(:table),
109
+ where, order, limit].reject(&:empty?).join(' ')
110
+ if args[:prepared]
111
+ [ sql, *params ]
112
+ else
113
+ sql
114
+ end
115
+ end
116
+
117
+ def project *args
118
+ args = args.compact.map(&:to_s).map(&:strip).reject(&:empty?)
119
+ if args.empty?
120
+ '*'
121
+ else
122
+ check args.join ', '
123
+ end
124
+ end
125
+
126
+ def order *args
127
+ args = args.compact.map(&:to_s).map(&:strip).reject(&:empty?)
128
+ if args.empty?
129
+ ''
130
+ else
131
+ check "order by #{args.join ', '}"
132
+ end
133
+ end
134
+
135
+ def limit *args
136
+ limit, offset = args.reverse.map { |e|
137
+ s = e.to_s.strip
138
+ s.empty? ? nil : s
139
+ }
140
+ arg = arg.to_s.strip
141
+ if offset
142
+ check "limit #{offset}, #{limit}"
143
+ elsif limit
144
+ check "limit #{limit}"
145
+ else
146
+ ''
147
+ end
148
+ end
149
+
150
+ def where *conds
151
+ where_internal false, conds
152
+ end
153
+
154
+ def where_prepared *conds
155
+ where_internal true, conds
156
+ end
157
+
158
+ private
159
+ OPERATOR_MAP = {
160
+ :gt => '>',
161
+ :ge => '>=',
162
+ :lt => '<',
163
+ :le => '<=',
164
+ :ne => '<>',
165
+ :> => '>',
166
+ :>= => '>=',
167
+ :< => '>',
168
+ :<= => '>=',
169
+ :like => 'like'
170
+ }
171
+
172
+ def expr? val
173
+ val.is_a?(Hash) && val.length == 1 && [:sql, :expr].include?(val.keys.first)
174
+ end
175
+
176
+ def check_keys args, known
177
+ raise ArgumentError, "hash expected" unless args.is_a?(Hash)
178
+ unknown = Set.new(args.keys) - known
179
+ raise ArgumentError, "unknown keys: #{unknown.to_a.join ', '}" unless unknown.empty?
180
+ end
181
+
182
+ def where_internal prepared, conds
183
+ sqls = []
184
+ params = []
185
+
186
+ conds =
187
+ case conds
188
+ when String, Hash
189
+ [conds]
190
+ when nil
191
+ []
192
+ when Array
193
+ conds
194
+ else
195
+ raise ArgumentError, "invalid argument: #{conds.class}"
196
+ end
197
+
198
+ conds.each do |cond|
199
+ case cond
200
+ when String
201
+ sql = cond.strip
202
+ next if sql.empty?
203
+ sqls << "(#{check sql})"
204
+ when Array
205
+ sql = cond[0].to_s.strip
206
+ next if sql.empty?
207
+ sql = check sql
208
+ if prepared
209
+ sqls << "(#{sql})"
210
+ params += cond[1..-1]
211
+ else
212
+ params = cond[1..-1]
213
+ sql = "(#{sql})".gsub('?') {
214
+ if params.empty?
215
+ '?'
216
+ else
217
+ quote params.shift
218
+ end
219
+ }
220
+ sqls << sql
221
+ end
222
+ when Hash
223
+ cond.each do |col, cnd|
224
+ ret = eval_hash_cond col, cnd, prepared
225
+ sqls << ret[0]
226
+ params += ret[1..-1] || []
227
+ end
228
+ when nil
229
+ else
230
+ raise ArgumentError, "invalid condition: #{cond}"
231
+ end
232
+ end
233
+
234
+ if prepared
235
+ sqls.empty? ? [''] : ["where #{sqls.join ' and '}"].concat(params)
236
+ else
237
+ sqls.empty? ? '' : "where #{sqls.join ' and '}"
238
+ end
239
+ end
240
+
241
+ def eval_hash_cond col, cnd, prepared
242
+ case cnd
243
+ when Numeric, String
244
+ prepared ? ["#{col} = ?", cnd] : [[col, quote(cnd)].join(' = ')]
245
+ when Range
246
+ if cnd.exclude_end?
247
+ prepared ?
248
+ ["#{col} >= ? and #{col} < ?", cnd.begin, cnd.end] :
249
+ ["#{col} >= #{quote cnd.begin} and #{col} < #{quote cnd.end}"]
250
+ else
251
+ prepared ?
252
+ ["#{col} between ? and ?", cnd.begin, cnd.end] :
253
+ ["#{col} between #{quote cnd.begin} and #{quote cnd.end}"]
254
+ end
255
+ when Array
256
+ sqls = []
257
+ params = []
258
+ cnd.each do |v|
259
+ ret = eval_hash_cond col, v, prepared
260
+ sqls << ret[0]
261
+ params += ret[1..-1]
262
+ end
263
+ ["(#{sqls.join(' or ')})", *params]
264
+ when nil
265
+ ["#{col} is null"]
266
+ when Hash
267
+ rets = cnd.map { |op, val|
268
+ case op
269
+ when :expr, :sql
270
+ ["#{col} = #{check val}"]
271
+ when :not
272
+ case val
273
+ when nil
274
+ ["#{col} is not null"]
275
+ when String, Numeric
276
+ prepared ?
277
+ ["#{col} <> ?", val] :
278
+ ["#{col} <> #{quote val}"]
279
+ else
280
+ ary = eval_hash_cond col, val, prepared
281
+ ary[0].prepend 'not '
282
+ ary
283
+ end
284
+ when :or
285
+ sqls = []
286
+ params = []
287
+ val.each do |v|
288
+ ret = eval_hash_cond col, v, prepared
289
+ sqls << ret[0]
290
+ params += ret[1..-1]
291
+ end
292
+ ["(#{sqls.join(' or ')})", *params]
293
+ when :gt, :>, :ge, :>=, :lt, :<, :le, :<=, :ne, :like
294
+ if val.is_a?(Hash)
295
+ if expr?(val)
296
+ [[col, OPERATOR_MAP[op], check(val.values.first)].join(' ')]
297
+ else
298
+ raise ArgumentError, "invalid condition"
299
+ end
300
+ elsif val.is_a?(Array)
301
+ prepared ?
302
+ ["(#{(["#{col} #{OPERATOR_MAP[op]} ?"] * val.length).join(' or ')})", *val] :
303
+ ["(#{val.map { |v| [col, OPERATOR_MAP[op], quote(v)].join ' ' }.join(' or ')})"]
304
+ else
305
+ prepared ?
306
+ ["#{col} #{OPERATOR_MAP[op]} ?", val] :
307
+ [[col, OPERATOR_MAP[op], quote(val)].join(' ')]
308
+ end
309
+ else
310
+ raise ArgumentError, "unexpected operator: #{op}"
311
+ end
312
+ }
313
+ [rets.map(&:first).join(' and '), *rets.inject([]) { |prms, r| prms.concat r[1..-1] }]
314
+ else
315
+ raise ArgumentError, "invalid condition: #{cnd}"
316
+ end
317
+ end
318
+
319
+ def insert_internal prefix, args
320
+ check_keys args, Set[:table, :data, :prepared]
321
+ prep = args[:prepared]
322
+ into = args.fetch(:table)
323
+ data = args.fetch(:data)
324
+
325
+ bind = []
326
+ cols = data.keys
327
+ vals = data.values.map { |val|
328
+ if prep
329
+ if expr?(val)
330
+ val.values.first
331
+ else
332
+ bind << val
333
+ '?'
334
+ end
335
+ else
336
+ quote(val)
337
+ end
338
+ }
339
+
340
+ sql = "#{prefix} #{into} (#{cols.join ', '}) values (#{vals.join ', '})"
341
+ if args[:prepared]
342
+ [sql] + bind
343
+ else
344
+ sql
345
+ end
346
+ end
347
+ end
348
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sql_helper/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "sql_helper"
8
+ spec.version = SQLHelper::VERSION
9
+ spec.authors = ["Junegunn Choi"]
10
+ spec.email = ["junegunn.c@gmail.com"]
11
+ spec.description = %q{A simplistic SQL generator}
12
+ spec.summary = %q{A simplistic SQL generator}
13
+ spec.homepage = "https://github.com/junegunn/sql_helper"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "minitest"
24
+ end
@@ -0,0 +1,179 @@
1
+ $VERBOSE = true
2
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
3
+ require 'sql_helper'
4
+ require 'bigdecimal'
5
+ require 'minitest/autorun'
6
+
7
+ class TestSQLHelper < MiniTest::Unit::TestCase
8
+ def setup
9
+ @conds = [
10
+ 'z <> 100',
11
+ ["y = ? or y = ? or y = ? or z = '???'", 200, "Macy's???", BigDecimal('3.141592')],
12
+ {
13
+ :a => "hello 'world'???",
14
+ :b => (1..10),
15
+ :c => (1...10),
16
+ :d => ['abc', "'def'"],
17
+ :e => { :sql => 'sysdate' },
18
+ :f => { :not => nil },
19
+ :g => { :gt => 100 },
20
+ :h => { :lt => 100 },
21
+ :i => { :like => 'ABC%' },
22
+ :j => { :not => { :like => 'ABC%' } },
23
+ :k => { :le => { :sql => 'sysdate' } },
24
+ :l => { :ge => 100, :le => 200 },
25
+ :m => { :not => [ 150, { :ge => 100, :le => 200 } ] },
26
+ :n => nil,
27
+ :o => { :not => (1..10) },
28
+ :p => { :or => [{ :gt => 100 }, { :lt => 50 }] },
29
+ :q => { :like => ['ABC%', 'DEF%'] },
30
+ :r => { :or => [{ :like => ['ABC%', 'DEF%'] }, { :not => { :like => 'XYZ%' } }] },
31
+ :s => { :not => 100 },
32
+ :t => { :not => 'str' },
33
+ :u => ('aa'..'zz')
34
+ },
35
+ [],
36
+ [nil],
37
+ '',
38
+ [' '],
39
+ ' '
40
+ ]
41
+
42
+ @wherep = ["where (z <> 100) and (y = ? or y = ? or y = ? or z = 'xxx') and a = ? and b between ? and ? and c >= ? and c < ? and (d = ? or d = ?) and e = sysdate and f is not null and g > ? and h < ? and i like ? and not j like ? and k <= sysdate and l >= ? and l <= ? and not (m = ? or m >= ? and m <= ?) and n is null and not o between ? and ? and (p > ? or p < ?) and (q like ? or q like ?) and ((r like ? or r like ?) or not r like ?) and s <> ? and t <> ? and u between ? and ?",
43
+ 200, "Macy's???", BigDecimal("3.141592"),
44
+ "hello 'world'???",
45
+ 1, 10,
46
+ 1, 10,
47
+ 'abc', "'def'",
48
+ 100,
49
+ 100,
50
+ 'ABC%',
51
+ 'ABC%',
52
+ 100, 200,
53
+ 150, 100, 200,
54
+ 1, 10,
55
+ 100, 50,
56
+ 'ABC%', 'DEF%',
57
+ 'ABC%', 'DEF%', 'XYZ%',
58
+ 100,
59
+ 'str',
60
+ 'aa', 'zz'
61
+ ]
62
+
63
+ params = @wherep[1..-1]
64
+ @where = @wherep[0].gsub('?') {
65
+ if params.empty?
66
+ '?'
67
+ else
68
+ SQLHelper.quote params.shift
69
+ end
70
+ }.sub('xxx', '???')
71
+ @wherep[0].sub!('xxx', '???')
72
+ end
73
+
74
+ def test_where
75
+ assert_equal @where, SQLHelper.where(*@conds)
76
+ assert_equal @where, SQLHelper.where(*(@conds + [nil, [], nil]))
77
+ end
78
+
79
+ def test_where_prepared
80
+ assert_equal @wherep, SQLHelper.where_prepared(*@conds)
81
+ end
82
+
83
+ def test_where_invalid
84
+ assert_raises(ArgumentError) { SQLHelper.where(5) }
85
+ assert_raises(ArgumentError) { SQLHelper.where(:true) }
86
+ end
87
+
88
+ def test_select
89
+ sql, *params = SQLHelper.select(
90
+ :prepared => true,
91
+ :project => [:a, :b, :c],
92
+ :table => :mytable,
93
+ :top => 10,
94
+ :where => @conds,
95
+ :order => 'a desc',
96
+ :limit => 100
97
+ )
98
+ assert_equal "select top 10 a, b, c from mytable #{@wherep[0]} order by a desc limit 100", sql
99
+ assert_equal @wherep[1..-1], params
100
+
101
+ sql, *params = SQLHelper.select(
102
+ :prepared => true,
103
+ :project => '*',
104
+ :table => 'mytable',
105
+ :where => @conds,
106
+ :order => ['a desc', 'b asc'],
107
+ :limit => [100, 300]
108
+ )
109
+ assert_equal "select * from mytable #{@wherep[0]} order by a desc, b asc limit 100, 300", sql
110
+ assert_equal @wherep[1..-1], params
111
+ end
112
+
113
+ def test_count
114
+ sql, *params = SQLHelper.count(
115
+ :prepared => true,
116
+ :table => :mytable,
117
+ :where => @conds
118
+ )
119
+ assert_equal "select count(*) from mytable #{@wherep[0]}", sql
120
+ assert_equal @wherep[1..-1], params
121
+ assert_equal "select count(*) from mytable where a is not null",
122
+ SQLHelper.count(:prepared => false, :table => :mytable, :where => { :a => { :not => nil } })
123
+ end
124
+
125
+ def test_insert
126
+ [:insert, :insert_ignore, :replace].each do |m|
127
+ sql, *binds = SQLHelper.send(m,
128
+ :table => :mytable,
129
+ :data => { :a => 100, :b => 200, :c => { :sql => 'sysdate' }, :d => "hello 'world'" },
130
+ :prepared => true
131
+ )
132
+ assert_equal %[#{m.to_s.gsub '_', ' '} into mytable (a, b, c, d) values (?, ?, sysdate, ?)], sql
133
+ assert_equal [100, 200, "hello 'world'"], binds
134
+
135
+ sql = SQLHelper.send(m,
136
+ :table => :mytable,
137
+ :data => { :a => 100, :b => 200, :c => { :sql => 'sysdate' }, :d => "hello 'world'" },
138
+ :prepared => false
139
+ )
140
+ assert_equal %[#{m.to_s.gsub '_', ' '} into mytable (a, b, c, d) values (100, 200, sysdate, 'hello ''world''')], sql
141
+ end
142
+ end
143
+
144
+ def test_delete
145
+ del = SQLHelper.delete(:table => 'mytable', :where => @conds, :prepared => true)
146
+ assert_equal "delete from mytable #{@wherep.first}", del.first
147
+ assert_equal @wherep[1..-1], del[1..-1]
148
+
149
+ assert_equal "delete from mytable #{@where}",
150
+ SQLHelper.delete(:table => :mytable, :where => @conds, :prepared => false)
151
+ end
152
+
153
+ def test_update
154
+ data = { :a => 100, :b => 200, :c => { :sql => 'sysdate' }, :d => "hello 'world'" }
155
+ sql, *binds = SQLHelper.update(:table => :mytable, :data => data, :where => @conds, :prepared => true)
156
+
157
+ assert_equal "update mytable set a = ?, b = ?, c = sysdate, d = ? #{@wherep.first}", sql
158
+ assert_equal [100, 200, "hello 'world'"] + @wherep[1..-1], binds
159
+
160
+ sql = SQLHelper.update(:table => :mytable, :data => data, :where => @conds, :prepared => false)
161
+ assert_equal "update mytable set a = 100, b = 200, c = sysdate, d = 'hello ''world''' #{@where}", sql
162
+ end
163
+
164
+ def test_check
165
+ [
166
+ %['hello],
167
+ %['hell'o'],
168
+ %[hel--lo],
169
+ %[hel;lo],
170
+ %[hel/*lo],
171
+ %[hel*/lo],
172
+ ].each do |sql|
173
+ assert_raises(SyntaxError) { SQLHelper.check sql }
174
+ assert_raises(SyntaxError) { SQLHelper.project sql }
175
+ assert_raises(SyntaxError) { SQLHelper.limit sql }
176
+ assert_raises(SyntaxError) { SQLHelper.order sql }
177
+ end
178
+ end
179
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sql_helper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Junegunn Choi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-06-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.3'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.3'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: minitest
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: A simplistic SQL generator
63
+ email:
64
+ - junegunn.c@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - LICENSE.txt
72
+ - README.md
73
+ - Rakefile
74
+ - lib/sql_helper.rb
75
+ - lib/sql_helper/version.rb
76
+ - sql_helper.gemspec
77
+ - test/test_sql_helper.rb
78
+ homepage: https://github.com/junegunn/sql_helper
79
+ licenses:
80
+ - MIT
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ segments:
92
+ - 0
93
+ hash: 1991983397644293356
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ segments:
101
+ - 0
102
+ hash: 1991983397644293356
103
+ requirements: []
104
+ rubyforge_project:
105
+ rubygems_version: 1.8.25
106
+ signing_key:
107
+ specification_version: 3
108
+ summary: A simplistic SQL generator
109
+ test_files:
110
+ - test/test_sql_helper.rb