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.
- data/CHANGELOG +413 -3
- data/README.rdoc +20 -6
- data/Rakefile +23 -16
- data/bin/sequel +1 -5
- data/doc/association_basics.rdoc +210 -43
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/mass_assignment.rdoc +54 -0
- data/doc/migration.rdoc +15 -538
- data/doc/model_hooks.rdoc +72 -27
- data/doc/opening_databases.rdoc +86 -50
- data/doc/prepared_statements.rdoc +40 -13
- data/doc/reflection.rdoc +8 -2
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/schema_modification.rdoc +547 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +115 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/ado.rb +40 -18
- data/lib/sequel/adapters/amalgalite.rb +15 -7
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do/mysql.rb +0 -5
- data/lib/sequel/adapters/do/postgres.rb +0 -5
- data/lib/sequel/adapters/do/sqlite.rb +0 -5
- data/lib/sequel/adapters/do.rb +17 -36
- data/lib/sequel/adapters/firebird.rb +27 -208
- data/lib/sequel/adapters/ibmdb.rb +448 -0
- data/lib/sequel/adapters/informix.rb +6 -23
- data/lib/sequel/adapters/jdbc/as400.rb +5 -31
- data/lib/sequel/adapters/jdbc/db2.rb +44 -0
- data/lib/sequel/adapters/jdbc/derby.rb +217 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
- data/lib/sequel/adapters/jdbc/h2.rb +26 -17
- data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
- data/lib/sequel/adapters/jdbc/informix.rb +26 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
- data/lib/sequel/adapters/jdbc/mysql.rb +9 -10
- data/lib/sequel/adapters/jdbc/oracle.rb +67 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +6 -11
- data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
- data/lib/sequel/adapters/jdbc/sqlserver.rb +41 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +107 -38
- data/lib/sequel/adapters/mock.rb +315 -0
- data/lib/sequel/adapters/mysql.rb +78 -182
- data/lib/sequel/adapters/mysql2.rb +24 -23
- data/lib/sequel/adapters/odbc/db2.rb +17 -0
- data/lib/sequel/adapters/odbc/mssql.rb +0 -5
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +2 -4
- data/lib/sequel/adapters/oracle.rb +349 -51
- data/lib/sequel/adapters/postgres.rb +169 -21
- data/lib/sequel/adapters/shared/access.rb +21 -6
- data/lib/sequel/adapters/shared/db2.rb +288 -0
- data/lib/sequel/adapters/shared/firebird.rb +214 -0
- data/lib/sequel/adapters/shared/informix.rb +45 -0
- data/lib/sequel/adapters/shared/mssql.rb +108 -65
- data/lib/sequel/adapters/shared/mysql.rb +56 -13
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
- data/lib/sequel/adapters/shared/oracle.rb +185 -34
- data/lib/sequel/adapters/shared/postgres.rb +107 -58
- data/lib/sequel/adapters/shared/progress.rb +0 -6
- data/lib/sequel/adapters/shared/sqlite.rb +168 -41
- data/lib/sequel/adapters/sqlite.rb +27 -18
- data/lib/sequel/adapters/swift/mysql.rb +9 -5
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +6 -4
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/tinytds.rb +152 -17
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +63 -0
- data/lib/sequel/ast_transformer.rb +190 -0
- data/lib/sequel/connection_pool/threaded.rb +3 -2
- data/lib/sequel/connection_pool.rb +1 -1
- data/lib/sequel/core.rb +46 -5
- data/lib/sequel/database/connecting.rb +5 -6
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +59 -1
- data/lib/sequel/database/logging.rb +1 -1
- data/lib/sequel/database/misc.rb +100 -19
- data/lib/sequel/database/query.rb +153 -58
- data/lib/sequel/database/schema_generator.rb +8 -5
- data/lib/sequel/database/schema_methods.rb +59 -29
- data/lib/sequel/dataset/actions.rb +194 -57
- data/lib/sequel/dataset/features.rb +81 -8
- data/lib/sequel/dataset/graph.rb +8 -7
- data/lib/sequel/dataset/misc.rb +50 -23
- data/lib/sequel/dataset/mutation.rb +5 -6
- data/lib/sequel/dataset/prepared_statements.rb +32 -15
- data/lib/sequel/dataset/query.rb +223 -42
- data/lib/sequel/dataset/sql.rb +58 -61
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/extensions/migration.rb +6 -4
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +997 -331
- data/lib/sequel/model/base.rb +386 -129
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model.rb +15 -8
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +114 -7
- data/lib/sequel/plugins/many_through_many.rb +65 -7
- data/lib/sequel/plugins/prepared_statements.rb +151 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/serialization.rb +6 -1
- data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
- data/lib/sequel/plugins/sharding.rb +12 -25
- data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/xml_serializer.rb +3 -3
- data/lib/sequel/sql.rb +107 -51
- data/lib/sequel/timezones.rb +44 -35
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/mssql_spec.rb +65 -29
- data/spec/adapters/mysql_spec.rb +122 -123
- data/spec/adapters/oracle_spec.rb +48 -76
- data/spec/adapters/postgres_spec.rb +213 -61
- data/spec/adapters/spec_helper.rb +6 -5
- data/spec/adapters/sqlite_spec.rb +35 -21
- data/spec/core/connection_pool_spec.rb +71 -92
- data/spec/core/core_sql_spec.rb +20 -31
- data/spec/core/database_spec.rb +729 -508
- data/spec/core/dataset_spec.rb +980 -1044
- data/spec/core/expression_filters_spec.rb +159 -42
- data/spec/core/mock_adapter_spec.rb +378 -0
- data/spec/core/object_graph_spec.rb +48 -114
- data/spec/core/schema_generator_spec.rb +3 -3
- data/spec/core/schema_spec.rb +298 -38
- data/spec/core/spec_helper.rb +6 -48
- data/spec/extensions/association_pks_spec.rb +38 -0
- data/spec/extensions/class_table_inheritance_spec.rb +1 -1
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/identity_map_spec.rb +162 -0
- data/spec/extensions/instance_hooks_spec.rb +71 -0
- data/spec/extensions/many_through_many_spec.rb +195 -20
- data/spec/extensions/migration_spec.rb +17 -17
- data/spec/extensions/named_timezones_spec.rb +22 -2
- data/spec/extensions/nested_attributes_spec.rb +4 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +79 -0
- data/spec/extensions/prepared_statements_spec.rb +72 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
- data/spec/extensions/schema_dumper_spec.rb +2 -2
- data/spec/extensions/schema_spec.rb +13 -21
- data/spec/extensions/serialization_modification_detection_spec.rb +37 -0
- data/spec/extensions/serialization_spec.rb +5 -8
- data/spec/extensions/single_table_inheritance_spec.rb +11 -0
- data/spec/extensions/spec_helper.rb +7 -1
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/to_dot_spec.rb +3 -5
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/extensions/xml_serializer_spec.rb +16 -4
- data/spec/integration/associations_test.rb +522 -21
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +375 -62
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +304 -116
- data/spec/integration/prepared_statement_test.rb +200 -120
- data/spec/integration/schema_test.rb +161 -30
- data/spec/integration/spec_helper.rb +39 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +172 -5
- data/spec/integration/type_test.rb +17 -3
- data/spec/model/association_reflection_spec.rb +174 -7
- data/spec/model/associations_spec.rb +849 -661
- data/spec/model/base_spec.rb +255 -95
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +640 -676
- data/spec/model/hooks_spec.rb +309 -67
- data/spec/model/model_spec.rb +207 -167
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +321 -218
- data/spec/model/spec_helper.rb +13 -71
- data/spec/model/validations_spec.rb +11 -0
- 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
|
|
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
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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
|
|
386
|
-
|
|
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
|
|
390
|
-
|
|
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
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
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
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
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
|