sequel 3.21.0 → 3.31.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 +485 -3
- data/README.rdoc +20 -6
- data/Rakefile +37 -19
- data/bin/sequel +1 -5
- data/doc/association_basics.rdoc +249 -43
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/dataset_filtering.rdoc +8 -0
- 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 +89 -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/release_notes/3.30.0.txt +135 -0
- data/doc/release_notes/3.31.0.txt +146 -0
- data/doc/schema_modification.rdoc +547 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +129 -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 +17 -9
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do/mysql.rb +5 -7
- 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 +16 -34
- data/lib/sequel/adapters/jdbc/db2.rb +45 -0
- data/lib/sequel/adapters/jdbc/derby.rb +247 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
- data/lib/sequel/adapters/jdbc/h2.rb +56 -29
- data/lib/sequel/adapters/jdbc/hsqldb.rb +170 -0
- data/lib/sequel/adapters/jdbc/informix.rb +26 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +11 -11
- data/lib/sequel/adapters/jdbc/oracle.rb +81 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +9 -13
- data/lib/sequel/adapters/jdbc/sqlite.rb +2 -6
- data/lib/sequel/adapters/jdbc/sqlserver.rb +71 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +231 -78
- data/lib/sequel/adapters/mock.rb +335 -0
- data/lib/sequel/adapters/mysql.rb +82 -184
- data/lib/sequel/adapters/mysql2.rb +26 -25
- data/lib/sequel/adapters/odbc/db2.rb +17 -0
- data/lib/sequel/adapters/odbc/mssql.rb +1 -6
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +3 -5
- data/lib/sequel/adapters/oracle.rb +351 -53
- data/lib/sequel/adapters/postgres.rb +194 -33
- data/lib/sequel/adapters/shared/access.rb +32 -9
- data/lib/sequel/adapters/shared/db2.rb +321 -0
- data/lib/sequel/adapters/shared/firebird.rb +221 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +231 -106
- data/lib/sequel/adapters/shared/mysql.rb +181 -63
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
- data/lib/sequel/adapters/shared/oracle.rb +231 -41
- data/lib/sequel/adapters/shared/postgres.rb +214 -82
- data/lib/sequel/adapters/shared/progress.rb +4 -7
- data/lib/sequel/adapters/shared/sqlite.rb +201 -57
- data/lib/sequel/adapters/sqlite.rb +29 -21
- data/lib/sequel/adapters/swift/mysql.rb +12 -7
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +8 -6
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/tinytds.rb +160 -19
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- 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 +104 -19
- data/lib/sequel/database/query.rb +153 -58
- data/lib/sequel/database/schema_generator.rb +17 -7
- data/lib/sequel/database/schema_methods.rb +59 -29
- data/lib/sequel/dataset/actions.rb +231 -76
- data/lib/sequel/dataset/features.rb +91 -8
- data/lib/sequel/dataset/graph.rb +38 -11
- data/lib/sequel/dataset/misc.rb +50 -23
- data/lib/sequel/dataset/mutation.rb +5 -6
- data/lib/sequel/dataset/prepared_statements.rb +48 -27
- data/lib/sequel/dataset/query.rb +236 -43
- data/lib/sequel/dataset/sql.rb +665 -253
- 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 +1020 -337
- data/lib/sequel/model/base.rb +414 -132
- 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 +88 -44
- data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
- data/lib/sequel/plugins/sharding.rb +21 -54
- 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 +109 -52
- data/lib/sequel/timezones.rb +57 -38
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/mssql_spec.rb +111 -29
- data/spec/adapters/mysql_spec.rb +135 -123
- data/spec/adapters/oracle_spec.rb +49 -77
- data/spec/adapters/postgres_spec.rb +267 -78
- 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 +21 -30
- data/spec/core/database_spec.rb +788 -512
- data/spec/core/dataset_spec.rb +1073 -1053
- data/spec/core/expression_filters_spec.rb +159 -42
- data/spec/core/mock_adapter_spec.rb +419 -0
- data/spec/core/object_graph_spec.rb +86 -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_autoreloading_spec.rb +1 -10
- data/spec/extensions/association_dependencies_spec.rb +2 -12
- data/spec/extensions/association_pks_spec.rb +66 -32
- data/spec/extensions/caching_spec.rb +23 -50
- data/spec/extensions/class_table_inheritance_spec.rb +31 -83
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/composition_spec.rb +18 -13
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/hook_class_methods_spec.rb +65 -91
- data/spec/extensions/identity_map_spec.rb +114 -22
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +53 -0
- data/spec/extensions/json_serializer_spec.rb +4 -5
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +17 -39
- data/spec/extensions/many_through_many_spec.rb +283 -250
- data/spec/extensions/migration_spec.rb +35 -32
- data/spec/extensions/named_timezones_spec.rb +23 -3
- data/spec/extensions/nested_attributes_spec.rb +97 -88
- data/spec/extensions/optimistic_locking_spec.rb +9 -20
- data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
- data/spec/extensions/prepared_statements_spec.rb +53 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +1 -6
- data/spec/extensions/rcte_tree_spec.rb +41 -43
- data/spec/extensions/schema_dumper_spec.rb +5 -8
- data/spec/extensions/schema_spec.rb +13 -21
- data/spec/extensions/serialization_modification_detection_spec.rb +37 -0
- data/spec/extensions/serialization_spec.rb +72 -43
- data/spec/extensions/sharding_spec.rb +66 -140
- data/spec/extensions/single_table_inheritance_spec.rb +18 -29
- data/spec/extensions/spec_helper.rb +13 -61
- data/spec/extensions/sql_expr_spec.rb +20 -60
- data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/timestamps_spec.rb +6 -6
- data/spec/extensions/to_dot_spec.rb +4 -7
- data/spec/extensions/touch_spec.rb +13 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +30 -51
- data/spec/extensions/validation_helpers_spec.rb +16 -35
- data/spec/extensions/xml_serializer_spec.rb +16 -4
- data/spec/integration/associations_test.rb +537 -21
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +461 -65
- 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 +212 -122
- 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 +201 -7
- data/spec/model/associations_spec.rb +865 -662
- data/spec/model/base_spec.rb +275 -95
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +677 -676
- data/spec/model/hooks_spec.rb +309 -67
- data/spec/model/model_spec.rb +222 -168
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +381 -218
- data/spec/model/spec_helper.rb +13 -71
- data/spec/model/validations_spec.rb +11 -0
- metadata +115 -73
|
@@ -197,35 +197,39 @@ if POSTGRES_DB.pool.respond_to?(:max_size) and POSTGRES_DB.pool.max_size > 1
|
|
|
197
197
|
|
|
198
198
|
specify "should handle FOR UPDATE" do
|
|
199
199
|
@ds.insert(:number=>20)
|
|
200
|
-
c = nil
|
|
201
|
-
|
|
200
|
+
c, t = nil, nil
|
|
201
|
+
q = Queue.new
|
|
202
202
|
POSTGRES_DB.transaction do
|
|
203
203
|
@ds.for_update.first(:id=>1)
|
|
204
204
|
t = Thread.new do
|
|
205
205
|
POSTGRES_DB.transaction do
|
|
206
|
+
q.push nil
|
|
206
207
|
@ds.filter(:id=>1).update(:name=>'Jim')
|
|
207
208
|
c = @ds.first(:id=>1)
|
|
209
|
+
q.push nil
|
|
208
210
|
end
|
|
209
211
|
end
|
|
210
|
-
|
|
212
|
+
q.pop
|
|
211
213
|
@ds.filter(:id=>1).update(:number=>30)
|
|
212
214
|
end
|
|
215
|
+
q.pop
|
|
213
216
|
t.join
|
|
214
217
|
c.should == {:id=>1, :number=>30, :name=>'Jim'}
|
|
215
218
|
end
|
|
216
219
|
|
|
217
220
|
specify "should handle FOR SHARE" do
|
|
218
221
|
@ds.insert(:number=>20)
|
|
219
|
-
c = nil
|
|
220
|
-
|
|
222
|
+
c, t = nil
|
|
223
|
+
q = Queue.new
|
|
221
224
|
POSTGRES_DB.transaction do
|
|
222
225
|
@ds.for_share.first(:id=>1)
|
|
223
226
|
t = Thread.new do
|
|
224
227
|
POSTGRES_DB.transaction do
|
|
225
228
|
c = @ds.for_share.filter(:id=>1).first
|
|
229
|
+
q.push nil
|
|
226
230
|
end
|
|
227
231
|
end
|
|
228
|
-
|
|
232
|
+
q.pop
|
|
229
233
|
@ds.filter(:id=>1).update(:name=>'Jim')
|
|
230
234
|
c.should == {:id=>1, :number=>20, :name=>nil}
|
|
231
235
|
end
|
|
@@ -351,17 +355,17 @@ describe "A PostgreSQL database" do
|
|
|
351
355
|
specify "should support opclass specification" do
|
|
352
356
|
@db.create_table(:posts){text :title; text :body; integer :user_id; index(:user_id, :opclass => :int4_ops, :type => :btree)}
|
|
353
357
|
@db.sqls.should == [
|
|
354
|
-
|
|
355
|
-
|
|
358
|
+
'CREATE TABLE "posts" ("title" text, "body" text, "user_id" integer)',
|
|
359
|
+
'CREATE INDEX "posts_user_id_index" ON "posts" USING btree ("user_id" int4_ops)'
|
|
356
360
|
]
|
|
357
361
|
end
|
|
358
362
|
|
|
359
363
|
specify "should support fulltext indexes and searching" do
|
|
360
364
|
@db.create_table(:posts){text :title; text :body; full_text_index [:title, :body]; full_text_index :title, :language => 'french'}
|
|
361
365
|
@db.sqls.should == [
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
366
|
+
%{CREATE TABLE "posts" ("title" text, "body" text)},
|
|
367
|
+
%{CREATE INDEX "posts_title_body_index" ON "posts" USING gin (to_tsvector('simple', (COALESCE("title", '') || ' ' || COALESCE("body", ''))))},
|
|
368
|
+
%{CREATE INDEX "posts_title_index" ON "posts" USING gin (to_tsvector('french', (COALESCE("title", ''))))}
|
|
365
369
|
]
|
|
366
370
|
|
|
367
371
|
@db[:posts].insert(:title=>'ruby rails', :body=>'yowsa')
|
|
@@ -373,48 +377,51 @@ describe "A PostgreSQL database" do
|
|
|
373
377
|
@db[:posts].full_text_search([:title, :body], ['yowsa', 'rails']).all.should == [:title=>'ruby rails', :body=>'yowsa']
|
|
374
378
|
@db[:posts].full_text_search(:title, 'scooby', :language => 'french').all.should == [{:title=>'ruby scooby', :body=>'x'}]
|
|
375
379
|
@db.sqls.should == [
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
380
|
+
%{SELECT * FROM "posts" WHERE (to_tsvector('simple', (COALESCE("title", ''))) @@ to_tsquery('simple', 'rails'))},
|
|
381
|
+
%{SELECT * FROM "posts" WHERE (to_tsvector('simple', (COALESCE("title", '') || ' ' || COALESCE("body", ''))) @@ to_tsquery('simple', 'yowsa | rails'))},
|
|
382
|
+
%{SELECT * FROM "posts" WHERE (to_tsvector('french', (COALESCE("title", ''))) @@ to_tsquery('french', 'scooby'))}]
|
|
383
|
+
|
|
384
|
+
@db[:posts].full_text_search(:title, :$n).call(:select, :n=>'rails').should == [{:title=>'ruby rails', :body=>'yowsa'}]
|
|
385
|
+
@db[:posts].full_text_search(:title, :$n).prepare(:select, :fts_select).call(:n=>'rails').should == [{:title=>'ruby rails', :body=>'yowsa'}]
|
|
379
386
|
end
|
|
380
387
|
|
|
381
388
|
specify "should support spatial indexes" do
|
|
382
389
|
@db.create_table(:posts){box :geom; spatial_index [:geom]}
|
|
383
390
|
@db.sqls.should == [
|
|
384
|
-
|
|
385
|
-
|
|
391
|
+
'CREATE TABLE "posts" ("geom" box)',
|
|
392
|
+
'CREATE INDEX "posts_geom_index" ON "posts" USING gist ("geom")'
|
|
386
393
|
]
|
|
387
394
|
end
|
|
388
395
|
|
|
389
396
|
specify "should support indexes with index type" do
|
|
390
397
|
@db.create_table(:posts){varchar :title, :size => 5; index :title, :type => 'hash'}
|
|
391
398
|
@db.sqls.should == [
|
|
392
|
-
|
|
393
|
-
|
|
399
|
+
'CREATE TABLE "posts" ("title" varchar(5))',
|
|
400
|
+
'CREATE INDEX "posts_title_index" ON "posts" USING hash ("title")'
|
|
394
401
|
]
|
|
395
402
|
end
|
|
396
403
|
|
|
397
404
|
specify "should support unique indexes with index type" do
|
|
398
405
|
@db.create_table(:posts){varchar :title, :size => 5; index :title, :type => 'btree', :unique => true}
|
|
399
406
|
@db.sqls.should == [
|
|
400
|
-
|
|
401
|
-
|
|
407
|
+
'CREATE TABLE "posts" ("title" varchar(5))',
|
|
408
|
+
'CREATE UNIQUE INDEX "posts_title_index" ON "posts" USING btree ("title")'
|
|
402
409
|
]
|
|
403
410
|
end
|
|
404
411
|
|
|
405
412
|
specify "should support partial indexes" do
|
|
406
413
|
@db.create_table(:posts){varchar :title, :size => 5; index :title, :where => {:title => '5'}}
|
|
407
414
|
@db.sqls.should == [
|
|
408
|
-
|
|
409
|
-
|
|
415
|
+
'CREATE TABLE "posts" ("title" varchar(5))',
|
|
416
|
+
'CREATE INDEX "posts_title_index" ON "posts" ("title") WHERE ("title" = \'5\')'
|
|
410
417
|
]
|
|
411
418
|
end
|
|
412
419
|
|
|
413
420
|
specify "should support identifiers for table names in indicies" do
|
|
414
421
|
@db.create_table(Sequel::SQL::Identifier.new(:posts)){varchar :title, :size => 5; index :title, :where => {:title => '5'}}
|
|
415
422
|
@db.sqls.should == [
|
|
416
|
-
|
|
417
|
-
|
|
423
|
+
'CREATE TABLE "posts" ("title" varchar(5))',
|
|
424
|
+
'CREATE INDEX "posts_title_index" ON "posts" ("title") WHERE ("title" = \'5\')'
|
|
418
425
|
]
|
|
419
426
|
end
|
|
420
427
|
|
|
@@ -427,7 +434,7 @@ end
|
|
|
427
434
|
describe "Postgres::Dataset#import" do
|
|
428
435
|
before do
|
|
429
436
|
@db = POSTGRES_DB
|
|
430
|
-
@db.create_table!(:test){
|
|
437
|
+
@db.create_table!(:test){primary_key :x; Integer :y}
|
|
431
438
|
@db.sqls.clear
|
|
432
439
|
@ds = @db[:test]
|
|
433
440
|
end
|
|
@@ -437,28 +444,45 @@ describe "Postgres::Dataset#import" do
|
|
|
437
444
|
|
|
438
445
|
specify "#import should return separate insert statements if server_version < 80200" do
|
|
439
446
|
@ds.meta_def(:server_version){80199}
|
|
440
|
-
|
|
441
447
|
@ds.import([:x, :y], [[1, 2], [3, 4]])
|
|
442
|
-
|
|
443
|
-
@db.sqls.should == [
|
|
444
|
-
'BEGIN',
|
|
445
|
-
'INSERT INTO test (x, y) VALUES (1, 2)',
|
|
446
|
-
'INSERT INTO test (x, y) VALUES (3, 4)',
|
|
447
|
-
'COMMIT'
|
|
448
|
-
]
|
|
448
|
+
@db.sqls.should == ['BEGIN', 'INSERT INTO "test" ("x", "y") VALUES (1, 2)', 'INSERT INTO "test" ("x", "y") VALUES (3, 4)', 'COMMIT']
|
|
449
449
|
@ds.all.should == [{:x=>1, :y=>2}, {:x=>3, :y=>4}]
|
|
450
450
|
end
|
|
451
451
|
|
|
452
452
|
specify "#import should a single insert statement if server_version >= 80200" do
|
|
453
453
|
@ds.meta_def(:server_version){80200}
|
|
454
|
-
|
|
455
454
|
@ds.import([:x, :y], [[1, 2], [3, 4]])
|
|
456
|
-
|
|
457
|
-
@
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
455
|
+
@db.sqls.should == ['BEGIN', 'INSERT INTO "test" ("x", "y") VALUES (1, 2), (3, 4)', 'COMMIT']
|
|
456
|
+
@ds.all.should == [{:x=>1, :y=>2}, {:x=>3, :y=>4}]
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
specify "#import should work correctly when returning primary keys for server_version < 80200" do
|
|
460
|
+
@ds.meta_def(:server_version){80199}
|
|
461
|
+
@ds.import([:x, :y], [[1, 2], [3, 4]], :return=>:primary_key).should == [1, 3]
|
|
462
|
+
@ds.all.should == [{:x=>1, :y=>2}, {:x=>3, :y=>4}]
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
specify "#import should work correctly when returning primary keys for server_version >= 80200" do
|
|
466
|
+
@ds.meta_def(:server_version){80200}
|
|
467
|
+
@ds.import([:x, :y], [[1, 2], [3, 4]], :return=>:primary_key).should == [1, 3]
|
|
468
|
+
@ds.all.should == [{:x=>1, :y=>2}, {:x=>3, :y=>4}]
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
specify "#import should work correctly when returning primary keys with :slice option for server_version < 80200" do
|
|
472
|
+
@ds.meta_def(:server_version){80199}
|
|
473
|
+
@ds.import([:x, :y], [[1, 2], [3, 4]], :return=>:primary_key, :slice=>1).should == [1, 3]
|
|
474
|
+
@ds.all.should == [{:x=>1, :y=>2}, {:x=>3, :y=>4}]
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
specify "#import should work correctly when returning primary keys with :slice option for server_version >= 80200" do
|
|
478
|
+
@ds.meta_def(:server_version){80200}
|
|
479
|
+
@ds.import([:x, :y], [[1, 2], [3, 4]], :return=>:primary_key, :slice=>1).should == [1, 3]
|
|
480
|
+
@ds.all.should == [{:x=>1, :y=>2}, {:x=>3, :y=>4}]
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
specify "#import should work correctly with an arbitrary returning value" do
|
|
484
|
+
@ds.meta_def(:server_version){80200}
|
|
485
|
+
@ds.returning(:y, :x).import([:x, :y], [[1, 2], [3, 4]]).should == [{:y=>2, :x=>1}, {:y=>4, :x=>3}]
|
|
462
486
|
@ds.all.should == [{:x=>1, :y=>2}, {:x=>3, :y=>4}]
|
|
463
487
|
end
|
|
464
488
|
end
|
|
@@ -487,36 +511,36 @@ describe "Postgres::Dataset#insert" do
|
|
|
487
511
|
@ds.insert(:value=>13).should == 3
|
|
488
512
|
|
|
489
513
|
@db.sqls.reject{|x| x =~ /pg_class/}.should == [
|
|
490
|
-
'INSERT INTO test5 (value) VALUES (10) RETURNING xid',
|
|
491
|
-
'INSERT INTO test5 (value) VALUES (20)',
|
|
514
|
+
'INSERT INTO "test5" ("value") VALUES (10) RETURNING "xid"',
|
|
515
|
+
'INSERT INTO "test5" ("value") VALUES (20)',
|
|
492
516
|
"SELECT currval('\"public\".test5_xid_seq')",
|
|
493
|
-
'INSERT INTO test5 (value) VALUES (13)',
|
|
517
|
+
'INSERT INTO "test5" ("value") VALUES (13)',
|
|
494
518
|
"SELECT currval('\"public\".test5_xid_seq')"
|
|
495
519
|
]
|
|
496
520
|
@ds.all.should == [{:xid=>1, :value=>10}, {:xid=>2, :value=>20}, {:xid=>3, :value=>13}]
|
|
497
521
|
end
|
|
498
522
|
|
|
499
|
-
specify "should
|
|
523
|
+
specify "should insert correctly if server_version < 80200" do
|
|
500
524
|
@ds.meta_def(:server_version){80100}
|
|
501
|
-
@ds.
|
|
502
|
-
@ds.
|
|
525
|
+
@ds.insert(:value=>10).should == 1
|
|
526
|
+
@ds.all.should == [{:xid=>1, :value=>10}]
|
|
503
527
|
end
|
|
504
528
|
|
|
505
|
-
specify "should
|
|
506
|
-
@ds.disable_insert_returning
|
|
507
|
-
@ds.
|
|
508
|
-
@ds.insert(:value=>10)
|
|
529
|
+
specify "should insert correctly if disabling insert returning" do
|
|
530
|
+
@ds.disable_insert_returning.insert(:value=>10).should == 1
|
|
531
|
+
@ds.all.should == [{:xid=>1, :value=>10}]
|
|
509
532
|
end
|
|
510
533
|
|
|
511
|
-
specify "should
|
|
512
|
-
@ds.meta_def(:server_version){
|
|
513
|
-
@ds.insert(:value
|
|
514
|
-
@
|
|
534
|
+
specify "should insert correctly if using a column array and a value array and server_version < 80200" do
|
|
535
|
+
@ds.meta_def(:server_version){80100}
|
|
536
|
+
@ds.insert([:value], [10]).should == 1
|
|
537
|
+
@ds.all.should == [{:xid=>1, :value=>10}]
|
|
515
538
|
end
|
|
516
539
|
|
|
517
|
-
specify "should
|
|
518
|
-
@ds.
|
|
519
|
-
@ds.
|
|
540
|
+
specify "should use INSERT RETURNING if server_version >= 80200" do
|
|
541
|
+
@ds.meta_def(:server_version){80201}
|
|
542
|
+
@ds.insert(:value=>10).should == 1
|
|
543
|
+
@db.sqls.last.should == 'INSERT INTO "test5" ("value") VALUES (10) RETURNING "xid"'
|
|
520
544
|
end
|
|
521
545
|
|
|
522
546
|
specify "should have insert_select return nil if server_version < 80200" do
|
|
@@ -606,10 +630,16 @@ describe "Postgres::Database schema qualified tables" do
|
|
|
606
630
|
POSTGRES_DB.drop_table(:domains)
|
|
607
631
|
end
|
|
608
632
|
|
|
609
|
-
specify "#
|
|
610
|
-
POSTGRES_DB.create_table(:
|
|
611
|
-
POSTGRES_DB.
|
|
612
|
-
|
|
633
|
+
specify "#schema should raise an exception if columns from tables in two separate schema are returned" do
|
|
634
|
+
POSTGRES_DB.create_table!(:public__domains){integer :d}
|
|
635
|
+
POSTGRES_DB.create_table(:schema_test__domains){integer :i}
|
|
636
|
+
begin
|
|
637
|
+
proc{POSTGRES_DB.schema(:domains)}.should raise_error(Sequel::Error)
|
|
638
|
+
POSTGRES_DB.schema(:public__domains).map{|x| x.first}.should == [:d]
|
|
639
|
+
POSTGRES_DB.schema(:schema_test__domains).map{|x| x.first}.should == [:i]
|
|
640
|
+
ensure
|
|
641
|
+
POSTGRES_DB.drop_table(:public__domains)
|
|
642
|
+
end
|
|
613
643
|
end
|
|
614
644
|
|
|
615
645
|
specify "#table_exists? should see if the table is in a given schema" do
|
|
@@ -909,7 +939,7 @@ describe "Postgres::Database functions, languages, and triggers" do
|
|
|
909
939
|
after do
|
|
910
940
|
@d.drop_function('tf', :if_exists=>true, :cascade=>true)
|
|
911
941
|
@d.drop_function('tf', :if_exists=>true, :cascade=>true, :args=>%w'integer integer')
|
|
912
|
-
@d.drop_language(:plpgsql, :if_exists=>true, :cascade=>true)
|
|
942
|
+
@d.drop_language(:plpgsql, :if_exists=>true, :cascade=>true) if @d.server_version < 90000
|
|
913
943
|
@d.drop_table(:test) rescue nil
|
|
914
944
|
end
|
|
915
945
|
|
|
@@ -940,19 +970,19 @@ describe "Postgres::Database functions, languages, and triggers" do
|
|
|
940
970
|
|
|
941
971
|
specify "#create_language and #drop_language should create and drop languages" do
|
|
942
972
|
@d.send(:create_language_sql, :plpgsql).should == 'CREATE LANGUAGE plpgsql'
|
|
943
|
-
@d.create_language(:plpgsql, :replace=>true)
|
|
973
|
+
@d.create_language(:plpgsql, :replace=>true) if @d.server_version < 90000
|
|
944
974
|
proc{@d.create_language(:plpgsql)}.should raise_error(Sequel::DatabaseError)
|
|
945
975
|
@d.send(:drop_language_sql, :plpgsql).should == 'DROP LANGUAGE plpgsql'
|
|
946
|
-
@d.drop_language(:plpgsql)
|
|
947
|
-
proc{@d.drop_language(:plpgsql)}.should raise_error(Sequel::DatabaseError)
|
|
976
|
+
@d.drop_language(:plpgsql) if @d.server_version < 90000
|
|
977
|
+
proc{@d.drop_language(:plpgsql)}.should raise_error(Sequel::DatabaseError) if @d.server_version < 90000
|
|
948
978
|
@d.send(:create_language_sql, :plpgsql, :replace=>true, :trusted=>true, :handler=>:a, :validator=>:b).should == (@d.server_version >= 90000 ? 'CREATE OR REPLACE TRUSTED LANGUAGE plpgsql HANDLER a VALIDATOR b' : 'CREATE TRUSTED LANGUAGE plpgsql HANDLER a VALIDATOR b')
|
|
949
979
|
@d.send(:drop_language_sql, :plpgsql, :if_exists=>true, :cascade=>true).should == 'DROP LANGUAGE IF EXISTS plpgsql CASCADE'
|
|
950
980
|
# Make sure if exists works
|
|
951
|
-
@d.drop_language(:plpgsql, :if_exists=>true, :cascade=>true)
|
|
981
|
+
@d.drop_language(:plpgsql, :if_exists=>true, :cascade=>true) if @d.server_version < 90000
|
|
952
982
|
end
|
|
953
983
|
|
|
954
984
|
specify "#create_trigger and #drop_trigger should create and drop triggers" do
|
|
955
|
-
@d.create_language(:plpgsql)
|
|
985
|
+
@d.create_language(:plpgsql) if @d.server_version < 90000
|
|
956
986
|
@d.create_function(:tf, 'BEGIN IF NEW.value IS NULL THEN RAISE EXCEPTION \'Blah\'; END IF; RETURN NEW; END;', :language=>:plpgsql, :returns=>:trigger)
|
|
957
987
|
@d.send(:create_trigger_sql, :test, :identity, :tf, :each_row=>true).should == 'CREATE TRIGGER identity BEFORE INSERT OR UPDATE OR DELETE ON test FOR EACH ROW EXECUTE PROCEDURE tf()'
|
|
958
988
|
@d.create_table(:test){String :name; Integer :value}
|
|
@@ -973,17 +1003,17 @@ describe "Postgres::Database functions, languages, and triggers" do
|
|
|
973
1003
|
end
|
|
974
1004
|
|
|
975
1005
|
if POSTGRES_DB.adapter_scheme == :postgres
|
|
976
|
-
describe "Postgres::Dataset #use_cursor" do
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1006
|
+
describe "Postgres::Dataset #use_cursor" do
|
|
1007
|
+
before(:all) do
|
|
1008
|
+
@db = POSTGRES_DB
|
|
1009
|
+
@db.create_table!(:test_cursor){Integer :x}
|
|
1010
|
+
@db.sqls.clear
|
|
1011
|
+
@ds = @db[:test_cursor]
|
|
1012
|
+
@db.transaction{1001.times{|i| @ds.insert(i)}}
|
|
1013
|
+
end
|
|
1014
|
+
after(:all) do
|
|
1015
|
+
@db.drop_table(:test_cursor) rescue nil
|
|
1016
|
+
end
|
|
987
1017
|
|
|
988
1018
|
specify "should return the same results as the non-cursor use" do
|
|
989
1019
|
@ds.all.should == @ds.use_cursor.all
|
|
@@ -1005,5 +1035,164 @@ describe "Postgres::Dataset #use_cursor" do
|
|
|
1005
1035
|
@ds.check_return
|
|
1006
1036
|
@ds.all.should == @ds.use_cursor.all
|
|
1007
1037
|
end
|
|
1038
|
+
end
|
|
1039
|
+
|
|
1040
|
+
describe "Postgres::PG_NAMED_TYPES" do
|
|
1041
|
+
before do
|
|
1042
|
+
@db = POSTGRES_DB
|
|
1043
|
+
Sequel::Postgres::PG_NAMED_TYPES[:interval] = lambda{|v| v.reverse}
|
|
1044
|
+
@db.instance_eval do
|
|
1045
|
+
disconnect
|
|
1046
|
+
@conversion_procs = nil
|
|
1047
|
+
end
|
|
1048
|
+
end
|
|
1049
|
+
after do
|
|
1050
|
+
Sequel::Postgres::PG_NAMED_TYPES.delete(:interval)
|
|
1051
|
+
@db.instance_eval do
|
|
1052
|
+
disconnect
|
|
1053
|
+
@conversion_procs = nil
|
|
1054
|
+
end
|
|
1055
|
+
@db.drop_table(:foo)
|
|
1056
|
+
end
|
|
1057
|
+
|
|
1058
|
+
specify "should look up conversion procs by name" do
|
|
1059
|
+
@db.create_table!(:foo){interval :bar}
|
|
1060
|
+
@db[:foo].insert('21 days')
|
|
1061
|
+
@db[:foo].get(:bar).should == 'syad 12'
|
|
1062
|
+
end
|
|
1063
|
+
end
|
|
1008
1064
|
end
|
|
1065
|
+
|
|
1066
|
+
if POSTGRES_DB.adapter_scheme == :postgres && SEQUEL_POSTGRES_USES_PG && POSTGRES_DB.server_version >= 90000
|
|
1067
|
+
describe "Postgres::Database#copy_table" do
|
|
1068
|
+
before(:all) do
|
|
1069
|
+
@db = POSTGRES_DB
|
|
1070
|
+
@db.create_table!(:test_copy){Integer :x; Integer :y}
|
|
1071
|
+
ds = @db[:test_copy]
|
|
1072
|
+
ds.insert(1, 2)
|
|
1073
|
+
ds.insert(3, 4)
|
|
1074
|
+
end
|
|
1075
|
+
after(:all) do
|
|
1076
|
+
@db.drop_table(:test_copy) rescue nil
|
|
1077
|
+
end
|
|
1078
|
+
|
|
1079
|
+
specify "without a block or options should return a text version of the table as a single string" do
|
|
1080
|
+
@db.copy_table(:test_copy).should == "1\t2\n3\t4\n"
|
|
1081
|
+
end
|
|
1082
|
+
|
|
1083
|
+
specify "without a block and with :format=>:csv should return a csv version of the table as a single string" do
|
|
1084
|
+
@db.copy_table(:test_copy, :format=>:csv).should == "1,2\n3,4\n"
|
|
1085
|
+
end
|
|
1086
|
+
|
|
1087
|
+
specify "should treat string as SQL code" do
|
|
1088
|
+
@db.copy_table('COPY "test_copy" TO STDOUT').should == "1\t2\n3\t4\n"
|
|
1089
|
+
end
|
|
1090
|
+
|
|
1091
|
+
specify "should respect given :options options" do
|
|
1092
|
+
@db.copy_table(:test_copy, :options=>"FORMAT csv, HEADER TRUE").should == "x,y\n1,2\n3,4\n"
|
|
1093
|
+
end
|
|
1094
|
+
|
|
1095
|
+
specify "should respect given :options options when :format is used" do
|
|
1096
|
+
@db.copy_table(:test_copy, :format=>:csv, :options=>"QUOTE '''', FORCE_QUOTE *").should == "'1','2'\n'3','4'\n"
|
|
1097
|
+
end
|
|
1098
|
+
|
|
1099
|
+
specify "should accept dataset as first argument" do
|
|
1100
|
+
@db.copy_table(@db[:test_copy].cross_join(:test_copy___tc).order(1, 2, 3, 4)).should == "1\t2\t1\t2\n1\t2\t3\t4\n3\t4\t1\t2\n3\t4\t3\t4\n"
|
|
1101
|
+
end
|
|
1102
|
+
|
|
1103
|
+
specify "with a block and no options should yield each row as a string in text format" do
|
|
1104
|
+
buf = []
|
|
1105
|
+
@db.copy_table(:test_copy){|b| buf << b}
|
|
1106
|
+
buf.should == ["1\t2\n", "3\t4\n"]
|
|
1107
|
+
end
|
|
1108
|
+
|
|
1109
|
+
specify "with a block and :format=>:csv should yield each row as a string in csv format" do
|
|
1110
|
+
buf = []
|
|
1111
|
+
@db.copy_table(:test_copy, :format=>:csv){|b| buf << b}
|
|
1112
|
+
buf.should == ["1,2\n", "3,4\n"]
|
|
1113
|
+
end
|
|
1114
|
+
|
|
1115
|
+
specify "should work fine when using a block that is terminated early with a following copy_table" do
|
|
1116
|
+
buf = []
|
|
1117
|
+
proc{@db.copy_table(:test_copy, :format=>:csv){|b| buf << b; break}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
1118
|
+
buf.should == ["1,2\n"]
|
|
1119
|
+
buf.clear
|
|
1120
|
+
proc{@db.copy_table(:test_copy, :format=>:csv){|b| buf << b; raise ArgumentError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
1121
|
+
buf.should == ["1,2\n"]
|
|
1122
|
+
buf.clear
|
|
1123
|
+
@db.copy_table(:test_copy){|b| buf << b}
|
|
1124
|
+
buf.should == ["1\t2\n", "3\t4\n"]
|
|
1125
|
+
end
|
|
1126
|
+
|
|
1127
|
+
specify "should work fine when using a block that is terminated early with a following regular query" do
|
|
1128
|
+
buf = []
|
|
1129
|
+
proc{@db.copy_table(:test_copy, :format=>:csv){|b| buf << b; break}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
1130
|
+
buf.should == ["1,2\n"]
|
|
1131
|
+
buf.clear
|
|
1132
|
+
proc{@db.copy_table(:test_copy, :format=>:csv){|b| buf << b; raise ArgumentError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
1133
|
+
buf.should == ["1,2\n"]
|
|
1134
|
+
@db[:test_copy].select_order_map(:x).should == [1, 3]
|
|
1135
|
+
end
|
|
1136
|
+
end
|
|
1137
|
+
|
|
1138
|
+
describe "Postgres::Database LISTEN/NOTIFY" do
|
|
1139
|
+
before(:all) do
|
|
1140
|
+
@db = POSTGRES_DB
|
|
1141
|
+
end
|
|
1142
|
+
|
|
1143
|
+
specify "should support listen and notify" do
|
|
1144
|
+
notify_pid = @db.synchronize{|conn| conn.backend_pid}
|
|
1145
|
+
|
|
1146
|
+
called = false
|
|
1147
|
+
@db.listen('foo', :after_listen=>proc{@db.notify('foo')}) do |ev, pid, payload|
|
|
1148
|
+
ev.should == 'foo'
|
|
1149
|
+
pid.should == notify_pid
|
|
1150
|
+
['', nil].should include(payload)
|
|
1151
|
+
called = true
|
|
1152
|
+
end.should == 'foo'
|
|
1153
|
+
called.should be_true
|
|
1154
|
+
|
|
1155
|
+
called = false
|
|
1156
|
+
@db.listen('foo', :after_listen=>proc{@db.notify('foo', :payload=>'bar')}) do |ev, pid, payload|
|
|
1157
|
+
ev.should == 'foo'
|
|
1158
|
+
pid.should == notify_pid
|
|
1159
|
+
payload.should == 'bar'
|
|
1160
|
+
called = true
|
|
1161
|
+
end.should == 'foo'
|
|
1162
|
+
called.should be_true
|
|
1163
|
+
|
|
1164
|
+
@db.listen('foo', :after_listen=>proc{@db.notify('foo')}).should == 'foo'
|
|
1165
|
+
|
|
1166
|
+
called = false
|
|
1167
|
+
called2 = false
|
|
1168
|
+
i = 0
|
|
1169
|
+
@db.listen(['foo', 'bar'], :after_listen=>proc{@db.notify('foo', :payload=>'bar'); @db.notify('bar', :payload=>'foo')}, :loop=>proc{i+=1}) do |ev, pid, payload|
|
|
1170
|
+
if !called
|
|
1171
|
+
ev.should == 'foo'
|
|
1172
|
+
pid.should == notify_pid
|
|
1173
|
+
payload.should == 'bar'
|
|
1174
|
+
called = true
|
|
1175
|
+
else
|
|
1176
|
+
ev.should == 'bar'
|
|
1177
|
+
pid.should == notify_pid
|
|
1178
|
+
payload.should == 'foo'
|
|
1179
|
+
called2 = true
|
|
1180
|
+
break
|
|
1181
|
+
end
|
|
1182
|
+
end.should be_nil
|
|
1183
|
+
called.should be_true
|
|
1184
|
+
called2.should be_true
|
|
1185
|
+
i.should == 1
|
|
1186
|
+
end
|
|
1187
|
+
|
|
1188
|
+
specify "should accept a :timeout option in listen" do
|
|
1189
|
+
@db.listen('foo2', :timeout=>0.001).should == nil
|
|
1190
|
+
called = false
|
|
1191
|
+
@db.listen('foo2', :timeout=>0.001){|ev, pid, payload| called = true}.should == nil
|
|
1192
|
+
called.should be_false
|
|
1193
|
+
i = 0
|
|
1194
|
+
@db.listen('foo2', :timeout=>0.001, :loop=>proc{i+=1; throw :stop if i > 3}){|ev, pid, payload| called = true}.should == nil
|
|
1195
|
+
i.should == 4
|
|
1196
|
+
end
|
|
1197
|
+
end
|
|
1009
1198
|
end
|
|
@@ -3,13 +3,17 @@ require 'logger'
|
|
|
3
3
|
unless Object.const_defined?('Sequel')
|
|
4
4
|
$:.unshift(File.join(File.dirname(File.expand_path(__FILE__)), "../../lib/"))
|
|
5
5
|
require 'sequel'
|
|
6
|
-
Sequel.quote_identifiers = false
|
|
7
6
|
end
|
|
8
7
|
begin
|
|
9
8
|
require File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), 'spec_config.rb')
|
|
10
9
|
rescue LoadError
|
|
11
10
|
end
|
|
12
11
|
|
|
12
|
+
if ENV['SEQUEL_COLUMNS_INTROSPECTION']
|
|
13
|
+
Sequel.extension :columns_introspection
|
|
14
|
+
Sequel::Dataset.introspect_all_columns
|
|
15
|
+
end
|
|
16
|
+
|
|
13
17
|
class Sequel::Database
|
|
14
18
|
def log_duration(duration, message)
|
|
15
19
|
log_info(message)
|
|
@@ -26,11 +30,8 @@ end
|
|
|
26
30
|
end
|
|
27
31
|
end
|
|
28
32
|
|
|
29
|
-
def self.log_specify(message, &block)
|
|
30
|
-
specify(message){log{instance_eval(&block)}}
|
|
31
|
-
end
|
|
32
|
-
|
|
33
33
|
def self.cspecify(message, *checked, &block)
|
|
34
|
+
return specify(message, &block) if ENV['SEQUEL_NO_PENDING']
|
|
34
35
|
pending = false
|
|
35
36
|
checked.each do |c|
|
|
36
37
|
case c
|
|
@@ -66,6 +66,17 @@ describe "An SQLite database" do
|
|
|
66
66
|
@db[:fk].all.should == [{:id=>1, :parent_id=>2}]
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
+
specify "should support a use_timestamp_timezones setting" do
|
|
70
|
+
@db.create_table!(:time){Time :time}
|
|
71
|
+
@db[:time].insert(Time.now)
|
|
72
|
+
@db[:time].get(:time.cast_string).should =~ /[-+]\d\d\d\d\z/
|
|
73
|
+
@db.use_timestamp_timezones = false
|
|
74
|
+
@db[:time].delete
|
|
75
|
+
@db[:time].insert(Time.now)
|
|
76
|
+
@db[:time].get(:time.cast_string).should_not =~ /[-+]\d\d\d\d\z/
|
|
77
|
+
@db.use_timestamp_timezones = true
|
|
78
|
+
end
|
|
79
|
+
|
|
69
80
|
specify "should provide a list of existing tables" do
|
|
70
81
|
@db.drop_table(:testing) rescue nil
|
|
71
82
|
@db.tables.should be_a_kind_of(Array)
|
|
@@ -133,13 +144,6 @@ describe "An SQLite dataset" do
|
|
|
133
144
|
@d = SQLITE_DB[:items]
|
|
134
145
|
end
|
|
135
146
|
|
|
136
|
-
specify "should handle string pattern matches correctly" do
|
|
137
|
-
@d.literal(:x.like('a')).should == "(x LIKE 'a')"
|
|
138
|
-
@d.literal(~:x.like('a')).should == "NOT (x LIKE 'a')"
|
|
139
|
-
@d.literal(:x.ilike('a')).should == "(x LIKE 'a')"
|
|
140
|
-
@d.literal(~:x.ilike('a')).should == "NOT (x LIKE 'a')"
|
|
141
|
-
end
|
|
142
|
-
|
|
143
147
|
specify "should raise errors if given a regexp pattern match" do
|
|
144
148
|
proc{@d.literal(:x.like(/a/))}.should raise_error(Sequel::Error)
|
|
145
149
|
proc{@d.literal(~:x.like(/a/))}.should raise_error(Sequel::Error)
|
|
@@ -164,27 +168,27 @@ end
|
|
|
164
168
|
|
|
165
169
|
describe "An SQLite dataset AS clause" do
|
|
166
170
|
specify "should use a string literal for :col___alias" do
|
|
167
|
-
SQLITE_DB.literal(:c___a).should == "c AS 'a'"
|
|
171
|
+
SQLITE_DB.literal(:c___a).should == "`c` AS 'a'"
|
|
168
172
|
end
|
|
169
173
|
|
|
170
174
|
specify "should use a string literal for :table__col___alias" do
|
|
171
|
-
SQLITE_DB.literal(:t__c___a).should == "t
|
|
175
|
+
SQLITE_DB.literal(:t__c___a).should == "`t`.`c` AS 'a'"
|
|
172
176
|
end
|
|
173
177
|
|
|
174
178
|
specify "should use a string literal for :column.as(:alias)" do
|
|
175
|
-
SQLITE_DB.literal(:c.as(:a)).should == "c AS 'a'"
|
|
179
|
+
SQLITE_DB.literal(:c.as(:a)).should == "`c` AS 'a'"
|
|
176
180
|
end
|
|
177
181
|
|
|
178
182
|
specify "should use a string literal in the SELECT clause" do
|
|
179
|
-
SQLITE_DB[:t].select(:c___a).sql.should == "SELECT c AS 'a' FROM t"
|
|
183
|
+
SQLITE_DB[:t].select(:c___a).sql.should == "SELECT `c` AS 'a' FROM `t`"
|
|
180
184
|
end
|
|
181
185
|
|
|
182
186
|
specify "should use a string literal in the FROM clause" do
|
|
183
|
-
SQLITE_DB[:t___a].sql.should == "SELECT * FROM t AS 'a'"
|
|
187
|
+
SQLITE_DB[:t___a].sql.should == "SELECT * FROM `t` AS 'a'"
|
|
184
188
|
end
|
|
185
189
|
|
|
186
190
|
specify "should use a string literal in the JOIN clause" do
|
|
187
|
-
SQLITE_DB[:t].join_table(:natural, :j, nil, :a).sql.should == "SELECT * FROM t NATURAL JOIN j AS 'a'"
|
|
191
|
+
SQLITE_DB[:t].join_table(:natural, :j, nil, :a).sql.should == "SELECT * FROM `t` NATURAL JOIN `j` AS 'a'"
|
|
188
192
|
end
|
|
189
193
|
end
|
|
190
194
|
|
|
@@ -313,6 +317,15 @@ describe "A SQLite database" do
|
|
|
313
317
|
@db[:test2].first.should == {:name => 'mmm'}
|
|
314
318
|
end
|
|
315
319
|
|
|
320
|
+
specify "should keep a composite primary key when dropping columns" do
|
|
321
|
+
@db.create_table!(:test2){Integer :a; Integer :b; Integer :c; primary_key [:a, :b]}
|
|
322
|
+
@db.drop_column :test2, :c
|
|
323
|
+
@db[:test2].columns.should == [:a, :b]
|
|
324
|
+
@db[:test2] << {:a=>1, :b=>2}
|
|
325
|
+
@db[:test2] << {:a=>2, :b=>3}
|
|
326
|
+
proc{@db[:test2] << {:a=>2, :b=>3}}.should raise_error(Sequel::Error)
|
|
327
|
+
end
|
|
328
|
+
|
|
316
329
|
specify "should keep column attributes when dropping a column" do
|
|
317
330
|
@db.create_table! :test3 do
|
|
318
331
|
primary_key :id
|
|
@@ -412,14 +425,15 @@ describe "A SQLite database" do
|
|
|
412
425
|
specify "should choose a temporary table name that isn't already used when dropping or renaming columns" do
|
|
413
426
|
sqls = []
|
|
414
427
|
@db.loggers << (l=Class.new{%w'info error'.each{|m| define_method(m){|sql| sqls << sql}}}.new)
|
|
415
|
-
@db.
|
|
428
|
+
@db.tables.each{|t| @db.drop_table(t) if t.to_s =~ /test3/}
|
|
429
|
+
@db.create_table :test3 do
|
|
416
430
|
Integer :h
|
|
417
431
|
Integer :i
|
|
418
432
|
end
|
|
419
|
-
@db.create_table
|
|
433
|
+
@db.create_table :test3_backup0 do
|
|
420
434
|
Integer :j
|
|
421
435
|
end
|
|
422
|
-
@db.create_table
|
|
436
|
+
@db.create_table :test3_backup1 do
|
|
423
437
|
Integer :k
|
|
424
438
|
end
|
|
425
439
|
|
|
@@ -428,20 +442,20 @@ describe "A SQLite database" do
|
|
|
428
442
|
@db[:test3_backup1].columns.should == [:k]
|
|
429
443
|
sqls.clear
|
|
430
444
|
@db.drop_column(:test3, :i)
|
|
431
|
-
sqls.any?{|x| x =~ /\
|
|
432
|
-
sqls.any?{|x| x =~ /\
|
|
445
|
+
sqls.any?{|x| x =~ /\AALTER TABLE.*test3.*RENAME TO.*test3_backup2/}.should == true
|
|
446
|
+
sqls.any?{|x| x =~ /\AALTER TABLE.*test3.*RENAME TO.*test3_backup[01]/}.should == false
|
|
433
447
|
@db[:test3].columns.should == [:h]
|
|
434
448
|
@db[:test3_backup0].columns.should == [:j]
|
|
435
449
|
@db[:test3_backup1].columns.should == [:k]
|
|
436
450
|
|
|
437
|
-
@db.create_table
|
|
451
|
+
@db.create_table :test3_backup2 do
|
|
438
452
|
Integer :l
|
|
439
453
|
end
|
|
440
454
|
|
|
441
455
|
sqls.clear
|
|
442
456
|
@db.rename_column(:test3, :h, :i)
|
|
443
|
-
sqls.any?{|x| x =~ /\
|
|
444
|
-
sqls.any?{|x| x =~ /\
|
|
457
|
+
sqls.any?{|x| x =~ /\AALTER TABLE.*test3.*RENAME TO.*test3_backup3/}.should == true
|
|
458
|
+
sqls.any?{|x| x =~ /\AALTER TABLE.*test3.*RENAME TO.*test3_backup[012]/}.should == false
|
|
445
459
|
@db[:test3].columns.should == [:i]
|
|
446
460
|
@db[:test3_backup0].columns.should == [:j]
|
|
447
461
|
@db[:test3_backup1].columns.should == [:k]
|