sequel_core 1.5.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/CHANGELOG +116 -0
  2. data/COPYING +19 -19
  3. data/README +83 -32
  4. data/Rakefile +9 -20
  5. data/bin/sequel +43 -112
  6. data/doc/cheat_sheet.rdoc +225 -0
  7. data/doc/dataset_filtering.rdoc +257 -0
  8. data/lib/sequel_core/adapters/adapter_skeleton.rb +4 -2
  9. data/lib/sequel_core/adapters/ado.rb +3 -1
  10. data/lib/sequel_core/adapters/db2.rb +4 -2
  11. data/lib/sequel_core/adapters/dbi.rb +127 -113
  12. data/lib/sequel_core/adapters/informix.rb +4 -2
  13. data/lib/sequel_core/adapters/jdbc.rb +5 -3
  14. data/lib/sequel_core/adapters/mysql.rb +112 -46
  15. data/lib/sequel_core/adapters/odbc.rb +5 -7
  16. data/lib/sequel_core/adapters/odbc_mssql.rb +12 -3
  17. data/lib/sequel_core/adapters/openbase.rb +3 -1
  18. data/lib/sequel_core/adapters/oracle.rb +11 -9
  19. data/lib/sequel_core/adapters/postgres.rb +261 -262
  20. data/lib/sequel_core/adapters/sqlite.rb +72 -22
  21. data/lib/sequel_core/connection_pool.rb +140 -73
  22. data/lib/sequel_core/core_ext.rb +201 -66
  23. data/lib/sequel_core/core_sql.rb +123 -153
  24. data/lib/sequel_core/database/schema.rb +156 -0
  25. data/lib/sequel_core/database.rb +321 -338
  26. data/lib/sequel_core/dataset/callback.rb +11 -12
  27. data/lib/sequel_core/dataset/convenience.rb +213 -240
  28. data/lib/sequel_core/dataset/pagination.rb +58 -43
  29. data/lib/sequel_core/dataset/parse_tree_sequelizer.rb +331 -0
  30. data/lib/sequel_core/dataset/query.rb +41 -0
  31. data/lib/sequel_core/dataset/schema.rb +15 -0
  32. data/lib/sequel_core/dataset/sequelizer.rb +41 -373
  33. data/lib/sequel_core/dataset/sql.rb +741 -632
  34. data/lib/sequel_core/dataset.rb +183 -168
  35. data/lib/sequel_core/deprecated.rb +1 -169
  36. data/lib/sequel_core/exceptions.rb +24 -19
  37. data/lib/sequel_core/migration.rb +44 -52
  38. data/lib/sequel_core/object_graph.rb +43 -42
  39. data/lib/sequel_core/pretty_table.rb +71 -76
  40. data/lib/sequel_core/schema/generator.rb +163 -105
  41. data/lib/sequel_core/schema/sql.rb +250 -93
  42. data/lib/sequel_core/schema.rb +2 -8
  43. data/lib/sequel_core/sql.rb +394 -0
  44. data/lib/sequel_core/worker.rb +37 -27
  45. data/lib/sequel_core.rb +99 -45
  46. data/spec/adapters/informix_spec.rb +0 -1
  47. data/spec/adapters/mysql_spec.rb +177 -124
  48. data/spec/adapters/oracle_spec.rb +0 -1
  49. data/spec/adapters/postgres_spec.rb +98 -58
  50. data/spec/adapters/sqlite_spec.rb +45 -4
  51. data/spec/blockless_filters_spec.rb +269 -0
  52. data/spec/connection_pool_spec.rb +21 -18
  53. data/spec/core_ext_spec.rb +169 -19
  54. data/spec/core_sql_spec.rb +56 -49
  55. data/spec/database_spec.rb +78 -17
  56. data/spec/dataset_spec.rb +300 -428
  57. data/spec/migration_spec.rb +1 -1
  58. data/spec/object_graph_spec.rb +5 -11
  59. data/spec/rcov.opts +1 -1
  60. data/spec/schema_generator_spec.rb +16 -4
  61. data/spec/schema_spec.rb +89 -10
  62. data/spec/sequelizer_spec.rb +56 -56
  63. data/spec/spec.opts +0 -5
  64. data/spec/spec_config.rb +7 -0
  65. data/spec/spec_config.rb.example +5 -5
  66. data/spec/spec_helper.rb +6 -0
  67. data/spec/worker_spec.rb +1 -1
  68. metadata +78 -63
