sequel 3.21.0 → 3.28.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 +294 -0
- data/README.rdoc +20 -6
- data/Rakefile +20 -15
- 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 +64 -27
- data/doc/opening_databases.rdoc +37 -10
- data/doc/prepared_statements.rdoc +16 -10
- 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/schema_modification.rdoc +547 -0
- data/doc/testing.rdoc +106 -0
- data/doc/transactions.rdoc +97 -0
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/ado.rb +12 -1
- data/lib/sequel/adapters/amalgalite.rb +4 -0
- data/lib/sequel/adapters/db2.rb +95 -58
- data/lib/sequel/adapters/do.rb +12 -0
- data/lib/sequel/adapters/firebird.rb +25 -203
- data/lib/sequel/adapters/ibmdb.rb +440 -0
- data/lib/sequel/adapters/informix.rb +4 -19
- data/lib/sequel/adapters/jdbc/as400.rb +0 -7
- data/lib/sequel/adapters/jdbc/db2.rb +49 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +34 -0
- data/lib/sequel/adapters/jdbc/h2.rb +16 -5
- data/lib/sequel/adapters/jdbc/informix.rb +31 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
- data/lib/sequel/adapters/jdbc/mysql.rb +9 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +2 -27
- data/lib/sequel/adapters/jdbc/postgresql.rb +6 -0
- data/lib/sequel/adapters/jdbc/sqlserver.rb +46 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +34 -0
- data/lib/sequel/adapters/jdbc.rb +62 -29
- data/lib/sequel/adapters/mysql.rb +22 -139
- data/lib/sequel/adapters/mysql2.rb +9 -14
- data/lib/sequel/adapters/odbc/db2.rb +21 -0
- data/lib/sequel/adapters/odbc.rb +15 -3
- data/lib/sequel/adapters/oracle.rb +17 -1
- data/lib/sequel/adapters/postgres.rb +111 -16
- data/lib/sequel/adapters/shared/access.rb +21 -0
- data/lib/sequel/adapters/shared/db2.rb +290 -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 +85 -47
- data/lib/sequel/adapters/shared/mysql.rb +50 -7
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +143 -0
- data/lib/sequel/adapters/shared/oracle.rb +0 -4
- data/lib/sequel/adapters/shared/postgres.rb +75 -43
- data/lib/sequel/adapters/shared/sqlite.rb +56 -8
- data/lib/sequel/adapters/sqlite.rb +12 -11
- data/lib/sequel/adapters/swift/mysql.rb +9 -0
- data/lib/sequel/adapters/tinytds.rb +139 -7
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +55 -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 +6 -5
- data/lib/sequel/database/connecting.rb +5 -5
- data/lib/sequel/database/dataset.rb +1 -1
- data/lib/sequel/database/dataset_defaults.rb +1 -1
- data/lib/sequel/database/logging.rb +1 -1
- data/lib/sequel/database/misc.rb +38 -17
- data/lib/sequel/database/query.rb +50 -19
- data/lib/sequel/database/schema_generator.rb +8 -5
- data/lib/sequel/database/schema_methods.rb +52 -27
- data/lib/sequel/dataset/actions.rb +167 -48
- data/lib/sequel/dataset/features.rb +57 -8
- data/lib/sequel/dataset/graph.rb +1 -1
- data/lib/sequel/dataset/misc.rb +39 -20
- data/lib/sequel/dataset/mutation.rb +3 -3
- data/lib/sequel/dataset/prepared_statements.rb +29 -14
- data/lib/sequel/dataset/query.rb +182 -32
- data/lib/sequel/dataset/sql.rb +31 -58
- 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/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +893 -309
- data/lib/sequel/model/base.rb +302 -105
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model.rb +13 -7
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/identity_map.rb +113 -6
- data/lib/sequel/plugins/many_through_many.rb +67 -5
- data/lib/sequel/plugins/prepared_statements.rb +140 -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/serialization_modification_detection.rb +51 -0
- data/lib/sequel/plugins/sharding.rb +12 -20
- data/lib/sequel/plugins/single_table_inheritance.rb +2 -0
- data/lib/sequel/plugins/update_primary_key.rb +1 -1
- data/lib/sequel/plugins/xml_serializer.rb +3 -3
- data/lib/sequel/sql.rb +107 -51
- data/lib/sequel/timezones.rb +12 -3
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/mssql_spec.rb +36 -0
- data/spec/adapters/mysql_spec.rb +36 -19
- data/spec/adapters/postgres_spec.rb +115 -28
- data/spec/adapters/spec_helper.rb +6 -0
- data/spec/adapters/sqlite_spec.rb +11 -0
- data/spec/core/connection_pool_spec.rb +62 -77
- data/spec/core/database_spec.rb +244 -287
- data/spec/core/dataset_spec.rb +383 -34
- data/spec/core/expression_filters_spec.rb +159 -41
- data/spec/core/schema_spec.rb +326 -3
- data/spec/core/spec_helper.rb +45 -0
- data/spec/extensions/association_pks_spec.rb +38 -0
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/identity_map_spec.rb +162 -0
- data/spec/extensions/many_through_many_spec.rb +195 -20
- data/spec/extensions/migration_spec.rb +17 -17
- data/spec/extensions/nested_attributes_spec.rb +1 -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 +12 -20
- data/spec/extensions/serialization_modification_detection_spec.rb +36 -0
- data/spec/extensions/single_table_inheritance_spec.rb +11 -0
- data/spec/extensions/spec_helper.rb +3 -1
- data/spec/extensions/to_dot_spec.rb +3 -5
- data/spec/extensions/xml_serializer_spec.rb +16 -4
- data/spec/integration/associations_test.rb +405 -15
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +240 -20
- data/spec/integration/plugin_test.rb +142 -5
- data/spec/integration/prepared_statement_test.rb +174 -95
- data/spec/integration/schema_test.rb +128 -16
- data/spec/integration/spec_helper.rb +15 -0
- data/spec/integration/transaction_test.rb +40 -0
- data/spec/integration/type_test.rb +16 -2
- data/spec/model/association_reflection_spec.rb +91 -0
- data/spec/model/associations_spec.rb +476 -5
- data/spec/model/base_spec.rb +91 -1
- data/spec/model/eager_loading_spec.rb +519 -31
- data/spec/model/hooks_spec.rb +161 -0
- data/spec/model/model_spec.rb +89 -2
- data/spec/model/plugins_spec.rb +17 -0
- data/spec/model/record_spec.rb +184 -12
- data/spec/model/spec_helper.rb +5 -0
- data/spec/model/validations_spec.rb +11 -0
- metadata +85 -34
|
@@ -6,18 +6,21 @@ describe "Database schema parser" do
|
|
|
6
6
|
@iom = INTEGRATION_DB.identifier_output_method
|
|
7
7
|
@iim = INTEGRATION_DB.identifier_input_method
|
|
8
8
|
@defsch = INTEGRATION_DB.default_schema
|
|
9
|
+
@qi = INTEGRATION_DB.quote_identifiers?
|
|
9
10
|
clear_sqls
|
|
10
11
|
end
|
|
11
12
|
after do
|
|
12
13
|
INTEGRATION_DB.identifier_output_method = @iom
|
|
13
14
|
INTEGRATION_DB.identifier_input_method = @iim
|
|
14
15
|
INTEGRATION_DB.default_schema = @defsch
|
|
16
|
+
INTEGRATION_DB.quote_identifiers = @qi
|
|
15
17
|
INTEGRATION_DB.drop_table(:items) if INTEGRATION_DB.table_exists?(:items)
|
|
16
18
|
end
|
|
17
19
|
|
|
18
20
|
specify "should handle a database with a identifier_output_method" do
|
|
19
21
|
INTEGRATION_DB.identifier_output_method = :reverse
|
|
20
22
|
INTEGRATION_DB.identifier_input_method = :reverse
|
|
23
|
+
INTEGRATION_DB.quote_identifiers = true
|
|
21
24
|
INTEGRATION_DB.default_schema = nil if INTEGRATION_DB.default_schema
|
|
22
25
|
INTEGRATION_DB.create_table!(:items){Integer :number}
|
|
23
26
|
INTEGRATION_DB.schema(:items, :reload=>true).should be_a_kind_of(Array)
|
|
@@ -85,7 +88,7 @@ describe "Database schema parser" do
|
|
|
85
88
|
INTEGRATION_DB.schema(:items).first.last[:ruby_default].should == 'blah'
|
|
86
89
|
end
|
|
87
90
|
|
|
88
|
-
|
|
91
|
+
cspecify "should parse types from the schema properly", [:jdbc, :db2] do
|
|
89
92
|
INTEGRATION_DB.create_table!(:items){Integer :number}
|
|
90
93
|
INTEGRATION_DB.schema(:items).first.last[:type].should == :integer
|
|
91
94
|
INTEGRATION_DB.create_table!(:items){Fixnum :number}
|
|
@@ -174,6 +177,24 @@ describe "Database schema modifiers" do
|
|
|
174
177
|
@db.create_table!(:items, :temp=>true){Integer :number}
|
|
175
178
|
end
|
|
176
179
|
|
|
180
|
+
specify "should have create_table? only create the table if it doesn't already exist" do
|
|
181
|
+
@db.create_table!(:items){String :a}
|
|
182
|
+
@db.create_table?(:items){String :b}
|
|
183
|
+
@db[:items].columns.should == [:a]
|
|
184
|
+
@db.drop_table(:items) rescue nil
|
|
185
|
+
@db.create_table?(:items){String :b}
|
|
186
|
+
@db[:items].columns.should == [:b]
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
specify "should have create_table? work correctly with indexes" do
|
|
190
|
+
@db.create_table!(:items){String :a, :index=>true}
|
|
191
|
+
@db.create_table?(:items){String :b, :index=>true}
|
|
192
|
+
@db[:items].columns.should == [:a]
|
|
193
|
+
@db.drop_table(:items) rescue nil
|
|
194
|
+
@db.create_table?(:items){String :b, :index=>true}
|
|
195
|
+
@db[:items].columns.should == [:b]
|
|
196
|
+
end
|
|
197
|
+
|
|
177
198
|
specify "should rename tables correctly" do
|
|
178
199
|
@db.drop_table(:items) rescue nil
|
|
179
200
|
@db.create_table!(:items2){Integer :number}
|
|
@@ -215,7 +236,7 @@ describe "Database schema modifiers" do
|
|
|
215
236
|
specify "should add columns to tables correctly" do
|
|
216
237
|
@db.create_table!(:items){Integer :number}
|
|
217
238
|
@ds.insert(:number=>10)
|
|
218
|
-
@db.alter_table(:items){add_column :name,
|
|
239
|
+
@db.alter_table(:items){add_column :name, String}
|
|
219
240
|
@db.schema(:items, :reload=>true).map{|x| x.first}.should == [:number, :name]
|
|
220
241
|
@ds.columns!.should == [:number, :name]
|
|
221
242
|
@ds.all.should == [{:number=>10, :name=>nil}]
|
|
@@ -228,6 +249,15 @@ describe "Database schema modifiers" do
|
|
|
228
249
|
@db.schema(:items, :reload=>true).map{|x| x.first}.should == [:number, :id]
|
|
229
250
|
@ds.columns!.should == [:number, :id]
|
|
230
251
|
@ds.map(:number).should == [10]
|
|
252
|
+
proc{@ds.insert(:id=>@ds.map(:id).first)}.should raise_error
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
cspecify "should drop primary key constraints from tables correctly", :sqlite do
|
|
256
|
+
@db.create_table!(:items){Integer :number; primary_key [:number], :name=>:items_pk}
|
|
257
|
+
@ds.insert(:number=>10)
|
|
258
|
+
@db.alter_table(:items){drop_constraint :items_pk, :type=>:primary_key}
|
|
259
|
+
@ds.map(:number).should == [10]
|
|
260
|
+
proc{@ds.insert(10)}.should_not raise_error
|
|
231
261
|
end
|
|
232
262
|
|
|
233
263
|
specify "should add foreign key columns to tables correctly" do
|
|
@@ -269,7 +299,7 @@ describe "Database schema modifiers" do
|
|
|
269
299
|
proc{@ds.insert(:n=>nil)}.should raise_error(Sequel::DatabaseError)
|
|
270
300
|
end
|
|
271
301
|
|
|
272
|
-
|
|
302
|
+
cspecify "should set column NULL/NOT NULL correctly", [:jdbc, :db2] do
|
|
273
303
|
@db.create_table!(:items, :engine=>:InnoDB){Integer :id}
|
|
274
304
|
@ds.insert(:id=>10)
|
|
275
305
|
@db.alter_table(:items){set_column_allow_null :id, false}
|
|
@@ -291,7 +321,7 @@ describe "Database schema modifiers" do
|
|
|
291
321
|
@ds.all.should == [{:id=>10}, {:id=>20}]
|
|
292
322
|
end
|
|
293
323
|
|
|
294
|
-
|
|
324
|
+
cspecify "should set column types correctly", [:jdbc, :db2] do
|
|
295
325
|
@db.create_table!(:items){Integer :id}
|
|
296
326
|
@ds.insert(:id=>10)
|
|
297
327
|
@db.alter_table(:items){set_column_type :id, String}
|
|
@@ -301,17 +331,50 @@ describe "Database schema modifiers" do
|
|
|
301
331
|
@ds.all.should == [{:id=>"10"}, {:id=>"20"}]
|
|
302
332
|
end
|
|
303
333
|
|
|
304
|
-
cspecify "should add unique constraints and foreign key table constraints correctly", :sqlite do
|
|
305
|
-
@db.create_table!(:items){Integer :id; Integer :item_id}
|
|
334
|
+
cspecify "should add unnamed unique constraints and foreign key table constraints correctly", :sqlite do
|
|
335
|
+
@db.create_table!(:items, :engine=>:InnoDB){Integer :id; Integer :item_id}
|
|
306
336
|
@db.alter_table(:items) do
|
|
307
337
|
add_unique_constraint [:item_id, :id]
|
|
308
338
|
add_foreign_key [:id, :item_id], :items, :key=>[:item_id, :id]
|
|
309
339
|
end
|
|
310
340
|
@db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :item_id]
|
|
311
341
|
@ds.columns!.should == [:id, :item_id]
|
|
342
|
+
proc{@ds.insert(1, 1)}.should_not raise_error
|
|
343
|
+
proc{@ds.insert(1, 1)}.should raise_error
|
|
344
|
+
proc{@ds.insert(1, 2)}.should raise_error
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
cspecify "should add named unique constraints and foreign key table constraints correctly", :sqlite do
|
|
348
|
+
@db.create_table!(:items, :engine=>:InnoDB){Integer :id, :null=>false; Integer :item_id, :null=>false}
|
|
349
|
+
@db.alter_table(:items) do
|
|
350
|
+
add_unique_constraint [:item_id, :id], :name=>:unique_iii
|
|
351
|
+
add_foreign_key [:id, :item_id], :items, :key=>[:item_id, :id], :name=>:fk_iii
|
|
352
|
+
end
|
|
353
|
+
@db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :item_id]
|
|
354
|
+
@ds.columns!.should == [:id, :item_id]
|
|
355
|
+
proc{@ds.insert(1, 1)}.should_not raise_error
|
|
356
|
+
proc{@ds.insert(1, 1)}.should raise_error
|
|
357
|
+
proc{@ds.insert(1, 2)}.should raise_error
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
cspecify "should drop unique constraints and foreign key table constraints correctly", :sqlite do
|
|
361
|
+
@db.create_table!(:items) do
|
|
362
|
+
Integer :id
|
|
363
|
+
Integer :item_id
|
|
364
|
+
unique [:item_id, :id], :name=>:items_uk
|
|
365
|
+
foreign_key [:id, :item_id], :items, :key=>[:item_id, :id], :name=>:items_fk
|
|
366
|
+
end
|
|
367
|
+
@db.alter_table(:items) do
|
|
368
|
+
drop_constraint(:items_fk, :type=>:foreign_key)
|
|
369
|
+
drop_constraint(:items_uk, :type=>:unique)
|
|
370
|
+
end
|
|
371
|
+
@db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :item_id]
|
|
372
|
+
@ds.columns!.should == [:id, :item_id]
|
|
373
|
+
proc{@ds.insert(1, 2)}.should_not raise_error
|
|
374
|
+
proc{@ds.insert(1, 2)}.should_not raise_error
|
|
312
375
|
end
|
|
313
376
|
|
|
314
|
-
cspecify "should remove columns from tables correctly", :h2, :mssql do
|
|
377
|
+
cspecify "should remove columns from tables correctly", :h2, :mssql, [:jdbc, :db2] do
|
|
315
378
|
@db.create_table!(:items) do
|
|
316
379
|
primary_key :id
|
|
317
380
|
String :name
|
|
@@ -332,7 +395,7 @@ describe "Database schema modifiers" do
|
|
|
332
395
|
@ds.columns!.should == [:id]
|
|
333
396
|
end
|
|
334
397
|
|
|
335
|
-
|
|
398
|
+
cspecify "should remove multiple columns in a single alter_table block", [:jdbc, :db2] do
|
|
336
399
|
@db.create_table!(:items) do
|
|
337
400
|
primary_key :id
|
|
338
401
|
String :name
|
|
@@ -362,25 +425,74 @@ describe "Database#tables" do
|
|
|
362
425
|
"xxxxx#{@@xxxxx += 1}"
|
|
363
426
|
end
|
|
364
427
|
end
|
|
365
|
-
@
|
|
366
|
-
@
|
|
428
|
+
@db = INTEGRATION_DB
|
|
429
|
+
@db.create_table(:sequel_test_table){Integer :a}
|
|
430
|
+
@db.create_view :sequel_test_view, @db[:sequel_test_table]
|
|
431
|
+
@iom = @db.identifier_output_method
|
|
432
|
+
@iim = @db.identifier_input_method
|
|
367
433
|
clear_sqls
|
|
368
434
|
end
|
|
369
435
|
after do
|
|
370
|
-
|
|
371
|
-
|
|
436
|
+
@db.identifier_output_method = @iom
|
|
437
|
+
@db.identifier_input_method = @iim
|
|
438
|
+
@db.drop_view :sequel_test_view
|
|
439
|
+
@db.drop_table :sequel_test_table
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
specify "should return an array of symbols" do
|
|
443
|
+
ts = @db.tables
|
|
444
|
+
ts.should be_a_kind_of(Array)
|
|
445
|
+
ts.each{|t| t.should be_a_kind_of(Symbol)}
|
|
446
|
+
ts.should include(:sequel_test_table)
|
|
447
|
+
ts.should_not include(:sequel_test_view)
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
specify "should respect the database's identifier_output_method" do
|
|
451
|
+
@db.identifier_output_method = :xxxxx
|
|
452
|
+
@db.identifier_input_method = :xxxxx
|
|
453
|
+
@db.tables.each{|t| t.to_s.should =~ /\Ax{5}\d+\z/}
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
begin
|
|
459
|
+
INTEGRATION_DB.views
|
|
460
|
+
rescue Sequel::NotImplemented
|
|
461
|
+
rescue
|
|
462
|
+
describe "Database#views" do
|
|
463
|
+
before do
|
|
464
|
+
class ::String
|
|
465
|
+
@@xxxxx = 0
|
|
466
|
+
def xxxxx
|
|
467
|
+
"xxxxx#{@@xxxxx += 1}"
|
|
468
|
+
end
|
|
469
|
+
end
|
|
470
|
+
@db = INTEGRATION_DB
|
|
471
|
+
@db.create_table(:sequel_test_table){Integer :a}
|
|
472
|
+
@db.create_view :sequel_test_view, @db[:sequel_test_table]
|
|
473
|
+
@iom = @db.identifier_output_method
|
|
474
|
+
@iim = @db.identifier_input_method
|
|
475
|
+
clear_sqls
|
|
476
|
+
end
|
|
477
|
+
after do
|
|
478
|
+
@db.identifier_output_method = @iom
|
|
479
|
+
@db.identifier_input_method = @iim
|
|
480
|
+
@db.drop_view :sequel_test_view
|
|
481
|
+
@db.drop_table :sequel_test_table
|
|
372
482
|
end
|
|
373
483
|
|
|
374
484
|
specify "should return an array of symbols" do
|
|
375
|
-
ts =
|
|
485
|
+
ts = @db.views
|
|
376
486
|
ts.should be_a_kind_of(Array)
|
|
377
487
|
ts.each{|t| t.should be_a_kind_of(Symbol)}
|
|
488
|
+
ts.should_not include(:sequel_test_table)
|
|
489
|
+
ts.should include(:sequel_test_view)
|
|
378
490
|
end
|
|
379
491
|
|
|
380
492
|
specify "should respect the database's identifier_output_method" do
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
493
|
+
@db.identifier_output_method = :xxxxx
|
|
494
|
+
@db.identifier_input_method = :xxxxx
|
|
495
|
+
@db.views.each{|t| t.to_s.should =~ /\Ax{5}\d+\z/}
|
|
384
496
|
end
|
|
385
497
|
end
|
|
386
498
|
end
|
|
@@ -9,6 +9,11 @@ begin
|
|
|
9
9
|
rescue LoadError
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
+
if ENV['SEQUEL_COLUMNS_INTROSPECTION']
|
|
13
|
+
Sequel.extension :columns_introspection
|
|
14
|
+
Sequel::Dataset.introspect_all_columns
|
|
15
|
+
end
|
|
16
|
+
|
|
12
17
|
Sequel::Model.use_transactions = false
|
|
13
18
|
|
|
14
19
|
$sqls = []
|
|
@@ -44,6 +49,7 @@ end
|
|
|
44
49
|
end
|
|
45
50
|
|
|
46
51
|
def self.cspecify(message, *checked, &block)
|
|
52
|
+
return specify(message, &block) if ENV['SEQUEL_NO_PENDING']
|
|
47
53
|
pending = false
|
|
48
54
|
checked.each do |c|
|
|
49
55
|
case c
|
|
@@ -84,3 +90,12 @@ if defined?(INTEGRATION_DB) || defined?(INTEGRATION_URL) || ENV['SEQUEL_INTEGRAT
|
|
|
84
90
|
else
|
|
85
91
|
INTEGRATION_DB = Sequel.sqlite('', :quote_identifiers=>false)
|
|
86
92
|
end
|
|
93
|
+
|
|
94
|
+
if INTEGRATION_DB.adapter_scheme == :ibmdb
|
|
95
|
+
def INTEGRATION_DB.drop_table(*tables)
|
|
96
|
+
super
|
|
97
|
+
rescue Sequel::DatabaseError
|
|
98
|
+
disconnect
|
|
99
|
+
super
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -134,4 +134,44 @@ describe "Database transactions" do
|
|
|
134
134
|
@d.count.should == i + 1
|
|
135
135
|
end
|
|
136
136
|
end
|
|
137
|
+
|
|
138
|
+
if (! defined?(RUBY_ENGINE) or RUBY_ENGINE == 'ruby' or (RUBY_ENGINE == 'rbx' && ![[:do, :sqlite], [:tinytds, :mssql]].include?([INTEGRATION_DB.adapter_scheme, INTEGRATION_DB.database_type]))) and RUBY_VERSION < '1.9'
|
|
139
|
+
specify "should handle Thread#kill for transactions inside threads" do
|
|
140
|
+
q = Queue.new
|
|
141
|
+
q1 = Queue.new
|
|
142
|
+
t = Thread.new do
|
|
143
|
+
@db.transaction do
|
|
144
|
+
@d << {:name => 'abc', :value => 1}
|
|
145
|
+
q1.push nil
|
|
146
|
+
q.pop
|
|
147
|
+
@d << {:name => 'def', :value => 2}
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
q1.pop
|
|
151
|
+
t.kill
|
|
152
|
+
@d.count.should == 0
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
if INTEGRATION_DB.supports_savepoints?
|
|
156
|
+
specify "should handle Thread#kill for transactions with savepoints inside threads" do
|
|
157
|
+
q = Queue.new
|
|
158
|
+
q1 = Queue.new
|
|
159
|
+
t = Thread.new do
|
|
160
|
+
@db.transaction do
|
|
161
|
+
@d << {:name => 'abc', :value => 1}
|
|
162
|
+
@db.transaction(:savepoint=>true) do
|
|
163
|
+
@d << {:name => 'def', :value => 2}
|
|
164
|
+
q1.push nil
|
|
165
|
+
q.pop
|
|
166
|
+
@d << {:name => 'ghi', :value => 3}
|
|
167
|
+
end
|
|
168
|
+
@d << {:name => 'jkl', :value => 4}
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
q1.pop
|
|
172
|
+
t.kill
|
|
173
|
+
@d.count.should == 0
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
137
177
|
end
|
|
@@ -6,7 +6,7 @@ describe "Supported types" do
|
|
|
6
6
|
INTEGRATION_DB[:items]
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
specify "should support casting correctly" do
|
|
10
10
|
ds = create_items_table_with_column(:number, Integer)
|
|
11
11
|
ds.insert(:number => 1)
|
|
12
12
|
ds.select(:number.cast_string.as(:n)).map(:n).should == %w'1'
|
|
@@ -68,6 +68,20 @@ describe "Supported types" do
|
|
|
68
68
|
ds.first[:dat].to_s.should == d.to_s
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
+
cspecify "should support generic time type", [:do], [:swift], [:odbc], [:jdbc, :mssql], [:jdbc, :postgres], [:mysql2], [:tinytds] do
|
|
72
|
+
ds = create_items_table_with_column(:tim, Time, :only_time=>true)
|
|
73
|
+
t = Sequel::SQLTime.now
|
|
74
|
+
ds.insert(:tim => t)
|
|
75
|
+
v = ds.first[:tim]
|
|
76
|
+
ds.literal(v).should == ds.literal(t)
|
|
77
|
+
v.should be_a_kind_of(Sequel::SQLTime)
|
|
78
|
+
ds.delete
|
|
79
|
+
ds.insert(:tim => v)
|
|
80
|
+
v2 = ds.first[:tim]
|
|
81
|
+
ds.literal(v2).should == ds.literal(t)
|
|
82
|
+
v2.should be_a_kind_of(Sequel::SQLTime)
|
|
83
|
+
end
|
|
84
|
+
|
|
71
85
|
cspecify "should support generic datetime type", [:do, :sqlite], [:jdbc, :sqlite] do
|
|
72
86
|
ds = create_items_table_with_column(:tim, DateTime)
|
|
73
87
|
t = DateTime.now
|
|
@@ -86,7 +100,7 @@ describe "Supported types" do
|
|
|
86
100
|
ds.first[:name].should be_a_kind_of(::Sequel::SQL::Blob)
|
|
87
101
|
end
|
|
88
102
|
|
|
89
|
-
cspecify "should support generic boolean type", [:do, :sqlite], [:jdbc, :sqlite], [:odbc, :mssql] do
|
|
103
|
+
cspecify "should support generic boolean type", [:do, :sqlite], [:jdbc, :sqlite], [:jdbc, :db2], [:odbc, :mssql] do
|
|
90
104
|
ds = create_items_table_with_column(:number, TrueClass)
|
|
91
105
|
ds.insert(:number => true)
|
|
92
106
|
ds.all.should == [{:number=>true}]
|
|
@@ -184,6 +184,7 @@ describe Sequel::Model::Associations::AssociationReflection, "#remove_before_des
|
|
|
184
184
|
@c.many_to_many :cs, :class=>@c
|
|
185
185
|
@c.association_reflection(:cs).remove_before_destroy?.should be_true
|
|
186
186
|
end
|
|
187
|
+
|
|
187
188
|
it "should be false for one_to_one and one_to_many associations" do
|
|
188
189
|
@c.one_to_one :c, :class=>@c
|
|
189
190
|
@c.association_reflection(:c).remove_before_destroy?.should be_false
|
|
@@ -192,3 +193,93 @@ describe Sequel::Model::Associations::AssociationReflection, "#remove_before_des
|
|
|
192
193
|
end
|
|
193
194
|
end
|
|
194
195
|
|
|
196
|
+
describe Sequel::Model::Associations::AssociationReflection, "#eager_limit_strategy" do
|
|
197
|
+
before do
|
|
198
|
+
@c = Class.new(Sequel::Model(:a))
|
|
199
|
+
end
|
|
200
|
+
after do
|
|
201
|
+
Sequel::Model.default_eager_limit_strategy = nil
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
it "should be nil by default for *_one associations" do
|
|
205
|
+
@c.many_to_one :c, :class=>@c
|
|
206
|
+
@c.association_reflection(:c).eager_limit_strategy.should be_nil
|
|
207
|
+
@c.one_to_one :c, :class=>@c
|
|
208
|
+
@c.association_reflection(:c).eager_limit_strategy.should be_nil
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
it "should be :ruby by default for *_many associations" do
|
|
212
|
+
@c.one_to_many :cs, :class=>@c, :limit=>1
|
|
213
|
+
@c.association_reflection(:cs).eager_limit_strategy.should == :ruby
|
|
214
|
+
@c.many_to_many :cs, :class=>@c, :limit=>1
|
|
215
|
+
@c.association_reflection(:cs).eager_limit_strategy.should == :ruby
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
it "should be nil for many_to_one associations" do
|
|
219
|
+
@c.many_to_one :c, :class=>@c, :eager_limit_strategy=>true
|
|
220
|
+
@c.association_reflection(:c).eager_limit_strategy.should be_nil
|
|
221
|
+
@c.many_to_one :c, :class=>@c, :eager_limit_strategy=>:distinct_on
|
|
222
|
+
@c.association_reflection(:c).eager_limit_strategy.should be_nil
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
it "should be a symbol for other associations if given a symbol" do
|
|
226
|
+
@c.one_to_one :c, :class=>@c, :eager_limit_strategy=>:distinct_on
|
|
227
|
+
@c.association_reflection(:c).eager_limit_strategy.should == :distinct_on
|
|
228
|
+
@c.one_to_many :cs, :class=>@c, :eager_limit_strategy=>:window_function, :limit=>1
|
|
229
|
+
@c.association_reflection(:cs).eager_limit_strategy.should == :window_function
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
it "should use :distinct_on for one_to_one associations if picking and the association dataset supports ordered distinct on" do
|
|
233
|
+
@c.dataset.meta_def(:supports_ordered_distinct_on?){true}
|
|
234
|
+
@c.one_to_one :c, :class=>@c, :eager_limit_strategy=>true
|
|
235
|
+
@c.association_reflection(:c).eager_limit_strategy.should == :distinct_on
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
it "should use :window_function for associations if picking and the association dataset supports window functions" do
|
|
239
|
+
@c.dataset.meta_def(:supports_window_functions?){true}
|
|
240
|
+
@c.one_to_one :c, :class=>@c, :eager_limit_strategy=>true
|
|
241
|
+
@c.association_reflection(:c).eager_limit_strategy.should == :window_function
|
|
242
|
+
@c.one_to_many :cs, :class=>@c, :eager_limit_strategy=>true, :limit=>1
|
|
243
|
+
@c.association_reflection(:cs).eager_limit_strategy.should == :window_function
|
|
244
|
+
@c.many_to_many :cs, :class=>@c, :eager_limit_strategy=>true, :limit=>1
|
|
245
|
+
@c.association_reflection(:cs).eager_limit_strategy.should == :window_function
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
it "should use :ruby for *_many associations if picking and the association dataset doesn't window functions" do
|
|
249
|
+
@c.one_to_many :cs, :class=>@c, :eager_limit_strategy=>true, :limit=>1
|
|
250
|
+
@c.association_reflection(:cs).eager_limit_strategy.should == :ruby
|
|
251
|
+
@c.many_to_many :cs, :class=>@c, :eager_limit_strategy=>true, :limit=>1
|
|
252
|
+
@c.association_reflection(:cs).eager_limit_strategy.should == :ruby
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
it "should respect Model.default_eager_limit_strategy to *_many associations" do
|
|
256
|
+
Sequel::Model.default_eager_limit_strategy = :window_function
|
|
257
|
+
Sequel::Model.default_eager_limit_strategy.should == :window_function
|
|
258
|
+
c = Class.new(Sequel::Model)
|
|
259
|
+
c.dataset = :a
|
|
260
|
+
c.default_eager_limit_strategy.should == :window_function
|
|
261
|
+
c.one_to_many :cs, :class=>c, :limit=>1
|
|
262
|
+
c.association_reflection(:cs).eager_limit_strategy.should == :window_function
|
|
263
|
+
c.many_to_many :cs, :class=>c, :limit=>1
|
|
264
|
+
c.association_reflection(:cs).eager_limit_strategy.should == :window_function
|
|
265
|
+
|
|
266
|
+
Sequel::Model.default_eager_limit_strategy = true
|
|
267
|
+
c = Class.new(Sequel::Model)
|
|
268
|
+
c.dataset = :a
|
|
269
|
+
c.one_to_many :cs, :class=>c, :limit=>1
|
|
270
|
+
c.association_reflection(:cs).eager_limit_strategy.should == :ruby
|
|
271
|
+
c.dataset.meta_def(:supports_window_functions?){true}
|
|
272
|
+
c.many_to_many :cs, :class=>c, :limit=>1
|
|
273
|
+
c.association_reflection(:cs).eager_limit_strategy.should == :window_function
|
|
274
|
+
|
|
275
|
+
c.default_eager_limit_strategy = :correlated_subquery
|
|
276
|
+
c.many_to_many :cs, :class=>c, :limit=>1
|
|
277
|
+
c.association_reflection(:cs).eager_limit_strategy.should == :correlated_subquery
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
it "should ignore Model.default_eager_limit_strategy for one_to_one associations" do
|
|
281
|
+
@c.default_eager_limit_strategy = :correlated_subquery
|
|
282
|
+
@c.one_to_one :c, :class=>@c
|
|
283
|
+
@c.association_reflection(:c).eager_limit_strategy.should be_nil
|
|
284
|
+
end
|
|
285
|
+
end
|