sequel 3.21.0 → 3.29.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 (200) hide show
  1. data/CHANGELOG +413 -3
  2. data/README.rdoc +20 -6
  3. data/Rakefile +23 -16
  4. data/bin/sequel +1 -5
  5. data/doc/association_basics.rdoc +210 -43
  6. data/doc/dataset_basics.rdoc +4 -4
  7. data/doc/mass_assignment.rdoc +54 -0
  8. data/doc/migration.rdoc +15 -538
  9. data/doc/model_hooks.rdoc +72 -27
  10. data/doc/opening_databases.rdoc +86 -50
  11. data/doc/prepared_statements.rdoc +40 -13
  12. data/doc/reflection.rdoc +8 -2
  13. data/doc/release_notes/3.22.0.txt +39 -0
  14. data/doc/release_notes/3.23.0.txt +172 -0
  15. data/doc/release_notes/3.24.0.txt +420 -0
  16. data/doc/release_notes/3.25.0.txt +88 -0
  17. data/doc/release_notes/3.26.0.txt +88 -0
  18. data/doc/release_notes/3.27.0.txt +82 -0
  19. data/doc/release_notes/3.28.0.txt +304 -0
  20. data/doc/release_notes/3.29.0.txt +459 -0
  21. data/doc/schema_modification.rdoc +547 -0
  22. data/doc/sharding.rdoc +7 -1
  23. data/doc/testing.rdoc +115 -0
  24. data/doc/transactions.rdoc +137 -0
  25. data/doc/virtual_rows.rdoc +2 -2
  26. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  27. data/lib/sequel/adapters/ado.rb +40 -18
  28. data/lib/sequel/adapters/amalgalite.rb +15 -7
  29. data/lib/sequel/adapters/db2.rb +175 -86
  30. data/lib/sequel/adapters/dbi.rb +15 -15
  31. data/lib/sequel/adapters/do/mysql.rb +0 -5
  32. data/lib/sequel/adapters/do/postgres.rb +0 -5
  33. data/lib/sequel/adapters/do/sqlite.rb +0 -5
  34. data/lib/sequel/adapters/do.rb +17 -36
  35. data/lib/sequel/adapters/firebird.rb +27 -208
  36. data/lib/sequel/adapters/ibmdb.rb +448 -0
  37. data/lib/sequel/adapters/informix.rb +6 -23
  38. data/lib/sequel/adapters/jdbc/as400.rb +5 -31
  39. data/lib/sequel/adapters/jdbc/db2.rb +44 -0
  40. data/lib/sequel/adapters/jdbc/derby.rb +217 -0
  41. data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
  42. data/lib/sequel/adapters/jdbc/h2.rb +26 -17
  43. data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
  44. data/lib/sequel/adapters/jdbc/informix.rb +26 -0
  45. data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
  46. data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
  47. data/lib/sequel/adapters/jdbc/mysql.rb +9 -10
  48. data/lib/sequel/adapters/jdbc/oracle.rb +67 -25
  49. data/lib/sequel/adapters/jdbc/postgresql.rb +6 -11
  50. data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
  51. data/lib/sequel/adapters/jdbc/sqlserver.rb +41 -0
  52. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  53. data/lib/sequel/adapters/jdbc.rb +107 -38
  54. data/lib/sequel/adapters/mock.rb +315 -0
  55. data/lib/sequel/adapters/mysql.rb +78 -182
  56. data/lib/sequel/adapters/mysql2.rb +24 -23
  57. data/lib/sequel/adapters/odbc/db2.rb +17 -0
  58. data/lib/sequel/adapters/odbc/mssql.rb +0 -5
  59. data/lib/sequel/adapters/odbc.rb +28 -9
  60. data/lib/sequel/adapters/openbase.rb +2 -4
  61. data/lib/sequel/adapters/oracle.rb +349 -51
  62. data/lib/sequel/adapters/postgres.rb +169 -21
  63. data/lib/sequel/adapters/shared/access.rb +21 -6
  64. data/lib/sequel/adapters/shared/db2.rb +288 -0
  65. data/lib/sequel/adapters/shared/firebird.rb +214 -0
  66. data/lib/sequel/adapters/shared/informix.rb +45 -0
  67. data/lib/sequel/adapters/shared/mssql.rb +108 -65
  68. data/lib/sequel/adapters/shared/mysql.rb +56 -13
  69. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
  70. data/lib/sequel/adapters/shared/oracle.rb +185 -34
  71. data/lib/sequel/adapters/shared/postgres.rb +107 -58
  72. data/lib/sequel/adapters/shared/progress.rb +0 -6
  73. data/lib/sequel/adapters/shared/sqlite.rb +168 -41
  74. data/lib/sequel/adapters/sqlite.rb +27 -18
  75. data/lib/sequel/adapters/swift/mysql.rb +9 -5
  76. data/lib/sequel/adapters/swift/postgres.rb +0 -5
  77. data/lib/sequel/adapters/swift/sqlite.rb +6 -4
  78. data/lib/sequel/adapters/swift.rb +5 -5
  79. data/lib/sequel/adapters/tinytds.rb +152 -17
  80. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +63 -0
  81. data/lib/sequel/ast_transformer.rb +190 -0
  82. data/lib/sequel/connection_pool/threaded.rb +3 -2
  83. data/lib/sequel/connection_pool.rb +1 -1
  84. data/lib/sequel/core.rb +46 -5
  85. data/lib/sequel/database/connecting.rb +5 -6
  86. data/lib/sequel/database/dataset.rb +4 -4
  87. data/lib/sequel/database/dataset_defaults.rb +59 -1
  88. data/lib/sequel/database/logging.rb +1 -1
  89. data/lib/sequel/database/misc.rb +100 -19
  90. data/lib/sequel/database/query.rb +153 -58
  91. data/lib/sequel/database/schema_generator.rb +8 -5
  92. data/lib/sequel/database/schema_methods.rb +59 -29
  93. data/lib/sequel/dataset/actions.rb +194 -57
  94. data/lib/sequel/dataset/features.rb +81 -8
  95. data/lib/sequel/dataset/graph.rb +8 -7
  96. data/lib/sequel/dataset/misc.rb +50 -23
  97. data/lib/sequel/dataset/mutation.rb +5 -6
  98. data/lib/sequel/dataset/prepared_statements.rb +32 -15
  99. data/lib/sequel/dataset/query.rb +223 -42
  100. data/lib/sequel/dataset/sql.rb +58 -61
  101. data/lib/sequel/dataset.rb +8 -0
  102. data/lib/sequel/exceptions.rb +4 -0
  103. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  104. data/lib/sequel/extensions/migration.rb +6 -4
  105. data/lib/sequel/extensions/named_timezones.rb +5 -0
  106. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  107. data/lib/sequel/extensions/to_dot.rb +95 -83
  108. data/lib/sequel/model/associations.rb +997 -331
  109. data/lib/sequel/model/base.rb +386 -129
  110. data/lib/sequel/model/errors.rb +1 -1
  111. data/lib/sequel/model/exceptions.rb +5 -1
  112. data/lib/sequel/model.rb +15 -8
  113. data/lib/sequel/plugins/association_pks.rb +22 -4
  114. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  115. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  116. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  117. data/lib/sequel/plugins/force_encoding.rb +6 -6
  118. data/lib/sequel/plugins/identity_map.rb +114 -7
  119. data/lib/sequel/plugins/many_through_many.rb +65 -7
  120. data/lib/sequel/plugins/prepared_statements.rb +151 -0
  121. data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
  122. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  123. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  124. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  125. data/lib/sequel/plugins/serialization.rb +6 -1
  126. data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
  127. data/lib/sequel/plugins/sharding.rb +12 -25
  128. data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
  129. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  130. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  131. data/lib/sequel/plugins/xml_serializer.rb +3 -3
  132. data/lib/sequel/sql.rb +107 -51
  133. data/lib/sequel/timezones.rb +44 -35
  134. data/lib/sequel/version.rb +1 -1
  135. data/spec/adapters/db2_spec.rb +146 -0
  136. data/spec/adapters/mssql_spec.rb +65 -29
  137. data/spec/adapters/mysql_spec.rb +122 -123
  138. data/spec/adapters/oracle_spec.rb +48 -76
  139. data/spec/adapters/postgres_spec.rb +213 -61
  140. data/spec/adapters/spec_helper.rb +6 -5
  141. data/spec/adapters/sqlite_spec.rb +35 -21
  142. data/spec/core/connection_pool_spec.rb +71 -92
  143. data/spec/core/core_sql_spec.rb +20 -31
  144. data/spec/core/database_spec.rb +729 -508
  145. data/spec/core/dataset_spec.rb +980 -1044
  146. data/spec/core/expression_filters_spec.rb +159 -42
  147. data/spec/core/mock_adapter_spec.rb +378 -0
  148. data/spec/core/object_graph_spec.rb +48 -114
  149. data/spec/core/schema_generator_spec.rb +3 -3
  150. data/spec/core/schema_spec.rb +298 -38
  151. data/spec/core/spec_helper.rb +6 -48
  152. data/spec/extensions/association_pks_spec.rb +38 -0
  153. data/spec/extensions/class_table_inheritance_spec.rb +1 -1
  154. data/spec/extensions/columns_introspection_spec.rb +91 -0
  155. data/spec/extensions/dataset_associations_spec.rb +199 -0
  156. data/spec/extensions/defaults_setter_spec.rb +64 -0
  157. data/spec/extensions/identity_map_spec.rb +162 -0
  158. data/spec/extensions/instance_hooks_spec.rb +71 -0
  159. data/spec/extensions/many_through_many_spec.rb +195 -20
  160. data/spec/extensions/migration_spec.rb +17 -17
  161. data/spec/extensions/named_timezones_spec.rb +22 -2
  162. data/spec/extensions/nested_attributes_spec.rb +4 -0
  163. data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
  164. data/spec/extensions/prepared_statements_safe_spec.rb +79 -0
  165. data/spec/extensions/prepared_statements_spec.rb +72 -0
  166. data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
  167. data/spec/extensions/schema_dumper_spec.rb +2 -2
  168. data/spec/extensions/schema_spec.rb +13 -21
  169. data/spec/extensions/serialization_modification_detection_spec.rb +37 -0
  170. data/spec/extensions/serialization_spec.rb +5 -8
  171. data/spec/extensions/single_table_inheritance_spec.rb +11 -0
  172. data/spec/extensions/spec_helper.rb +7 -1
  173. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  174. data/spec/extensions/to_dot_spec.rb +3 -5
  175. data/spec/extensions/typecast_on_load_spec.rb +1 -6
  176. data/spec/extensions/xml_serializer_spec.rb +16 -4
  177. data/spec/integration/associations_test.rb +522 -21
  178. data/spec/integration/database_test.rb +4 -2
  179. data/spec/integration/dataset_test.rb +375 -62
  180. data/spec/integration/eager_loader_test.rb +19 -21
  181. data/spec/integration/model_test.rb +80 -1
  182. data/spec/integration/plugin_test.rb +304 -116
  183. data/spec/integration/prepared_statement_test.rb +200 -120
  184. data/spec/integration/schema_test.rb +161 -30
  185. data/spec/integration/spec_helper.rb +39 -30
  186. data/spec/integration/timezone_test.rb +38 -12
  187. data/spec/integration/transaction_test.rb +172 -5
  188. data/spec/integration/type_test.rb +17 -3
  189. data/spec/model/association_reflection_spec.rb +174 -7
  190. data/spec/model/associations_spec.rb +849 -661
  191. data/spec/model/base_spec.rb +255 -95
  192. data/spec/model/dataset_methods_spec.rb +7 -27
  193. data/spec/model/eager_loading_spec.rb +640 -676
  194. data/spec/model/hooks_spec.rb +309 -67
  195. data/spec/model/model_spec.rb +207 -167
  196. data/spec/model/plugins_spec.rb +24 -13
  197. data/spec/model/record_spec.rb +321 -218
  198. data/spec/model/spec_helper.rb +13 -71
  199. data/spec/model/validations_spec.rb +11 -0
  200. metadata +95 -38