@@ -1,5 +1,28 @@
1
1
  require File.join(File.dirname(__FILE__), 'spec_helper')
2
2
 
3
+ context "Array#all_two_pairs?" do
4
+ specify "should return false if empty" do
5
+ [].all_two_pairs?.should == false
6
+ end
7
+
8
+ specify "should return false if any of the elements is not an array" do
9
+ [1].all_two_pairs?.should == false
10
+ [[1,2],1].all_two_pairs?.should == false
11
+ end
12
+
13
+ specify "should return false if any of the elements has a length other than two" do
14
+ [[1,2],[]].all_two_pairs?.should == false
15
+ [[1,2],[1]].all_two_pairs?.should == false
16
+ [[1,2],[1,2,3]].all_two_pairs?.should == false
17
+ end
18
+
19
+ specify "should return true if all of the elements are arrays with a length of two" do
20
+ [[1,2]].all_two_pairs?.should == true
21
+ [[1,2],[1,2]].all_two_pairs?.should == true
22
+ [[1,2],[1,2],[1,2]].all_two_pairs?.should == true
23
+ end
24
+ end
25
+
3
26
  context "Array#to_sql" do
4
27
  specify "should concatenate multiple lines into a single string" do
5
28
  "SELECT * \r\nFROM items\r\n WHERE a = 1".split.to_sql. \
@@ -51,25 +74,14 @@ context "String#lit" do
51
74
  end
52
75
 
53
76
  specify "should inhibit string literalization" do
54
- db = Sequel::Database.new
55
- ds = db[:t]
56
-
57
- ds.update_sql(:stamp => "NOW()".lit).should == \
77
+ Sequel::Database.new[:t].update_sql(:stamp => "NOW()".expr).should == \
58
78
  "UPDATE t SET stamp = NOW()"
59
79
  end
60
- end
61
80
 
62
- context "String#expr" do
63
- specify "should return an LiteralString object" do
81
+ specify "should be aliased as expr" do
64
82
  'xyz'.expr.should be_a_kind_of(Sequel::LiteralString)
65
83
  'xyz'.expr.to_s.should == 'xyz'
66
- end
67
-
68
- specify "should inhibit string literalization" do
69
- db = Sequel::Database.new
70
- ds = db[:t]
71
-
72
- ds.update_sql(:stamp => "NOW()".expr).should == \
84
+ Sequel::Database.new[:t].update_sql(:stamp => "NOW()".expr).should == \
73
85
  "UPDATE t SET stamp = NOW()"
74
86
  end
75
87
  end
@@ -149,20 +161,21 @@ end
149
161
  context "Column references" do
150
162
  setup do
151
163
  @c = Class.new(Sequel::Dataset) do
152
- def quote_column_ref(c); "`#{c}`"; end
164
+ def quoted_identifier(c); "`#{c}`"; end
153
165
  end
154
166
  @ds = @c.new(nil)
167
+ @ds.quote_identifiers = true
155
168
  end
156
169
 
157
170
  specify "should be quoted properly" do
158
171
  @ds.literal(:xyz).should == "`xyz`"
159
- @ds.literal(:xyz__abc).should == "xyz.`abc`"
172
+ @ds.literal(:xyz__abc).should == "`xyz`.`abc`"
160
173
 
161
174
  @ds.literal(:xyz.as(:x)).should == "`xyz` AS `x`"
162
- @ds.literal(:xyz__abc.as(:x)).should == "xyz.`abc` AS `x`"
175
+ @ds.literal(:xyz__abc.as(:x)).should == "`xyz`.`abc` AS `x`"
163
176
 
164
177
  @ds.literal(:xyz___x).should == "`xyz` AS `x`"
