sequel_core 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.
Files changed (57) hide show
  1. data/CHANGELOG +1003 -0
  2. data/COPYING +18 -0
  3. data/README +81 -0
  4. data/Rakefile +176 -0
  5. data/bin/sequel +41 -0
  6. data/lib/sequel_core.rb +59 -0
  7. data/lib/sequel_core/adapters/adapter_skeleton.rb +68 -0
  8. data/lib/sequel_core/adapters/ado.rb +100 -0
  9. data/lib/sequel_core/adapters/db2.rb +158 -0
  10. data/lib/sequel_core/adapters/dbi.rb +126 -0
  11. data/lib/sequel_core/adapters/informix.rb +87 -0
  12. data/lib/sequel_core/adapters/jdbc.rb +108 -0
  13. data/lib/sequel_core/adapters/mysql.rb +269 -0
  14. data/lib/sequel_core/adapters/odbc.rb +145 -0
  15. data/lib/sequel_core/adapters/odbc_mssql.rb +93 -0
  16. data/lib/sequel_core/adapters/openbase.rb +90 -0
  17. data/lib/sequel_core/adapters/oracle.rb +99 -0
  18. data/lib/sequel_core/adapters/postgres.rb +519 -0
  19. data/lib/sequel_core/adapters/sqlite.rb +192 -0
  20. data/lib/sequel_core/array_keys.rb +296 -0
  21. data/lib/sequel_core/connection_pool.rb +152 -0
  22. data/lib/sequel_core/core_ext.rb +59 -0
  23. data/lib/sequel_core/core_sql.rb +191 -0
  24. data/lib/sequel_core/database.rb +433 -0
  25. data/lib/sequel_core/dataset.rb +409 -0
  26. data/lib/sequel_core/dataset/convenience.rb +321 -0
  27. data/lib/sequel_core/dataset/sequelizer.rb +354 -0
  28. data/lib/sequel_core/dataset/sql.rb +586 -0
  29. data/lib/sequel_core/exceptions.rb +45 -0
  30. data/lib/sequel_core/migration.rb +191 -0
  31. data/lib/sequel_core/model.rb +8 -0
  32. data/lib/sequel_core/pretty_table.rb +73 -0
  33. data/lib/sequel_core/schema.rb +8 -0
  34. data/lib/sequel_core/schema/schema_generator.rb +131 -0
  35. data/lib/sequel_core/schema/schema_sql.rb +131 -0
  36. data/lib/sequel_core/worker.rb +58 -0
  37. data/spec/adapters/informix_spec.rb +139 -0
  38. data/spec/adapters/mysql_spec.rb +330 -0
  39. data/spec/adapters/oracle_spec.rb +130 -0
  40. data/spec/adapters/postgres_spec.rb +189 -0
  41. data/spec/adapters/sqlite_spec.rb +345 -0
  42. data/spec/array_keys_spec.rb +679 -0
  43. data/spec/connection_pool_spec.rb +356 -0
  44. data/spec/core_ext_spec.rb +67 -0
  45. data/spec/core_sql_spec.rb +301 -0
  46. data/spec/database_spec.rb +812 -0
  47. data/spec/dataset_spec.rb +2381 -0
  48. data/spec/migration_spec.rb +261 -0
  49. data/spec/pretty_table_spec.rb +66 -0
  50. data/spec/rcov.opts +4 -0
  51. data/spec/schema_generator_spec.rb +86 -0
  52. data/spec/schema_spec.rb +230 -0
  53. data/spec/sequelizer_spec.rb +448 -0
  54. data/spec/spec.opts +5 -0
  55. data/spec/spec_helper.rb +44 -0
  56. data/spec/worker_spec.rb +96 -0
  57. metadata +162 -0
