sequel 3.33.0 → 3.34.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +140 -0
- data/Rakefile +7 -0
- data/bin/sequel +22 -2
- data/doc/dataset_basics.rdoc +1 -1
- data/doc/mass_assignment.rdoc +3 -1
- data/doc/querying.rdoc +28 -4
- data/doc/reflection.rdoc +23 -3
- data/doc/release_notes/3.34.0.txt +671 -0
- data/doc/schema_modification.rdoc +18 -2
- data/doc/virtual_rows.rdoc +49 -0
- data/lib/sequel/adapters/do/mysql.rb +0 -5
- data/lib/sequel/adapters/ibmdb.rb +9 -4
- data/lib/sequel/adapters/jdbc.rb +9 -4
- data/lib/sequel/adapters/jdbc/h2.rb +8 -2
- data/lib/sequel/adapters/jdbc/mysql.rb +0 -5
- data/lib/sequel/adapters/jdbc/postgresql.rb +43 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +19 -0
- data/lib/sequel/adapters/mock.rb +24 -3
- data/lib/sequel/adapters/mysql.rb +29 -50
- data/lib/sequel/adapters/mysql2.rb +13 -28
- data/lib/sequel/adapters/oracle.rb +8 -2
- data/lib/sequel/adapters/postgres.rb +115 -20
- data/lib/sequel/adapters/shared/db2.rb +1 -1
- data/lib/sequel/adapters/shared/mssql.rb +14 -3
- data/lib/sequel/adapters/shared/mysql.rb +59 -11
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +6 -0
- data/lib/sequel/adapters/shared/oracle.rb +1 -1
- data/lib/sequel/adapters/shared/postgres.rb +127 -30
- data/lib/sequel/adapters/shared/sqlite.rb +55 -38
- data/lib/sequel/adapters/sqlite.rb +9 -3
- data/lib/sequel/adapters/swift.rb +2 -2
- data/lib/sequel/adapters/swift/mysql.rb +0 -5
- data/lib/sequel/adapters/swift/postgres.rb +10 -0
- data/lib/sequel/ast_transformer.rb +4 -0
- data/lib/sequel/connection_pool.rb +8 -0
- data/lib/sequel/connection_pool/sharded_single.rb +5 -0
- data/lib/sequel/connection_pool/sharded_threaded.rb +17 -0
- data/lib/sequel/connection_pool/single.rb +5 -0
- data/lib/sequel/connection_pool/threaded.rb +14 -0
- data/lib/sequel/core.rb +24 -3
- data/lib/sequel/database/connecting.rb +24 -14
- data/lib/sequel/database/dataset_defaults.rb +1 -0
- data/lib/sequel/database/misc.rb +16 -25
- data/lib/sequel/database/query.rb +20 -2
- data/lib/sequel/database/schema_generator.rb +2 -2
- data/lib/sequel/database/schema_methods.rb +120 -23
- data/lib/sequel/dataset/actions.rb +91 -18
- data/lib/sequel/dataset/features.rb +5 -0
- data/lib/sequel/dataset/prepared_statements.rb +6 -2
- data/lib/sequel/dataset/sql.rb +68 -51
- data/lib/sequel/extensions/_pretty_table.rb +79 -0
- data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +18 -13
- data/lib/sequel/extensions/migration.rb +4 -0
- data/lib/sequel/extensions/null_dataset.rb +90 -0
- data/lib/sequel/extensions/pg_array.rb +460 -0
- data/lib/sequel/extensions/pg_array_ops.rb +220 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +174 -0
- data/lib/sequel/extensions/pg_hstore.rb +296 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +259 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +316 -0
- data/lib/sequel/extensions/pretty_table.rb +5 -71
- data/lib/sequel/extensions/query_literals.rb +79 -0
- data/lib/sequel/extensions/schema_caching.rb +76 -0
- data/lib/sequel/extensions/schema_dumper.rb +227 -31
- data/lib/sequel/extensions/select_remove.rb +35 -0
- data/lib/sequel/extensions/sql_expr.rb +4 -110
- data/lib/sequel/extensions/to_dot.rb +1 -1
- data/lib/sequel/model.rb +11 -2
- data/lib/sequel/model/associations.rb +35 -7
- data/lib/sequel/model/base.rb +159 -36
- data/lib/sequel/no_core_ext.rb +2 -0
- data/lib/sequel/plugins/caching.rb +25 -18
- data/lib/sequel/plugins/composition.rb +1 -1
- data/lib/sequel/plugins/hook_class_methods.rb +1 -1
- data/lib/sequel/plugins/identity_map.rb +11 -3
- data/lib/sequel/plugins/instance_filters.rb +10 -0
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
- data/lib/sequel/plugins/nested_attributes.rb +4 -3
- data/lib/sequel/plugins/prepared_statements.rb +3 -1
- data/lib/sequel/plugins/prepared_statements_associations.rb +5 -1
- data/lib/sequel/plugins/schema.rb +7 -2
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/static_cache.rb +99 -0
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/sql.rb +417 -7
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/firebird_spec.rb +1 -1
- data/spec/adapters/mssql_spec.rb +12 -15
- data/spec/adapters/mysql_spec.rb +81 -23
- data/spec/adapters/postgres_spec.rb +444 -77
- data/spec/adapters/spec_helper.rb +2 -0
- data/spec/adapters/sqlite_spec.rb +8 -8
- data/spec/core/connection_pool_spec.rb +85 -0
- data/spec/core/database_spec.rb +29 -5
- data/spec/core/dataset_spec.rb +171 -3
- data/spec/core/expression_filters_spec.rb +364 -0
- data/spec/core/mock_adapter_spec.rb +17 -3
- data/spec/core/schema_spec.rb +133 -0
- data/spec/extensions/association_dependencies_spec.rb +13 -13
- data/spec/extensions/caching_spec.rb +26 -3
- data/spec/extensions/class_table_inheritance_spec.rb +2 -2
- data/spec/{core/core_sql_spec.rb → extensions/core_extensions_spec.rb} +23 -94
- data/spec/extensions/force_encoding_spec.rb +4 -2
- data/spec/extensions/hook_class_methods_spec.rb +5 -2
- data/spec/extensions/identity_map_spec.rb +17 -0
- data/spec/extensions/instance_filters_spec.rb +1 -1
- data/spec/extensions/lazy_attributes_spec.rb +2 -2
- data/spec/extensions/list_spec.rb +4 -4
- data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
- data/spec/extensions/migration_spec.rb +6 -2
- data/spec/extensions/nested_attributes_spec.rb +20 -0
- data/spec/extensions/null_dataset_spec.rb +85 -0
- data/spec/extensions/optimistic_locking_spec.rb +2 -2
- data/spec/extensions/pg_array_ops_spec.rb +105 -0
- data/spec/extensions/pg_array_spec.rb +196 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +64 -0
- data/spec/extensions/pg_hstore_ops_spec.rb +136 -0
- data/spec/extensions/pg_hstore_spec.rb +195 -0
- data/spec/extensions/pg_statement_cache_spec.rb +209 -0
- data/spec/extensions/prepared_statements_spec.rb +4 -0
- data/spec/extensions/pretty_table_spec.rb +6 -0
- data/spec/extensions/query_literals_spec.rb +168 -0
- data/spec/extensions/schema_caching_spec.rb +41 -0
- data/spec/extensions/schema_dumper_spec.rb +231 -11
- data/spec/extensions/schema_spec.rb +14 -2
- data/spec/extensions/select_remove_spec.rb +38 -0
- data/spec/extensions/sharding_spec.rb +6 -6
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +2 -1
- data/spec/extensions/sql_expr_spec.rb +28 -19
- data/spec/extensions/static_cache_spec.rb +145 -0
- data/spec/extensions/touch_spec.rb +1 -1
- data/spec/extensions/typecast_on_load_spec.rb +9 -1
- data/spec/integration/associations_test.rb +6 -6
- data/spec/integration/database_test.rb +1 -1
- data/spec/integration/dataset_test.rb +89 -26
- data/spec/integration/migrator_test.rb +2 -3
- data/spec/integration/model_test.rb +3 -3
- data/spec/integration/plugin_test.rb +85 -22
- data/spec/integration/prepared_statement_test.rb +28 -8
- data/spec/integration/schema_test.rb +78 -7
- data/spec/integration/spec_helper.rb +1 -0
- data/spec/integration/timezone_test.rb +1 -1
- data/spec/integration/transaction_test.rb +4 -6
- data/spec/integration/type_test.rb +2 -2
- data/spec/model/associations_spec.rb +94 -8
- data/spec/model/base_spec.rb +4 -4
- data/spec/model/hooks_spec.rb +2 -2
- data/spec/model/model_spec.rb +19 -7
- data/spec/model/record_spec.rb +135 -58
- data/spec/model/spec_helper.rb +1 -0
- metadata +35 -7
data/lib/sequel/version.rb
CHANGED
@@ -3,7 +3,7 @@ module Sequel
|
|
3
3
|
MAJOR = 3
|
4
4
|
# The minor version of Sequel. Bumped for every non-patch level
|
5
5
|
# release, generally around once a month.
|
6
|
-
MINOR =
|
6
|
+
MINOR = 34
|
7
7
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
8
8
|
# releases that fix regressions from previous versions.
|
9
9
|
TINY = 0
|
data/spec/adapters/mssql_spec.rb
CHANGED
@@ -67,10 +67,10 @@ end
|
|
67
67
|
describe "MSSQL full_text_search" do
|
68
68
|
before do
|
69
69
|
@db = MSSQL_DB
|
70
|
-
@db.drop_table(:posts)
|
70
|
+
@db.drop_table?(:posts)
|
71
71
|
end
|
72
72
|
after do
|
73
|
-
@db.drop_table(:posts)
|
73
|
+
@db.drop_table?(:posts)
|
74
74
|
end
|
75
75
|
|
76
76
|
specify "should support fulltext indexes and full_text_search" do
|
@@ -109,8 +109,7 @@ describe "MSSQL Dataset#output" do
|
|
109
109
|
@ds = @db[:items]
|
110
110
|
end
|
111
111
|
after do
|
112
|
-
@db.drop_table(:items)
|
113
|
-
@db.drop_table(:out)
|
112
|
+
@db.drop_table?(:items, :out)
|
114
113
|
end
|
115
114
|
|
116
115
|
specify "should format OUTPUT clauses without INTO for DELETE statements" do
|
@@ -256,7 +255,7 @@ describe "MSSQL::Dataset#import" do
|
|
256
255
|
@ds = @db[:test]
|
257
256
|
end
|
258
257
|
after do
|
259
|
-
@db.drop_table(:test)
|
258
|
+
@db.drop_table?(:test)
|
260
259
|
end
|
261
260
|
|
262
261
|
specify "#import should work correctly with an arbitrary output value" do
|
@@ -291,7 +290,7 @@ describe "Offset support" do
|
|
291
290
|
@ds.import [:id, :parent_id], [[1,nil],[2,nil],[3,1],[4,1],[5,3],[6,5]]
|
292
291
|
end
|
293
292
|
after do
|
294
|
-
@db.drop_table(:i)
|
293
|
+
@db.drop_table?(:i)
|
295
294
|
end
|
296
295
|
|
297
296
|
specify "should return correct rows" do
|
@@ -314,8 +313,7 @@ describe "Common Table Expressions" do
|
|
314
313
|
@ds.import [:id, :parent_id], [[1,nil],[2,nil],[3,1],[4,1],[5,3],[6,5]]
|
315
314
|
end
|
316
315
|
after do
|
317
|
-
@db.drop_table(:i1)
|
318
|
-
@db.drop_table(:i2)
|
316
|
+
@db.drop_table?(:i1, :i2)
|
319
317
|
end
|
320
318
|
|
321
319
|
specify "using #with should be able to update" do
|
@@ -385,7 +383,7 @@ describe "MSSSQL::Dataset#insert" do
|
|
385
383
|
@ds = @db[:test5]
|
386
384
|
end
|
387
385
|
after do
|
388
|
-
@db.drop_table(:test5)
|
386
|
+
@db.drop_table?(:test5)
|
389
387
|
end
|
390
388
|
|
391
389
|
specify "should have insert_select return nil if disable_insert_output is used" do
|
@@ -424,8 +422,7 @@ describe "MSSSQL::Dataset#into" do
|
|
424
422
|
@db[:t].insert(:id => 1, :value => "test")
|
425
423
|
@db << @db[:t].into(:new).select_sql
|
426
424
|
@db[:new].all.should == [{:id => 1, :value => "test"}]
|
427
|
-
@db.drop_table(:t)
|
428
|
-
@db.drop_table(:new)
|
425
|
+
@db.drop_table?(:t, :new)
|
429
426
|
end
|
430
427
|
end
|
431
428
|
|
@@ -434,7 +431,7 @@ describe "A MSSQL database" do
|
|
434
431
|
@db = MSSQL_DB
|
435
432
|
end
|
436
433
|
after do
|
437
|
-
@db.drop_table(:a)
|
434
|
+
@db.drop_table?(:a)
|
438
435
|
end
|
439
436
|
|
440
437
|
specify "should handle many existing types for set_column_allow_null" do
|
@@ -461,7 +458,7 @@ describe "MSSQL::Database#rename_table" do
|
|
461
458
|
MSSQL_DB.create_table! :'foo bar' do
|
462
459
|
text :name
|
463
460
|
end
|
464
|
-
MSSQL_DB.drop_table :baz
|
461
|
+
MSSQL_DB.drop_table? :baz
|
465
462
|
proc { MSSQL_DB.rename_table 'foo bar', 'baz' }.should_not raise_error
|
466
463
|
end
|
467
464
|
|
@@ -501,7 +498,7 @@ describe "MSSQL::Database#mssql_unicode_strings = false" do
|
|
501
498
|
MSSQL_DB.mssql_unicode_strings = false
|
502
499
|
end
|
503
500
|
after do
|
504
|
-
MSSQL_DB.drop_table(:items)
|
501
|
+
MSSQL_DB.drop_table?(:items)
|
505
502
|
MSSQL_DB.mssql_unicode_strings = true
|
506
503
|
end
|
507
504
|
|
@@ -535,7 +532,7 @@ describe "A MSSQL database adds index with include" do
|
|
535
532
|
end
|
536
533
|
|
537
534
|
after :all do
|
538
|
-
@db.drop_table @table_name
|
535
|
+
@db.drop_table? @table_name
|
539
536
|
end
|
540
537
|
|
541
538
|
cspecify "should be able add index with include" do
|
data/spec/adapters/mysql_spec.rb
CHANGED
@@ -26,9 +26,7 @@ def logger.method_missing(m, msg)
|
|
26
26
|
MYSQL_DB.sqls << msg
|
27
27
|
end
|
28
28
|
MYSQL_DB.loggers = [logger]
|
29
|
-
MYSQL_DB.drop_table(:items
|
30
|
-
MYSQL_DB.drop_table(:dolls) rescue nil
|
31
|
-
MYSQL_DB.drop_table(:booltest) rescue nil
|
29
|
+
MYSQL_DB.drop_table?(:items, :dolls, :booltest)
|
32
30
|
|
33
31
|
SQL_BEGIN = 'BEGIN'
|
34
32
|
SQL_ROLLBACK = 'ROLLBACK'
|
@@ -40,7 +38,7 @@ describe "MySQL", '#create_table' do
|
|
40
38
|
MYSQL_DB.sqls.clear
|
41
39
|
end
|
42
40
|
after do
|
43
|
-
@db.drop_table(:dolls)
|
41
|
+
@db.drop_table?(:dolls)
|
44
42
|
end
|
45
43
|
|
46
44
|
specify "should allow to specify options for MySQL" do
|
@@ -83,7 +81,7 @@ describe "MySQL", '#create_table' do
|
|
83
81
|
@db.schema(:dolls).map{|k, v| v[:auto_increment]}.should == [nil, nil, true]
|
84
82
|
end
|
85
83
|
|
86
|
-
|
84
|
+
cspecify "should support collate with various other column options", :swift do
|
87
85
|
@db.create_table!(:dolls){ String :name, :size=>128, :collate=>:utf8_bin, :default=>'foo', :null=>false, :unique=>true}
|
88
86
|
@db[:dolls].insert
|
89
87
|
@db[:dolls].select_map(:name).should == ["foo"]
|
@@ -113,7 +111,7 @@ if MYSQL_DB.adapter_scheme == :mysql
|
|
113
111
|
end
|
114
112
|
after do
|
115
113
|
@db.convert_tinyint_to_bool = true
|
116
|
-
@db.drop_table(:booltest)
|
114
|
+
@db.drop_table?(:booltest)
|
117
115
|
end
|
118
116
|
|
119
117
|
specify "should consider tinyint(1) datatypes as boolean if set, but not larger tinyints" do
|
@@ -161,7 +159,7 @@ describe "A MySQL dataset" do
|
|
161
159
|
MYSQL_DB.sqls.clear
|
162
160
|
end
|
163
161
|
after do
|
164
|
-
MYSQL_DB.drop_table(:items)
|
162
|
+
MYSQL_DB.drop_table?(:items)
|
165
163
|
end
|
166
164
|
|
167
165
|
specify "should quote columns and tables using back-ticks if quoting identifiers" do
|
@@ -241,6 +239,12 @@ describe "A MySQL dataset" do
|
|
241
239
|
@d.filter(:name => /^bc/).count.should == 1
|
242
240
|
end
|
243
241
|
|
242
|
+
specify "should have explain output" do
|
243
|
+
@d.explain.should be_a_kind_of(String)
|
244
|
+
@d.explain(:extended=>true).should be_a_kind_of(String)
|
245
|
+
@d.explain.should_not == @d.explain(:extended=>true)
|
246
|
+
end
|
247
|
+
|
244
248
|
specify "should correctly literalize strings with comment backslashes in them" do
|
245
249
|
@d.delete
|
246
250
|
proc {@d << {:name => ':\\'}}.should_not raise_error
|
@@ -285,7 +289,7 @@ describe "Dataset#distinct" do
|
|
285
289
|
@ds = @db[:a]
|
286
290
|
end
|
287
291
|
after do
|
288
|
-
@db.drop_table(:a)
|
292
|
+
@db.drop_table?(:a)
|
289
293
|
end
|
290
294
|
|
291
295
|
it "#distinct with arguments should return results distinct on those arguments" do
|
@@ -450,12 +454,12 @@ describe "A MySQL database with table options" do
|
|
450
454
|
Sequel::MySQL.default_collate = 'utf8_general_ci'
|
451
455
|
|
452
456
|
@db = MYSQL_DB
|
453
|
-
@db.drop_table(:items)
|
457
|
+
@db.drop_table?(:items)
|
454
458
|
|
455
459
|
MYSQL_DB.sqls.clear
|
456
460
|
end
|
457
461
|
after do
|
458
|
-
@db.drop_table(:items)
|
462
|
+
@db.drop_table?(:items)
|
459
463
|
|
460
464
|
Sequel::MySQL.default_engine = nil
|
461
465
|
Sequel::MySQL.default_charset = nil
|
@@ -481,12 +485,11 @@ end
|
|
481
485
|
describe "A MySQL database" do
|
482
486
|
before do
|
483
487
|
@db = MYSQL_DB
|
484
|
-
@db.drop_table(:items)
|
488
|
+
@db.drop_table?(:items)
|
485
489
|
MYSQL_DB.sqls.clear
|
486
490
|
end
|
487
491
|
after do
|
488
|
-
@db.drop_table(:items)
|
489
|
-
@db.drop_table(:users) rescue nil
|
492
|
+
@db.drop_table?(:items, :users)
|
490
493
|
end
|
491
494
|
|
492
495
|
specify "should support defaults for boolean columns" do
|
@@ -601,8 +604,7 @@ end
|
|
601
604
|
|
602
605
|
describe "MySQL foreign key support" do
|
603
606
|
after do
|
604
|
-
MYSQL_DB.drop_table(:testfk)
|
605
|
-
MYSQL_DB.drop_table(:testpk) rescue nil
|
607
|
+
MYSQL_DB.drop_table?(:testfk, :testpk)
|
606
608
|
end
|
607
609
|
|
608
610
|
specify "should create table without :key" do
|
@@ -674,11 +676,11 @@ end
|
|
674
676
|
describe "A MySQL database" do
|
675
677
|
before do
|
676
678
|
@db = MYSQL_DB
|
677
|
-
@db.drop_table(:posts)
|
679
|
+
@db.drop_table?(:posts)
|
678
680
|
@db.sqls.clear
|
679
681
|
end
|
680
682
|
after do
|
681
|
-
@db.drop_table(:posts)
|
683
|
+
@db.drop_table?(:posts)
|
682
684
|
end
|
683
685
|
|
684
686
|
specify "should support fulltext indexes and full_text_search" do
|
@@ -750,7 +752,7 @@ describe "MySQL::Dataset#insert and related methods" do
|
|
750
752
|
MYSQL_DB.sqls.clear
|
751
753
|
end
|
752
754
|
after do
|
753
|
-
MYSQL_DB.drop_table(:items)
|
755
|
+
MYSQL_DB.drop_table?(:items)
|
754
756
|
end
|
755
757
|
|
756
758
|
specify "#insert should insert record with default values when no arguments given" do
|
@@ -786,6 +788,62 @@ describe "MySQL::Dataset#insert and related methods" do
|
|
786
788
|
@d.all.should == [{:name => 'abc', :value => 6}, {:name => 'def', :value => 2}]
|
787
789
|
end
|
788
790
|
|
791
|
+
specify "#multi_replace should insert multiple records in a single statement" do
|
792
|
+
@d.multi_replace([{:name => 'abc'}, {:name => 'def'}])
|
793
|
+
|
794
|
+
MYSQL_DB.sqls.should == [
|
795
|
+
SQL_BEGIN,
|
796
|
+
"REPLACE INTO `items` (`name`) VALUES ('abc'), ('def')",
|
797
|
+
SQL_COMMIT
|
798
|
+
]
|
799
|
+
|
800
|
+
@d.all.should == [
|
801
|
+
{:name => 'abc', :value => nil}, {:name => 'def', :value => nil}
|
802
|
+
]
|
803
|
+
end
|
804
|
+
|
805
|
+
specify "#multi_replace should split the list of records into batches if :commit_every option is given" do
|
806
|
+
@d.multi_replace([{:value => 1}, {:value => 2}, {:value => 3}, {:value => 4}],
|
807
|
+
:commit_every => 2)
|
808
|
+
|
809
|
+
MYSQL_DB.sqls.should == [
|
810
|
+
SQL_BEGIN,
|
811
|
+
"REPLACE INTO `items` (`value`) VALUES (1), (2)",
|
812
|
+
SQL_COMMIT,
|
813
|
+
SQL_BEGIN,
|
814
|
+
"REPLACE INTO `items` (`value`) VALUES (3), (4)",
|
815
|
+
SQL_COMMIT
|
816
|
+
]
|
817
|
+
|
818
|
+
@d.all.should == [
|
819
|
+
{:name => nil, :value => 1},
|
820
|
+
{:name => nil, :value => 2},
|
821
|
+
{:name => nil, :value => 3},
|
822
|
+
{:name => nil, :value => 4}
|
823
|
+
]
|
824
|
+
end
|
825
|
+
|
826
|
+
specify "#multi_replace should split the list of records into batches if :slice option is given" do
|
827
|
+
@d.multi_replace([{:value => 1}, {:value => 2}, {:value => 3}, {:value => 4}],
|
828
|
+
:slice => 2)
|
829
|
+
|
830
|
+
MYSQL_DB.sqls.should == [
|
831
|
+
SQL_BEGIN,
|
832
|
+
"REPLACE INTO `items` (`value`) VALUES (1), (2)",
|
833
|
+
SQL_COMMIT,
|
834
|
+
SQL_BEGIN,
|
835
|
+
"REPLACE INTO `items` (`value`) VALUES (3), (4)",
|
836
|
+
SQL_COMMIT
|
837
|
+
]
|
838
|
+
|
839
|
+
@d.all.should == [
|
840
|
+
{:name => nil, :value => 1},
|
841
|
+
{:name => nil, :value => 2},
|
842
|
+
{:name => nil, :value => 3},
|
843
|
+
{:name => nil, :value => 4}
|
844
|
+
]
|
845
|
+
end
|
846
|
+
|
789
847
|
specify "#multi_insert should insert multiple records in a single statement" do
|
790
848
|
@d.multi_insert([{:name => 'abc'}, {:name => 'def'}])
|
791
849
|
|
@@ -916,7 +974,7 @@ describe "MySQL::Dataset#update and related methods" do
|
|
916
974
|
@d = MYSQL_DB[:items]
|
917
975
|
end
|
918
976
|
after do
|
919
|
-
MYSQL_DB.drop_table(:items)
|
977
|
+
MYSQL_DB.drop_table?(:items)
|
920
978
|
end
|
921
979
|
|
922
980
|
specify "#update_ignore should not raise error where normal update would fail" do
|
@@ -937,7 +995,7 @@ describe "MySQL::Dataset#replace" do
|
|
937
995
|
MYSQL_DB.sqls.clear
|
938
996
|
end
|
939
997
|
after do
|
940
|
-
MYSQL_DB.drop_table(:items)
|
998
|
+
MYSQL_DB.drop_table?(:items)
|
941
999
|
end
|
942
1000
|
|
943
1001
|
specify "should use default values if they exist" do
|
@@ -1005,7 +1063,7 @@ describe "MySQL::Dataset#calc_found_rows" do
|
|
1005
1063
|
MYSQL_DB.create_table!(:items){Integer :a}
|
1006
1064
|
end
|
1007
1065
|
after do
|
1008
|
-
MYSQL_DB.drop_table(:items)
|
1066
|
+
MYSQL_DB.drop_table?(:items)
|
1009
1067
|
end
|
1010
1068
|
|
1011
1069
|
specify "should add the SQL_CALC_FOUND_ROWS keyword when selecting" do
|
@@ -1035,7 +1093,7 @@ if MYSQL_DB.adapter_scheme == :mysql or MYSQL_DB.adapter_scheme == :jdbc or MYSQ
|
|
1035
1093
|
MYSQL_DB.sqls.clear
|
1036
1094
|
end
|
1037
1095
|
after do
|
1038
|
-
MYSQL_DB.drop_table(:items)
|
1096
|
+
MYSQL_DB.drop_table?(:items)
|
1039
1097
|
MYSQL_DB.execute('DROP PROCEDURE test_sproc')
|
1040
1098
|
end
|
1041
1099
|
|
@@ -1126,7 +1184,7 @@ if MYSQL_DB.adapter_scheme == :mysql
|
|
1126
1184
|
MYSQL_DB[:b].insert(25)
|
1127
1185
|
end
|
1128
1186
|
after do
|
1129
|
-
MYSQL_DB.drop_table(:a, :b)
|
1187
|
+
MYSQL_DB.drop_table?(:a, :b)
|
1130
1188
|
end
|
1131
1189
|
|
1132
1190
|
specify "should combine all results by default" do
|
@@ -6,6 +6,14 @@ unless defined?(POSTGRES_DB)
|
|
6
6
|
end
|
7
7
|
INTEGRATION_DB = POSTGRES_DB unless defined?(INTEGRATION_DB)
|
8
8
|
|
9
|
+
# Automatic parameterization changes the SQL used, so don't check
|
10
|
+
# for expected SQL if it is being used.
|
11
|
+
if defined?(Sequel::Postgres::AutoParameterize)
|
12
|
+
check_sqls = false
|
13
|
+
else
|
14
|
+
check_sqls = true
|
15
|
+
end
|
16
|
+
|
9
17
|
def POSTGRES_DB.sqls
|
10
18
|
(@sqls ||= [])
|
11
19
|
end
|
@@ -13,7 +21,7 @@ logger = Object.new
|
|
13
21
|
def logger.method_missing(m, msg)
|
14
22
|
POSTGRES_DB.sqls << msg
|
15
23
|
end
|
16
|
-
POSTGRES_DB.loggers
|
24
|
+
POSTGRES_DB.loggers << logger
|
17
25
|
|
18
26
|
#POSTGRES_DB.instance_variable_set(:@server_version, 80100)
|
19
27
|
POSTGRES_DB.create_table! :test do
|
@@ -61,7 +69,6 @@ describe "A PostgreSQL dataset" do
|
|
61
69
|
end
|
62
70
|
|
63
71
|
specify "should quote columns and tables using double quotes if quoting identifiers" do
|
64
|
-
@d.quote_identifiers = true
|
65
72
|
@d.select(:name).sql.should == \
|
66
73
|
'SELECT "name" FROM "test"'
|
67
74
|
|
@@ -89,27 +96,28 @@ describe "A PostgreSQL dataset" do
|
|
89
96
|
@d.select('max(test."name") AS "max_name"'.lit).sql.should == \
|
90
97
|
'SELECT max(test."name") AS "max_name" FROM "test"'
|
91
98
|
|
92
|
-
@d.
|
93
|
-
"
|
99
|
+
@d.insert_sql(:x => :y).should =~ \
|
100
|
+
/\AINSERT INTO "test" \("x"\) VALUES \("y"\)( RETURNING NULL)?\z/
|
94
101
|
|
95
|
-
|
96
|
-
|
102
|
+
if check_sqls
|
103
|
+
@d.select(:test.sql_function(:abc, 'hello')).sql.should == \
|
104
|
+
"SELECT test(\"abc\", 'hello') FROM \"test\""
|
97
105
|
|
98
|
-
|
99
|
-
|
106
|
+
@d.select(:test.sql_function(:abc__def, 'hello')).sql.should == \
|
107
|
+
"SELECT test(\"abc\".\"def\", 'hello') FROM \"test\""
|
100
108
|
|
101
|
-
|
102
|
-
|
109
|
+
@d.select(:test.sql_function(:abc__def, 'hello').as(:x2)).sql.should == \
|
110
|
+
"SELECT test(\"abc\".\"def\", 'hello') AS \"x2\" FROM \"test\""
|
103
111
|
|
104
|
-
|
105
|
-
|
112
|
+
@d.insert_sql(:value => 333).should =~ \
|
113
|
+
/\AINSERT INTO "test" \("value"\) VALUES \(333\)( RETURNING NULL)?\z/
|
106
114
|
|
107
|
-
|
108
|
-
|
115
|
+
@d.disable_insert_returning.insert_sql(:value => 333).should =~ \
|
116
|
+
/\AINSERT INTO "test" \("value"\) VALUES \(333\)\z/
|
117
|
+
end
|
109
118
|
end
|
110
119
|
|
111
120
|
specify "should quote fields correctly when reversing the order if quoting identifiers" do
|
112
|
-
@d.quote_identifiers = true
|
113
121
|
@d.reverse_order(:name).sql.should == \
|
114
122
|
'SELECT * FROM "test" ORDER BY "name" DESC'
|
115
123
|
|
@@ -167,7 +175,7 @@ describe "Dataset#distinct" do
|
|
167
175
|
@ds = @db[:a]
|
168
176
|
end
|
169
177
|
after do
|
170
|
-
@db.drop_table(:a)
|
178
|
+
@db.drop_table?(:a)
|
171
179
|
end
|
172
180
|
|
173
181
|
it "#distinct with arguments should return results distinct on those arguments" do
|
@@ -191,7 +199,7 @@ if POSTGRES_DB.pool.respond_to?(:max_size) and POSTGRES_DB.pool.max_size > 1
|
|
191
199
|
@ds = POSTGRES_DB[:items]
|
192
200
|
end
|
193
201
|
after do
|
194
|
-
POSTGRES_DB.drop_table(:items)
|
202
|
+
POSTGRES_DB.drop_table?(:items)
|
195
203
|
POSTGRES_DB.disconnect
|
196
204
|
end
|
197
205
|
|
@@ -240,27 +248,60 @@ end
|
|
240
248
|
|
241
249
|
describe "A PostgreSQL dataset with a timestamp field" do
|
242
250
|
before do
|
243
|
-
@
|
251
|
+
@db = POSTGRES_DB
|
252
|
+
@d = @db[:test3]
|
244
253
|
@d.delete
|
245
254
|
end
|
255
|
+
after do
|
256
|
+
@db.convert_infinite_timestamps = false if @db.adapter_scheme == :postgres
|
257
|
+
end
|
246
258
|
|
247
|
-
cspecify "should store milliseconds in time fields for Time objects", :do do
|
259
|
+
cspecify "should store milliseconds in time fields for Time objects", :do, :swift do
|
248
260
|
t = Time.now
|
249
261
|
@d << {:value=>1, :time=>t}
|
250
|
-
t2 = @d[:value =>
|
262
|
+
t2 = @d[:value =>1][:time]
|
251
263
|
@d.literal(t2).should == @d.literal(t)
|
252
264
|
t2.strftime('%Y-%m-%d %H:%M:%S').should == t.strftime('%Y-%m-%d %H:%M:%S')
|
253
265
|
t2.is_a?(Time) ? t2.usec : t2.strftime('%N').to_i/1000 == t.usec
|
254
266
|
end
|
255
267
|
|
256
|
-
cspecify "should store milliseconds in time fields for DateTime objects", :do do
|
268
|
+
cspecify "should store milliseconds in time fields for DateTime objects", :do, :swift do
|
257
269
|
t = DateTime.now
|
258
270
|
@d << {:value=>1, :time=>t}
|
259
|
-
t2 = @d[:value =>
|
271
|
+
t2 = @d[:value =>1][:time]
|
260
272
|
@d.literal(t2).should == @d.literal(t)
|
261
273
|
t2.strftime('%Y-%m-%d %H:%M:%S').should == t.strftime('%Y-%m-%d %H:%M:%S')
|
262
274
|
t2.is_a?(Time) ? t2.usec : t2.strftime('%N').to_i/1000 == t.strftime('%N').to_i/1000
|
263
275
|
end
|
276
|
+
|
277
|
+
if POSTGRES_DB.adapter_scheme == :postgres
|
278
|
+
specify "should handle infinite timestamps if convert_infinite_timestamps is set" do
|
279
|
+
@d << {:time=>'infinity'.cast(:timestamp)}
|
280
|
+
@db.convert_infinite_timestamps = :nil
|
281
|
+
@db[:test3].get(:time).should == nil
|
282
|
+
@db.convert_infinite_timestamps = :string
|
283
|
+
@db[:test3].get(:time).should == 'infinity'
|
284
|
+
@db.convert_infinite_timestamps = :float
|
285
|
+
@db[:test3].get(:time).should == 1.0/0.0
|
286
|
+
|
287
|
+
@d.update(:time=>'-infinity'.cast(:timestamp))
|
288
|
+
@db.convert_infinite_timestamps = :nil
|
289
|
+
@db[:test3].get(:time).should == nil
|
290
|
+
@db.convert_infinite_timestamps = :string
|
291
|
+
@db[:test3].get(:time).should == '-infinity'
|
292
|
+
@db.convert_infinite_timestamps = :float
|
293
|
+
@db[:test3].get(:time).should == -1.0/0.0
|
294
|
+
end
|
295
|
+
|
296
|
+
specify "should handle conversions from infinite strings/floats in models" do
|
297
|
+
c = Class.new(Sequel::Model(:test3))
|
298
|
+
@db.convert_infinite_timestamps = :float
|
299
|
+
c.new(:time=>'infinity').time.should == 'infinity'
|
300
|
+
c.new(:time=>'-infinity').time.should == '-infinity'
|
301
|
+
c.new(:time=>1.0/0.0).time.should == 1.0/0.0
|
302
|
+
c.new(:time=>-1.0/0.0).time.should == -1.0/0.0
|
303
|
+
end
|
304
|
+
end
|
264
305
|
end
|
265
306
|
|
266
307
|
describe "PostgreSQL's EXPLAIN and ANALYZE" do
|
@@ -317,11 +358,11 @@ end
|
|
317
358
|
describe "A PostgreSQL database" do
|
318
359
|
before do
|
319
360
|
@db = POSTGRES_DB
|
320
|
-
@db.drop_table(:posts)
|
361
|
+
@db.drop_table?(:posts)
|
321
362
|
@db.sqls.clear
|
322
363
|
end
|
323
364
|
after do
|
324
|
-
@db.drop_table(:posts)
|
365
|
+
@db.drop_table?(:posts)
|
325
366
|
end
|
326
367
|
|
327
368
|
specify "should support resetting the primary key sequence" do
|
@@ -364,9 +405,9 @@ describe "A PostgreSQL database" do
|
|
364
405
|
@db.create_table(:posts){text :title; text :body; full_text_index [:title, :body]; full_text_index :title, :language => 'french'}
|
365
406
|
@db.sqls.should == [
|
366
407
|
%{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", ''))))}
|
369
|
-
]
|
408
|
+
%{CREATE INDEX "posts_title_body_index" ON "posts" USING gin (to_tsvector('simple'::regconfig, (COALESCE("title", '') || ' ' || COALESCE("body", ''))))},
|
409
|
+
%{CREATE INDEX "posts_title_index" ON "posts" USING gin (to_tsvector('french'::regconfig, (COALESCE("title", ''))))}
|
410
|
+
] if check_sqls
|
370
411
|
|
371
412
|
@db[:posts].insert(:title=>'ruby rails', :body=>'yowsa')
|
372
413
|
@db[:posts].insert(:title=>'sequel', :body=>'ruby')
|
@@ -377,9 +418,9 @@ describe "A PostgreSQL database" do
|
|
377
418
|
@db[:posts].full_text_search([:title, :body], ['yowsa', 'rails']).all.should == [:title=>'ruby rails', :body=>'yowsa']
|
378
419
|
@db[:posts].full_text_search(:title, 'scooby', :language => 'french').all.should == [{:title=>'ruby scooby', :body=>'x'}]
|
379
420
|
@db.sqls.should == [
|
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'))}]
|
421
|
+
%{SELECT * FROM "posts" WHERE (to_tsvector('simple'::regconfig, (COALESCE("title", ''))) @@ to_tsquery('simple'::regconfig, 'rails'))},
|
422
|
+
%{SELECT * FROM "posts" WHERE (to_tsvector('simple'::regconfig, (COALESCE("title", '') || ' ' || COALESCE("body", ''))) @@ to_tsquery('simple'::regconfig, 'yowsa | rails'))},
|
423
|
+
%{SELECT * FROM "posts" WHERE (to_tsvector('french'::regconfig, (COALESCE("title", ''))) @@ to_tsquery('french'::regconfig, 'scooby'))}] if check_sqls
|
383
424
|
|
384
425
|
@db[:posts].full_text_search(:title, :$n).call(:select, :n=>'rails').should == [{:title=>'ruby rails', :body=>'yowsa'}]
|
385
426
|
@db[:posts].full_text_search(:title, :$n).prepare(:select, :fts_select).call(:n=>'rails').should == [{:title=>'ruby rails', :body=>'yowsa'}]
|
@@ -439,13 +480,13 @@ describe "Postgres::Dataset#import" do
|
|
439
480
|
@ds = @db[:test]
|
440
481
|
end
|
441
482
|
after do
|
442
|
-
@db.drop_table(:test)
|
483
|
+
@db.drop_table?(:test)
|
443
484
|
end
|
444
485
|
|
445
486
|
specify "#import should return separate insert statements if server_version < 80200" do
|
446
487
|
@ds.meta_def(:server_version){80199}
|
447
488
|
@ds.import([:x, :y], [[1, 2], [3, 4]])
|
448
|
-
@db.sqls.should == ['BEGIN', 'INSERT INTO "test" ("x", "y") VALUES (1, 2)', 'INSERT INTO "test" ("x", "y") VALUES (3, 4)', 'COMMIT']
|
489
|
+
@db.sqls.should == ['BEGIN', 'INSERT INTO "test" ("x", "y") VALUES (1, 2)', 'INSERT INTO "test" ("x", "y") VALUES (3, 4)', 'COMMIT'] if check_sqls
|
449
490
|
@ds.all.should == [{:x=>1, :y=>2}, {:x=>3, :y=>4}]
|
450
491
|
end
|
451
492
|
|
@@ -495,7 +536,7 @@ describe "Postgres::Dataset#insert" do
|
|
495
536
|
@ds = @db[:test5]
|
496
537
|
end
|
497
538
|
after do
|
498
|
-
@db.drop_table(:test5)
|
539
|
+
@db.drop_table?(:test5)
|
499
540
|
end
|
500
541
|
|
501
542
|
specify "should work with static SQL" do
|
@@ -516,7 +557,7 @@ describe "Postgres::Dataset#insert" do
|
|
516
557
|
"SELECT currval('\"public\".test5_xid_seq')",
|
517
558
|
'INSERT INTO "test5" ("value") VALUES (13)',
|
518
559
|
"SELECT currval('\"public\".test5_xid_seq')"
|
519
|
-
]
|
560
|
+
] if check_sqls
|
520
561
|
@ds.all.should == [{:xid=>1, :value=>10}, {:xid=>2, :value=>20}, {:xid=>3, :value=>13}]
|
521
562
|
end
|
522
563
|
|
@@ -540,7 +581,7 @@ describe "Postgres::Dataset#insert" do
|
|
540
581
|
specify "should use INSERT RETURNING if server_version >= 80200" do
|
541
582
|
@ds.meta_def(:server_version){80201}
|
542
583
|
@ds.insert(:value=>10).should == 1
|
543
|
-
@db.sqls.last.should == 'INSERT INTO "test5" ("value") VALUES (10) RETURNING "xid"'
|
584
|
+
@db.sqls.last.should == 'INSERT INTO "test5" ("value") VALUES (10) RETURNING "xid"' if check_sqls
|
544
585
|
end
|
545
586
|
|
546
587
|
specify "should have insert_select return nil if server_version < 80200" do
|
@@ -582,7 +623,6 @@ describe "Postgres::Database schema qualified tables" do
|
|
582
623
|
POSTGRES_DB.instance_variable_set(:@primary_key_sequences, {})
|
583
624
|
end
|
584
625
|
after do
|
585
|
-
POSTGRES_DB.quote_identifiers = false
|
586
626
|
POSTGRES_DB << "DROP SCHEMA schema_test CASCADE"
|
587
627
|
POSTGRES_DB.default_schema = nil
|
588
628
|
end
|
@@ -638,7 +678,7 @@ describe "Postgres::Database schema qualified tables" do
|
|
638
678
|
POSTGRES_DB.schema(:public__domains).map{|x| x.first}.should == [:d]
|
639
679
|
POSTGRES_DB.schema(:schema_test__domains).map{|x| x.first}.should == [:i]
|
640
680
|
ensure
|
641
|
-
POSTGRES_DB.drop_table(:public__domains)
|
681
|
+
POSTGRES_DB.drop_table?(:public__domains)
|
642
682
|
end
|
643
683
|
end
|
644
684
|
|
@@ -658,7 +698,6 @@ describe "Postgres::Database schema qualified tables" do
|
|
658
698
|
end
|
659
699
|
|
660
700
|
specify "should be able to get serial sequences for tables that have spaces in the name in a given schema" do
|
661
|
-
POSTGRES_DB.quote_identifiers = true
|
662
701
|
POSTGRES_DB.create_table(:"schema_test__schema test"){primary_key :i}
|
663
702
|
POSTGRES_DB.primary_key_sequence(:"schema_test__schema test").should == '"schema_test"."schema test_i_seq"'
|
664
703
|
end
|
@@ -670,7 +709,6 @@ describe "Postgres::Database schema qualified tables" do
|
|
670
709
|
end
|
671
710
|
|
672
711
|
specify "should be able to get custom sequences for tables that have spaces in the name in a given schema" do
|
673
|
-
POSTGRES_DB.quote_identifiers = true
|
674
712
|
POSTGRES_DB << "CREATE SEQUENCE schema_test.\"ks eq\""
|
675
713
|
POSTGRES_DB.create_table(:"schema_test__schema test"){integer :j; primary_key :k, :type=>:integer, :default=>"nextval('schema_test.\"ks eq\"'::regclass)".lit}
|
676
714
|
POSTGRES_DB.primary_key_sequence(:"schema_test__schema test").should == '"schema_test"."ks eq"'
|
@@ -691,7 +729,6 @@ describe "Postgres::Database schema qualified tables and eager graphing" do
|
|
691
729
|
@db = POSTGRES_DB
|
692
730
|
@db.run "DROP SCHEMA s CASCADE" rescue nil
|
693
731
|
@db.run "CREATE SCHEMA s"
|
694
|
-
@db.quote_identifiers = true
|
695
732
|
|
696
733
|
@db.create_table(:s__bands){primary_key :id; String :name}
|
697
734
|
@db.create_table(:s__albums){primary_key :id; String :name; foreign_key :band_id, :s__bands}
|
@@ -733,7 +770,6 @@ describe "Postgres::Database schema qualified tables and eager graphing" do
|
|
733
770
|
@m4 = @Member.create(:name=>"JC", :band=>@b2)
|
734
771
|
end
|
735
772
|
after(:all) do
|
736
|
-
@db.quote_identifiers = false
|
737
773
|
@db.run "DROP SCHEMA s CASCADE"
|
738
774
|
end
|
739
775
|
|
@@ -916,7 +952,7 @@ if POSTGRES_DB.dataset.supports_window_functions?
|
|
916
952
|
@ds.insert(:id=>6, :group_id=>2, :amount=>100000)
|
917
953
|
end
|
918
954
|
after do
|
919
|
-
@db.drop_table(:i1)
|
955
|
+
@db.drop_table?(:i1)
|
920
956
|
end
|
921
957
|
|
922
958
|
specify "should give correct results for window functions" do
|
@@ -941,7 +977,7 @@ describe "Postgres::Database functions, languages, schemas, and triggers" do
|
|
941
977
|
@d.drop_function('tf', :if_exists=>true, :cascade=>true, :args=>%w'integer integer')
|
942
978
|
@d.drop_language(:plpgsql, :if_exists=>true, :cascade=>true) if @d.server_version < 90000
|
943
979
|
@d.drop_schema(:sequel, :if_exists=>true, :cascade=>true)
|
944
|
-
@d.drop_table(:test)
|
980
|
+
@d.drop_table?(:test)
|
945
981
|
end
|
946
982
|
|
947
983
|
specify "#create_function and #drop_function should create and drop functions" do
|
@@ -983,9 +1019,9 @@ describe "Postgres::Database functions, languages, schemas, and triggers" do
|
|
983
1019
|
end
|
984
1020
|
|
985
1021
|
specify "#create_schema and #drop_schema should create and drop schemas" do
|
986
|
-
@d.send(:create_schema_sql, :sequel).should == 'CREATE SCHEMA sequel'
|
987
|
-
@d.send(:drop_schema_sql, :sequel).should == 'DROP SCHEMA sequel'
|
988
|
-
@d.send(:drop_schema_sql, :sequel, :if_exists=>true, :cascade=>true).should == 'DROP SCHEMA IF EXISTS sequel CASCADE'
|
1022
|
+
@d.send(:create_schema_sql, :sequel).should == 'CREATE SCHEMA "sequel"'
|
1023
|
+
@d.send(:drop_schema_sql, :sequel).should == 'DROP SCHEMA "sequel"'
|
1024
|
+
@d.send(:drop_schema_sql, :sequel, :if_exists=>true, :cascade=>true).should == 'DROP SCHEMA IF EXISTS "sequel" CASCADE'
|
989
1025
|
@d.create_schema(:sequel)
|
990
1026
|
@d.create_table(:sequel__test){Integer :a}
|
991
1027
|
if @d.server_version >= 80200
|
@@ -998,7 +1034,7 @@ describe "Postgres::Database functions, languages, schemas, and triggers" do
|
|
998
1034
|
specify "#create_trigger and #drop_trigger should create and drop triggers" do
|
999
1035
|
@d.create_language(:plpgsql) if @d.server_version < 90000
|
1000
1036
|
@d.create_function(:tf, 'BEGIN IF NEW.value IS NULL THEN RAISE EXCEPTION \'Blah\'; END IF; RETURN NEW; END;', :language=>:plpgsql, :returns=>:trigger)
|
1001
|
-
@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()'
|
1037
|
+
@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()'
|
1002
1038
|
@d.create_table(:test){String :name; Integer :value}
|
1003
1039
|
@d.create_trigger(:test, :identity, :tf, :each_row=>true)
|
1004
1040
|
@d[:test].insert(:name=>'a', :value=>1)
|
@@ -1007,10 +1043,10 @@ describe "Postgres::Database functions, languages, schemas, and triggers" do
|
|
1007
1043
|
@d[:test].filter(:name=>'a').all.should == [{:name=>'a', :value=>1}]
|
1008
1044
|
@d[:test].filter(:name=>'a').update(:value=>3)
|
1009
1045
|
@d[:test].filter(:name=>'a').all.should == [{:name=>'a', :value=>3}]
|
1010
|
-
@d.send(:drop_trigger_sql, :test, :identity).should == 'DROP TRIGGER identity ON test'
|
1046
|
+
@d.send(:drop_trigger_sql, :test, :identity).should == 'DROP TRIGGER identity ON "test"'
|
1011
1047
|
@d.drop_trigger(:test, :identity)
|
1012
|
-
@d.send(:create_trigger_sql, :test, :identity, :tf, :after=>true, :events=>:insert, :args=>[1, 'a']).should == 'CREATE TRIGGER identity AFTER INSERT ON test EXECUTE PROCEDURE tf(1, \'a\')'
|
1013
|
-
@d.send(:drop_trigger_sql, :test, :identity, :if_exists=>true, :cascade=>true).should == 'DROP TRIGGER IF EXISTS identity ON test CASCADE'
|
1048
|
+
@d.send(:create_trigger_sql, :test, :identity, :tf, :after=>true, :events=>:insert, :args=>[1, 'a']).should == 'CREATE TRIGGER identity AFTER INSERT ON "test" EXECUTE PROCEDURE tf(1, \'a\')'
|
1049
|
+
@d.send(:drop_trigger_sql, :test, :identity, :if_exists=>true, :cascade=>true).should == 'DROP TRIGGER IF EXISTS identity ON "test" CASCADE'
|
1014
1050
|
# Make sure if exists works
|
1015
1051
|
@d.drop_trigger(:test, :identity, :if_exists=>true, :cascade=>true)
|
1016
1052
|
end
|
@@ -1026,7 +1062,7 @@ if POSTGRES_DB.adapter_scheme == :postgres
|
|
1026
1062
|
@db.transaction{1001.times{|i| @ds.insert(i)}}
|
1027
1063
|
end
|
1028
1064
|
after(:all) do
|
1029
|
-
@db.drop_table(:test_cursor)
|
1065
|
+
@db.drop_table?(:test_cursor)
|
1030
1066
|
end
|
1031
1067
|
|
1032
1068
|
specify "should return the same results as the non-cursor use" do
|
@@ -1055,23 +1091,17 @@ if POSTGRES_DB.adapter_scheme == :postgres
|
|
1055
1091
|
before do
|
1056
1092
|
@db = POSTGRES_DB
|
1057
1093
|
Sequel::Postgres::PG_NAMED_TYPES[:interval] = lambda{|v| v.reverse}
|
1058
|
-
@db.
|
1059
|
-
disconnect
|
1060
|
-
@conversion_procs = nil
|
1061
|
-
end
|
1094
|
+
@db.reset_conversion_procs
|
1062
1095
|
end
|
1063
1096
|
after do
|
1064
1097
|
Sequel::Postgres::PG_NAMED_TYPES.delete(:interval)
|
1065
|
-
@db.
|
1066
|
-
|
1067
|
-
@conversion_procs = nil
|
1068
|
-
end
|
1069
|
-
@db.drop_table(:foo)
|
1098
|
+
@db.reset_conversion_procs
|
1099
|
+
@db.drop_table?(:foo)
|
1070
1100
|
end
|
1071
1101
|
|
1072
1102
|
specify "should look up conversion procs by name" do
|
1073
1103
|
@db.create_table!(:foo){interval :bar}
|
1074
|
-
@db[:foo].insert('21 days')
|
1104
|
+
@db[:foo].insert('21 days'.cast(:interval))
|
1075
1105
|
@db[:foo].get(:bar).should == 'syad 12'
|
1076
1106
|
end
|
1077
1107
|
end
|
@@ -1087,7 +1117,7 @@ if POSTGRES_DB.adapter_scheme == :postgres && SEQUEL_POSTGRES_USES_PG && POSTGRE
|
|
1087
1117
|
ds.insert(3, 4)
|
1088
1118
|
end
|
1089
1119
|
after(:all) do
|
1090
|
-
@db.drop_table(:test_copy)
|
1120
|
+
@db.drop_table?(:test_copy)
|
1091
1121
|
end
|
1092
1122
|
|
1093
1123
|
specify "without a block or options should return a text version of the table as a single string" do
|
@@ -1111,7 +1141,7 @@ if POSTGRES_DB.adapter_scheme == :postgres && SEQUEL_POSTGRES_USES_PG && POSTGRE
|
|
1111
1141
|
end
|
1112
1142
|
|
1113
1143
|
specify "should accept dataset as first argument" do
|
1114
|
-
@db.copy_table(@db[:test_copy].cross_join(:test_copy___tc).order(
|
1144
|
+
@db.copy_table(@db[:test_copy].cross_join(:test_copy___tc).order(:test_copy__x, :test_copy__y, :tc__x, :tc__y)).should == "1\t2\t1\t2\n1\t2\t3\t4\n3\t4\t1\t2\n3\t4\t3\t4\n"
|
1115
1145
|
end
|
1116
1146
|
|
1117
1147
|
specify "with a block and no options should yield each row as a string in text format" do
|
@@ -1207,11 +1237,11 @@ if POSTGRES_DB.adapter_scheme == :postgres && SEQUEL_POSTGRES_USES_PG && POSTGRE
|
|
1207
1237
|
i = 0
|
1208
1238
|
@db.listen('foo2', :timeout=>0.001, :loop=>proc{i+=1; throw :stop if i > 3}){|ev, pid, payload| called = true}.should == nil
|
1209
1239
|
i.should == 4
|
1210
|
-
end
|
1240
|
+
end unless RUBY_VERSION == '1.9.2' && RUBY_PLATFORM =~ /mingw/ # Ruby freezes on this spec on this platform/version
|
1211
1241
|
end
|
1212
1242
|
end
|
1213
1243
|
|
1214
|
-
describe '
|
1244
|
+
describe 'PostgreSQL special float handling' do
|
1215
1245
|
before do
|
1216
1246
|
@db = POSTGRES_DB
|
1217
1247
|
@db.create_table!(:test5){Float :value}
|
@@ -1219,22 +1249,24 @@ describe 'POSTGRES special float handling' do
|
|
1219
1249
|
@ds = @db[:test5]
|
1220
1250
|
end
|
1221
1251
|
after do
|
1222
|
-
@db.drop_table(:test5)
|
1252
|
+
@db.drop_table?(:test5)
|
1223
1253
|
end
|
1224
1254
|
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1255
|
+
if check_sqls
|
1256
|
+
specify 'should quote NaN' do
|
1257
|
+
nan = 0.0/0.0
|
1258
|
+
@ds.insert_sql(:value => nan).should == %q{INSERT INTO "test5" ("value") VALUES ('NaN')}
|
1259
|
+
end
|
1229
1260
|
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1261
|
+
specify 'should quote +Infinity' do
|
1262
|
+
inf = 1.0/0.0
|
1263
|
+
@ds.insert_sql(:value => inf).should == %q{INSERT INTO "test5" ("value") VALUES ('Infinity')}
|
1264
|
+
end
|
1234
1265
|
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1266
|
+
specify 'should quote -Infinity' do
|
1267
|
+
inf = -1.0/0.0
|
1268
|
+
@ds.insert_sql(:value => inf).should == %q{INSERT INTO "test5" ("value") VALUES ('-Infinity')}
|
1269
|
+
end
|
1238
1270
|
end
|
1239
1271
|
|
1240
1272
|
if POSTGRES_DB.adapter_scheme == :postgres
|
@@ -1257,3 +1289,338 @@ describe 'POSTGRES special float handling' do
|
|
1257
1289
|
end
|
1258
1290
|
end
|
1259
1291
|
end
|
1292
|
+
|
1293
|
+
describe 'PostgreSQL array handling' do
|
1294
|
+
before(:all) do
|
1295
|
+
Sequel.extension :pg_array
|
1296
|
+
@db = POSTGRES_DB
|
1297
|
+
@db.extend Sequel::Postgres::PGArray::DatabaseMethods
|
1298
|
+
@ds = @db[:items]
|
1299
|
+
@native = POSTGRES_DB.adapter_scheme == :postgres
|
1300
|
+
end
|
1301
|
+
after do
|
1302
|
+
@db.drop_table?(:items)
|
1303
|
+
end
|
1304
|
+
|
1305
|
+
specify 'insert and retrieve integer and float arrays of various sizes' do
|
1306
|
+
@db.create_table!(:items) do
|
1307
|
+
column :i2, 'int2[]'
|
1308
|
+
column :i4, 'int4[]'
|
1309
|
+
column :i8, 'int8[]'
|
1310
|
+
column :r, 'real[]'
|
1311
|
+
column :dp, 'double precision[]'
|
1312
|
+
end
|
1313
|
+
@ds.insert([1].pg_array(:int2), [nil, 2].pg_array(:int4), [3, nil].pg_array(:int8), [4, nil, 4.5].pg_array(:real), [5, nil, 5.5].pg_array("double precision"))
|
1314
|
+
@ds.count.should == 1
|
1315
|
+
if @native
|
1316
|
+
rs = @ds.all
|
1317
|
+
rs.should == [{:i2=>[1], :i4=>[nil, 2], :i8=>[3, nil], :r=>[4.0, nil, 4.5], :dp=>[5.0, nil, 5.5]}]
|
1318
|
+
rs.first.values.each{|v| v.should_not be_a_kind_of(Array)}
|
1319
|
+
rs.first.values.each{|v| v.to_a.should be_a_kind_of(Array)}
|
1320
|
+
@ds.delete
|
1321
|
+
@ds.insert(rs.first)
|
1322
|
+
@ds.all.should == rs
|
1323
|
+
|
1324
|
+
@ds.delete
|
1325
|
+
@ds.insert([[1], [2]].pg_array(:int2), [[nil, 2], [3, 4]].pg_array(:int4), [[3, nil], [nil, nil]].pg_array(:int8), [[4, nil], [nil, 4.5]].pg_array(:real), [[5, nil], [nil, 5.5]].pg_array("double precision"))
|
1326
|
+
rs = @ds.all
|
1327
|
+
rs.should == [{:i2=>[[1], [2]], :i4=>[[nil, 2], [3, 4]], :i8=>[[3, nil], [nil, nil]], :r=>[[4, nil], [nil, 4.5]], :dp=>[[5, nil], [nil, 5.5]]}]
|
1328
|
+
rs.first.values.each{|v| v.should_not be_a_kind_of(Array)}
|
1329
|
+
rs.first.values.each{|v| v.to_a.should be_a_kind_of(Array)}
|
1330
|
+
@ds.delete
|
1331
|
+
@ds.insert(rs.first)
|
1332
|
+
@ds.all.should == rs
|
1333
|
+
end
|
1334
|
+
end
|
1335
|
+
|
1336
|
+
specify 'insert and retrieve decimal arrays' do
|
1337
|
+
@db.create_table!(:items) do
|
1338
|
+
column :n, 'numeric[]'
|
1339
|
+
end
|
1340
|
+
@ds.insert([BigDecimal.new('1.000000000000000000001'), nil, BigDecimal.new('1')].pg_array(:numeric))
|
1341
|
+
@ds.count.should == 1
|
1342
|
+
if @native
|
1343
|
+
rs = @ds.all
|
1344
|
+
rs.should == [{:n=>[BigDecimal.new('1.000000000000000000001'), nil, BigDecimal.new('1')]}]
|
1345
|
+
rs.first.values.each{|v| v.should_not be_a_kind_of(Array)}
|
1346
|
+
rs.first.values.each{|v| v.to_a.should be_a_kind_of(Array)}
|
1347
|
+
@ds.delete
|
1348
|
+
@ds.insert(rs.first)
|
1349
|
+
@ds.all.should == rs
|
1350
|
+
|
1351
|
+
@ds.delete
|
1352
|
+
@ds.insert([[BigDecimal.new('1.0000000000000000000000000000001'), nil], [nil, BigDecimal.new('1')]].pg_array(:numeric))
|
1353
|
+
rs = @ds.all
|
1354
|
+
rs.should == [{:n=>[[BigDecimal.new('1.0000000000000000000000000000001'), nil], [nil, BigDecimal.new('1')]]}]
|
1355
|
+
rs.first.values.each{|v| v.should_not be_a_kind_of(Array)}
|
1356
|
+
rs.first.values.each{|v| v.to_a.should be_a_kind_of(Array)}
|
1357
|
+
@ds.delete
|
1358
|
+
@ds.insert(rs.first)
|
1359
|
+
@ds.all.should == rs
|
1360
|
+
end
|
1361
|
+
end
|
1362
|
+
|
1363
|
+
specify 'insert and retrieve string arrays' do
|
1364
|
+
@db.create_table!(:items) do
|
1365
|
+
column :c, 'char(4)[]'
|
1366
|
+
column :vc, 'varchar[]'
|
1367
|
+
column :t, 'text[]'
|
1368
|
+
end
|
1369
|
+
@ds.insert(['a', nil, 'NULL', 'b"\'c'].pg_array('char(4)'), ['a', nil, 'NULL', 'b"\'c'].pg_array(:varchar), ['a', nil, 'NULL', 'b"\'c'].pg_array(:text))
|
1370
|
+
@ds.count.should == 1
|
1371
|
+
if @native
|
1372
|
+
rs = @ds.all
|
1373
|
+
rs.should == [{:c=>['a ', nil, 'NULL', 'b"\'c'], :vc=>['a', nil, 'NULL', 'b"\'c'], :t=>['a', nil, 'NULL', 'b"\'c']}]
|
1374
|
+
rs.first.values.each{|v| v.should_not be_a_kind_of(Array)}
|
1375
|
+
rs.first.values.each{|v| v.to_a.should be_a_kind_of(Array)}
|
1376
|
+
@ds.delete
|
1377
|
+
@ds.insert(rs.first)
|
1378
|
+
@ds.all.should == rs
|
1379
|
+
|
1380
|
+
@ds.delete
|
1381
|
+
@ds.insert([[['a'], [nil]], [['NULL'], ['b"\'c']]].pg_array('char(4)'), [[['a'], ['']], [['NULL'], ['b"\'c']]].pg_array(:varchar), [[['a'], [nil]], [['NULL'], ['b"\'c']]].pg_array(:text))
|
1382
|
+
rs = @ds.all
|
1383
|
+
rs.should == [{:c=>[[['a '], [nil]], [['NULL'], ['b"\'c']]], :vc=>[[['a'], ['']], [['NULL'], ['b"\'c']]], :t=>[[['a'], [nil]], [['NULL'], ['b"\'c']]]}]
|
1384
|
+
rs.first.values.each{|v| v.should_not be_a_kind_of(Array)}
|
1385
|
+
rs.first.values.each{|v| v.to_a.should be_a_kind_of(Array)}
|
1386
|
+
@ds.delete
|
1387
|
+
@ds.insert(rs.first)
|
1388
|
+
@ds.all.should == rs
|
1389
|
+
end
|
1390
|
+
end
|
1391
|
+
|
1392
|
+
specify 'use arrays in bound variables' do
|
1393
|
+
@db.create_table!(:items) do
|
1394
|
+
column :i, 'int4[]'
|
1395
|
+
end
|
1396
|
+
@ds.call(:insert, {:i=>[1,2]}, {:i=>:$i})
|
1397
|
+
@ds.get(:i).should == [1, 2]
|
1398
|
+
@ds.filter(:i=>:$i).call(:first, :i=>[1,2]).should == {:i=>[1,2]}
|
1399
|
+
@ds.filter(:i=>:$i).call(:first, :i=>[1,3]).should == nil
|
1400
|
+
|
1401
|
+
@db.create_table!(:items) do
|
1402
|
+
column :i, 'text[]'
|
1403
|
+
end
|
1404
|
+
a = ["\"\\\\\"{}\n\t\r \v\b123afP", 'NULL', nil, '']
|
1405
|
+
@ds.call(:insert, {:i=>:$i}, :i=>a.pg_array)
|
1406
|
+
@ds.get(:i).should == a
|
1407
|
+
@ds.filter(:i=>:$i).call(:first, :i=>a).should == {:i=>a}
|
1408
|
+
@ds.filter(:i=>:$i).call(:first, :i=>['', nil, nil, 'a']).should == nil
|
1409
|
+
end if POSTGRES_DB.adapter_scheme == :postgres && SEQUEL_POSTGRES_USES_PG
|
1410
|
+
|
1411
|
+
specify 'with models' do
|
1412
|
+
@db.create_table!(:items) do
|
1413
|
+
primary_key :id
|
1414
|
+
column :i, 'integer[]'
|
1415
|
+
column :f, 'double precision[]'
|
1416
|
+
column :d, 'numeric[]'
|
1417
|
+
column :t, 'text[]'
|
1418
|
+
end
|
1419
|
+
c = Class.new(Sequel::Model(@db[:items]))
|
1420
|
+
c.plugin :typecast_on_load, :i, :f, :d, :t unless @native
|
1421
|
+
o = c.create(:i=>[1,2, nil], :f=>[[1, 2.5], [3, 4.5]], :d=>[1, BigDecimal.new('1.000000000000000000001')], :t=>[%w'a b c', ['NULL', nil, '1']])
|
1422
|
+
o.i.should == [1, 2, nil]
|
1423
|
+
o.f.should == [[1, 2.5], [3, 4.5]]
|
1424
|
+
o.d.should == [BigDecimal.new('1'), BigDecimal.new('1.000000000000000000001')]
|
1425
|
+
o.t.should == [%w'a b c', ['NULL', nil, '1']]
|
1426
|
+
end
|
1427
|
+
|
1428
|
+
specify 'operations/functions with pg_array_ops' do
|
1429
|
+
Sequel.extension :pg_array_ops
|
1430
|
+
@db.create_table!(:items){column :i, 'integer[]'; column :i2, 'integer[]'; column :i3, 'integer[]'; column :i4, 'integer[]'; column :i5, 'integer[]'}
|
1431
|
+
@ds.insert([1, 2, 3].pg_array, [2, 1].pg_array, [4, 4].pg_array, [[5, 5], [4, 3]].pg_array, [1, nil, 5].pg_array)
|
1432
|
+
|
1433
|
+
@ds.get(:i.pg_array > :i3).should be_false
|
1434
|
+
@ds.get(:i3.pg_array > :i).should be_true
|
1435
|
+
|
1436
|
+
@ds.get(:i.pg_array >= :i3).should be_false
|
1437
|
+
@ds.get(:i.pg_array >= :i).should be_true
|
1438
|
+
|
1439
|
+
@ds.get(:i3.pg_array < :i).should be_false
|
1440
|
+
@ds.get(:i.pg_array < :i3).should be_true
|
1441
|
+
|
1442
|
+
@ds.get(:i3.pg_array <= :i).should be_false
|
1443
|
+
@ds.get(:i.pg_array <= :i).should be_true
|
1444
|
+
|
1445
|
+
@ds.get({5=>:i.pg_array.any}.sql_expr).should be_false
|
1446
|
+
@ds.get({1=>:i.pg_array.any}.sql_expr).should be_true
|
1447
|
+
|
1448
|
+
@ds.get({1=>:i3.pg_array.all}.sql_expr).should be_false
|
1449
|
+
@ds.get({4=>:i3.pg_array.all}.sql_expr).should be_true
|
1450
|
+
|
1451
|
+
@ds.get(:i2.pg_array[1]).should == 2
|
1452
|
+
@ds.get(:i2.pg_array[2]).should == 1
|
1453
|
+
|
1454
|
+
@ds.get(:i4.pg_array[2][1]).should == 4
|
1455
|
+
@ds.get(:i4.pg_array[2][2]).should == 3
|
1456
|
+
|
1457
|
+
@ds.get(:i.pg_array.contains(:i2)).should be_true
|
1458
|
+
@ds.get(:i.pg_array.contains(:i3)).should be_false
|
1459
|
+
|
1460
|
+
@ds.get(:i2.pg_array.contained_by(:i)).should be_true
|
1461
|
+
@ds.get(:i.pg_array.contained_by(:i2)).should be_false
|
1462
|
+
|
1463
|
+
@ds.get(:i.pg_array.overlaps(:i2)).should be_true
|
1464
|
+
@ds.get(:i2.pg_array.overlaps(:i3)).should be_false
|
1465
|
+
|
1466
|
+
@ds.get(:i.pg_array.dims).should == '[1:3]'
|
1467
|
+
@ds.get(:i.pg_array.length).should == 3
|
1468
|
+
@ds.get(:i.pg_array.lower).should == 1
|
1469
|
+
|
1470
|
+
if @db.server_version >= 90000
|
1471
|
+
@ds.get(:i5.pg_array.join).should == '15'
|
1472
|
+
@ds.get(:i5.pg_array.join(':')).should == '1:5'
|
1473
|
+
@ds.get(:i5.pg_array.join(':', '*')).should == '1:*:5'
|
1474
|
+
end
|
1475
|
+
@ds.select(:i.pg_array.unnest).from_self.count.should == 3 if @db.server_version >= 80400
|
1476
|
+
|
1477
|
+
if @native
|
1478
|
+
@ds.get(:i.pg_array.push(4)).should == [1, 2, 3, 4]
|
1479
|
+
@ds.get(:i.pg_array.unshift(4)).should == [4, 1, 2, 3]
|
1480
|
+
@ds.get(:i.pg_array.concat(:i2)).should == [1, 2, 3, 2, 1]
|
1481
|
+
end
|
1482
|
+
end
|
1483
|
+
end
|
1484
|
+
|
1485
|
+
describe 'PostgreSQL hstore handling' do
|
1486
|
+
before(:all) do
|
1487
|
+
Sequel.extension :pg_hstore
|
1488
|
+
@db = POSTGRES_DB
|
1489
|
+
@db.extend Sequel::Postgres::HStore::DatabaseMethods
|
1490
|
+
@ds = @db[:items]
|
1491
|
+
@h = {'a'=>'b', 'c'=>nil, 'd'=>'NULL', 'e'=>'\\\\" \\\' ,=>'}
|
1492
|
+
@native = POSTGRES_DB.adapter_scheme == :postgres
|
1493
|
+
end
|
1494
|
+
after do
|
1495
|
+
@db.drop_table?(:items)
|
1496
|
+
end
|
1497
|
+
|
1498
|
+
specify 'insert and retrieve hstore values' do
|
1499
|
+
@db.create_table!(:items) do
|
1500
|
+
column :h, :hstore
|
1501
|
+
end
|
1502
|
+
@ds.insert(@h.hstore)
|
1503
|
+
@ds.count.should == 1
|
1504
|
+
if @native
|
1505
|
+
rs = @ds.all
|
1506
|
+
v = rs.first[:h]
|
1507
|
+
v.should_not be_a_kind_of(Hash)
|
1508
|
+
v.to_hash.should be_a_kind_of(Hash)
|
1509
|
+
v.to_hash.should == @h
|
1510
|
+
@ds.delete
|
1511
|
+
@ds.insert(rs.first)
|
1512
|
+
@ds.all.should == rs
|
1513
|
+
end
|
1514
|
+
end
|
1515
|
+
|
1516
|
+
specify 'use hstore in bound variables' do
|
1517
|
+
@db.create_table!(:items) do
|
1518
|
+
column :i, :hstore
|
1519
|
+
end
|
1520
|
+
@ds.call(:insert, {:i=>@h.hstore}, {:i=>:$i})
|
1521
|
+
@ds.get(:i).should == @h
|
1522
|
+
@ds.filter(:i=>:$i).call(:first, :i=>@h.hstore).should == {:i=>@h}
|
1523
|
+
@ds.filter(:i=>:$i).call(:first, :i=>{}.hstore).should == nil
|
1524
|
+
|
1525
|
+
@ds.delete
|
1526
|
+
@ds.call(:insert, {:i=>@h}, {:i=>:$i})
|
1527
|
+
@ds.get(:i).should == @h
|
1528
|
+
@ds.filter(:i=>:$i).call(:first, :i=>@h).should == {:i=>@h}
|
1529
|
+
@ds.filter(:i=>:$i).call(:first, :i=>{}).should == nil
|
1530
|
+
end if POSTGRES_DB.adapter_scheme == :postgres && SEQUEL_POSTGRES_USES_PG
|
1531
|
+
|
1532
|
+
specify 'with models' do
|
1533
|
+
@db.create_table!(:items) do
|
1534
|
+
primary_key :id
|
1535
|
+
column :h, :hstore
|
1536
|
+
end
|
1537
|
+
c = Class.new(Sequel::Model(@db[:items]))
|
1538
|
+
c.plugin :typecast_on_load, :h unless @native
|
1539
|
+
c.create(:h=>@h.hstore).h.should == @h
|
1540
|
+
end
|
1541
|
+
|
1542
|
+
specify 'operations/functions with pg_hstore_ops' do
|
1543
|
+
Sequel.extension :pg_hstore_ops
|
1544
|
+
Sequel.extension :pg_array
|
1545
|
+
Sequel.extension :pg_array_ops
|
1546
|
+
@db.create_table!(:items){hstore :h1; hstore :h2; hstore :h3; String :t}
|
1547
|
+
@ds.insert({'a'=>'b', 'c'=>nil}.hstore, {'a'=>'b'}.hstore, {'d'=>'e'}.hstore)
|
1548
|
+
h1 = :h1.hstore
|
1549
|
+
h2 = :h2.hstore
|
1550
|
+
h3 = :h3.hstore
|
1551
|
+
|
1552
|
+
@ds.get(h1['a']).should == 'b'
|
1553
|
+
@ds.get(h1['d']).should == nil
|
1554
|
+
|
1555
|
+
@ds.get(h2.concat(h3).keys.pg_array.length).should == 2
|
1556
|
+
@ds.get(h1.concat(h3).keys.pg_array.length).should == 3
|
1557
|
+
@ds.get(h2.merge(h3).keys.pg_array.length).should == 2
|
1558
|
+
@ds.get(h1.merge(h3).keys.pg_array.length).should == 3
|
1559
|
+
|
1560
|
+
unless @db.adapter_scheme == :do
|
1561
|
+
# Broken DataObjects thinks operators with ? represent placeholders
|
1562
|
+
@ds.get(h1.contain_all(%w'a c'.pg_array)).should == true
|
1563
|
+
@ds.get(h1.contain_all(%w'a d'.pg_array)).should == false
|
1564
|
+
|
1565
|
+
@ds.get(h1.contain_any(%w'a d'.pg_array)).should == true
|
1566
|
+
@ds.get(h1.contain_any(%w'e d'.pg_array)).should == false
|
1567
|
+
end
|
1568
|
+
|
1569
|
+
@ds.get(h1.contains(h2)).should == true
|
1570
|
+
@ds.get(h1.contains(h3)).should == false
|
1571
|
+
|
1572
|
+
@ds.get(h2.contained_by(h1)).should == true
|
1573
|
+
@ds.get(h2.contained_by(h3)).should == false
|
1574
|
+
|
1575
|
+
@ds.get(h1.defined('a')).should == true
|
1576
|
+
@ds.get(h1.defined('c')).should == false
|
1577
|
+
@ds.get(h1.defined('d')).should == false
|
1578
|
+
|
1579
|
+
@ds.get(h1.delete('a')['c']).should == nil
|
1580
|
+
@ds.get(h1.delete(%w'a d'.pg_array)['c']).should == nil
|
1581
|
+
@ds.get(h1.delete(h2)['c']).should == nil
|
1582
|
+
|
1583
|
+
@ds.from({'a'=>'b', 'c'=>nil}.hstore.op.each).order(:key).all.should == [{:key=>'a', :value=>'b'}, {:key=>'c', :value=>nil}]
|
1584
|
+
|
1585
|
+
unless @db.adapter_scheme == :do
|
1586
|
+
@ds.get(h1.has_key?('c')).should == true
|
1587
|
+
@ds.get(h1.include?('c')).should == true
|
1588
|
+
@ds.get(h1.key?('c')).should == true
|
1589
|
+
@ds.get(h1.member?('c')).should == true
|
1590
|
+
@ds.get(h1.exist?('c')).should == true
|
1591
|
+
@ds.get(h1.has_key?('d')).should == false
|
1592
|
+
@ds.get(h1.include?('d')).should == false
|
1593
|
+
@ds.get(h1.key?('d')).should == false
|
1594
|
+
@ds.get(h1.member?('d')).should == false
|
1595
|
+
@ds.get(h1.exist?('d')).should == false
|
1596
|
+
end
|
1597
|
+
|
1598
|
+
@ds.get(h1.hstore.hstore.hstore.keys.pg_array.length).should == 2
|
1599
|
+
@ds.get(h1.keys.pg_array.length).should == 2
|
1600
|
+
@ds.get(h2.keys.pg_array.length).should == 1
|
1601
|
+
@ds.get(h1.akeys.pg_array.length).should == 2
|
1602
|
+
@ds.get(h2.akeys.pg_array.length).should == 1
|
1603
|
+
|
1604
|
+
@ds.from({'t'=>'s'}.hstore.op.populate(Sequel::SQL::Cast.new(nil, :items))).select_map(:t).should == ['s']
|
1605
|
+
@ds.from(:items___i).select({'t'=>'s'}.hstore.op.record_set(:i).as(:r)).from_self(:alias=>:s).select('(r).*'.lit).from_self.select_map(:t).should == ['s']
|
1606
|
+
|
1607
|
+
@ds.from({'t'=>'s', 'a'=>'b'}.hstore.op.skeys.as(:s)).select_order_map(:s).should == %w'a t'
|
1608
|
+
|
1609
|
+
@ds.get(h1.slice(%w'a c'.pg_array).keys.pg_array.length).should == 2
|
1610
|
+
@ds.get(h1.slice(%w'd c'.pg_array).keys.pg_array.length).should == 1
|
1611
|
+
@ds.get(h1.slice(%w'd e'.pg_array).keys.pg_array.length).should == nil
|
1612
|
+
|
1613
|
+
@ds.from({'t'=>'s', 'a'=>'b'}.hstore.op.svals.as(:s)).select_order_map(:s).should == %w'b s'
|
1614
|
+
|
1615
|
+
@ds.get(h1.to_array.pg_array.length).should == 4
|
1616
|
+
@ds.get(h2.to_array.pg_array.length).should == 2
|
1617
|
+
|
1618
|
+
@ds.get(h1.to_matrix.pg_array.length).should == 2
|
1619
|
+
@ds.get(h2.to_matrix.pg_array.length).should == 1
|
1620
|
+
|
1621
|
+
@ds.get(h1.values.pg_array.length).should == 2
|
1622
|
+
@ds.get(h2.values.pg_array.length).should == 1
|
1623
|
+
@ds.get(h1.avals.pg_array.length).should == 2
|
1624
|
+
@ds.get(h2.avals.pg_array.length).should == 1
|
1625
|
+
end
|
1626
|
+
end if POSTGRES_DB.type_supported?(:hstore)
|