165
- @ds.literal(:xyz__abc___x).should == "xyz.`abc` AS `x`"
178
+ @ds.literal(:xyz__abc___x).should == "`xyz`.`abc` AS `x`"
166
179
  end
167
180
 
168
181
  specify "should be quoted properly in SQL functions" do
@@ -178,7 +191,7 @@ context "Column references" do
178
191
 
179
192
  specify "should be quoted properly in a cast function" do
180
193
  @ds.literal(:x.cast_as(:integer)).should == "cast(`x` AS integer)"
181
- @ds.literal(:x__y.cast_as(:varchar[20])).should == "cast(x.`y` AS varchar(20))"
194
+ @ds.literal(:x__y.cast_as(:varchar[20])).should == "cast(`x`.`y` AS varchar(20))"
182
195
  end
183
196
  end
184
197
 
@@ -187,10 +200,15 @@ context "Symbol#*" do
187
200
  @ds = Sequel::Dataset.new(nil)
188
201
  end
189
202
 
190
- specify "should format a qualified wildcard" do
203
+ specify "should format a qualified wildcard if no argument" do
191
204
  :xyz.*.to_s(@ds).should == 'xyz.*'
192
205
  :abc.*.to_s(@ds).should == 'abc.*'
193
206
  end
207
+
208
+ specify "should format a filter expression if an argument" do
209
+ :xyz.*(3).to_s(@ds).should == '(xyz * 3)'
210
+ :abc.*(5).to_s(@ds).should == '(abc * 5)'
211
+ end
194
212
  end
195
213
 
196
214
  context "Symbol#to_column_ref" do
@@ -219,38 +237,21 @@ context "Symbol#to_column_ref" do
219
237
  :ABC.to_column_ref(@ds).should == 'ABC'
220
238
  :Zvashtoy__aBcD.to_column_ref(@ds).should == 'Zvashtoy.aBcD'
221
239
  end
240
+
241
+ specify "should support spaces inside column names" do
242
+ @ds.quote_identifiers = true
243
+ :"AB C".to_column_ref(@ds).should == '"AB C"'
244
+ :"Zvas htoy__aB cD".to_column_ref(@ds).should == '"Zvas htoy"."aB cD"'
245
+ :"aB cD___XX XX".to_column_ref(@ds).should == '"aB cD" AS "XX XX"'
246
+ :"Zva shtoy__aB cD___XX XX".to_column_ref(@ds).should == '"Zva shtoy"."aB cD" AS "XX XX"'
247
+ end
222
248
  end
223
249
 
224
- ### DEPRECATED
225
250
  context "Symbol" do
226
251
  setup do
227
252
  @ds = Sequel::Dataset.new(nil)
228
253
  end
229
254
 
230
- specify "should support MIN for specifying min function" do
231
- :abc__def.MIN.to_s(@ds).should == 'min(abc.def)'
232
- end
233
-
234
- specify "should support MAX for specifying max function" do
235
- :abc__def.MAX.to_s(@ds).should == 'max(abc.def)'
236
- end
237
-
238
- specify "should support SUM for specifying sum function" do
239
- :abc__def.SUM.to_s(@ds).should == 'sum(abc.def)'
240
- end
241
-
242
- specify "should support AVG for specifying avg function" do
243
- :abc__def.AVG.to_s(@ds).should == 'avg(abc.def)'
244
- end
245
-
246
- specify "should support COUNT for specifying count function" do
247
- :abc__def.COUNT.to_s(@ds).should == 'count(abc.def)'
248
- end
249
-
250
- specify "should support any other function using upper case letters" do
251
- :abc__def.DADA.to_s(@ds).should == 'dada(abc.def)'
252
- end
253
-
254
255
  specify "should support upper case outer functions" do
255
256
  :COUNT['1'].to_s(@ds).should == "COUNT('1')"
256
257
  end
@@ -265,10 +266,6 @@ context "Symbol" do
265
266
  :abc.cast_as(:integer).to_s(@ds).should == "cast(abc AS integer)"
266
267
  end
267
268
 
268
- specify "should raise NoMethodError for non-uppercase invalid methods" do
269
- proc {:abc.dfaxs}.should raise_error(NoMethodError)
270
- end
271
-
272
269
  specify "should support subscript access using | operator" do
