sequel 3.21.0 → 3.29.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 +413 -3
- data/README.rdoc +20 -6
- data/Rakefile +23 -16
- data/bin/sequel +1 -5
- 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 +72 -27
- data/doc/opening_databases.rdoc +86 -50
- data/doc/prepared_statements.rdoc +40 -13
- data/doc/reflection.rdoc +8 -2
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/schema_modification.rdoc +547 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +115 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/ado.rb +40 -18
- data/lib/sequel/adapters/amalgalite.rb +15 -7
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do/mysql.rb +0 -5
- data/lib/sequel/adapters/do/postgres.rb +0 -5
- data/lib/sequel/adapters/do/sqlite.rb +0 -5
- data/lib/sequel/adapters/do.rb +17 -36
- data/lib/sequel/adapters/firebird.rb +27 -208
- data/lib/sequel/adapters/ibmdb.rb +448 -0
- data/lib/sequel/adapters/informix.rb +6 -23
- data/lib/sequel/adapters/jdbc/as400.rb +5 -31
- data/lib/sequel/adapters/jdbc/db2.rb +44 -0
- data/lib/sequel/adapters/jdbc/derby.rb +217 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
- data/lib/sequel/adapters/jdbc/h2.rb +26 -17
- data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
- data/lib/sequel/adapters/jdbc/informix.rb +26 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
- data/lib/sequel/adapters/jdbc/mysql.rb +9 -10
- data/lib/sequel/adapters/jdbc/oracle.rb +67 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +6 -11
- data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
- data/lib/sequel/adapters/jdbc/sqlserver.rb +41 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +107 -38
- data/lib/sequel/adapters/mock.rb +315 -0
- data/lib/sequel/adapters/mysql.rb +78 -182
- data/lib/sequel/adapters/mysql2.rb +24 -23
- data/lib/sequel/adapters/odbc/db2.rb +17 -0
- data/lib/sequel/adapters/odbc/mssql.rb +0 -5
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +2 -4
- data/lib/sequel/adapters/oracle.rb +349 -51
- data/lib/sequel/adapters/postgres.rb +169 -21
- data/lib/sequel/adapters/shared/access.rb +21 -6
- data/lib/sequel/adapters/shared/db2.rb +288 -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 +108 -65
- data/lib/sequel/adapters/shared/mysql.rb +56 -13
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
- data/lib/sequel/adapters/shared/oracle.rb +185 -34
- data/lib/sequel/adapters/shared/postgres.rb +107 -58
- data/lib/sequel/adapters/shared/progress.rb +0 -6
- data/lib/sequel/adapters/shared/sqlite.rb +168 -41
- data/lib/sequel/adapters/sqlite.rb +27 -18
- data/lib/sequel/adapters/swift/mysql.rb +9 -5
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +6 -4
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/tinytds.rb +152 -17
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +63 -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 +46 -5
- data/lib/sequel/database/connecting.rb +5 -6
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +59 -1
- data/lib/sequel/database/logging.rb +1 -1
- data/lib/sequel/database/misc.rb +100 -19
- data/lib/sequel/database/query.rb +153 -58
- data/lib/sequel/database/schema_generator.rb +8 -5
- data/lib/sequel/database/schema_methods.rb +59 -29
- data/lib/sequel/dataset/actions.rb +194 -57
- data/lib/sequel/dataset/features.rb +81 -8
- data/lib/sequel/dataset/graph.rb +8 -7
- data/lib/sequel/dataset/misc.rb +50 -23
- data/lib/sequel/dataset/mutation.rb +5 -6
- data/lib/sequel/dataset/prepared_statements.rb +32 -15
- data/lib/sequel/dataset/query.rb +223 -42
- data/lib/sequel/dataset/sql.rb +58 -61
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/extensions/migration.rb +6 -4
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +997 -331
- data/lib/sequel/model/base.rb +386 -129
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model.rb +15 -8
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +114 -7
- data/lib/sequel/plugins/many_through_many.rb +65 -7
- data/lib/sequel/plugins/prepared_statements.rb +151 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/serialization.rb +6 -1
- data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
- data/lib/sequel/plugins/sharding.rb +12 -25
- data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/xml_serializer.rb +3 -3
- data/lib/sequel/sql.rb +107 -51
- data/lib/sequel/timezones.rb +44 -35
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/mssql_spec.rb +65 -29
- data/spec/adapters/mysql_spec.rb +122 -123
- data/spec/adapters/oracle_spec.rb +48 -76
- data/spec/adapters/postgres_spec.rb +213 -61
- data/spec/adapters/spec_helper.rb +6 -5
- data/spec/adapters/sqlite_spec.rb +35 -21
- data/spec/core/connection_pool_spec.rb +71 -92
- data/spec/core/core_sql_spec.rb +20 -31
- data/spec/core/database_spec.rb +729 -508
- data/spec/core/dataset_spec.rb +980 -1044
- data/spec/core/expression_filters_spec.rb +159 -42
- data/spec/core/mock_adapter_spec.rb +378 -0
- data/spec/core/object_graph_spec.rb +48 -114
- data/spec/core/schema_generator_spec.rb +3 -3
- data/spec/core/schema_spec.rb +298 -38
- data/spec/core/spec_helper.rb +6 -48
- data/spec/extensions/association_pks_spec.rb +38 -0
- data/spec/extensions/class_table_inheritance_spec.rb +1 -1
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/identity_map_spec.rb +162 -0
- data/spec/extensions/instance_hooks_spec.rb +71 -0
- data/spec/extensions/many_through_many_spec.rb +195 -20
- data/spec/extensions/migration_spec.rb +17 -17
- data/spec/extensions/named_timezones_spec.rb +22 -2
- data/spec/extensions/nested_attributes_spec.rb +4 -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 +13 -21
- data/spec/extensions/serialization_modification_detection_spec.rb +37 -0
- data/spec/extensions/serialization_spec.rb +5 -8
- data/spec/extensions/single_table_inheritance_spec.rb +11 -0
- data/spec/extensions/spec_helper.rb +7 -1
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/to_dot_spec.rb +3 -5
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/extensions/xml_serializer_spec.rb +16 -4
- data/spec/integration/associations_test.rb +522 -21
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +375 -62
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +304 -116
- data/spec/integration/prepared_statement_test.rb +200 -120
- data/spec/integration/schema_test.rb +161 -30
- data/spec/integration/spec_helper.rb +39 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +172 -5
- data/spec/integration/type_test.rb +17 -3
- data/spec/model/association_reflection_spec.rb +174 -7
- data/spec/model/associations_spec.rb +849 -661
- data/spec/model/base_spec.rb +255 -95
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +640 -676
- data/spec/model/hooks_spec.rb +309 -67
- data/spec/model/model_spec.rb +207 -167
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +321 -218
- data/spec/model/spec_helper.rb +13 -71
- data/spec/model/validations_spec.rb +11 -0
- metadata +95 -38
|
@@ -2,218 +2,230 @@ 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
|
-
integer :
|
|
8
|
+
integer :numb
|
|
8
9
|
end
|
|
9
10
|
@c = Class.new(Sequel::Model(:items))
|
|
10
|
-
@ds =
|
|
11
|
-
@ds.insert(:
|
|
12
|
-
@ds.
|
|
13
|
-
prepared_arg_placeholder == '$' ? :"#{sym}__int" : sym
|
|
14
|
-
end
|
|
11
|
+
@ds = @db[:items]
|
|
12
|
+
@ds.insert(:numb=>10)
|
|
13
|
+
@pr = @ds.requires_placeholder_type_specifiers? ? proc{|i| :"#{i}__integer"} : proc{|i| i}
|
|
15
14
|
end
|
|
16
15
|
after do
|
|
17
|
-
|
|
16
|
+
@db.drop_table(:items)
|
|
18
17
|
end
|
|
19
18
|
|
|
20
19
|
specify "should support bound variables with select, all, and first" do
|
|
21
|
-
@ds.filter(:
|
|
22
|
-
@ds.filter(:
|
|
23
|
-
@ds.filter(:
|
|
20
|
+
@ds.filter(:numb=>:$n).call(:select, :n=>10).should == [{:id=>1, :numb=>10}]
|
|
21
|
+
@ds.filter(:numb=>:$n).call(:all, :n=>10).should == [{:id=>1, :numb=>10}]
|
|
22
|
+
@ds.filter(:numb=>:$n).call(:first, :n=>10).should == {:id=>1, :numb=>10}
|
|
24
23
|
end
|
|
25
24
|
|
|
26
25
|
specify "should support blocks for select and all" do
|
|
27
|
-
@ds.filter(:
|
|
28
|
-
@ds.filter(:
|
|
26
|
+
@ds.filter(:numb=>:$n).call(:select, :n=>10){|r| r[:numb] *= 2}.should == [{:id=>1, :numb=>20}]
|
|
27
|
+
@ds.filter(:numb=>:$n).call(:all, :n=>10){|r| r[:numb] *= 2}.should == [{:id=>1, :numb=>20}]
|
|
29
28
|
end
|
|
30
29
|
|
|
31
30
|
specify "should support binding variables before the call with #bind" do
|
|
32
|
-
@ds.filter(:
|
|
33
|
-
@ds.filter(:
|
|
34
|
-
@ds.filter(:
|
|
31
|
+
@ds.filter(:numb=>:$n).bind(:n=>10).call(:select).should == [{:id=>1, :numb=>10}]
|
|
32
|
+
@ds.filter(:numb=>:$n).bind(:n=>10).call(:all).should == [{:id=>1, :numb=>10}]
|
|
33
|
+
@ds.filter(:numb=>:$n).bind(:n=>10).call(:first).should == {:id=>1, :numb=>10}
|
|
35
34
|
|
|
36
|
-
@ds.bind(:n=>10).filter(:
|
|
37
|
-
@ds.bind(:n=>10).filter(:
|
|
38
|
-
@ds.bind(:n=>10).filter(:
|
|
35
|
+
@ds.bind(:n=>10).filter(:numb=>:$n).call(:select).should == [{:id=>1, :numb=>10}]
|
|
36
|
+
@ds.bind(:n=>10).filter(:numb=>:$n).call(:all).should == [{:id=>1, :numb=>10}]
|
|
37
|
+
@ds.bind(:n=>10).filter(:numb=>:$n).call(:first).should == {:id=>1, :numb=>10}
|
|
39
38
|
end
|
|
40
39
|
|
|
41
40
|
specify "should allow overriding variables specified with #bind" do
|
|
42
|
-
@ds.filter(:
|
|
43
|
-
@ds.filter(:
|
|
44
|
-
@ds.filter(:
|
|
41
|
+
@ds.filter(:numb=>:$n).bind(:n=>1).call(:select, :n=>10).should == [{:id=>1, :numb=>10}]
|
|
42
|
+
@ds.filter(:numb=>:$n).bind(:n=>1).call(:all, :n=>10).should == [{:id=>1, :numb=>10}]
|
|
43
|
+
@ds.filter(:numb=>:$n).bind(:n=>1).call(:first, :n=>10).should == {:id=>1, :numb=>10}
|
|
45
44
|
|
|
46
|
-
@ds.filter(:
|
|
47
|
-
@ds.filter(:
|
|
48
|
-
@ds.filter(:
|
|
45
|
+
@ds.filter(:numb=>:$n).bind(:n=>1).bind(:n=>10).call(:select).should == [{:id=>1, :numb=>10}]
|
|
46
|
+
@ds.filter(:numb=>:$n).bind(:n=>1).bind(:n=>10).call(:all).should == [{:id=>1, :numb=>10}]
|
|
47
|
+
@ds.filter(:numb=>:$n).bind(:n=>1).bind(:n=>10).call(:first).should == {:id=>1, :numb=>10}
|
|
49
48
|
end
|
|
50
49
|
|
|
51
50
|
specify "should support placeholder literal strings with call" do
|
|
52
|
-
@ds.filter("
|
|
51
|
+
@ds.filter("numb = ?", :$n).call(:select, :n=>10).should == [{:id=>1, :numb=>10}]
|
|
53
52
|
end
|
|
54
53
|
|
|
55
54
|
specify "should support named placeholder literal strings and handle multiple named placeholders correctly with call" do
|
|
56
|
-
@ds.filter("
|
|
57
|
-
@ds.insert(:
|
|
58
|
-
@ds.insert(:
|
|
59
|
-
@ds.filter("
|
|
55
|
+
@ds.filter("numb = :n", :n=>:$n).call(:select, :n=>10).should == [{:id=>1, :numb=>10}]
|
|
56
|
+
@ds.insert(:numb=>20)
|
|
57
|
+
@ds.insert(:numb=>30)
|
|
58
|
+
@ds.filter("numb > :n1 AND numb < :n2 AND numb = :n3", :n3=>:$n3, :n2=>:$n2, :n1=>:$n1).call(:select, :n3=>20, :n2=>30, :n1=>10).should == [{:id=>2, :numb=>20}]
|
|
60
59
|
end
|
|
61
60
|
|
|
62
61
|
specify "should support datasets with static sql and placeholders with call" do
|
|
63
|
-
|
|
62
|
+
@db["SELECT * FROM items WHERE numb = ?", :$n].call(:select, :n=>10).should == [{:id=>1, :numb=>10}]
|
|
64
63
|
end
|
|
65
64
|
|
|
66
65
|
specify "should support subselects with call" do
|
|
67
|
-
@ds.filter(:id=>:$i).filter(:
|
|
66
|
+
@ds.filter(:id=>:$i).filter(:numb=>@ds.select(:numb).filter(:numb=>:$n)).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).should == [{:id=>1, :numb=>10}]
|
|
68
67
|
end
|
|
69
68
|
|
|
70
69
|
specify "should support subselects with literal strings with call" do
|
|
71
|
-
@ds.filter(:id=>:$i, :
|
|
70
|
+
@ds.filter(:id=>:$i, :numb=>@ds.select(:numb).filter("numb = ?", :$n)).call(:select, :n=>10, :i=>1).should == [{:id=>1, :numb=>10}]
|
|
72
71
|
end
|
|
73
72
|
|
|
74
73
|
specify "should support subselects with static sql and placeholders with call" do
|
|
75
|
-
@ds.filter(:id=>:$i, :
|
|
74
|
+
@ds.filter(:id=>:$i, :numb=>@db["SELECT numb FROM items WHERE numb = ?", :$n]).call(:select, :n=>10, :i=>1).should == [{:id=>1, :numb=>10}]
|
|
76
75
|
end
|
|
77
76
|
|
|
78
77
|
specify "should support subselects of subselects with call" do
|
|
79
|
-
@ds.filter(:id=>:$i).filter(:
|
|
78
|
+
@ds.filter(:id=>:$i).filter(:numb=>@ds.select(:numb).filter(:numb=>@ds.select(:numb).filter(:numb=>:$n))).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).should == [{:id=>1, :numb=>10}]
|
|
80
79
|
end
|
|
81
80
|
|
|
82
|
-
|
|
83
|
-
@ds.insert(:
|
|
84
|
-
ds = @ds.limit(
|
|
85
|
-
ds.call(:select, :n=>1, :n2=>0).should == [{:id=>1, :
|
|
86
|
-
ds.call(:select, :n=>1, :n2=>1).should == [{:id=>2, :
|
|
81
|
+
cspecify "should support using a bound variable for a limit and offset", [:jdbc, :db2] do
|
|
82
|
+
@ds.insert(:numb=>20)
|
|
83
|
+
ds = @ds.limit(:$n, :$n2).order(:id)
|
|
84
|
+
ds.call(:select, :n=>1, :n2=>0).should == [{:id=>1, :numb=>10}]
|
|
85
|
+
ds.call(:select, :n=>1, :n2=>1).should == [{:id=>2, :numb=>20}]
|
|
87
86
|
ds.call(:select, :n=>1, :n2=>2).should == []
|
|
88
|
-
ds.call(:select, :n=>2, :n2=>0).should == [{:id=>1, :
|
|
89
|
-
ds.call(:select, :n=>2, :n2=>1).should == [{:id=>2, :
|
|
87
|
+
ds.call(:select, :n=>2, :n2=>0).should == [{:id=>1, :numb=>10}, {:id=>2, :numb=>20}]
|
|
88
|
+
ds.call(:select, :n=>2, :n2=>1).should == [{:id=>2, :numb=>20}]
|
|
90
89
|
end
|
|
91
90
|
|
|
92
91
|
specify "should support bound variables with insert" do
|
|
93
|
-
@ds.call(:insert, {:n=>20}, :
|
|
92
|
+
@ds.call(:insert, {:n=>20}, :numb=>:$n)
|
|
94
93
|
@ds.count.should == 2
|
|
95
|
-
@ds.order(:id).map(:
|
|
94
|
+
@ds.order(:id).map(:numb).should == [10, 20]
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
specify "should support bound variables with NULL values" do
|
|
98
|
+
@ds.delete
|
|
99
|
+
@ds.call(:insert, {:n=>nil}, :numb=>@pr[:$n])
|
|
100
|
+
@ds.count.should == 1
|
|
101
|
+
@ds.map(:numb).should == [nil]
|
|
96
102
|
end
|
|
97
103
|
|
|
98
104
|
specify "should have insert return primary key value when using bound arguments" do
|
|
99
|
-
@ds.call(:insert, {:n=>20}, :
|
|
100
|
-
@ds.filter(:id=>2).first[:
|
|
105
|
+
@ds.call(:insert, {:n=>20}, :numb=>:$n).should == 2
|
|
106
|
+
@ds.filter(:id=>2).first[:numb].should == 20
|
|
101
107
|
end
|
|
102
108
|
|
|
103
109
|
specify "should support bound variables with delete" do
|
|
104
|
-
@ds.filter(:
|
|
110
|
+
@ds.filter(:numb=>:$n).call(:delete, :n=>10).should == 1
|
|
105
111
|
@ds.count.should == 0
|
|
106
112
|
end
|
|
107
113
|
|
|
108
114
|
specify "should support bound variables with update" do
|
|
109
|
-
@ds.filter(:
|
|
110
|
-
@ds.all.should == [{:id=>1, :
|
|
115
|
+
@ds.filter(:numb=>:$n).call(:update, {:n=>10, :nn=>20}, :numb=>:numb+:$nn).should == 1
|
|
116
|
+
@ds.all.should == [{:id=>1, :numb=>30}]
|
|
111
117
|
end
|
|
112
118
|
|
|
113
119
|
specify "should support prepared statements with select, first, and all" do
|
|
114
|
-
@ds.filter(:
|
|
115
|
-
|
|
116
|
-
@ds.filter(:
|
|
117
|
-
|
|
118
|
-
@ds.filter(:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
120
|
+
@ds.filter(:numb=>:$n).prepare(:select, :select_n)
|
|
121
|
+
@db.call(:select_n, :n=>10).should == [{:id=>1, :numb=>10}]
|
|
122
|
+
@ds.filter(:numb=>:$n).prepare(:all, :select_n)
|
|
123
|
+
@db.call(:select_n, :n=>10).should == [{:id=>1, :numb=>10}]
|
|
124
|
+
@ds.filter(:numb=>:$n).prepare(:first, :select_n)
|
|
125
|
+
@db.call(:select_n, :n=>10).should == {:id=>1, :numb=>10}
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
specify "should support prepared statements being call multiple times with different arguments" do
|
|
129
|
+
@ds.filter(:numb=>:$n).prepare(:select, :select_n)
|
|
130
|
+
@db.call(:select_n, :n=>10).should == [{:id=>1, :numb=>10}]
|
|
131
|
+
@db.call(:select_n, :n=>0).should == []
|
|
132
|
+
@db.call(:select_n, :n=>10).should == [{:id=>1, :numb=>10}]
|
|
125
133
|
end
|
|
126
134
|
|
|
127
135
|
specify "should support placeholder literal strings with prepare" do
|
|
128
|
-
@ds.filter("
|
|
136
|
+
@ds.filter("numb = ?", :$n).prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :numb=>10}]
|
|
129
137
|
end
|
|
130
138
|
|
|
131
139
|
specify "should support named placeholder literal strings and handle multiple named placeholders correctly with prepare" do
|
|
132
|
-
@ds.filter("
|
|
133
|
-
@ds.insert(:
|
|
134
|
-
@ds.insert(:
|
|
135
|
-
@ds.filter("
|
|
140
|
+
@ds.filter("numb = :n", :n=>:$n).prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :numb=>10}]
|
|
141
|
+
@ds.insert(:numb=>20)
|
|
142
|
+
@ds.insert(:numb=>30)
|
|
143
|
+
@ds.filter("numb > :n1 AND numb < :n2 AND numb = :n3", :n3=>:$n3, :n2=>:$n2, :n1=>:$n1).call(:select, :n3=>20, :n2=>30, :n1=>10).should == [{:id=>2, :numb=>20}]
|
|
136
144
|
end
|
|
137
145
|
|
|
138
146
|
specify "should support datasets with static sql and placeholders with prepare" do
|
|
139
|
-
|
|
147
|
+
@db["SELECT * FROM items WHERE numb = ?", :$n].prepare(:select, :seq_select).call(:n=>10).should == [{:id=>1, :numb=>10}]
|
|
140
148
|
end
|
|
141
149
|
|
|
142
150
|
specify "should support subselects with prepare" do
|
|
143
|
-
@ds.filter(:id=>:$i).filter(:
|
|
151
|
+
@ds.filter(:id=>:$i).filter(:numb=>@ds.select(:numb).filter(:numb=>:$n)).filter(:id=>:$j).prepare(:select, :seq_select).call(:n=>10, :i=>1, :j=>1).should == [{:id=>1, :numb=>10}]
|
|
144
152
|
end
|
|
145
153
|
|
|
146
154
|
specify "should support subselects with literal strings with prepare" do
|
|
147
|
-
@ds.filter(:id=>:$i, :
|
|
155
|
+
@ds.filter(:id=>:$i, :numb=>@ds.select(:numb).filter("numb = ?", :$n)).prepare(:select, :seq_select).call(:n=>10, :i=>1).should == [{:id=>1, :numb=>10}]
|
|
148
156
|
end
|
|
149
157
|
|
|
150
158
|
specify "should support subselects with static sql and placeholders with prepare" do
|
|
151
|
-
@ds.filter(:id=>:$i, :
|
|
159
|
+
@ds.filter(:id=>:$i, :numb=>@db["SELECT numb FROM items WHERE numb = ?", :$n]).prepare(:select, :seq_select).call(:n=>10, :i=>1).should == [{:id=>1, :numb=>10}]
|
|
152
160
|
end
|
|
153
161
|
|
|
154
162
|
specify "should support subselects of subselects with prepare" do
|
|
155
|
-
@ds.filter(:id=>:$i).filter(:
|
|
163
|
+
@ds.filter(:id=>:$i).filter(:numb=>@ds.select(:numb).filter(:numb=>@ds.select(:numb).filter(:numb=>:$n))).filter(:id=>:$j).prepare(:select, :seq_select).call(:n=>10, :i=>1, :j=>1).should == [{:id=>1, :numb=>10}]
|
|
156
164
|
end
|
|
157
165
|
|
|
158
|
-
|
|
159
|
-
@ds.insert(:
|
|
160
|
-
ps = @ds.limit(
|
|
161
|
-
ps.call(:n=>1, :n2=>0).should == [{:id=>1, :
|
|
162
|
-
ps.call(:n=>1, :n2=>1).should == [{:id=>2, :
|
|
166
|
+
cspecify "should support using a prepared_statement for a limit and offset", :db2 do
|
|
167
|
+
@ds.insert(:numb=>20)
|
|
168
|
+
ps = @ds.limit(:$n, :$n2).order(:id).prepare(:select, :seq_select)
|
|
169
|
+
ps.call(:n=>1, :n2=>0).should == [{:id=>1, :numb=>10}]
|
|
170
|
+
ps.call(:n=>1, :n2=>1).should == [{:id=>2, :numb=>20}]
|
|
163
171
|
ps.call(:n=>1, :n2=>2).should == []
|
|
164
|
-
ps.call(:n=>2, :n2=>0).should == [{:id=>1, :
|
|
165
|
-
ps.call(:n=>2, :n2=>1).should == [{:id=>2, :
|
|
172
|
+
ps.call(:n=>2, :n2=>0).should == [{:id=>1, :numb=>10}, {:id=>2, :numb=>20}]
|
|
173
|
+
ps.call(:n=>2, :n2=>1).should == [{:id=>2, :numb=>20}]
|
|
166
174
|
end
|
|
167
175
|
|
|
168
176
|
specify "should support prepared statements with insert" do
|
|
169
|
-
@ds.prepare(:insert, :insert_n, :
|
|
170
|
-
|
|
177
|
+
@ds.prepare(:insert, :insert_n, :numb=>:$n)
|
|
178
|
+
@db.call(:insert_n, :n=>20)
|
|
171
179
|
@ds.count.should == 2
|
|
172
|
-
@ds.order(:id).map(:
|
|
180
|
+
@ds.order(:id).map(:numb).should == [10, 20]
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
specify "should support prepared statements with NULL values" do
|
|
184
|
+
@ds.delete
|
|
185
|
+
@ds.prepare(:insert, :insert_n, :numb=>@pr[:$n])
|
|
186
|
+
@db.call(:insert_n, :n=>nil)
|
|
187
|
+
@ds.count.should == 1
|
|
188
|
+
@ds.map(:numb).should == [nil]
|
|
173
189
|
end
|
|
174
190
|
|
|
175
191
|
specify "should have insert return primary key value when using prepared statements" do
|
|
176
|
-
@ds.prepare(:insert, :insert_n, :
|
|
177
|
-
|
|
178
|
-
@ds.filter(:id=>2).first[:
|
|
192
|
+
@ds.prepare(:insert, :insert_n, :numb=>:$n)
|
|
193
|
+
@db.call(:insert_n, :n=>20).should == 2
|
|
194
|
+
@ds.filter(:id=>2).first[:numb].should == 20
|
|
179
195
|
end
|
|
180
196
|
|
|
181
197
|
specify "should support prepared statements with delete" do
|
|
182
|
-
@ds.filter(:
|
|
183
|
-
|
|
198
|
+
@ds.filter(:numb=>:$n).prepare(:delete, :delete_n)
|
|
199
|
+
@db.call(:delete_n, :n=>10).should == 1
|
|
184
200
|
@ds.count.should == 0
|
|
185
201
|
end
|
|
186
202
|
|
|
187
203
|
specify "should support prepared statements with update" do
|
|
188
|
-
@ds.filter(:
|
|
189
|
-
|
|
190
|
-
@ds.all.should == [{:id=>1, :
|
|
204
|
+
@ds.filter(:numb=>:$n).prepare(:update, :update_n, :numb=>:numb+:$nn)
|
|
205
|
+
@db.call(:update_n, :n=>10, :nn=>20).should == 1
|
|
206
|
+
@ds.all.should == [{:id=>1, :numb=>30}]
|
|
191
207
|
end
|
|
192
208
|
|
|
193
209
|
specify "model datasets should return model instances when using select, all, and first with bound variables" do
|
|
194
|
-
@c.filter(:
|
|
195
|
-
@c.filter(:
|
|
196
|
-
@c.filter(:
|
|
210
|
+
@c.filter(:numb=>:$n).call(:select, :n=>10).should == [@c.load(:id=>1, :numb=>10)]
|
|
211
|
+
@c.filter(:numb=>:$n).call(:all, :n=>10).should == [@c.load(:id=>1, :numb=>10)]
|
|
212
|
+
@c.filter(:numb=>:$n).call(:first, :n=>10).should == @c.load(:id=>1, :numb=>10)
|
|
197
213
|
end
|
|
198
214
|
|
|
199
215
|
specify "model datasets should return model instances when using select, all, and first with prepared statements" do
|
|
200
|
-
@c.filter(:
|
|
201
|
-
|
|
202
|
-
@c.filter(:
|
|
203
|
-
|
|
204
|
-
@c.filter(:
|
|
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
|
|
216
|
+
@c.filter(:numb=>:$n).prepare(:select, :select_n1)
|
|
217
|
+
@db.call(:select_n1, :n=>10).should == [@c.load(:id=>1, :numb=>10)]
|
|
218
|
+
@c.filter(:numb=>:$n).prepare(:all, :select_n1)
|
|
219
|
+
@db.call(:select_n1, :n=>10).should == [@c.load(:id=>1, :numb=>10)]
|
|
220
|
+
@c.filter(:numb=>:$n).prepare(:first, :select_n1)
|
|
221
|
+
@db.call(:select_n1, :n=>10).should == @c.load(:id=>1, :numb=>10)
|
|
211
222
|
end
|
|
212
223
|
end
|
|
213
224
|
|
|
214
225
|
describe "Bound Argument Types" do
|
|
215
226
|
before do
|
|
216
|
-
INTEGRATION_DB
|
|
227
|
+
@db = INTEGRATION_DB
|
|
228
|
+
@db.create_table!(:items) do
|
|
217
229
|
primary_key :id
|
|
218
230
|
Date :d
|
|
219
231
|
DateTime :dt
|
|
@@ -223,7 +235,7 @@ describe "Bound Argument Types" do
|
|
|
223
235
|
Float :f
|
|
224
236
|
TrueClass :b
|
|
225
237
|
end
|
|
226
|
-
@ds =
|
|
238
|
+
@ds = @db[:items]
|
|
227
239
|
@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
240
|
@ds.insert(@vs)
|
|
229
241
|
@ds.meta_def(:ba) do |sym, type|
|
|
@@ -232,39 +244,107 @@ describe "Bound Argument Types" do
|
|
|
232
244
|
end
|
|
233
245
|
after do
|
|
234
246
|
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)
|
|
247
|
+
@db.drop_table(:items)
|
|
239
248
|
end
|
|
240
249
|
|
|
241
|
-
cspecify "should handle date type", [:do, :sqlite], :mssql, [:jdbc, :sqlite] do
|
|
242
|
-
@ds.filter(:d
|
|
250
|
+
cspecify "should handle date type", [:do, :sqlite], :mssql, [:jdbc, :sqlite], :oracle do
|
|
251
|
+
@ds.filter(:d=>:$x).prepare(:first, :ps_date).call(:x=>@vs[:d])[:d].should == @vs[:d]
|
|
243
252
|
end
|
|
244
253
|
|
|
245
|
-
cspecify "should handle datetime type", [:do], [:mysql2], [:swift], [:jdbc, :sqlite], [:tinytds] do
|
|
254
|
+
cspecify "should handle datetime type", [:do], [:mysql2], [:swift], [:jdbc, :sqlite], [:tinytds], [:oracle] do
|
|
246
255
|
Sequel.datetime_class = DateTime
|
|
247
|
-
@ds.filter(:dt
|
|
256
|
+
@ds.filter(:dt=>:$x).prepare(:first, :ps_datetime).call(:x=>@vs[:dt])[:dt].should == @vs[:dt]
|
|
248
257
|
end
|
|
249
258
|
|
|
250
259
|
cspecify "should handle time type", [:do], [:jdbc, :sqlite] do
|
|
251
|
-
@ds.filter(:t
|
|
260
|
+
@ds.filter(:t=>:$x).prepare(:first, :ps_time).call(:x=>@vs[:t])[:t].should == @vs[:t]
|
|
252
261
|
end
|
|
253
262
|
|
|
254
|
-
cspecify "should handle blob type", [:swift] do
|
|
255
|
-
@ds.filter(:file
|
|
263
|
+
cspecify "should handle blob type", [:swift], [:odbc], [:jdbc, :db2], :oracle, :derby do
|
|
264
|
+
@ds.filter(:file=>:$x).prepare(:first, :ps_blob).call(:x=>@vs[:file])[:file].should == @vs[:file]
|
|
256
265
|
end
|
|
257
266
|
|
|
258
267
|
cspecify "should handle float type", [:swift, :sqlite] do
|
|
259
|
-
@ds.filter(:f
|
|
268
|
+
@ds.filter(:f=>:$x).prepare(:first, :ps_float).call(:x=>@vs[:f])[:f].should == @vs[:f]
|
|
260
269
|
end
|
|
261
270
|
|
|
262
271
|
specify "should handle string type" do
|
|
263
|
-
@ds.filter(:s
|
|
272
|
+
@ds.filter(:s=>:$x).prepare(:first, :ps_string).call(:x=>@vs[:s])[:s].should == @vs[:s]
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
cspecify "should handle boolean type", [:do, :sqlite], [:odbc, :mssql], [:jdbc, :sqlite], [:jdbc, :db2], :oracle do
|
|
276
|
+
@ds.filter(:b=>:$x).prepare(:first, :ps_string).call(:x=>@vs[:b])[:b].should == @vs[:b]
|
|
277
|
+
end
|
|
278
|
+
end unless Sequel.guarded?([:swift, :postgres])
|
|
279
|
+
|
|
280
|
+
describe "Dataset#unbind" do
|
|
281
|
+
before do
|
|
282
|
+
@ds = ds = INTEGRATION_DB[:items]
|
|
283
|
+
@ct = proc do |t, v|
|
|
284
|
+
INTEGRATION_DB.create_table!(:items) do
|
|
285
|
+
column :c, t
|
|
286
|
+
end
|
|
287
|
+
ds.insert(:c=>v)
|
|
288
|
+
end
|
|
289
|
+
@u = proc{|ds| ds, bv = ds.unbind; ds.call(:first, bv)}
|
|
290
|
+
end
|
|
291
|
+
after do
|
|
292
|
+
INTEGRATION_DB.drop_table(:items) rescue nil
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
specify "should unbind values assigned to equality and inequality statements" do
|
|
296
|
+
@ct[Integer, 10]
|
|
297
|
+
@u[@ds.filter(:c=>10)].should == {:c=>10}
|
|
298
|
+
@u[@ds.exclude(:c=>10)].should == nil
|
|
299
|
+
@u[@ds.filter{c < 10}].should == nil
|
|
300
|
+
@u[@ds.filter{c <= 10}].should == {:c=>10}
|
|
301
|
+
@u[@ds.filter{c > 10}].should == nil
|
|
302
|
+
@u[@ds.filter{c >= 10}].should == {:c=>10}
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
cspecify "should handle numerics and strings", [:odbc], [:swift, :sqlite] do
|
|
306
|
+
@ct[Integer, 10]
|
|
307
|
+
@u[@ds.filter(:c=>10)].should == {:c=>10}
|
|
308
|
+
@ct[Float, 0.0]
|
|
309
|
+
@u[@ds.filter{c < 1}].should == {:c=>0.0}
|
|
310
|
+
@ct[String, 'foo']
|
|
311
|
+
@u[@ds.filter(:c=>'foo')].should == {:c=>'foo'}
|
|
312
|
+
|
|
313
|
+
INTEGRATION_DB.create_table!(:items) do
|
|
314
|
+
BigDecimal :c, :size=>[15,2]
|
|
315
|
+
end
|
|
316
|
+
@ds.insert(:c=>BigDecimal.new('1.1'))
|
|
317
|
+
@u[@ds.filter{c > 0}].should == {:c=>BigDecimal.new('1.1')}
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
cspecify "should handle dates and times", [:do], [:jdbc, :mssql], [:jdbc, :sqlite], [:tinytds], :oracle do
|
|
321
|
+
@ct[Date, Date.today]
|
|
322
|
+
@u[@ds.filter(:c=>Date.today)].should == {:c=>Date.today}
|
|
323
|
+
t = Time.now
|
|
324
|
+
@ct[Time, t]
|
|
325
|
+
@u[@ds.filter{c < t + 1}][:c].to_i.should == t.to_i
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
specify "should handle QualifiedIdentifiers" do
|
|
329
|
+
@ct[Integer, 10]
|
|
330
|
+
@u[@ds.filter{items__c > 1}].should == {:c=>10}
|
|
264
331
|
end
|
|
265
332
|
|
|
266
|
-
|
|
267
|
-
|
|
333
|
+
specify "should handle deep nesting" do
|
|
334
|
+
INTEGRATION_DB.create_table!(:items) do
|
|
335
|
+
Integer :a
|
|
336
|
+
Integer :b
|
|
337
|
+
Integer :c
|
|
338
|
+
Integer :d
|
|
339
|
+
end
|
|
340
|
+
@ds.insert(:a=>2, :b=>0, :c=>3, :d=>5)
|
|
341
|
+
@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}
|
|
342
|
+
@u[@ds.filter{a > 1}.and{b < 2}.or(:c=>3).and({~{:d=>5}=>1}.case(0) => 1)].should == nil
|
|
268
343
|
end
|
|
269
|
-
end unless INTEGRATION_DB.adapter_scheme == :swift && INTEGRATION_DB.database_type == :postgres
|
|
270
344
|
|
|
345
|
+
specify "should handle case where the same variable has the same value in multiple places " do
|
|
346
|
+
@ct[Integer, 1]
|
|
347
|
+
@u[@ds.filter{c > 1}.or{c < 1}.invert].should == {:c=>1}
|
|
348
|
+
@u[@ds.filter{c > 1}.or{c < 1}].should == nil
|
|
349
|
+
end
|
|
350
|
+
end
|