sequel 3.21.0 → 3.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +294 -0
- data/README.rdoc +20 -6
- data/Rakefile +20 -15
- data/doc/association_basics.rdoc +210 -43
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/mass_assignment.rdoc +54 -0
- data/doc/migration.rdoc +15 -538
- data/doc/model_hooks.rdoc +64 -27
- data/doc/opening_databases.rdoc +37 -10
- data/doc/prepared_statements.rdoc +16 -10
- data/doc/reflection.rdoc +8 -2
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/schema_modification.rdoc +547 -0
- data/doc/testing.rdoc +106 -0
- data/doc/transactions.rdoc +97 -0
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/ado.rb +12 -1
- data/lib/sequel/adapters/amalgalite.rb +4 -0
- data/lib/sequel/adapters/db2.rb +95 -58
- data/lib/sequel/adapters/do.rb +12 -0
- data/lib/sequel/adapters/firebird.rb +25 -203
- data/lib/sequel/adapters/ibmdb.rb +440 -0
- data/lib/sequel/adapters/informix.rb +4 -19
- data/lib/sequel/adapters/jdbc/as400.rb +0 -7
- data/lib/sequel/adapters/jdbc/db2.rb +49 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +34 -0
- data/lib/sequel/adapters/jdbc/h2.rb +16 -5
- data/lib/sequel/adapters/jdbc/informix.rb +31 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
- data/lib/sequel/adapters/jdbc/mysql.rb +9 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +2 -27
- data/lib/sequel/adapters/jdbc/postgresql.rb +6 -0
- data/lib/sequel/adapters/jdbc/sqlserver.rb +46 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +34 -0
- data/lib/sequel/adapters/jdbc.rb +62 -29
- data/lib/sequel/adapters/mysql.rb +22 -139
- data/lib/sequel/adapters/mysql2.rb +9 -14
- data/lib/sequel/adapters/odbc/db2.rb +21 -0
- data/lib/sequel/adapters/odbc.rb +15 -3
- data/lib/sequel/adapters/oracle.rb +17 -1
- data/lib/sequel/adapters/postgres.rb +111 -16
- data/lib/sequel/adapters/shared/access.rb +21 -0
- data/lib/sequel/adapters/shared/db2.rb +290 -0
- data/lib/sequel/adapters/shared/firebird.rb +214 -0
- data/lib/sequel/adapters/shared/informix.rb +45 -0
- data/lib/sequel/adapters/shared/mssql.rb +85 -47
- data/lib/sequel/adapters/shared/mysql.rb +50 -7
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +143 -0
- data/lib/sequel/adapters/shared/oracle.rb +0 -4
- data/lib/sequel/adapters/shared/postgres.rb +75 -43
- data/lib/sequel/adapters/shared/sqlite.rb +56 -8
- data/lib/sequel/adapters/sqlite.rb +12 -11
- data/lib/sequel/adapters/swift/mysql.rb +9 -0
- data/lib/sequel/adapters/tinytds.rb +139 -7
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +55 -0
- data/lib/sequel/ast_transformer.rb +190 -0
- data/lib/sequel/connection_pool/threaded.rb +3 -2
- data/lib/sequel/connection_pool.rb +1 -1
- data/lib/sequel/core.rb +6 -5
- data/lib/sequel/database/connecting.rb +5 -5
- data/lib/sequel/database/dataset.rb +1 -1
- data/lib/sequel/database/dataset_defaults.rb +1 -1
- data/lib/sequel/database/logging.rb +1 -1
- data/lib/sequel/database/misc.rb +38 -17
- data/lib/sequel/database/query.rb +50 -19
- data/lib/sequel/database/schema_generator.rb +8 -5
- data/lib/sequel/database/schema_methods.rb +52 -27
- data/lib/sequel/dataset/actions.rb +167 -48
- data/lib/sequel/dataset/features.rb +57 -8
- data/lib/sequel/dataset/graph.rb +1 -1
- data/lib/sequel/dataset/misc.rb +39 -20
- data/lib/sequel/dataset/mutation.rb +3 -3
- data/lib/sequel/dataset/prepared_statements.rb +29 -14
- data/lib/sequel/dataset/query.rb +182 -32
- data/lib/sequel/dataset/sql.rb +31 -58
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/extensions/migration.rb +6 -4
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +893 -309
- data/lib/sequel/model/base.rb +302 -105
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model.rb +13 -7
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/identity_map.rb +113 -6
- data/lib/sequel/plugins/many_through_many.rb +67 -5
- data/lib/sequel/plugins/prepared_statements.rb +140 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
- data/lib/sequel/plugins/sharding.rb +12 -20
- data/lib/sequel/plugins/single_table_inheritance.rb +2 -0
- data/lib/sequel/plugins/update_primary_key.rb +1 -1
- data/lib/sequel/plugins/xml_serializer.rb +3 -3
- data/lib/sequel/sql.rb +107 -51
- data/lib/sequel/timezones.rb +12 -3
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/mssql_spec.rb +36 -0
- data/spec/adapters/mysql_spec.rb +36 -19
- data/spec/adapters/postgres_spec.rb +115 -28
- data/spec/adapters/spec_helper.rb +6 -0
- data/spec/adapters/sqlite_spec.rb +11 -0
- data/spec/core/connection_pool_spec.rb +62 -77
- data/spec/core/database_spec.rb +244 -287
- data/spec/core/dataset_spec.rb +383 -34
- data/spec/core/expression_filters_spec.rb +159 -41
- data/spec/core/schema_spec.rb +326 -3
- data/spec/core/spec_helper.rb +45 -0
- data/spec/extensions/association_pks_spec.rb +38 -0
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/identity_map_spec.rb +162 -0
- data/spec/extensions/many_through_many_spec.rb +195 -20
- data/spec/extensions/migration_spec.rb +17 -17
- data/spec/extensions/nested_attributes_spec.rb +1 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +79 -0
- data/spec/extensions/prepared_statements_spec.rb +72 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
- data/spec/extensions/schema_dumper_spec.rb +2 -2
- data/spec/extensions/schema_spec.rb +12 -20
- data/spec/extensions/serialization_modification_detection_spec.rb +36 -0
- data/spec/extensions/single_table_inheritance_spec.rb +11 -0
- data/spec/extensions/spec_helper.rb +3 -1
- data/spec/extensions/to_dot_spec.rb +3 -5
- data/spec/extensions/xml_serializer_spec.rb +16 -4
- data/spec/integration/associations_test.rb +405 -15
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +240 -20
- data/spec/integration/plugin_test.rb +142 -5
- data/spec/integration/prepared_statement_test.rb +174 -95
- data/spec/integration/schema_test.rb +128 -16
- data/spec/integration/spec_helper.rb +15 -0
- data/spec/integration/transaction_test.rb +40 -0
- data/spec/integration/type_test.rb +16 -2
- data/spec/model/association_reflection_spec.rb +91 -0
- data/spec/model/associations_spec.rb +476 -5
- data/spec/model/base_spec.rb +91 -1
- data/spec/model/eager_loading_spec.rb +519 -31
- data/spec/model/hooks_spec.rb +161 -0
- data/spec/model/model_spec.rb +89 -2
- data/spec/model/plugins_spec.rb +17 -0
- data/spec/model/record_spec.rb +184 -12
- data/spec/model/spec_helper.rb +5 -0
- data/spec/model/validations_spec.rb +11 -0
- metadata +85 -34
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# coding: utf-8
|
|
3
|
+
#Author: Roy L Zuo (roylzuo at gmail dot com)
|
|
4
|
+
#Description:
|
|
5
|
+
|
|
6
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
|
7
|
+
|
|
8
|
+
require ENV['SEQUEL_DB2_SPEC_REQUIRE'] if ENV['SEQUEL_DB2_SPEC_REQUIRE']
|
|
9
|
+
|
|
10
|
+
unless defined?(DB2_DB)
|
|
11
|
+
DB2_DB = Sequel.connect(ENV['SEQUEL_DB2_SPEC_DB']||DB2_URL)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
if DB2_DB.table_exists?(:test)
|
|
15
|
+
DB2_DB.drop_table :test
|
|
16
|
+
end
|
|
17
|
+
INTEGRATION_DB = DB2_DB unless defined?(INTEGRATION_DB)
|
|
18
|
+
|
|
19
|
+
describe Sequel::Database do
|
|
20
|
+
before do
|
|
21
|
+
@db = DB2_DB
|
|
22
|
+
@db.create_table(:test){String :a}
|
|
23
|
+
@ds = @db[:test]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
after do
|
|
27
|
+
@db.drop_table(:test)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
specify "should provide disconnect functionality after preparing a connection" do
|
|
31
|
+
@ds.prepare(:first, :a).call
|
|
32
|
+
@db.disconnect
|
|
33
|
+
@db.pool.size.should == 0
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
specify "should return version correctly" do
|
|
37
|
+
@db.db2_version.should match(/DB2 v/i)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe "Simple Dataset operations" do
|
|
42
|
+
before do
|
|
43
|
+
DB2_DB.create_table!(:items) do
|
|
44
|
+
Integer :id, :primary_key => true
|
|
45
|
+
Integer :number
|
|
46
|
+
end
|
|
47
|
+
@ds = DB2_DB[:items]
|
|
48
|
+
@ds.insert(:number=>10, :id => 1 )
|
|
49
|
+
end
|
|
50
|
+
after do
|
|
51
|
+
DB2_DB.drop_table(:items)
|
|
52
|
+
end
|
|
53
|
+
cspecify "should insert with a primary key specified", :mssql do
|
|
54
|
+
@ds.insert(:id=>100, :number=>20)
|
|
55
|
+
@ds.count.should == 2
|
|
56
|
+
@ds.order(:id).all.should == [{:id=>1, :number=>10}, {:id=>100, :number=>20}]
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe Sequel::Database do
|
|
61
|
+
before do
|
|
62
|
+
@db = DB2_DB
|
|
63
|
+
end
|
|
64
|
+
after do
|
|
65
|
+
@db.drop_table(:items)
|
|
66
|
+
end
|
|
67
|
+
specify "should parse primary keys from the schema properly" do
|
|
68
|
+
@db.create_table!(:items){Integer :number}
|
|
69
|
+
@db.schema(:items).collect{|k,v| k if v[:primary_key]}.compact.should == []
|
|
70
|
+
@db.create_table!(:items){primary_key :number}
|
|
71
|
+
@db.schema(:items).collect{|k,v| k if v[:primary_key]}.compact.should == [:number]
|
|
72
|
+
@db.create_table!(:items){Integer :number1, :null => false; Integer :number2, :null => false; primary_key [:number1, :number2]}
|
|
73
|
+
@db.schema(:items).collect{|k,v| k if v[:primary_key]}.compact.should == [:number1, :number2]
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
describe "Sequel::IBMDB.convert_smallint_to_bool" do
|
|
78
|
+
before do
|
|
79
|
+
@db = DB2_DB
|
|
80
|
+
@db.create_table!(:booltest){column :b, 'smallint'; column :i, 'integer'}
|
|
81
|
+
@ds = @db[:booltest]
|
|
82
|
+
end
|
|
83
|
+
after do
|
|
84
|
+
Sequel::IBMDB.convert_smallint_to_bool = true
|
|
85
|
+
@db.drop_table(:booltest)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
specify "should consider smallint datatypes as boolean if set, but not larger smallints" do
|
|
89
|
+
@db.schema(:booltest, :reload=>true).first.last[:type].should == :boolean
|
|
90
|
+
@db.schema(:booltest, :reload=>true).first.last[:db_type].should match /smallint/i
|
|
91
|
+
Sequel::IBMDB.convert_smallint_to_bool = false
|
|
92
|
+
@db.schema(:booltest, :reload=>true).first.last[:type].should == :integer
|
|
93
|
+
@db.schema(:booltest, :reload=>true).first.last[:db_type].should match /smallint/i
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
specify "should return smallints as bools and integers as integers when set" do
|
|
97
|
+
Sequel::IBMDB.convert_smallint_to_bool = true
|
|
98
|
+
@ds.delete
|
|
99
|
+
@ds << {:b=>true, :i=>10}
|
|
100
|
+
@ds.all.should == [{:b=>true, :i=>10}]
|
|
101
|
+
@ds.delete
|
|
102
|
+
@ds << {:b=>false, :i=>0}
|
|
103
|
+
@ds.all.should == [{:b=>false, :i=>0}]
|
|
104
|
+
@ds.delete
|
|
105
|
+
@ds << {:b=>true, :i=>1}
|
|
106
|
+
@ds.all.should == [{:b=>true, :i=>1}]
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
specify "should return all smallints as integers when unset" do
|
|
110
|
+
Sequel::IBMDB.convert_smallint_to_bool = false
|
|
111
|
+
@ds.delete
|
|
112
|
+
@ds << {:b=>true, :i=>10}
|
|
113
|
+
@ds.all.should == [{:b=>1, :i=>10}]
|
|
114
|
+
@ds.delete
|
|
115
|
+
@ds << {:b=>false, :i=>0}
|
|
116
|
+
@ds.all.should == [{:b=>0, :i=>0}]
|
|
117
|
+
|
|
118
|
+
@ds.delete
|
|
119
|
+
@ds << {:b=>1, :i=>10}
|
|
120
|
+
@ds.all.should == [{:b=>1, :i=>10}]
|
|
121
|
+
@ds.delete
|
|
122
|
+
@ds << {:b=>0, :i=>0}
|
|
123
|
+
@ds.all.should == [{:b=>0, :i=>0}]
|
|
124
|
+
end
|
|
125
|
+
end if DB2_DB.adapter_scheme == :ibmdb
|
|
126
|
+
|
|
127
|
+
describe "Simple Dataset operations in transactions" do
|
|
128
|
+
before do
|
|
129
|
+
DB2_DB.create_table!(:items_insert_in_transaction) do
|
|
130
|
+
Integer :id, :primary_key => true
|
|
131
|
+
integer :number
|
|
132
|
+
end
|
|
133
|
+
@ds = DB2_DB[:items_insert_in_transaction]
|
|
134
|
+
end
|
|
135
|
+
after do
|
|
136
|
+
DB2_DB.drop_table(:items_insert_in_transaction)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
specify "should insert correctly with a primary key specified inside a transaction" do
|
|
140
|
+
DB2_DB.transaction do
|
|
141
|
+
@ds.insert(:id=>100, :number=>20)
|
|
142
|
+
@ds.count.should == 1
|
|
143
|
+
@ds.order(:id).all.should == [{:id=>100, :number=>20}]
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
data/spec/adapters/mssql_spec.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
1
2
|
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
|
2
3
|
|
|
3
4
|
require ENV['SEQUEL_MSSQL_SPEC_REQUIRE'] if ENV['SEQUEL_MSSQL_SPEC_REQUIRE']
|
|
@@ -440,3 +441,38 @@ describe "MSSQL::Dataset#count" do
|
|
|
440
441
|
MSSQL_DB[:items].select(:name, :value).group(:name, :value).order(:name).count.should == 1
|
|
441
442
|
end
|
|
442
443
|
end
|
|
444
|
+
|
|
445
|
+
describe "MSSQL::Database#create_table" do
|
|
446
|
+
specify "should support collate with various other column options" do
|
|
447
|
+
MSSQL_DB.create_table!(:items){ String :name, :size => 128, :collate => :sql_latin1_general_cp1_ci_as, :default => 'foo', :null => false, :unique => true}
|
|
448
|
+
MSSQL_DB[:items].insert
|
|
449
|
+
MSSQL_DB[:items].select_map(:name).should == ["foo"]
|
|
450
|
+
end
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
describe "MSSQL::Database#mssql_unicode_strings = false" do
|
|
454
|
+
before do
|
|
455
|
+
MSSQL_DB.mssql_unicode_strings = false
|
|
456
|
+
end
|
|
457
|
+
after do
|
|
458
|
+
MSSQL_DB.drop_table(:items)
|
|
459
|
+
MSSQL_DB.mssql_unicode_strings = true
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
specify "should work correctly" do
|
|
463
|
+
MSSQL_DB.create_table!(:items){String :name}
|
|
464
|
+
MSSQL_DB[:items].mssql_unicode_strings.should == false
|
|
465
|
+
MSSQL_DB[:items].insert(:name=>'foo')
|
|
466
|
+
MSSQL_DB[:items].select_map(:name).should == ['foo']
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
specify "should be overridable at the dataset level" do
|
|
470
|
+
MSSQL_DB.create_table!(:items){String :name}
|
|
471
|
+
ds = MSSQL_DB[:items]
|
|
472
|
+
ds.mssql_unicode_strings.should == false
|
|
473
|
+
ds.mssql_unicode_strings = true
|
|
474
|
+
ds.mssql_unicode_strings.should == true
|
|
475
|
+
ds.insert(:name=>'foo')
|
|
476
|
+
ds.select_map(:name).should == ['foo']
|
|
477
|
+
end
|
|
478
|
+
end
|
data/spec/adapters/mysql_spec.rb
CHANGED
|
@@ -82,6 +82,12 @@ describe "MySQL", '#create_table' do
|
|
|
82
82
|
end
|
|
83
83
|
@db.schema(:dolls).map{|k, v| v[:auto_increment]}.should == [nil, nil, true]
|
|
84
84
|
end
|
|
85
|
+
|
|
86
|
+
specify "should support collate with various other column options" do
|
|
87
|
+
@db.create_table!(:dolls){ String :name, :size=>128, :collate=>:utf8_bin, :default=>'foo', :null=>false, :unique=>true}
|
|
88
|
+
@db[:dolls].insert
|
|
89
|
+
@db[:dolls].select_map(:name).should == ["foo"]
|
|
90
|
+
end
|
|
85
91
|
end
|
|
86
92
|
|
|
87
93
|
describe "A MySQL database" do
|
|
@@ -950,7 +956,7 @@ describe "MySQL::Dataset#calc_found_rows" do
|
|
|
950
956
|
end
|
|
951
957
|
end
|
|
952
958
|
|
|
953
|
-
if MYSQL_DB.adapter_scheme == :mysql or MYSQL_DB.adapter_scheme == :jdbc
|
|
959
|
+
if MYSQL_DB.adapter_scheme == :mysql or MYSQL_DB.adapter_scheme == :jdbc or MYSQL_DB.adapter_scheme == :mysql2
|
|
954
960
|
describe "MySQL Stored Procedures" do
|
|
955
961
|
before do
|
|
956
962
|
MYSQL_DB.create_table(:items){Integer :id; Integer :value}
|
|
@@ -971,26 +977,37 @@ if MYSQL_DB.adapter_scheme == :mysql or MYSQL_DB.adapter_scheme == :jdbc
|
|
|
971
977
|
MYSQL_DB[:items].count.should == 0
|
|
972
978
|
end
|
|
973
979
|
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
980
|
+
# Mysql2 doesn't support stored procedures that return result sets, probably because
|
|
981
|
+
# CLIENT_MULTI_RESULTS is not set.
|
|
982
|
+
unless MYSQL_DB.adapter_scheme == :mysql2
|
|
983
|
+
specify "should be callable on the dataset object" do
|
|
984
|
+
MYSQL_DB.execute_ddl('CREATE PROCEDURE test_sproc(a INTEGER) BEGIN SELECT *, a AS b FROM items; END')
|
|
985
|
+
MYSQL_DB[:items].delete
|
|
986
|
+
@d = MYSQL_DB[:items]
|
|
987
|
+
@d.call_sproc(:select, :test_sproc, 3).should == []
|
|
988
|
+
@d.insert(:value=>1)
|
|
989
|
+
@d.call_sproc(:select, :test_sproc, 4).should == [{:id=>nil, :value=>1, :b=>4}]
|
|
990
|
+
@d.row_proc = proc{|r| r.keys.each{|k| r[k] *= 2 if r[k].is_a?(Integer)}; r}
|
|
991
|
+
@d.call_sproc(:select, :test_sproc, 3).should == [{:id=>nil, :value=>2, :b=>6}]
|
|
992
|
+
end
|
|
993
|
+
|
|
994
|
+
specify "should be callable on the dataset object with multiple arguments" do
|
|
995
|
+
MYSQL_DB.execute_ddl('CREATE PROCEDURE test_sproc(a INTEGER, c INTEGER) BEGIN SELECT *, a AS b, c AS d FROM items; END')
|
|
996
|
+
MYSQL_DB[:items].delete
|
|
997
|
+
@d = MYSQL_DB[:items]
|
|
998
|
+
@d.call_sproc(:select, :test_sproc, 3, 4).should == []
|
|
999
|
+
@d.insert(:value=>1)
|
|
1000
|
+
@d.call_sproc(:select, :test_sproc, 4, 5).should == [{:id=>nil, :value=>1, :b=>4, :d=>5}]
|
|
1001
|
+
@d.row_proc = proc{|r| r.keys.each{|k| r[k] *= 2 if r[k].is_a?(Integer)}; r}
|
|
1002
|
+
@d.call_sproc(:select, :test_sproc, 3, 4).should == [{:id=>nil, :value=>2, :b=>6, :d => 8}]
|
|
1003
|
+
end
|
|
983
1004
|
end
|
|
984
|
-
|
|
985
|
-
specify "should
|
|
986
|
-
MYSQL_DB.execute_ddl('CREATE PROCEDURE test_sproc(
|
|
1005
|
+
|
|
1006
|
+
specify "should deal with nil values" do
|
|
1007
|
+
MYSQL_DB.execute_ddl('CREATE PROCEDURE test_sproc(i INTEGER, v INTEGER) BEGIN INSERT INTO items VALUES (i, v); END')
|
|
987
1008
|
MYSQL_DB[:items].delete
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
@d.insert(:value=>1)
|
|
991
|
-
@d.call_sproc(:select, :test_sproc, 4, 5).should == [{:id=>nil, :value=>1, :b=>4, :d=>5}]
|
|
992
|
-
@d.row_proc = proc{|r| r.keys.each{|k| r[k] *= 2 if r[k].is_a?(Integer)}; r}
|
|
993
|
-
@d.call_sproc(:select, :test_sproc, 3, 4).should == [{:id=>nil, :value=>2, :b=>6, :d => 8}]
|
|
1009
|
+
MYSQL_DB.call_sproc(:test_sproc, :args=>[1, nil])
|
|
1010
|
+
MYSQL_DB[:items].all.should == [{:id=>1, :value=>nil}]
|
|
994
1011
|
end
|
|
995
1012
|
end
|
|
996
1013
|
end
|
|
@@ -514,11 +514,6 @@ describe "Postgres::Dataset#insert" do
|
|
|
514
514
|
@db.sqls.last.should == 'INSERT INTO test5 (value) VALUES (10) RETURNING xid'
|
|
515
515
|
end
|
|
516
516
|
|
|
517
|
-
specify "should have insert_returning_sql use the RETURNING keyword" do
|
|
518
|
-
@ds.insert_returning_sql(:xid, :value=>10).should == "INSERT INTO test5 (value) VALUES (10) RETURNING xid"
|
|
519
|
-
@ds.insert_returning_sql('*'.lit, :value=>10).should == "INSERT INTO test5 (value) VALUES (10) RETURNING *"
|
|
520
|
-
end
|
|
521
|
-
|
|
522
517
|
specify "should have insert_select return nil if server_version < 80200" do
|
|
523
518
|
@ds.meta_def(:server_version){80100}
|
|
524
519
|
@ds.insert_select(:value=>10).should == nil
|
|
@@ -606,12 +601,6 @@ describe "Postgres::Database schema qualified tables" do
|
|
|
606
601
|
POSTGRES_DB.drop_table(:domains)
|
|
607
602
|
end
|
|
608
603
|
|
|
609
|
-
specify "#table_exists? should not include tables from the default non-public schemas" do
|
|
610
|
-
POSTGRES_DB.create_table(:schema_test__schema_test){integer :i}
|
|
611
|
-
POSTGRES_DB.table_exists?(:schema_test).should == true
|
|
612
|
-
POSTGRES_DB.table_exists?(:domain_udt_usage).should == false
|
|
613
|
-
end
|
|
614
|
-
|
|
615
604
|
specify "#table_exists? should see if the table is in a given schema" do
|
|
616
605
|
POSTGRES_DB.create_table(:schema_test__schema_test){integer :i}
|
|
617
606
|
POSTGRES_DB.table_exists?(:schema_test__schema_test).should == true
|
|
@@ -909,7 +898,7 @@ describe "Postgres::Database functions, languages, and triggers" do
|
|
|
909
898
|
after do
|
|
910
899
|
@d.drop_function('tf', :if_exists=>true, :cascade=>true)
|
|
911
900
|
@d.drop_function('tf', :if_exists=>true, :cascade=>true, :args=>%w'integer integer')
|
|
912
|
-
@d.drop_language(:plpgsql, :if_exists=>true, :cascade=>true)
|
|
901
|
+
@d.drop_language(:plpgsql, :if_exists=>true, :cascade=>true) if @d.server_version < 90000
|
|
913
902
|
@d.drop_table(:test) rescue nil
|
|
914
903
|
end
|
|
915
904
|
|
|
@@ -940,19 +929,19 @@ describe "Postgres::Database functions, languages, and triggers" do
|
|
|
940
929
|
|
|
941
930
|
specify "#create_language and #drop_language should create and drop languages" do
|
|
942
931
|
@d.send(:create_language_sql, :plpgsql).should == 'CREATE LANGUAGE plpgsql'
|
|
943
|
-
@d.create_language(:plpgsql, :replace=>true)
|
|
932
|
+
@d.create_language(:plpgsql, :replace=>true) if @d.server_version < 90000
|
|
944
933
|
proc{@d.create_language(:plpgsql)}.should raise_error(Sequel::DatabaseError)
|
|
945
934
|
@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)
|
|
935
|
+
@d.drop_language(:plpgsql) if @d.server_version < 90000
|
|
936
|
+
proc{@d.drop_language(:plpgsql)}.should raise_error(Sequel::DatabaseError) if @d.server_version < 90000
|
|
948
937
|
@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
938
|
@d.send(:drop_language_sql, :plpgsql, :if_exists=>true, :cascade=>true).should == 'DROP LANGUAGE IF EXISTS plpgsql CASCADE'
|
|
950
939
|
# Make sure if exists works
|
|
951
|
-
@d.drop_language(:plpgsql, :if_exists=>true, :cascade=>true)
|
|
940
|
+
@d.drop_language(:plpgsql, :if_exists=>true, :cascade=>true) if @d.server_version < 90000
|
|
952
941
|
end
|
|
953
942
|
|
|
954
943
|
specify "#create_trigger and #drop_trigger should create and drop triggers" do
|
|
955
|
-
@d.create_language(:plpgsql)
|
|
944
|
+
@d.create_language(:plpgsql) if @d.server_version < 90000
|
|
956
945
|
@d.create_function(:tf, 'BEGIN IF NEW.value IS NULL THEN RAISE EXCEPTION \'Blah\'; END IF; RETURN NEW; END;', :language=>:plpgsql, :returns=>:trigger)
|
|
957
946
|
@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
947
|
@d.create_table(:test){String :name; Integer :value}
|
|
@@ -973,17 +962,17 @@ describe "Postgres::Database functions, languages, and triggers" do
|
|
|
973
962
|
end
|
|
974
963
|
|
|
975
964
|
if POSTGRES_DB.adapter_scheme == :postgres
|
|
976
|
-
describe "Postgres::Dataset #use_cursor" do
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
965
|
+
describe "Postgres::Dataset #use_cursor" do
|
|
966
|
+
before(:all) do
|
|
967
|
+
@db = POSTGRES_DB
|
|
968
|
+
@db.create_table!(:test_cursor){Integer :x}
|
|
969
|
+
@db.sqls.clear
|
|
970
|
+
@ds = @db[:test_cursor]
|
|
971
|
+
@db.transaction{1001.times{|i| @ds.insert(i)}}
|
|
972
|
+
end
|
|
973
|
+
after(:all) do
|
|
974
|
+
@db.drop_table(:test_cursor) rescue nil
|
|
975
|
+
end
|
|
987
976
|
|
|
988
977
|
specify "should return the same results as the non-cursor use" do
|
|
989
978
|
@ds.all.should == @ds.use_cursor.all
|
|
@@ -1005,5 +994,103 @@ describe "Postgres::Dataset #use_cursor" do
|
|
|
1005
994
|
@ds.check_return
|
|
1006
995
|
@ds.all.should == @ds.use_cursor.all
|
|
1007
996
|
end
|
|
997
|
+
end
|
|
998
|
+
|
|
999
|
+
describe "Postgres::PG_NAMED_TYPES" do
|
|
1000
|
+
before do
|
|
1001
|
+
@db = POSTGRES_DB
|
|
1002
|
+
Sequel::Postgres::PG_NAMED_TYPES[:interval] = lambda{|v| v.reverse}
|
|
1003
|
+
@db.instance_eval do
|
|
1004
|
+
disconnect
|
|
1005
|
+
@conversion_procs = nil
|
|
1006
|
+
end
|
|
1007
|
+
end
|
|
1008
|
+
after do
|
|
1009
|
+
Sequel::Postgres::PG_NAMED_TYPES.delete(:interval)
|
|
1010
|
+
@db.instance_eval do
|
|
1011
|
+
disconnect
|
|
1012
|
+
@conversion_procs = nil
|
|
1013
|
+
end
|
|
1014
|
+
@db.drop_table(:foo)
|
|
1015
|
+
end
|
|
1016
|
+
|
|
1017
|
+
specify "should look up conversion procs by name" do
|
|
1018
|
+
@db.create_table!(:foo){interval :bar}
|
|
1019
|
+
@db[:foo].insert('21 days')
|
|
1020
|
+
@db[:foo].get(:bar).should == 'syad 12'
|
|
1021
|
+
end
|
|
1022
|
+
end
|
|
1008
1023
|
end
|
|
1024
|
+
|
|
1025
|
+
if POSTGRES_DB.adapter_scheme == :postgres && SEQUEL_POSTGRES_USES_PG && POSTGRES_DB.server_version >= 90000
|
|
1026
|
+
describe "Postgres::Database#copy_table" do
|
|
1027
|
+
before(:all) do
|
|
1028
|
+
@db = POSTGRES_DB
|
|
1029
|
+
@db.create_table!(:test_copy){Integer :x; Integer :y}
|
|
1030
|
+
ds = @db[:test_copy]
|
|
1031
|
+
ds.insert(1, 2)
|
|
1032
|
+
ds.insert(3, 4)
|
|
1033
|
+
end
|
|
1034
|
+
after(:all) do
|
|
1035
|
+
@db.drop_table(:test_copy) rescue nil
|
|
1036
|
+
end
|
|
1037
|
+
|
|
1038
|
+
specify "without a block or options should return a text version of the table as a single string" do
|
|
1039
|
+
@db.copy_table(:test_copy).should == "1\t2\n3\t4\n"
|
|
1040
|
+
end
|
|
1041
|
+
|
|
1042
|
+
specify "without a block and with :format=>:csv should return a csv version of the table as a single string" do
|
|
1043
|
+
@db.copy_table(:test_copy, :format=>:csv).should == "1,2\n3,4\n"
|
|
1044
|
+
end
|
|
1045
|
+
|
|
1046
|
+
specify "should treat string as SQL code" do
|
|
1047
|
+
@db.copy_table('COPY "test_copy" TO STDOUT').should == "1\t2\n3\t4\n"
|
|
1048
|
+
end
|
|
1049
|
+
|
|
1050
|
+
specify "should respect given :options options" do
|
|
1051
|
+
@db.copy_table(:test_copy, :options=>"FORMAT csv, HEADER TRUE").should == "x,y\n1,2\n3,4\n"
|
|
1052
|
+
end
|
|
1053
|
+
|
|
1054
|
+
specify "should respect given :options options when :format is used" do
|
|
1055
|
+
@db.copy_table(:test_copy, :format=>:csv, :options=>"QUOTE '''', FORCE_QUOTE *").should == "'1','2'\n'3','4'\n"
|
|
1056
|
+
end
|
|
1057
|
+
|
|
1058
|
+
specify "should accept dataset as first argument" do
|
|
1059
|
+
@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"
|
|
1060
|
+
end
|
|
1061
|
+
|
|
1062
|
+
specify "with a block and no options should yield each row as a string in text format" do
|
|
1063
|
+
buf = []
|
|
1064
|
+
@db.copy_table(:test_copy){|b| buf << b}
|
|
1065
|
+
buf.should == ["1\t2\n", "3\t4\n"]
|
|
1066
|
+
end
|
|
1067
|
+
|
|
1068
|
+
specify "with a block and :format=>:csv should yield each row as a string in csv format" do
|
|
1069
|
+
buf = []
|
|
1070
|
+
@db.copy_table(:test_copy, :format=>:csv){|b| buf << b}
|
|
1071
|
+
buf.should == ["1,2\n", "3,4\n"]
|
|
1072
|
+
end
|
|
1073
|
+
|
|
1074
|
+
specify "should work fine when using a block that is terminated early with a following copy_table" do
|
|
1075
|
+
buf = []
|
|
1076
|
+
proc{@db.copy_table(:test_copy, :format=>:csv){|b| buf << b; break}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
1077
|
+
buf.should == ["1,2\n"]
|
|
1078
|
+
buf.clear
|
|
1079
|
+
proc{@db.copy_table(:test_copy, :format=>:csv){|b| buf << b; raise ArgumentError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
1080
|
+
buf.should == ["1,2\n"]
|
|
1081
|
+
buf.clear
|
|
1082
|
+
@db.copy_table(:test_copy){|b| buf << b}
|
|
1083
|
+
buf.should == ["1\t2\n", "3\t4\n"]
|
|
1084
|
+
end
|
|
1085
|
+
|
|
1086
|
+
specify "should work fine when using a block that is terminated early with a following regular query" do
|
|
1087
|
+
buf = []
|
|
1088
|
+
proc{@db.copy_table(:test_copy, :format=>:csv){|b| buf << b; break}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
1089
|
+
buf.should == ["1,2\n"]
|
|
1090
|
+
buf.clear
|
|
1091
|
+
proc{@db.copy_table(:test_copy, :format=>:csv){|b| buf << b; raise ArgumentError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
1092
|
+
buf.should == ["1,2\n"]
|
|
1093
|
+
@db[:test_copy].select_order_map(:x).should == [1, 3]
|
|
1094
|
+
end
|
|
1095
|
+
end
|
|
1009
1096
|
end
|
|
@@ -10,6 +10,11 @@ begin
|
|
|
10
10
|
rescue LoadError
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
+
if ENV['SEQUEL_COLUMNS_INTROSPECTION']
|
|
14
|
+
Sequel.extension :columns_introspection
|
|
15
|
+
Sequel::Dataset.introspect_all_columns
|
|
16
|
+
end
|
|
17
|
+
|
|
13
18
|
class Sequel::Database
|
|
14
19
|
def log_duration(duration, message)
|
|
15
20
|
log_info(message)
|
|
@@ -31,6 +36,7 @@ end
|
|
|
31
36
|
end
|
|
32
37
|
|
|
33
38
|
def self.cspecify(message, *checked, &block)
|
|
39
|
+
return specify(message, &block) if ENV['SEQUEL_NO_PENDING']
|
|
34
40
|
pending = false
|
|
35
41
|
checked.each do |c|
|
|
36
42
|
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)
|