@@ -6,7 +6,6 @@ String.send(:include, Sequel::SQL::StringMethods)
6
6
  describe "Blockless Ruby Filters" do
7
7
  before do
8
8
  db = Sequel::Database.new
9
- db.quote_identifiers = false
10
9
  @d = db[:items]
11
10
  def @d.l(*args, &block)
12
11
  literal(filter_expr(*args, &block))
@@ -186,31 +185,26 @@ describe "Blockless Ruby Filters" do
186
185
  @d.l(~((((:x - :y)/(:x + :y))*:z) <= 100)).should == '((((x - y) / (x + y)) * z) > 100)'
187
186
  end
188
187
 
189
- it "should not allow negation of string expressions" do
190
- proc{~:x.sql_string}.should raise_error
191
- proc{~([:x, :y].sql_string_join)}.should raise_error
188
+ it "should not add ~ method to string expressions" do
189
+ proc{~:x.sql_string}.should raise_error(NoMethodError)
192
190
  end
193
191
 
194
- it "should not allow mathematical or string operations on true, false, or nil" do
195
- proc{:x + 1}.should_not raise_error
196
- proc{:x - true}.should raise_error(Sequel::Error)
197
- proc{:x / false}.should raise_error(Sequel::Error)
198
- proc{:x * nil}.should raise_error(Sequel::Error)
199
- proc{[:x, nil].sql_string_join}.should raise_error(Sequel::Error)
192
+ it "should allow mathematical or string operations on true, false, or nil" do
193
+ @d.lit(:x + 1).should == '(x + 1)'
194
+ @d.lit(:x - true).should == "(x - 't')"
195
+ @d.lit(:x / false).should == "(x / 'f')"
196
+ @d.lit(:x * nil).should == '(x * NULL)'
197
+ @d.lit([:x, nil].sql_string_join).should == '(x || NULL)'
200
198
  end
