sql_helper 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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