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