201
199
 
202
- it "should not allow mathematical or string operations on boolean complex expressions" do
203
- proc{:x + (:y + 1)}.should_not raise_error
204
- proc{:x - (~:y)}.should raise_error(Sequel::Error)
205
- proc{:x / (:y & :z)}.should raise_error(Sequel::Error)
206
- proc{:x * (:y | :z)}.should raise_error(Sequel::Error)
207
- proc{:x + :y.like('a')}.should raise_error(Sequel::Error)
208
- proc{:x - :y.like(/a/)}.should raise_error(Sequel::Error)
209
- proc{:x * :y.like(/a/i)}.should raise_error(Sequel::Error)
210
- proc{:x + ~:y.like('a')}.should raise_error(Sequel::Error)
211
- proc{:x - ~:y.like(/a/)}.should raise_error(Sequel::Error)
212
- proc{:x * ~:y.like(/a/i)}.should raise_error(Sequel::Error)
213
- proc{[:x, ~:y.like(/a/i)].sql_string_join}.should raise_error(Sequel::Error)
200
+ it "should allow mathematical or string operations on boolean complex expressions" do
201
+ @d.lit(:x + (:y + 1)).should == '(x + y + 1)'
202
+ @d.lit(:x - ~:y).should == '(x - NOT y)'
203
+ @d.lit(:x / (:y & :z)).should == '(x / (y AND z))'
204
+ @d.lit(:x * (:y | :z)).should == '(x * (y OR z))'
205
+ @d.lit(:x + :y.like('a')).should == "(x + (y LIKE 'a'))"
206
+ @d.lit(:x - ~:y.like('a')).should == "(x - (y NOT LIKE 'a'))"
207
+ @d.lit([:x, ~:y.like('a')].sql_string_join).should == "(x || (y NOT LIKE 'a'))"
214
208
  end
215
209
 
216
210
  it "should support AND conditions via &" do
@@ -382,12 +376,12 @@ describe "Blockless Ruby Filters" do
382
376
  @d.l((:x + 1) & (:x + 2) > 100).should == '(((x + 1) & (x + 2)) > 100)'
383
377
  end
384
378
 
385
- it "should raise an error if use a Bitwise method on a ComplexExpression that isn't a NumericExpression" do
386
- proc{(:x + 1) & (:x & 2)}.should raise_error(Sequel::Error)
379
+ it "should allow using a Bitwise method on a ComplexExpression that isn't a NumericExpression" do
380
+ @d.lit((:x + 1) & (:x + '2')).should == "((x + 1) & (x || '2'))"
387
381
  end
388
382
 
389
- it "should raise an error if use a Boolean method on a ComplexExpression that isn't a BooleanExpression" do
390
- proc{:x & (:x + 2)}.should raise_error(Sequel::Error)
383
+ it "should allow using a Boolean method on a ComplexExpression that isn't a BooleanExpression" do
384
+ @d.l(:x & (:x + '2')).should == "(x AND (x || '2'))"
391
385
  end
392
386
 
393
387
  it "should raise an error if attempting to invert a ComplexExpression that isn't a BooleanExpression" do
@@ -424,10 +418,94 @@ describe "Blockless Ruby Filters" do
424
418
  @d.l(~{:x => Sequel::SQLFALSE}).should == '(x IS NOT FALSE)'
425
419
  end
426
420
 
421
+ it "should support direct negation of SQL::Constants" do
422
+ @d.l({:x => ~Sequel::NULL}).should == '(x IS NOT NULL)'
423
+ @d.l({:x => ~Sequel::NOTNULL}).should == '(x IS NULL)'
424
+ @d.l({:x => ~Sequel::TRUE}).should == '(x IS FALSE)'
425
+ @d.l({:x => ~Sequel::FALSE}).should == '(x IS TRUE)'
426
+ @d.l({:x => ~Sequel::SQLTRUE}).should == '(x IS FALSE)'
427
+ @d.l({:x => ~Sequel::SQLFALSE}).should == '(x IS TRUE)'
428
+ end
429
+
430
+ it "should raise an error if trying to invert an invalid SQL::Constant" do
431
+ proc{~Sequel::CURRENT_DATE}.should raise_error(Sequel::Error)
432
+ end
433
+
427
434
  it "should raise an error if trying to create an invalid complex expression" do
428
435
  proc{Sequel::SQL::ComplexExpression.new(:BANG, 1, 2)}.should raise_error(Sequel::Error)
429
436
  end
430
437
 
