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
|
@@ -2,86 +2,84 @@ require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
|
|
2
2
|
|
|
3
3
|
describe "Prepared Statements and Bound Arguments" do
|
|
4
4
|
before do
|
|
5
|
-
INTEGRATION_DB
|
|
5
|
+
@db = INTEGRATION_DB
|
|
6
|
+
@db.create_table!(:items) do
|
|
6
7
|
primary_key :id
|
|
7
8
|
integer :number
|
|
8
9
|
end
|
|
9
10
|
@c = Class.new(Sequel::Model(:items))
|
|
10
|
-
@ds =
|
|
11
|
+
@ds = @db[:items]
|
|
11
12
|
@ds.insert(:number=>10)
|
|
12
|
-
@ds.meta_def(:ba) do |sym|
|
|
13
|
-
prepared_arg_placeholder == '$' ? :"#{sym}__int" : sym
|
|
14
|
-
end
|
|
15
13
|
end
|
|
16
14
|
after do
|
|
17
|
-
|
|
15
|
+
@db.drop_table(:items)
|
|
18
16
|
end
|
|
19
17
|
|
|
20
18
|
specify "should support bound variables with select, all, and first" do
|
|
21
|
-
@ds.filter(:number
|
|
22
|
-
@ds.filter(:number
|
|
23
|
-
@ds.filter(:number
|
|
19
|
+
@ds.filter(:number=>:$n).call(:select, :n=>10).should == [{:id=>1, :number=>10}]
|
|
20
|
+
@ds.filter(:number=>:$n).call(:all, :n=>10).should == [{:id=>1, :number=>10}]
|
|
21
|
+
@ds.filter(:number=>:$n).call(:first, :n=>10).should == {:id=>1, :number=>10}
|
|
24
22
|
end
|
|
25
23
|
|
|
26
24
|
specify "should support blocks for select and all" do
|
|
27
|
-
@ds.filter(:number
|
|
28
|
-
@ds.filter(:number
|
|
25
|
+
@ds.filter(:number=>:$n).call(:select, :n=>10){|r| r[:number] *= 2}.should == [{:id=>1, :number=>20}]
|
|
26
|
+
@ds.filter(:number=>:$n).call(:all, :n=>10){|r| r[:number] *= 2}.should == [{:id=>1, :number=>20}]
|
|
29
27
|
end
|
|
30
28
|
|
|
31
29
|
specify "should support binding variables before the call with #bind" do
|
|
32
|
-
@ds.filter(:number
|
|
33
|
-
@ds.filter(:number
|
|
34
|
-
@ds.filter(:number
|
|
30
|
+
@ds.filter(:number=>:$n).bind(:n=>10).call(:select).should == [{:id=>1, :number=>10}]
|
|
31
|
+
@ds.filter(:number=>:$n).bind(:n=>10).call(:all).should == [{:id=>1, :number=>10}]
|
|
32
|
+
@ds.filter(:number=>:$n).bind(:n=>10).call(:first).should == {:id=>1, :number=>10}
|
|
35
33
|
|
|
36
|
-
@ds.bind(:n=>10).filter(:number
|
|
37
|
-
@ds.bind(:n=>10).filter(:number
|
|
38
|
-
@ds.bind(:n=>10).filter(:number
|
|
34
|
+
@ds.bind(:n=>10).filter(:number=>:$n).call(:select).should == [{:id=>1, :number=>10}]
|
|
35
|
+
@ds.bind(:n=>10).filter(:number=>:$n).call(:all).should == [{:id=>1, :number=>10}]
|
|
36
|
+
@ds.bind(:n=>10).filter(:number=>:$n).call(:first).should == {:id=>1, :number=>10}
|
|
39
37
|
end
|
|
40
38
|
|
|
41
39
|
specify "should allow overriding variables specified with #bind" do
|
|
42
|
-
@ds.filter(:number
|
|
43
|
-
@ds.filter(:number
|
|
44
|
-
@ds.filter(:number
|
|
40
|
+
@ds.filter(:number=>:$n).bind(:n=>1).call(:select, :n=>10).should == [{:id=>1, :number=>10}]
|
|
41
|
+
@ds.filter(:number=>:$n).bind(:n=>1).call(:all, :n=>10).should == [{:id=>1, :number=>10}]
|
|
42
|
+
@ds.filter(:number=>:$n).bind(:n=>1).call(:first, :n=>10).should == {:id=>1, :number=>10}
|
|
45
43
|
|
|
46
|
-
@ds.filter(:number
|
|
47
|
-
@ds.filter(:number
|
|
48
|
-
@ds.filter(:number
|
|
44
|
+
@ds.filter(:number=>:$n).bind(:n=>1).bind(:n=>10).call(:select).should == [{:id=>1, :number=>10}]
|
|
45
|
+
@ds.filter(:number=>:$n).bind(:n=>1).bind(:n=>10).call(:all).should == [{:id=>1, :number=>10}]
|
|
46
|
+
@ds.filter(:number=>:$n).bind(:n=>1).bind(:n=>10).call(:first).should == {:id=>1, :number=>10}
|
|
49
47
|
end
|
|
50
48
|
|
|
51
49
|
specify "should support placeholder literal strings with call" do
|
|
52
|
-
@ds.filter("number = ?",
|
|
50
|
+
@ds.filter("number = ?", :$n).call(:select, :n=>10).should == [{:id=>1, :number=>10}]
|
|
53
51
|
end
|
|
54
52
|
|
|
55
53
|
specify "should support named placeholder literal strings and handle multiple named placeholders correctly with call" do
|
|
56
|
-
@ds.filter("number = :n", :n
|
|
54
|
+
@ds.filter("number = :n", :n=>:$n).call(:select, :n=>10).should == [{:id=>1, :number=>10}]
|
|
57
55
|
@ds.insert(:number=>20)
|
|
58
56
|
@ds.insert(:number=>30)
|
|
59
|
-
@ds.filter("number > :n1 AND number < :n2 AND number = :n3", :n3
|
|
57
|
+
@ds.filter("number > :n1 AND number < :n2 AND number = :n3", :n3=>:$n3, :n2=>:$n2, :n1=>:$n1).call(:select, :n3=>20, :n2=>30, :n1=>10).should == [{:id=>2, :number=>20}]
|
|
60
58
|
end
|
|
61
59
|
|
|
62
60
|
specify "should support datasets with static sql and placeholders with call" do
|
|
63
|
-
|
|
61
|
+
@db["SELECT * FROM items WHERE number = ?", :$n].call(:select, :n=>10).should == [{:id=>1, :number=>10}]
|
|
64
62
|
end
|
|
65
63
|
|
|
66
64
|
specify "should support subselects with call" do
|
|
67
|
-
@ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number
|
|
65
|
+
@ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>:$n)).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
|
|
68
66
|
end
|
|
69
67
|
|
|
70
68
|
specify "should support subselects with literal strings with call" do
|
|
71
|
-
@ds.filter(:id=>:$i, :number=>@ds.select(:number).filter("number = ?",
|
|
69
|
+
@ds.filter(:id=>:$i, :number=>@ds.select(:number).filter("number = ?", :$n)).call(:select, :n=>10, :i=>1).should == [{:id=>1, :number=>10}]
|
|
72
70
|
end
|
|
73
71
|
|
|
74
72
|
specify "should support subselects with static sql and placeholders with call" do
|
|
75
|
-
@ds.filter(:id=>:$i, :number
|
|
73
|
+
@ds.filter(:id=>:$i, :number=>@db["SELECT number FROM items WHERE number = ?", :$n]).call(:select, :n=>10, :i=>1).should == [{:id=>1, :number=>10}]
|
|
76
74
|
end
|
|
77
75
|
|
|
78
76
|
specify "should support subselects of subselects with call" do
|
|
79
|
-
@ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>@ds.select(:number).filter(:number
|
|
77
|
+
@ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>@ds.select(:number).filter(:number=>:$n))).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
|
|
80
78
|
end
|
|
81
79
|
|
|
82
|
-
|
|
80
|
+
cspecify "should support using a bound variable for a limit and offset", [:jdbc, :db2] do
|
|
83
81
|
@ds.insert(:number=>20)
|
|
84
|
-
ds = @ds.limit(
|
|
82
|
+
ds = @ds.limit(:$n, :$n2).order(:id)
|
|
85
83
|
ds.call(:select, :n=>1, :n2=>0).should == [{:id=>1, :number=>10}]
|
|
86
84
|
ds.call(:select, :n=>1, :n2=>1).should == [{:id=>2, :number=>20}]
|
|
87
85
|
ds.call(:select, :n=>1, :n2=>2).should == []
|
|
@@ -90,74 +88,83 @@ describe "Prepared Statements and Bound Arguments" do
|
|
|
90
88
|
end
|
|
91
89
|
|
|
92
90
|
specify "should support bound variables with insert" do
|
|
93
|
-
@ds.call(:insert, {:n=>20}, :number
|
|
91
|
+
@ds.call(:insert, {:n=>20}, :number=>:$n)
|
|
94
92
|
@ds.count.should == 2
|
|
95
93
|
@ds.order(:id).map(:number).should == [10, 20]
|
|
96
94
|
end
|
|
97
95
|
|
|
96
|
+
specify "should support bound variables with NULL values" do
|
|
97
|
+
@ds.delete
|
|
98
|
+
@ds.call(:insert, {:n=>nil}, :number=>:$n)
|
|
99
|
+
@ds.count.should == 1
|
|
100
|
+
@ds.map(:number).should == [nil]
|
|
101
|
+
end
|
|
102
|
+
|
|
98
103
|
specify "should have insert return primary key value when using bound arguments" do
|
|
99
|
-
@ds.call(:insert, {:n=>20}, :number
|
|
104
|
+
@ds.call(:insert, {:n=>20}, :number=>:$n).should == 2
|
|
100
105
|
@ds.filter(:id=>2).first[:number].should == 20
|
|
101
106
|
end
|
|
102
107
|
|
|
103
108
|
specify "should support bound variables with delete" do
|
|
104
|
-
@ds.filter(:number
|
|
109
|
+
@ds.filter(:number=>:$n).call(:delete, :n=>10).should == 1
|
|
105
110
|
@ds.count.should == 0
|
|
106
111
|
end
|
|
107
112
|
|
|
108
113
|
specify "should support bound variables with update" do
|
|
109
|
-
@ds.filter(:number
|
|
114
|
+
@ds.filter(:number=>:$n).call(:update, {:n=>10, :nn=>20}, :number=>:number+:$nn).should == 1
|
|
110
115
|
@ds.all.should == [{:id=>1, :number=>30}]
|
|
111
116
|
end
|
|
112
117
|
|
|
113
118
|
specify "should support prepared statements with select, first, and all" do
|
|
114
|
-
@ds.filter(:number
|
|
115
|
-
|
|
116
|
-
@ds.filter(:number
|
|
117
|
-
|
|
118
|
-
@ds.filter(:number
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
119
|
+
@ds.filter(:number=>:$n).prepare(:select, :select_n)
|
|
120
|
+
@db.call(:select_n, :n=>10).should == [{:id=>1, :number=>10}]
|
|
121
|
+
@ds.filter(:number=>:$n).prepare(:all, :select_n)
|
|
122
|
+
@db.call(:select_n, :n=>10).should == [{:id=>1, :number=>10}]
|
|
123
|
+
@ds.filter(:number=>:$n).prepare(:first, :select_n)
|
|
124
|
+
@db.call(:select_n, :n=>10).should == {:id=>1, :number=>10}
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
specify "should support prepared statements being call multiple times with different arguments" do
|
|
128
|
+
@ds.filter(:number=>:$n).prepare(:select, :select_n)
|
|
129
|
+
@db.call(:select_n, :n=>10).should == [{:id=>1, :number=>10}]
|
|
130
|
+
@db.call(:select_n, :n=>0).should == []
|
|
131
|
+
@db.call(:select_n, :n=>10).should == [{:id=>1, :number=>10}]
|
|
125
132
|
end
|
|
126
133
|
|
|
127
134
|
specify "should support placeholder literal strings with prepare" do
|
|
128
|
-
@ds.filter("number = ?",
|
|
135
|
+
@ds.filter("number = ?", :$n).prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :number=>10}]
|
|
129
136
|
end
|
|
130
137
|
|
|
131
138
|
specify "should support named placeholder literal strings and handle multiple named placeholders correctly with prepare" do
|
|
132
|
-
@ds.filter("number = :n", :n
|
|
139
|
+
@ds.filter("number = :n", :n=>:$n).prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :number=>10}]
|
|
133
140
|
@ds.insert(:number=>20)
|
|
134
141
|
@ds.insert(:number=>30)
|
|
135
|
-
@ds.filter("number > :n1 AND number < :n2 AND number = :n3", :n3
|
|
142
|
+
@ds.filter("number > :n1 AND number < :n2 AND number = :n3", :n3=>:$n3, :n2=>:$n2, :n1=>:$n1).call(:select, :n3=>20, :n2=>30, :n1=>10).should == [{:id=>2, :number=>20}]
|
|
136
143
|
end
|
|
137
144
|
|
|
138
145
|
specify "should support datasets with static sql and placeholders with prepare" do
|
|
139
|
-
|
|
146
|
+
@db["SELECT * FROM items WHERE number = ?", :$n].prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :number=>10}]
|
|
140
147
|
end
|
|
141
148
|
|
|
142
149
|
specify "should support subselects with prepare" do
|
|
143
|
-
@ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number
|
|
150
|
+
@ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>:$n)).filter(:id=>:$j).prepare(:select, :seq_select).call(:n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
|
|
144
151
|
end
|
|
145
152
|
|
|
146
153
|
specify "should support subselects with literal strings with prepare" do
|
|
147
|
-
@ds.filter(:id=>:$i, :number=>@ds.select(:number).filter("number = ?",
|
|
154
|
+
@ds.filter(:id=>:$i, :number=>@ds.select(:number).filter("number = ?", :$n)).prepare(:select, :seq_select).call(:n=>10, :i=>1).should == [{:id=>1, :number=>10}]
|
|
148
155
|
end
|
|
149
156
|
|
|
150
157
|
specify "should support subselects with static sql and placeholders with prepare" do
|
|
151
|
-
@ds.filter(:id=>:$i, :number
|
|
158
|
+
@ds.filter(:id=>:$i, :number=>@db["SELECT number FROM items WHERE number = ?", :$n]).prepare(:select, :seq_select).call(:n=>10, :i=>1).should == [{:id=>1, :number=>10}]
|
|
152
159
|
end
|
|
153
160
|
|
|
154
161
|
specify "should support subselects of subselects with prepare" do
|
|
155
|
-
@ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>@ds.select(:number).filter(:number
|
|
162
|
+
@ds.filter(:id=>:$i).filter(:number=>@ds.select(:number).filter(:number=>@ds.select(:number).filter(:number=>:$n))).filter(:id=>:$j).prepare(:select, :seq_select).call(:n=>10, :i=>1, :j=>1).should == [{:id=>1, :number=>10}]
|
|
156
163
|
end
|
|
157
164
|
|
|
158
|
-
|
|
165
|
+
cspecify "should support using a prepared_statement for a limit and offset", :db2 do
|
|
159
166
|
@ds.insert(:number=>20)
|
|
160
|
-
ps = @ds.limit(
|
|
167
|
+
ps = @ds.limit(:$n, :$n2).order(:id).prepare(:select, :seq_select)
|
|
161
168
|
ps.call(:n=>1, :n2=>0).should == [{:id=>1, :number=>10}]
|
|
162
169
|
ps.call(:n=>1, :n2=>1).should == [{:id=>2, :number=>20}]
|
|
163
170
|
ps.call(:n=>1, :n2=>2).should == []
|
|
@@ -166,54 +173,58 @@ describe "Prepared Statements and Bound Arguments" do
|
|
|
166
173
|
end
|
|
167
174
|
|
|
168
175
|
specify "should support prepared statements with insert" do
|
|
169
|
-
@ds.prepare(:insert, :insert_n, :number
|
|
170
|
-
|
|
176
|
+
@ds.prepare(:insert, :insert_n, :number=>:$n)
|
|
177
|
+
@db.call(:insert_n, :n=>20)
|
|
171
178
|
@ds.count.should == 2
|
|
172
179
|
@ds.order(:id).map(:number).should == [10, 20]
|
|
173
180
|
end
|
|
174
181
|
|
|
182
|
+
specify "should support prepared statements with NULL values" do
|
|
183
|
+
@ds.delete
|
|
184
|
+
@ds.prepare(:insert, :insert_n, :number=>:$n)
|
|
185
|
+
@db.call(:insert_n, :n=>nil)
|
|
186
|
+
@ds.count.should == 1
|
|
187
|
+
@ds.map(:number).should == [nil]
|
|
188
|
+
end
|
|
189
|
+
|
|
175
190
|
specify "should have insert return primary key value when using prepared statements" do
|
|
176
|
-
@ds.prepare(:insert, :insert_n, :number
|
|
177
|
-
|
|
191
|
+
@ds.prepare(:insert, :insert_n, :number=>:$n)
|
|
192
|
+
@db.call(:insert_n, :n=>20).should == 2
|
|
178
193
|
@ds.filter(:id=>2).first[:number].should == 20
|
|
179
194
|
end
|
|
180
195
|
|
|
181
196
|
specify "should support prepared statements with delete" do
|
|
182
|
-
@ds.filter(:number
|
|
183
|
-
|
|
197
|
+
@ds.filter(:number=>:$n).prepare(:delete, :delete_n)
|
|
198
|
+
@db.call(:delete_n, :n=>10).should == 1
|
|
184
199
|
@ds.count.should == 0
|
|
185
200
|
end
|
|
186
201
|
|
|
187
202
|
specify "should support prepared statements with update" do
|
|
188
|
-
@ds.filter(:number
|
|
189
|
-
|
|
203
|
+
@ds.filter(:number=>:$n).prepare(:update, :update_n, :number=>:number+:$nn)
|
|
204
|
+
@db.call(:update_n, :n=>10, :nn=>20).should == 1
|
|
190
205
|
@ds.all.should == [{:id=>1, :number=>30}]
|
|
191
206
|
end
|
|
192
207
|
|
|
193
208
|
specify "model datasets should return model instances when using select, all, and first with bound variables" do
|
|
194
|
-
@c.filter(:number
|
|
195
|
-
@c.filter(:number
|
|
196
|
-
@c.filter(:number
|
|
209
|
+
@c.filter(:number=>:$n).call(:select, :n=>10).should == [@c.load(:id=>1, :number=>10)]
|
|
210
|
+
@c.filter(:number=>:$n).call(:all, :n=>10).should == [@c.load(:id=>1, :number=>10)]
|
|
211
|
+
@c.filter(:number=>:$n).call(:first, :n=>10).should == @c.load(:id=>1, :number=>10)
|
|
197
212
|
end
|
|
198
213
|
|
|
199
214
|
specify "model datasets should return model instances when using select, all, and first with prepared statements" do
|
|
200
|
-
@c.filter(:number
|
|
201
|
-
|
|
202
|
-
@c.filter(:number
|
|
203
|
-
|
|
204
|
-
@c.filter(:number
|
|
205
|
-
|
|
206
|
-
if INTEGRATION_DB.adapter_scheme == :jdbc and INTEGRATION_DB.database_type == :sqlite
|
|
207
|
-
# Work around for open prepared statements on a table not allowing the
|
|
208
|
-
# dropping of a table when using SQLite over JDBC
|
|
209
|
-
INTEGRATION_DB.synchronize{|c| c.prepared_statements[:select_n][1].close}
|
|
210
|
-
end
|
|
215
|
+
@c.filter(:number=>:$n).prepare(:select, :select_n)
|
|
216
|
+
@db.call(:select_n, :n=>10).should == [@c.load(:id=>1, :number=>10)]
|
|
217
|
+
@c.filter(:number=>:$n).prepare(:all, :select_n)
|
|
218
|
+
@db.call(:select_n, :n=>10).should == [@c.load(:id=>1, :number=>10)]
|
|
219
|
+
@c.filter(:number=>:$n).prepare(:first, :select_n)
|
|
220
|
+
@db.call(:select_n, :n=>10).should == @c.load(:id=>1, :number=>10)
|
|
211
221
|
end
|
|
212
222
|
end
|
|
213
223
|
|
|
214
224
|
describe "Bound Argument Types" do
|
|
215
225
|
before do
|
|
216
|
-
INTEGRATION_DB
|
|
226
|
+
@db = INTEGRATION_DB
|
|
227
|
+
@db.create_table!(:items) do
|
|
217
228
|
primary_key :id
|
|
218
229
|
Date :d
|
|
219
230
|
DateTime :dt
|
|
@@ -223,7 +234,7 @@ describe "Bound Argument Types" do
|
|
|
223
234
|
Float :f
|
|
224
235
|
TrueClass :b
|
|
225
236
|
end
|
|
226
|
-
@ds =
|
|
237
|
+
@ds = @db[:items]
|
|
227
238
|
@vs = {:d=>Date.civil(2010, 10, 11), :dt=>DateTime.civil(2010, 10, 12, 13, 14, 15), :f=>1.0, :s=>'str', :t=>Time.at(20101010), :file=>Sequel::SQL::Blob.new('blob'), :b=>true}
|
|
228
239
|
@ds.insert(@vs)
|
|
229
240
|
@ds.meta_def(:ba) do |sym, type|
|
|
@@ -232,39 +243,107 @@ describe "Bound Argument Types" do
|
|
|
232
243
|
end
|
|
233
244
|
after do
|
|
234
245
|
Sequel.datetime_class = Time
|
|
235
|
-
|
|
236
|
-
INTEGRATION_DB.synchronize{|c| c.prepared_statements.each{|k, ps| ps[1].close}.clear}
|
|
237
|
-
end
|
|
238
|
-
INTEGRATION_DB.drop_table(:items)
|
|
246
|
+
@db.drop_table(:items)
|
|
239
247
|
end
|
|
240
248
|
|
|
241
249
|
cspecify "should handle date type", [:do, :sqlite], :mssql, [:jdbc, :sqlite] do
|
|
242
|
-
@ds.filter(:d
|
|
250
|
+
@ds.filter(:d=>:$x).prepare(:first, :ps_date).call(:x=>@vs[:d])[:d].should == @vs[:d]
|
|
243
251
|
end
|
|
244
252
|
|
|
245
253
|
cspecify "should handle datetime type", [:do], [:mysql2], [:swift], [:jdbc, :sqlite], [:tinytds] do
|
|
246
254
|
Sequel.datetime_class = DateTime
|
|
247
|
-
@ds.filter(:dt
|
|
255
|
+
@ds.filter(:dt=>:$x).prepare(:first, :ps_datetime).call(:x=>@vs[:dt])[:dt].should == @vs[:dt]
|
|
248
256
|
end
|
|
249
257
|
|
|
250
258
|
cspecify "should handle time type", [:do], [:jdbc, :sqlite] do
|
|
251
|
-
@ds.filter(:t
|
|
259
|
+
@ds.filter(:t=>:$x).prepare(:first, :ps_time).call(:x=>@vs[:t])[:t].should == @vs[:t]
|
|
252
260
|
end
|
|
253
261
|
|
|
254
|
-
cspecify "should handle blob type", [:swift] do
|
|
255
|
-
@ds.filter(:file
|
|
262
|
+
cspecify "should handle blob type", [:swift], [:odbc], [:jdbc, :db2] do
|
|
263
|
+
@ds.filter(:file=>:$x).prepare(:first, :ps_blob).call(:x=>@vs[:file])[:file].should == @vs[:file]
|
|
256
264
|
end
|
|
257
265
|
|
|
258
266
|
cspecify "should handle float type", [:swift, :sqlite] do
|
|
259
|
-
@ds.filter(:f
|
|
267
|
+
@ds.filter(:f=>:$x).prepare(:first, :ps_float).call(:x=>@vs[:f])[:f].should == @vs[:f]
|
|
260
268
|
end
|
|
261
269
|
|
|
262
270
|
specify "should handle string type" do
|
|
263
|
-
@ds.filter(:s
|
|
271
|
+
@ds.filter(:s=>:$x).prepare(:first, :ps_string).call(:x=>@vs[:s])[:s].should == @vs[:s]
|
|
264
272
|
end
|
|
265
273
|
|
|
266
|
-
cspecify "should handle boolean type", [:do, :sqlite], [:odbc, :mssql], [:jdbc, :sqlite] do
|
|
267
|
-
@ds.filter(:b
|
|
274
|
+
cspecify "should handle boolean type", [:do, :sqlite], [:odbc, :mssql], [:jdbc, :sqlite], [:jdbc, :db2] do
|
|
275
|
+
@ds.filter(:b=>:$x).prepare(:first, :ps_string).call(:x=>@vs[:b])[:b].should == @vs[:b]
|
|
268
276
|
end
|
|
269
277
|
end unless INTEGRATION_DB.adapter_scheme == :swift && INTEGRATION_DB.database_type == :postgres
|
|
270
278
|
|
|
279
|
+
describe "Dataset#unbind" do
|
|
280
|
+
before do
|
|
281
|
+
@ds = ds = INTEGRATION_DB[:items]
|
|
282
|
+
@ct = proc do |t, v|
|
|
283
|
+
INTEGRATION_DB.create_table!(:items) do
|
|
284
|
+
column :c, t
|
|
285
|
+
end
|
|
286
|
+
ds.insert(:c=>v)
|
|
287
|
+
end
|
|
288
|
+
@u = proc{|ds| ds, bv = ds.unbind; ds.call(:first, bv)}
|
|
289
|
+
end
|
|
290
|
+
after do
|
|
291
|
+
INTEGRATION_DB.drop_table(:items) rescue nil
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
specify "should unbind values assigned to equality and inequality statements" do
|
|
295
|
+
@ct[Integer, 10]
|
|
296
|
+
@u[@ds.filter(:c=>10)].should == {:c=>10}
|
|
297
|
+
@u[@ds.exclude(:c=>10)].should == nil
|
|
298
|
+
@u[@ds.filter{c < 10}].should == nil
|
|
299
|
+
@u[@ds.filter{c <= 10}].should == {:c=>10}
|
|
300
|
+
@u[@ds.filter{c > 10}].should == nil
|
|
301
|
+
@u[@ds.filter{c >= 10}].should == {:c=>10}
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
cspecify "should handle numerics and strings", [:odbc], [:swift, :sqlite] do
|
|
305
|
+
@ct[Integer, 10]
|
|
306
|
+
@u[@ds.filter(:c=>10)].should == {:c=>10}
|
|
307
|
+
@ct[Float, 0.0]
|
|
308
|
+
@u[@ds.filter{c < 1}].should == {:c=>0.0}
|
|
309
|
+
@ct[String, 'foo']
|
|
310
|
+
@u[@ds.filter(:c=>'foo')].should == {:c=>'foo'}
|
|
311
|
+
|
|
312
|
+
INTEGRATION_DB.create_table!(:items) do
|
|
313
|
+
BigDecimal :c, :size=>[15,2]
|
|
314
|
+
end
|
|
315
|
+
@ds.insert(:c=>BigDecimal.new('1.1'))
|
|
316
|
+
@u[@ds.filter{c > 0}].should == {:c=>BigDecimal.new('1.1')}
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
cspecify "should handle dates and times", [:sqlite], [:do], [:jdbc, :mssql], [:tinytds] do
|
|
320
|
+
@ct[Date, Date.today]
|
|
321
|
+
@u[@ds.filter(:c=>Date.today)].should == {:c=>Date.today}
|
|
322
|
+
t = Time.now
|
|
323
|
+
@ct[Time, t]
|
|
324
|
+
@u[@ds.filter{c < t + 1}][:c].to_i.should == t.to_i
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
specify "should handle QualifiedIdentifiers" do
|
|
328
|
+
@ct[Integer, 10]
|
|
329
|
+
@u[@ds.filter{items__c > 1}].should == {:c=>10}
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
specify "should handle deep nesting" do
|
|
333
|
+
INTEGRATION_DB.create_table!(:items) do
|
|
334
|
+
Integer :a
|
|
335
|
+
Integer :b
|
|
336
|
+
Integer :c
|
|
337
|
+
Integer :d
|
|
338
|
+
end
|
|
339
|
+
@ds.insert(:a=>2, :b=>0, :c=>3, :d=>5)
|
|
340
|
+
@u[@ds.filter{a > 1}.and{b < 2}.or(:c=>3).and({~{:d=>4}=>1}.case(0) => 1)].should == {:a=>2, :b=>0, :c=>3, :d=>5}
|
|
341
|
+
@u[@ds.filter{a > 1}.and{b < 2}.or(:c=>3).and({~{:d=>5}=>1}.case(0) => 1)].should == nil
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
specify "should handle case where the same variable has the same value in multiple places " do
|
|
345
|
+
@ct[Integer, 1]
|
|
346
|
+
@u[@ds.filter{c > 1}.or{c < 1}.invert].should == {:c=>1}
|
|
347
|
+
@u[@ds.filter{c > 1}.or{c < 1}].should == nil
|
|
348
|
+
end
|
|
349
|
+
end
|