@@ -0,0 +1,448 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ context "Sequelizer without ParseTree" do
4
+ setup do
5
+ module Kernel
6
+ alias_method :orig_sq_require, :require
7
+ def require(*args); raise LoadError; end
8
+ end
9
+ old_verbose = $VERBOSE
10
+ $VERBOSE = nil
11
+ load(File.join(File.dirname(__FILE__), '../lib/sequel_core/dataset/sequelizer.rb'))
12
+ $VERBOSE = old_verbose
13
+ @db = Sequel::Database.new
14
+ @ds = @db[:items]
15
+ end
16
+
17
+ teardown do
18
+ module Kernel
19
+ alias_method :require, :orig_sq_require
20
+ end
21
+ old_verbose = $VERBOSE
22
+ $VERBOSE = nil
23
+ load(File.join(File.dirname(__FILE__), '../lib/sequel_core/dataset/sequelizer.rb'))
24
+ $VERBOSE = old_verbose
25
+ end
26
+
27
+ specify "should raise error when converting proc to SQL" do
28
+ proc {@ds.proc_to_sql(proc {:x > 1})}.should raise_error(Sequel::Error)
29
+ end
30
+ end
31
+
32
+ context "Sequelizer without Ruby2Ruby" do
33
+ setup do
34
+ module Kernel
35
+ alias_method :orig_sq_require, :require
36
+ def require(name); raise LoadError if name == 'ruby2ruby'; end
37
+ end
38
+ old_verbose = $VERBOSE
39
+ $VERBOSE = nil
40
+ load(File.join(File.dirname(__FILE__), '../lib/sequel_core/dataset/sequelizer.rb'))
41
+ $VERBOSE = old_verbose
42
+ @db = Sequel::Database.new
43
+ @ds = @db[:items]
44
+ end
45
+
46
+ teardown do
47
+ module Kernel
48
+ alias_method :require, :orig_sq_require
49
+ end
50
+ old_verbose = $VERBOSE
51
+ $VERBOSE = nil
52
+ load(File.join(File.dirname(__FILE__), '../lib/sequel_core/dataset/sequelizer.rb'))
53
+ $VERBOSE = old_verbose
54
+ end
55
+
56
+ specify "should raise error only when using external expressions" do
57
+ proc {@ds.proc_to_sql(proc {:x > 1})}.should_not raise_error(Sequel::Error)
58
+ proc {@ds.proc_to_sql(proc {1 + 1})}.should raise_error(Sequel::Error)
59
+ end
60
+ end
61
+
62
+ context "Proc#to_sql" do
63
+ DB = Sequel::Database.new
64
+ DS = DB[:items]
65
+
66
+ class ::Proc
67
+ def to_sql
68
+ DS.proc_to_sql(self)
69
+ end
70
+
71
+ def to_sql_comma_separated
72
+ DS.proc_to_sql(self, :comma_separated => true)
73
+ end
74
+ end
75
+
76
+ def DS.match_expr(l, r)
77
+ case r
78
+ when String
79
+ "(#{literal(l)} LIKE #{literal(r)})"
80
+ when Regexp
81
+ "(#{literal(l)} ~ #{literal(r.source)})"
82
+ else
83
+ raise Sequel::Error, "Unsupported match pattern class (#{r.class})."
84
+ end
85
+ end
86
+
87
+ specify "should support <sym> <op> <lit>" do
88
+ proc {:x > 100}.to_sql.should == '(x > 100)'
89
+ proc {:x < 100}.to_sql.should == '(x < 100)'
90
+ proc {:x >= 100}.to_sql.should == '(x >= 100)'
91
+ proc {:x <= 100}.to_sql.should == '(x <= 100)'
92
+ proc {:x == 100}.to_sql.should == '(x = 100)'
93
+ end
94
+
95
+ specify "should support number literals" do
96
+ proc {:x > 123.45}.to_sql.should == '(x > 123.45)'
97
+ proc {:x > -30_000}.to_sql.should == '(x > -30000)'
98
+ end
99
+
100
+ specify "should support string literals" do
101
+ proc {:x == 'abc'}.to_sql.should == "(x = 'abc')"
102
+ proc {:y == "ab'cd"}.to_sql.should == "(y = 'ab''cd')"
103
+ end
104
+
105
+ specify "should support boolean literals" do
106
+ proc {:x == false}.to_sql.should == "(x = 'f')"
107
+ proc {:x == true}.to_sql.should == "(x = 't')"
108
+ end
109
+
110
+ specify "should support nil literal and nil?" do
111
+ proc {:x == nil}.to_sql.should == "(x IS NULL)"
112
+ proc {:x.nil?}.to_sql.should == "(x IS NULL)"
113
+ end
114
+
115
+ specify "should support local vars or method references" do
116
+ proc {proc {:x == a}.to_sql}.should raise_error(NameError)
117
+ b = 123
118
+ proc {:x == b}.to_sql.should == "(x = 123)"
119
+ def xyz; 321; end
120
+ proc {:x == xyz}.to_sql.should == "(x = 321)"
121
+ proc {:x == xyz.to_s}.to_sql.should == "(x = '321')"
122
+
123
+ def y1(x); x; end
124
+ def y2; 111; end
125
+
126
+ proc {:x == y1(222)}.to_sql.should == "(x = 222)"
127
+ proc {:x == y2}.to_sql.should == "(x = 111)"
128
+ end
129
+
130
+ specify "sould support subscript access on symbols" do
131
+ proc {:x|1 > 0}.to_sql.should == "(x[1] > 0)"
132
+ proc {:x|2|3 > 0}.to_sql.should == "(x[2, 3] > 0)"
133
+ proc {:x|[4, 5] > 0}.to_sql.should == "(x[4, 5] > 0)"
134
+ end
135
+
136
+ specify "should support constants" do
137
+ ZZZ = 444
138
+ proc {:x == ZZZ}.to_sql.should == "(x = 444)"
139
+
140
+ CCCD = Module.new
141
+ CCCD::DDD = 'hi'
142
+ proc {:x == CCCD::DDD}.to_sql.should == "(x = 'hi')"
143
+ end
144
+
145
+ specify "should support instance attributes" do
146
+ @abc = 123
147
+ proc {:x == @abc}.to_sql.should == "(x = 123)"
148
+ end
149
+
150
+ specify "should support class attributes" do
151
+ @@abc = 321
152
+ proc {:x == @@abc}.to_sql.should == "(x = 321)"
153
+ end
154
+
155
+ specify "should support like? pattern" do
156
+ proc {:x.like? '%abc'}.to_sql.should == "(x LIKE '%abc')"
157
+ end
158
+
159
+ specify "should support =~ operator" do
160
+ # stock SQL version does not know about regexps
161
+ proc {:x =~ '123'}.to_sql.should == "(x LIKE '123')"
162
+
163
+ proc {:x =~ /^123/}.to_sql.should == "(x ~ '^123')"
164
+ end
165
+
166
+ specify "should raise on =~ operator for unsupported types" do
167
+ proc {proc {:x =~ 123}.to_sql}.should raise_error(Sequel::Error)
168
+ end
169
+
170
+ specify "should support != operator" do
171
+ proc {:x != 100}.to_sql.should == "(NOT (x = 100))"
172
+ end
173
+
174
+ specify "should support !~ operator" do
175
+ proc {:x !~ '123'}.to_sql.should == "(NOT (x LIKE '123'))"
176
+ end
177
+
178
+ specify "should support ! operator" do
179
+ proc {!:x}.to_sql.should == "(x = 'f')"
180
+ proc {!(:x > 100)}.to_sql.should == "(NOT (x > 100))"
181
+ end
182
+
183
+ specify "should support && operator" do
184
+ proc {1 && 2}.to_sql.should == "(1 AND 2)"
185
+ proc {:x > 100 && :y < 100}.to_sql.should == "((x > 100) AND (y < 100))"
186
+ proc {:x && :y && :z}.to_sql.should == "(x AND (y AND z))"
187
+ end
188
+
189
+ specify "should support << operator for assignment" do
190
+ proc {:x << 1}.to_sql.should == "x = 1"
191
+ end
192
+
193
+ specify "should concatenate separate statements using AND" do
194
+ proc {:x == 20; :y == 30}.to_sql.should == "((x = 20) AND (y = 30))"
195
+ proc {:x != 1; :y != 2; :z != 3}.to_sql.should == \
196
+ "((NOT (x = 1)) AND (NOT (y = 2)) AND (NOT (z = 3)))"
197
+ end
198
+
199
+ specify "should concatenate separate statements using custom join argument" do
200
+ proc {:x << 20; :y << 30}.to_sql_comma_separated.should == "x = 20, y = 30"
201
+ z = 333
202
+ proc {:x << :x + 1; :y << z}.to_sql_comma_separated.should == "x = (x + 1), y = 333"
203
+ end
204
+
205
+ specify "should support || operator" do
206
+ proc {1 || 2}.to_sql.should == "(1 OR 2)"
207
+ proc {:x > 100 || :y < 100}.to_sql.should == "((x > 100) OR (y < 100))"
208
+ proc {:x || :y || :z}.to_sql.should == "(x OR (y OR z))"
209
+ end
210
+
211
+ specify "should support operator combinations" do
212
+ proc {(:x > 1 || :y > 2) && (:z > 3)}.to_sql.should == "(((x > 1) OR (y > 2)) AND (z > 3))"
213
+ proc {(1 && 2) || (3 || 4)}.to_sql.should == "((1 AND 2) OR (3 OR 4))"
214
+ proc {(:x != 2) || (:y == 3) || !(:z == 4)}.to_sql.should == \
215
+ "((NOT (x = 2)) OR ((y = 3) OR (NOT (z = 4))))"
216
+ end
217
+
218
+ specify "should support late bound column references" do
219
+ def abc; :tttt; end
220
+ proc {abc > 2}.to_sql.should == "(tttt > 2)"
221
+ end
222
+
223
+ specify "should support qualified column references" do
224
+ proc {:x__y > 3}.to_sql.should == "(x.y > 3)"
225
+ end
226
+
227
+ specify "should support functions on columns" do
228
+ proc {:x.MAX > 100}.to_sql.should == "(max(x) > 100)"
229
+ proc {:x.COUNT > 100}.to_sql.should == "(count(x) > 100)"
230
+ end
231
+
232
+ specify "should support SQL functions" do
233
+ proc {:MAX[:x] > 100}.to_sql.should == "(MAX(x) > 100)"
234
+
235
+ proc {:MAX[:x__y] > 100}.to_sql.should == "(MAX(x.y) > 100)"
236
+ end
237
+
238
+ specify "should support SQL functions with multiple arguments" do
239
+ proc {:sum[1, 2, 3] > 100}.to_sql.should == "(sum(1, 2, 3) > 100)"
240
+
241
+ proc {:x[1, DB[:y].select(:z), "a'b"] > 100}.to_sql.should == \
242
+ "(x(1, (SELECT z FROM y), 'a''b') > 100)"
243
+ end
244
+
245
+ specify "should support SQL functions without arguments" do
246
+ proc {:abc[] > 100}.to_sql.should == "(abc() > 100)"
247
+
248
+ proc {:now[] - :last_stamp > 100}.to_sql.should == \
249
+ "((now() - last_stamp) > 100)"
250
+ end
251
+
252
+ specify "should do stuff like..." do
253
+ proc {:price < 100 || :category != 'ruby'}.to_sql.should == \
254
+ "((price < 100) OR (NOT (category = 'ruby')))"
255
+ t = Time.now
256
+ proc {:node_id == 1 && :stamp < t}.to_sql.should == \
257
+ "((node_id = 1) AND (stamp < #{DS.literal(t)}))"
258
+
259
+ proc {1 < :x}.to_sql.should == "(1 < x)"
260
+ end
261
+
262
+ specify "should complain if someone is crazy" do
263
+ proc {proc {def x; 1; end}.to_sql}.should raise_error(Sequel::Error::InvalidExpression)
264
+ a = 1
265
+ proc {proc {a = 1}.to_sql}.should raise_error(Sequel::Error::InvalidExpression)
266
+ end
267
+
268
+ specify "should support comparison to Range objects" do
269
+ proc {:x == (1..10)}.to_sql.should == \
270
+ "(x >= 1 AND x <= 10)"
271
+
272
+ proc {:x == (1...10)}.to_sql.should == \
273
+ "(x >= 1 AND x < 10)"
274
+
275
+ a, b = 3, 5
276
+ proc {:x == (a..b)}.to_sql.should == \
277
+ "(x >= 3 AND x <= 5)"
278
+
279
+ proc {:x == (a...b)}.to_sql.should == \
280
+ "(x >= 3 AND x < 5)"
281
+
282
+ t1 = Time.now - 4000
283
+ t2 = Time.now - 2000
284
+
285
+ proc {:stamp == (t1..t2)}.to_sql.should == \
286
+ "(stamp >= #{DS.literal(t1)} AND stamp <= #{DS.literal(t2)})"
287
+ end
288
+
289
+ specify "should support comparison to sub-queries" do
290
+ @ds2 = DB[:test].select(:node_id)
291
+
292
+ proc {:id == @ds2}.to_sql.should == \
293
+ "(id IN (SELECT node_id FROM test))"
294
+
295
+ proc {:id == DB[:test].select(:node_id)}.to_sql.should == \
296
+ "(id IN (SELECT node_id FROM test))"
297
+
298
+ proc {:id == DB[:test].select(:node_id).filter {:active == true}}.to_sql.should == \
299
+ "(id IN (SELECT node_id FROM test WHERE (active = 't')))"
300
+
301
+ proc {:price >= DB[:items].select(:price)}.to_sql.should == \
302
+ "(price >= (SELECT price FROM items))"
303
+ end
304
+
305
+ specify "should support comparison to arrays" do
306
+ proc {:id == [1, 3, 7, 15]}.to_sql.should == \
307
+ "(id IN (1, 3, 7, 15))"
308
+ end
309
+
310
+ specify "should not literalize String#expr and String#lit" do
311
+ proc {'x'.lit == 1}.to_sql.should == "(x = 1)"
312
+ proc {'x.y'.expr == 1}.to_sql.should == "(x.y = 1)"
313
+ end
314
+
315
+ specify "should support in/in? operator" do
316
+ proc {:x.in [3, 4, 5]}.to_sql.should == "(x IN (3, 4, 5))"
317
+ proc {:x.in?(3, 4, 5)}.to_sql.should == "(x IN (3, 4, 5))"
318
+
319
+ proc {:x.in(1..10)}.to_sql.should == "(x >= 1 AND x <= 10)"
320
+ proc {:x.in?(1..10)}.to_sql.should == "(x >= 1 AND x <= 10)"
321
+
322
+ @ds2 = DB[:test].select(:node_id)
323
+ proc {:x.in @ds2}.to_sql.should == "(x IN (SELECT node_id FROM test))"
324
+ end
325
+
326
+ specify "should support nested procs" do
327
+ proc {:x > 10 || proc{:y > 20}}.to_sql.should == \
328
+ "((x > 10) OR (y > 20))"
329
+
330
+ def pr(&block)
331
+ proc {:x > 10 || block}
332
+ end
333
+
334
+ pr {:y > 20}.to_sql.should == \
335
+ "((x > 10) OR (y > 20))"
336
+ end
337
+
338
+ specify "should support unfolding of calls to #each" do
339
+ # from http://groups.google.com/group/sequel-talk/browse_thread/thread/54a660568515fbb7
340
+ periods = [:day, :week, :month, :year, :alltime]
341
+ idx = 1
342
+ v = 2
343
+ pr = proc do
344
+ periods.each do |p|
345
+ (p|idx) << (p|idx) + v
346
+ end
347
+ end
348
+ pr.to_sql_comma_separated.should == \
349
+ "day[1] = (day[1] + 2), week[1] = (week[1] + 2), month[1] = (month[1] + 2), year[1] = (year[1] + 2), alltime[1] = (alltime[1] + 2)"
350
+ end
351
+
352
+ specify "should support unfolding of calls to Hash#each" do
353
+ periods = {:month => 3}
354
+ idx = 1
355
+ pr = proc do
356
+ periods.each do |k, v|
357
+ k << k + v
358
+ end
359
+ end
360
+ pr.to_sql_comma_separated.should == "month = (month + 3)"
361
+ end
362
+
363
+ specify "should support local arguments" do
364
+ def t(x)
365
+ proc {x > 10}.to_sql
366
+ end
367
+ t(:y).should == "(y > 10)"
368
+ end
369
+
370
+ specify "should support binary operators on local context" do
371
+ XXX = 1
372
+ YYY = 2
373
+ proc {XXX || YYY}.to_sql.should == "(1 OR 2)"
374
+
375
+ xxx = 1
376
+ yyy = 2
377
+ proc {xxx && yyy}.to_sql.should == "(1 AND 2)"
378
+ end
379
+
380
+ specify "should support arithmetics" do
381
+ zzz = 300
382
+ proc {(:x + 100) > zzz}.to_sql.should == "((x + 100) > 300)"
383
+
384
+ proc {(:x + :y * 100) > zzz}.to_sql.should == "((x + (y * 100)) > 300)"
385
+
386
+ proc {:units * :price}.to_sql.should == "(units * price)"
387
+ end
388
+
389
+ specify "should support | operator" do
390
+ proc {(:x | 1) > 0}.to_sql.should == "(x[1] > 0)"
391
+ proc {10 | 1}.to_sql.should == 11
392
+ end
393
+
394
+ specify "should support globals" do
395
+ $aaaa_zzzz = 400
396
+ proc {:x > $aaaa_zzzz}.to_sql.should == "(x > 400)"
397
+ end
398
+
399
+ specify "should support Regexp macros" do
400
+ "abc" =~ /(ab)/
401
+ proc {:x == $1}.to_sql.should == "(x = 'ab')"
402
+ end
403
+
404
+ specify "should evaluate expression not referring to symbols or literal strings." do
405
+ proc {:x > 2 * 3}.to_sql.should == "(x > 6)"
406
+ y = 3
407
+ proc {:x > y * 4}.to_sql.should == "(x > 12)"
408
+
409
+ proc {:AVG[:x] > 4}.to_sql.should == "(AVG(x) > 4)"
410
+
411
+ proc {:AVG[:x] > 4}.to_sql.should == "(AVG(x) > 4)"
412
+
413
+ proc {:y == (1 > 2)}.to_sql.should == "(y = 'f')"
414
+ end
415
+
416
+ specify "should support ternary operator" do
417
+ y = true
418
+ proc {:x > (y ? 1 : 2)}.to_sql.should == "(x > 1)"
419
+
420
+ proc {((1 > 2) ? :x : :y) > 3}.to_sql.should == "(y > 3)"
421
+ end
422
+
423
+ specify "should support strings with embedded Ruby code in them and literalize them" do
424
+ proc {:n == "#{1+2}"}.to_sql.should == "(n = '3')"
425
+
426
+ y = "12'34"
427
+
428
+ proc {:x > "#{y}"}.to_sql.should == "(x > '12''34')"
429
+ end
430
+
431
+ specify "should support format strings and literalize the result" do
432
+ prod = 1
433
+ proc {:x == "abc%d" % prod}.to_sql.should == "(x = 'abc1')"
434
+
435
+ proc {:x == ("%d" % prod).lit}.to_sql.should == "(x = 1)"
436
+ end
437
+ end
438
+
439
+ context "Proc#to_sql stock" do
440
+ specify "should not support regexps" do
441
+ db = Sequel::Database.new
442
+ ds = db[:items]
443
+
444
+ p = proc {:x =~ /abc/}
445
+ proc {ds.proc_to_sql(p)}.should raise_error(Sequel::Error)
446
+ end
447
+ end
448
+
@@ -0,0 +1,5 @@
1
+ --colour
2
+ --backtrace
3
+ --format
4
+ specdoc
5
+ --diff