438
+ it "should use a string concatentation for + if given a string" do
439
+ @d.lit(:x + '1').should == "(x || '1')"
440
+ @d.lit(:x + '1' + '1').should == "(x || '1' || '1')"
441
+ end
442
+
443
+ it "should use an addition for + if given a literal string" do
444
+ @d.lit(:x + '1'.lit).should == "(x + 1)"
445
+ @d.lit(:x + '1'.lit + '1'.lit).should == "(x + 1 + 1)"
446
+ end
447
+
448
+ it "should use a bitwise operator for & and | if given an integer" do
449
+ @d.lit(:x & 1).should == "(x & 1)"
450
+ @d.lit(:x | 1).should == "(x | 1)"
451
+ @d.lit(:x & 1 & 1).should == "(x & 1 & 1)"
452
+ @d.lit(:x | 1 | 1).should == "(x | 1 | 1)"
453
+ end
454
+
455
+ it "should allow adding a string to an integer expression" do
456
+ @d.lit(:x + 1 + 'a').should == "(x + 1 + 'a')"
457
+ end
458
+
459
+ it "should allow adding an integer to an string expression" do
460
+ @d.lit(:x + 'a' + 1).should == "(x || 'a' || 1)"
461
+ end
462
+
463
+ it "should allow adding a boolean to an integer expression" do
464
+ @d.lit(:x + 1 + true).should == "(x + 1 + 't')"
465
+ end
466
+
467
+ it "should allow adding a boolean to an string expression" do
468
+ @d.lit(:x + 'a' + true).should == "(x || 'a' || 't')"
469
+ end
470
+
471
+ it "should allow using a boolean operation with an integer on an boolean expression" do
472
+ @d.lit(:x & :a & 1).should == "(x AND a AND 1)"
473
+ end
474
+
475
+ it "should allow using a boolean operation with a string on an boolean expression" do
476
+ @d.lit(:x & :a & 'a').should == "(x AND a AND 'a')"
477
+ end
478
+
479
+ it "should allowing AND of boolean expression and literal string" do
480
+ @d.lit(:x & :a & 'a'.lit).should == "(x AND a AND a)"
481
+ end
482
+
483
+ it "should allowing + of integer expression and literal string" do
484
+ @d.lit(:x + :a + 'a'.lit).should == "(x + a + a)"
485
+ end
486
+
487
+ it "should allowing + of string expression and literal string" do
488
+ @d.lit(:x + 'a' + 'a'.lit).should == "(x || 'a' || a)"
489
+ end
490
+
491
+ it "should allow sql_{string,boolean,number} methods on numeric expressions" do
492
+ @d.lit((:x + 1).sql_string + 'a').should == "((x + 1) || 'a')"
493
+ @d.lit((:x + 1).sql_boolean & 1).should == "((x + 1) AND 1)"
494
+ @d.lit((:x + 1).sql_number + 'a').should == "(x + 1 + 'a')"
495
+ end
496
+
497
+ it "should allow sql_{string,boolean,number} methods on string expressions" do
498
+ @d.lit((:x + 'a').sql_string + 'a').should == "(x || 'a' || 'a')"
499
+ @d.lit((:x + 'a').sql_boolean & 1).should == "((x || 'a') AND 1)"
500
+ @d.lit((:x + 'a').sql_number + 'a').should == "((x || 'a') + 'a')"
501
+ end
502
+
503
+ it "should allow sql_{string,boolean,number} methods on boolean expressions" do
504
+ @d.lit((:x & :y).sql_string + 'a').should == "((x AND y) || 'a')"
505
+ @d.lit((:x & :y).sql_boolean & 1).should == "(x AND y AND 1)"
506
+ @d.lit((:x & :y).sql_number + 'a').should == "((x AND y) + 'a')"
507
+ end
508
+
431
509
  it "should raise an error if trying to literalize an invalid complex expression" do
432
510
  ce = :x + 1
433
511
  ce.instance_variable_set(:@op, :BANG)
@@ -439,26 +517,65 @@ describe "Blockless Ruby Filters" do
439
517
  e2 = ~:comment.like('%:hidden:%')
440
518
  e1.should == e2
441
519
  end
520
+
521
+ it "should support expression filter methods on Datasets" do
522
+ d = @d.select(:a)
523
+
524
+ @d.lit(d + 1).should == '((SELECT a FROM items) + 1)'
525
+ @d.lit(d - 1).should == '((SELECT a FROM items) - 1)'
526
+ @d.lit(d * 1).should == '((SELECT a FROM items) * 1)'
527
+ @d.lit(d / 1).should == '((SELECT a FROM items) / 1)'
528
+
529
+ @d.lit(d => 1).should == '((SELECT a FROM items) = 1)'
530
+ @d.lit(~{d => 1}).should == '((SELECT a FROM items) != 1)'
531
+ @d.lit(d > 1).should == '((SELECT a FROM items) > 1)'
532
+ @d.lit(d < 1).should == '((SELECT a FROM items) < 1)'
533
+ @d.lit(d >= 1).should == '((SELECT a FROM items) >= 1)'
534
+ @d.lit(d <= 1).should == '((SELECT a FROM items) <= 1)'
535
+
536
+ @d.lit(d.as(:b)).should == '(SELECT a FROM items) AS b'
537
+
538
+ @d.lit(d & :b).should == '((SELECT a FROM items) AND b)'
539
+ @d.lit(d | :b).should == '((SELECT a FROM items) OR b)'
540
+ @d.lit(~d).should == 'NOT (SELECT a FROM items)'
541
+
542
+ @d.lit(d.cast(Integer)).should == 'CAST((SELECT a FROM items) AS integer)'
543
+ @d.lit(d.cast_numeric).should == 'CAST((SELECT a FROM items) AS integer)'
544
+ @d.lit(d.cast_string).should == 'CAST((SELECT a FROM items) AS varchar(255))'
545
+ @d.lit(d.cast_numeric << :b).should == '(CAST((SELECT a FROM items) AS integer) << b)'
546
+ @d.lit(d.cast_string + :b).should == '(CAST((SELECT a FROM items) AS varchar(255)) || b)'
547
+
548
+ @d.lit(d.extract(:year)).should == 'extract(year FROM (SELECT a FROM items))'
549
+ @d.lit(d.sql_boolean & :b).should == '((SELECT a FROM items) AND b)'
550
+ @d.lit(d.sql_number << :b).should == '((SELECT a FROM items) << b)'
551
+ @d.lit(d.sql_string + :b).should == '((SELECT a FROM items) || b)'
552
+
553
+ @d.lit(d.asc).should == '(SELECT a FROM items) ASC'
554
+ @d.lit(d.desc).should == '(SELECT a FROM items) DESC'
555
+
556
+ @d.lit(d.like(:b)).should == '((SELECT a FROM items) LIKE b)'
557
+ @d.lit(d.ilike(:b)).should == '((SELECT a FROM items) ILIKE b)'
558
+ end
442
559
 