273
270
  (:abc|1).to_s(@ds).should == 'abc[1]'
274
271
  (:abc|[1]).to_s(@ds).should == 'abc[1]'
@@ -298,6 +295,16 @@ context "String#to_date" do
298
295
  end
299
296
  end
300
297
 
298
+ context "String#to_datetime" do
299
+ specify "should convert the string into a DateTime object" do
300
+ "2007-07-11 10:11:12a".to_datetime.should == DateTime.parse("2007-07-11 10:11:12a")
301
+ end
302
+
303
+ specify "should raise Error::InvalidValue for an invalid date" do
304
+ proc {'0000-00-00'.to_datetime}.should raise_error(Sequel::Error::InvalidValue)
305
+ end
306
+ end
307
+
301
308
  context "Sequel::SQL::Function#==" do
302
309
  specify "should be true for functions with the same name and arguments, false otherwise" do
303
310
  a = :date[:t]
@@ -9,8 +9,17 @@ context "A new Database" do
9
9
  @db.opts.should == {1 => 2, :logger => 3}
10
10
  end
11
11
 
12
- specify "should set the logger from opts[:logger]" do
12
+ specify "should set the logger from opts[:logger] and opts[:loggers]" do
13
13
  @db.logger.should == 3
14
+ @db.loggers.should == [3]
15
+ Sequel::Database.new(1 => 2, :loggers => 3).logger.should == 3
16
+ Sequel::Database.new(1 => 2, :loggers => 3).loggers.should == [3]
17
+ Sequel::Database.new(1 => 2, :loggers => [3]).logger.should == 3
18
+ Sequel::Database.new(1 => 2, :loggers => [3]).loggers.should == [3]
19
+ Sequel::Database.new(1 => 2, :logger => 4, :loggers => 3).logger.should == 4
20
+ Sequel::Database.new(1 => 2, :logger => 4, :loggers => 3).loggers.should == [4,3]
21
+ Sequel::Database.new(1 => 2, :logger => [4], :loggers => [3]).logger.should == 4
22
+ Sequel::Database.new(1 => 2, :logger => [4], :loggers => [3]).loggers.should == [4,3]
14
23
  end
15
24
 
16
25
  specify "should create a connection pool" do
@@ -88,7 +97,7 @@ context "Database#dataset" do
88
97
  e.sql.should == 'SELECT * FROM miu'
89
98
  end
90
99
 
91
- specify "should provide a filtered #from dataset if a block is given" do
100
+ pt_specify "should provide a filtered #from dataset if a block is given" do
92
101
  d = @db.from(:mau) {:x > 100}
93
102
  d.should be_a_kind_of(Sequel::Dataset)
94
103
  d.sql.should == 'SELECT * FROM mau WHERE (x > 100)'
@@ -435,6 +444,18 @@ context "Database#transaction" do
435
444
  @db.sql.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
436
445
  end
437
446
 
447
+ specify "should handle returning inside of the block by committing" do
448
+ def @db.ret_commit
449
+ transaction do
450
+ execute 'DROP TABLE test;'
451
+ return
452
+ execute 'DROP TABLE test2;';
453
+ end
454
+ end
455
+ @db.ret_commit
456
+ @db.sql.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
457
+ end
458
+
438
459
  specify "should issue ROLLBACK if an exception is raised, and re-raise" do
439
460
  @db.transaction {@db.execute 'DROP TABLE test'; raise RuntimeError} rescue nil
440
461
  @db.sql.should == ['BEGIN', 'DROP TABLE test', 'ROLLBACK']
@@ -477,7 +498,15 @@ end
477
498
  context "A Database adapter with a scheme" do
478
499
  setup do
479
500
  class CCC < Sequel::Database
501
+ if defined?(DISCONNECTS)
502
+ DISCONNECTS.clear
503
+ else
504
+ DISCONNECTS = []
505
+ end
480
506
  set_adapter_scheme :ccc
507
+ def disconnect
508
+ DISCONNECTS << self
509
+ end
481
510
  end
482
511
  end
483
512
 