443
560
  if RUBY_VERSION < '1.9.0'
444
561
  it "should not allow inequality operations on true, false, or nil" do
445
- proc{:x > 1}.should_not raise_error
446
- proc{:x < true}.should raise_error(Sequel::Error)
447
- proc{:x >= false}.should raise_error(Sequel::Error)
448
- proc{:x <= nil}.should raise_error(Sequel::Error)
562
+ @d.lit(:x > 1).should == "(x > 1)"
563
+ @d.lit(:x < true).should == "(x < 't')"
564
+ @d.lit(:x >= false).should == "(x >= 'f')"
565
+ @d.lit(:x <= nil).should == "(x <= NULL)"
449
566
  end
450
567
 
451
568
  it "should not allow inequality operations on boolean complex expressions" do
452
- proc{:x > (:y > 5)}.should raise_error(Sequel::Error)
453
- proc{:x < (:y < 5)}.should raise_error(Sequel::Error)
454
- proc{:x >= (:y >= 5)}.should raise_error(Sequel::Error)
455
- proc{:x <= (:y <= 5)}.should raise_error(Sequel::Error)
456
- proc{:x > {:y => nil}}.should raise_error(Sequel::Error)
457
- proc{:x < ~{:y => nil}}.should raise_error(Sequel::Error)
458
- proc{:x >= {:y => 5}}.should raise_error(Sequel::Error)
459
- proc{:x <= ~{:y => 5}}.should raise_error(Sequel::Error)
460
- proc{:x >= {:y => [1,2,3]}}.should raise_error(Sequel::Error)
461
- proc{:x <= ~{:y => [1,2,3]}}.should raise_error(Sequel::Error)
569
+ @d.lit(:x > (:y > 5)).should == "(x > (y > 5))"
570
+ @d.lit(:x < (:y < 5)).should == "(x < (y < 5))"
571
+ @d.lit(:x >= (:y >= 5)).should == "(x >= (y >= 5))"
572
+ @d.lit(:x <= (:y <= 5)).should == "(x <= (y <= 5))"
573
+ @d.lit(:x > {:y => nil}).should == "(x > (y IS NULL))"
574
+ @d.lit(:x < ~{:y => nil}).should == "(x < (y IS NOT NULL))"
575
+ @d.lit(:x >= {:y => 5}).should == "(x >= (y = 5))"
576
+ @d.lit(:x <= ~{:y => 5}).should == "(x <= (y != 5))"
577
+ @d.lit(:x >= {:y => [1,2,3]}).should == "(x >= (y IN (1, 2, 3)))"
578
+ @d.lit(:x <= ~{:y => [1,2,3]}).should == "(x <= (y NOT IN (1, 2, 3)))"
462
579
  end
463
580
 
464
581
  it "should support >, <, >=, and <= via Symbol#>,<,>=,<=" do
@@ -553,7 +670,7 @@ describe Sequel::SQL::VirtualRow do
553
670
  end
554
671
 
555
672
  it "should support :frame=>:rows option for window function calls" do
556
- @d.l{rank(:over, :frame=>:rows){}}.should == 'rank() OVER (ROWS UNBOUNDED PRECEDING)'
673
+ @d.l{rank(:over, :frame=>:rows){}}.should == 'rank() OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)'
557
674
  end
558
675
 
559
676
  it "should support :frame=>'some string' option for window function calls" do
@@ -565,7 +682,7 @@ describe Sequel::SQL::VirtualRow do
565
682
  end
566
683
 
567
684
  it "should support all these options together" do
568
- @d.l{count(:over, :* =>true, :partition=>a, :order=>b, :window=>:win, :frame=>:rows){}}.should == 'count(*) OVER ("win" PARTITION BY "a" ORDER BY "b" ROWS UNBOUNDED PRECEDING)'
685
+ @d.l{count(:over, :* =>true, :partition=>a, :order=>b, :window=>:win, :frame=>:rows){}}.should == 'count(*) OVER ("win" PARTITION BY "a" ORDER BY "b" ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)'
569
686
  end
570
687
 
571
688
  it "should raise an error if window functions are not supported" do