@@ -499,25 +528,40 @@ context "A Database adapter with a scheme" do
499
528
  c.opts[:database].should == 'db'
500
529
  end
501
530
 
502
- specify "should be accessible through Sequel.open" do
503
- c = Sequel.open 'ccc://localhost/db'
504
- c.should be_a_kind_of(CCC)
505
- c.opts[:host].should == 'localhost'
506
- c.opts[:database].should == 'db'
531
+ specify "should be accessible through Sequel.connect via a block" do
532
+ x = nil
533
+ y = nil
534
+ z = nil
535
+
536
+ p = proc do |c|
537
+ c.should be_a_kind_of(CCC)
538
+ c.opts[:host].should == 'localhost'
539
+ c.opts[:database].should == 'db'
540
+ z = y
541
+ y = x
542
+ x = c
543
+ end
544
+ Sequel::Database.connect('ccc://localhost/db', &p).should == nil
545
+ CCC::DISCONNECTS.should == [x]
546
+
547
+ Sequel.connect('ccc://localhost/db', &p).should == nil
548
+ CCC::DISCONNECTS.should == [y, x]
549
+
550
+ Sequel.send(:def_adapter_method, :ccc)
551
+ Sequel.ccc('db', :host=>'localhost', &p).should == nil
552
+ CCC::DISCONNECTS.should == [z, y, x]
507
553
  end
508
554
 
509
- ### DEPRECATED
510
- specify "should be accessible through Sequel()" do
511
- c = Sequel('ccc://localhost/db')
555
+ specify "should be accessible through Sequel.open" do
556
+ c = Sequel.open 'ccc://localhost/db'
512
557
  c.should be_a_kind_of(CCC)
513
558
  c.opts[:host].should == 'localhost'
514
559
  c.opts[:database].should == 'db'
515
560
  end
516
561
 
517
562
  specify "should be accessible through Sequel.<adapter>" do
518
- class << Sequel
519
- def_adapter_method(:ccc)
520
- end
563
+ Sequel.send(:def_adapter_method, :ccc)
564
+
521
565
  # invalid parameters
522
566
  proc {Sequel.ccc('abc', 'def')}.should raise_error(Sequel::Error)
523
567
 
@@ -681,9 +725,26 @@ context "A database" do
681
725
  db = Sequel::Database.new
682
726
  s = "I'm a logger"
683
727
  db.logger = s
684
- db.logger.should be(s)
728
+ db.logger.should == s
729
+ db.loggers.should == [s]
685
730
  db.logger = nil
686
- db.logger.should be_nil
731
+ db.logger.should == nil
732
+ db.loggers.should == []
733
+
734
+ db.loggers = [s]
735
+ db.logger.should == s
736
+ db.loggers.should == [s]
737
+ db.loggers = []
738
+ db.logger.should == nil
739
+ db.loggers.should == []
740
+
741
+ t = "I'm also a logger"
742
+ db.loggers = [s, t]
743
+ db.logger.should == s
744
+ db.loggers.should == [s,t]
745
+ db.loggers = []
746
+ db.logger.should == nil
747
+ db.loggers.should == []
687
748
  end
688
749
  end
689
750
 
@@ -720,7 +781,7 @@ context "Database#fetch" do
720
781
  sql.should == "select * from xyz where x = 15 and y = 'abc'"
721
782
 
722
783
  # and Aman Gupta's example
723
- @db.fetch('select name from table where name = ? or id in (?)',
784
+ @db.fetch('select name from table where name = ? or id in ?',
724
785
  'aman', [3,4,7]) {|r| sql = r[:sql]}
725
786
  sql.should == "select name from table where name = 'aman' or id in (3, 4, 7)"
726
787
  end
@@ -739,7 +800,7 @@ context "Database#fetch" do
739
800
  ds.select_sql.should == 'select * from xyz'
740
801
  ds.sql.should == 'select * from xyz'
741
802
 
742
- ds.filter! {:price < 100}
803
+ ds.filter!(:price < 100)
743
804
  ds.select_sql.should == 'select * from xyz'
744
805
  ds.sql.should == 'select * from xyz'
745
806
  end