@@ -0,0 +1,378 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ describe "Sequel Mock Adapter" do
4
+ specify "should have an adapter method" do
5
+ db = Sequel.mock
6
+ db.should be_a_kind_of(Sequel::Mock::Database)
7
+ db.adapter_scheme.should == :mock
8
+ end
9
+
10
+ specify "should each not return any rows by default" do
11
+ called = false
12
+ Sequel.mock[:t].each{|r| called = true}
13
+ called.should be_false
14
+ end
15
+
16
+ specify "should return 0 for update and delete by default" do
17
+ Sequel.mock[:t].update(:a=>1).should == 0
18
+ Sequel.mock[:t].delete.should == 0
19
+ end
20
+
21
+ specify "should return nil for insert by default" do
22
+ Sequel.mock[:t].insert(:a=>1).should be_nil
23
+ end
24
+
25
+ specify "should be able to set the rows returned by each using :fetch option with a single hash" do
26
+ rs = []
27
+ db = Sequel.mock(:fetch=>{:a=>1})
28
+ db[:t].each{|r| rs << r}
29
+ rs.should == [{:a=>1}]
30
+ db[:t].each{|r| rs << r}
31
+ rs.should == [{:a=>1}, {:a=>1}]
32
+ db[:t].each{|r| r[:a] = 2; rs << r}
33
+ rs.should == [{:a=>1}, {:a=>1}, {:a=>2}]
34
+ db[:t].each{|r| rs << r}
35
+ rs.should == [{:a=>1}, {:a=>1}, {:a=>2}, {:a=>1}]
36
+ end
37
+
38
+ specify "should be able to set the rows returned by each using :fetch option with an array of hashes" do
39
+ rs = []
40
+ db = Sequel.mock(:fetch=>[{:a=>1}, {:a=>2}])
41
+ db[:t].each{|r| rs << r}
42
+ rs.should == [{:a=>1}, {:a=>2}]
43
+ db[:t].each{|r| rs << r}
44
+ rs.should == [{:a=>1}, {:a=>2}, {:a=>1}, {:a=>2}]
45
+ db[:t].each{|r| r[:a] += 2; rs << r}
46
+ rs.should == [{:a=>1}, {:a=>2}, {:a=>1}, {:a=>2}, {:a=>3}, {:a=>4}]
47
+ db[:t].each{|r| rs << r}
48
+ rs.should == [{:a=>1}, {:a=>2}, {:a=>1}, {:a=>2}, {:a=>3}, {:a=>4}, {:a=>1}, {:a=>2}]
49
+ end
50
+
51
+ specify "should be able to set the rows returned by each using :fetch option with an array or arrays of hashes" do
52
+ rs = []
53
+ db = Sequel.mock(:fetch=>[[{:a=>1}, {:a=>2}], [{:a=>3}, {:a=>4}]])
54
+ db[:t].each{|r| rs << r}
55
+ rs.should == [{:a=>1}, {:a=>2}]
56
+ db[:t].each{|r| rs << r}
57
+ rs.should == [{:a=>1}, {:a=>2}, {:a=>3}, {:a=>4}]
58
+ db[:t].each{|r| rs << r}
59
+ rs.should == [{:a=>1}, {:a=>2}, {:a=>3}, {:a=>4}]
60
+ end
61
+
62
+ specify "should be able to set the rows returned by each using :fetch option with a proc that takes sql" do
63
+ rs = []
64
+ db = Sequel.mock(:fetch=>proc{|sql| sql =~ /FROM t/ ? {:b=>1} : [{:a=>1}, {:a=>2}]})
65
+ db[:t].each{|r| rs << r}
66
+ rs.should == [{:b=>1}]
67
+ db[:b].each{|r| rs << r}
68
+ rs.should == [{:b=>1}, {:a=>1}, {:a=>2}]
69
+ db[:t].each{|r| r[:b] += 1; rs << r}
70
+ db[:b].each{|r| r[:a] += 2; rs << r}
71
+ rs.should == [{:b=>1}, {:a=>1}, {:a=>2}, {:b=>2}, {:a=>3}, {:a=>4}]
72
+ db[:t].each{|r| rs << r}
73
+ db[:b].each{|r| rs << r}
74
+ rs.should == [{:b=>1}, {:a=>1}, {:a=>2}, {:b=>2}, {:a=>3}, {:a=>4}, {:b=>1}, {:a=>1}, {:a=>2}]
75
+ end
76
+
77
+ specify "should have a fetch= method for setting rows returned by each after the fact" do
78
+ rs = []
79
+ db = Sequel.mock
80
+ db.fetch = {:a=>1}
81
+ db[:t].each{|r| rs << r}
82
+ rs.should == [{:a=>1}]
83
+ db[:t].each{|r| rs << r}
84
+ rs.should == [{:a=>1}] * 2
85
+ end
86
+
87
+ specify "should be able to set an exception to raise by setting the :fetch option to an exception class " do
88
+ db = Sequel.mock(:fetch=>ArgumentError)
89
+ proc{db[:t].all}.should raise_error(Sequel::DatabaseError)
90
+ begin
91
+ db[:t].all
92
+ rescue => e
93
+ end
94
+ e.should be_a_kind_of(Sequel::DatabaseError)
95
+ e.wrapped_exception.should be_a_kind_of(ArgumentError)
96
+ end
97
+
98
+ specify "should be able to set separate kinds of results for fetch using an array" do
99
+ rs = []
100
+ db = Sequel.mock(:fetch=>[{:a=>1}, [{:a=>2}, {:a=>3}], proc{|s| {:a=>4}}, proc{|s| }, nil, ArgumentError])
101
+ db[:t].each{|r| rs << r}
102
+ rs.should == [{:a=>1}]
103
+ db[:t].each{|r| rs << r}
104
+ rs.should == [{:a=>1}, {:a=>2}, {:a=>3}]
105
+ db[:t].each{|r| rs << r}
106
+ rs.should == [{:a=>1}, {:a=>2}, {:a=>3}, {:a=>4}]
107
+ db[:t].each{|r| rs << r}
108
+ rs.should == [{:a=>1}, {:a=>2}, {:a=>3}, {:a=>4}]
109
+ db[:t].each{|r| rs << r}
110
+ rs.should == [{:a=>1}, {:a=>2}, {:a=>3}, {:a=>4}]
111
+ proc{db[:t].all}.should raise_error(Sequel::DatabaseError)
112
+ end
113
+
114
+ specify "should be able to set the rows returned by each on a per dataset basis using _fetch" do
115
+ rs = []
116
+ db = Sequel.mock(:fetch=>{:a=>1})
117
+ ds = db[:t]
118
+ ds.each{|r| rs << r}
119
+ rs.should == [{:a=>1}]
120
+ ds._fetch = {:b=>2}
121
+ ds.each{|r| rs << r}
122
+ rs.should == [{:a=>1}, {:b=>2}]
123
+ end
124
+
125
+ specify "should be able to set the number of rows modified by update and delete using :numrows option as an integer" do
126
+ db = Sequel.mock(:numrows=>2)
127
+ db[:t].update(:a=>1).should == 2
128
+ db[:t].delete.should == 2
129
+ db[:t].update(:a=>1).should == 2
130
+ db[:t].delete.should == 2
131
+ end
132
+
133
+ specify "should be able to set the number of rows modified by update and delete using :numrows option as an array of integers" do
134
+ db = Sequel.mock(:numrows=>[2, 1])
135
+ db[:t].update(:a=>1).should == 2
136
+ db[:t].delete.should == 1
137
+ db[:t].update(:a=>1).should == 0
138
+ db[:t].delete.should == 0
139
+ end
140
+
141
+ specify "should be able to set the number of rows modified by update and delete using :numrows option as a proc" do
142
+ db = Sequel.mock(:numrows=>proc{|sql| sql =~ / t/ ? 2 : 1})
143
+ db[:t].update(:a=>1).should == 2
144
+ db[:t].delete.should == 2
145
+ db[:b].update(:a=>1).should == 1
146
+ db[:b].delete.should == 1
147
+ end
148
+
149
+ specify "should be able to set an exception to raise by setting the :numrows option to an exception class " do
150
+ db = Sequel.mock(:numrows=>ArgumentError)
151
+ proc{db[:t].update(:a=>1)}.should raise_error(Sequel::DatabaseError)
152
+ begin
153
+ db[:t].delete
154
+ rescue => e
155
+ end
156
+ e.should be_a_kind_of(Sequel::DatabaseError)
157
+ e.wrapped_exception.should be_a_kind_of(ArgumentError)
158
+ end
159
+
160
+ specify "should be able to set separate kinds of results for numrows using an array" do
161
+ db = Sequel.mock(:numrows=>[1, proc{|s| 2}, nil, ArgumentError])
162
+ db[:t].delete.should == 1
163
+ db[:t].update(:a=>1).should == 2
164
+ db[:t].delete.should == 0
165
+ proc{db[:t].delete}.should raise_error(Sequel::DatabaseError)
166
+ end
167
+
168
+ specify "should have a numrows= method to set the number of rows modified by update and delete after the fact" do
169
+ db = Sequel.mock
170
+ db.numrows = 2
171
+ db[:t].update(:a=>1).should == 2
172
+ db[:t].delete.should == 2
173
+ db[:t].update(:a=>1).should == 2
174
+ db[:t].delete.should == 2
175
+ end
176
+
177
+ specify "should be able to set the number of rows modified by update and delete on a per dataset basis" do
178
+ db = Sequel.mock(:numrows=>2)
179
+ ds = db[:t]
180
+ ds.update(:a=>1).should == 2
181
+ ds.delete.should == 2
182
+ ds.numrows = 3
183
+ ds.update(:a=>1).should == 3
184
+ ds.delete.should == 3
185
+ end
186
+
187
+ specify "should be able to set the autogenerated primary key returned by insert using :autoid option as an integer" do
188
+ db = Sequel.mock(:autoid=>1)
189
+ db[:t].insert(:a=>1).should == 1
190
+ db[:t].insert(:a=>1).should == 2
191
+ db[:t].insert(:a=>1).should == 3
192
+ end
193
+
194
+ specify "should be able to set the autogenerated primary key returned by insert using :autoid option as an array of integers" do
195
+ db = Sequel.mock(:autoid=>[1, 3, 5])
196
+ db[:t].insert(:a=>1).should == 1
197
+ db[:t].insert(:a=>1).should == 3
198
+ db[:t].insert(:a=>1).should == 5
199
+ db[:t].insert(:a=>1).should be_nil
200
+ end
201
+
202
+ specify "should be able to set the autogenerated primary key returned by insert using :autoid option as a proc" do
203
+ db = Sequel.mock(:autoid=>proc{|sql| sql =~ /INTO t / ? 2 : 1})
204
+ db[:t].insert(:a=>1).should == 2
205
+ db[:t].insert(:a=>1).should == 2
206
+ db[:b].insert(:a=>1).should == 1
207
+ db[:b].insert(:a=>1).should == 1
208
+ end
209
+
210
+ specify "should be able to set an exception to raise by setting the :autoid option to an exception class " do
211
+ db = Sequel.mock(:autoid=>ArgumentError)
212
+ proc{db[:t].insert(:a=>1)}.should raise_error(Sequel::DatabaseError)
213
+ begin
214
+ db[:t].insert
215
+ rescue => e
216
+ end
217
+ e.should be_a_kind_of(Sequel::DatabaseError)
218
+ e.wrapped_exception.should be_a_kind_of(ArgumentError)
219
+ end
220
+
221
+ specify "should be able to set separate kinds of results for autoid using an array" do
222
+ db = Sequel.mock(:autoid=>[1, proc{|s| 2}, nil, ArgumentError])
223
+ db[:t].insert.should == 1
224
+ db[:t].insert.should == 2
225
+ db[:t].insert.should == nil
226
+ proc{db[:t].insert}.should raise_error(Sequel::DatabaseError)
227
+ end
228
+
229
+ specify "should have an autoid= method to set the autogenerated primary key returned by insert after the fact" do
230
+ db = Sequel.mock
231
+ db.autoid = 1
232
+ db[:t].insert(:a=>1).should == 1
233
+ db[:t].insert(:a=>1).should == 2
234
+ db[:t].insert(:a=>1).should == 3
235
+ end
236
+
237
+ specify "should be able to set the autogenerated primary key returned by insert on a per dataset basis" do
238
+ db = Sequel.mock(:autoid=>1)
239
+ ds = db[:t]
240
+ ds.insert(:a=>1).should == 1
241
+ ds.autoid = 5
242
+ ds.insert(:a=>1).should == 5
243
+ ds.insert(:a=>1).should == 6
244
+ db[:t].insert(:a=>1).should == 2
245
+ end
246
+
247
+ specify "should be able to set the columns to set in the dataset as an array of symbols" do
248
+ db = Sequel.mock(:columns=>[:a, :b])
249
+ db[:t].columns.should == [:a, :b]
250
+ db.sqls.should == ["SELECT * FROM t LIMIT 1"]
251
+ ds = db[:t]
252
+ ds.all
253
+ db.sqls.should == ["SELECT * FROM t"]
254
+ ds.columns.should == [:a, :b]
255
+ db.sqls.should == []
256
+ db[:t].columns.should == [:a, :b]
257
+ end
258
+
259
+ specify "should be able to set the columns to set in the dataset as an array of arrays of symbols" do
260
+ db = Sequel.mock(:columns=>[[:a, :b], [:c, :d]])
261
+ db[:t].columns.should == [:a, :b]
262
+ db[:t].columns.should == [:c, :d]
263
+ end
264
+
265
+ specify "should be able to set the columns to set in the dataset as a proc" do
266
+ db = Sequel.mock(:columns=>proc{|sql| (sql =~ / t/) ? [:a, :b] : [:c, :d]})
267
+ db[:b].columns.should == [:c, :d]
268
+ db[:t].columns.should == [:a, :b]
269
+ end
270
+
271
+ specify "should have a columns= method to set the columns to set after the fact" do
272
+ db = Sequel.mock
273
+ db.columns = [[:a, :b], [:c, :d]]
274
+ db[:t].columns.should == [:a, :b]
275
+ db[:t].columns.should == [:c, :d]
276
+ end
277
+
278
+ specify "should keep a record of all executed SQL in #sqls" do
279
+ db = Sequel.mock
280
+ db[:t].all
281
+ db[:b].delete
282
+ db[:c].insert(:a=>1)
283
+ db[:d].update(:a=>1)
284
+ db.sqls.should == ['SELECT * FROM t', 'DELETE FROM b', 'INSERT INTO c (a) VALUES (1)', 'UPDATE d SET a = 1']
285
+ end
286
+
287
+ specify "should clear sqls on retrieval" do
288
+ db = Sequel.mock
289
+ db[:t].all
290
+ db.sqls.should == ['SELECT * FROM t']
291
+ db.sqls.should == []
292
+ end
293
+
294
+ specify "should also log SQL executed to the given loggers" do
295
+ a = []
296
+ def a.method_missing(m, *x) push(*x) end
297
+ db = Sequel.mock(:loggers=>[a])
298
+ db[:t].all
299
+ db[:b].delete
300
+ db[:c].insert(:a=>1)
301
+ db[:d].update(:a=>1)
302
+ a.should == ['SELECT * FROM t', 'DELETE FROM b', 'INSERT INTO c (a) VALUES (1)', 'UPDATE d SET a = 1']
303
+ end
304
+
305
+ specify "should correctly handle transactions" do
306
+ db = Sequel.mock
307
+ db.transaction{db[:a].all}
308
+ db.sqls.should == ['BEGIN', 'SELECT * FROM a', 'COMMIT']
309
+ db.transaction{db[:a].all; raise Sequel::Rollback}
310
+ db.sqls.should == ['BEGIN', 'SELECT * FROM a', 'ROLLBACK']
311
+ proc{db.transaction{db[:a].all; raise ArgumentError}}.should raise_error(ArgumentError)
312
+ db.sqls.should == ['BEGIN', 'SELECT * FROM a', 'ROLLBACK']
313
+ proc{db.transaction(:rollback=>:reraise){db[:a].all; raise Sequel::Rollback}}.should raise_error(Sequel::Rollback)
314
+ db.sqls.should == ['BEGIN', 'SELECT * FROM a', 'ROLLBACK']
315
+ db.transaction(:rollback=>:always){db[:a].all}
316
+ db.sqls.should == ['BEGIN', 'SELECT * FROM a', 'ROLLBACK']
317
+ db.transaction{db.transaction{db[:a].all; raise Sequel::Rollback}}
318
+ db.sqls.should == ['BEGIN', 'SELECT * FROM a', 'ROLLBACK']
319
+ db.transaction{db.transaction(:savepoint=>true){db[:a].all; raise Sequel::Rollback}}
320
+ db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'SELECT * FROM a', 'ROLLBACK TO SAVEPOINT autopoint_1', 'COMMIT']
321
+ db.transaction{db.transaction(:savepoint=>true){db[:a].all}; raise Sequel::Rollback}
322
+ db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'SELECT * FROM a', 'RELEASE SAVEPOINT autopoint_1', 'ROLLBACK']
323
+ end
324
+
325
+ specify "should correctly handle transactions when sharding" do
326
+ db = Sequel.mock(:servers=>{:test=>{}})
327
+ db.transaction{db.transaction(:server=>:test){db[:a].all; db[:t].server(:test).all}}
328
+ db.sqls.should == ['BEGIN', 'BEGIN -- test', 'SELECT * FROM a', 'SELECT * FROM t -- test', 'COMMIT -- test', 'COMMIT']
329
+ end
330
+
331
+ specify "should yield a mock connection object from synchronize" do
332
+ c = Sequel.mock.synchronize{|conn| conn}
333
+ c.should be_a_kind_of(Sequel::Mock::Connection)
334
+ end
335
+
336
+ specify "should deal correctly with sharding" do
337
+ db = Sequel.mock(:servers=>{:test=>{}})
338
+ c1 = db.synchronize{|conn| conn}
339
+ c2 = db.synchronize(:test){|conn| conn}
340
+ c1.server.should == :default
341
+ c2.server.should == :test
342
+ end
343
+
344
+ specify "should disconnect correctly" do
345
+ db = Sequel.mock
346
+ db.test_connection
347
+ proc{db.disconnect}.should_not raise_error
348
+ end
349
+
350
+ specify "should accept :extend option for extending the object with a module" do
351
+ Sequel.mock(:extend=>Module.new{def foo(v) v * 2 end}).foo(3).should == 6
352
+ end
353
+
354
+ specify "should accept :sqls option for where to store the SQL queries" do
355
+ a = []
356
+ Sequel.mock(:sqls=>a)[:t].all
357
+ a.should == ['SELECT * FROM t']
358
+ end
359
+
360
+ specify "should include :append option in SQL if it is given" do
361
+ db = Sequel.mock(:append=>'a')
362
+ db[:t].all
363
+ db.sqls.should == ['SELECT * FROM t -- a']
364
+ end
365
+
366
+ specify "should append :arguments option to execute to the SQL if present" do
367
+ db = Sequel.mock
368
+ db.execute('SELECT * FROM t', :arguments=>[1, 2])
369
+ db.sqls.should == ['SELECT * FROM t -- args: [1, 2]']
370
+ end
371
+
372
+ specify "should have Dataset#columns take columns to set and return self" do
373
+ db = Sequel.mock
374
+ ds = db[:t].columns(:id, :a, :b)
375
+ ds.should be_a_kind_of(Sequel::Mock::Dataset)
376
+ ds.columns.should == [:id, :a, :b]
377
+ end
378
+ end