sequel 4.22.0 → 4.23.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.
- checksums.yaml +4 -4
- data/CHANGELOG +22 -0
- data/README.rdoc +6 -0
- data/Rakefile +59 -81
- data/doc/migration.rdoc +2 -0
- data/doc/release_notes/4.23.0.txt +65 -0
- data/doc/sharding.rdoc +16 -14
- data/doc/testing.rdoc +61 -77
- data/lib/sequel/adapters/jdbc.rb +1 -0
- data/lib/sequel/adapters/mock.rb +0 -1
- data/lib/sequel/adapters/postgres.rb +1 -0
- data/lib/sequel/adapters/postgresql.rb +1 -0
- data/lib/sequel/adapters/shared/postgres.rb +3 -3
- data/lib/sequel/connection_pool/sharded_threaded.rb +5 -0
- data/lib/sequel/connection_pool/threaded.rb +9 -1
- data/lib/sequel/database/connecting.rb +1 -1
- data/lib/sequel/database/transactions.rb +2 -1
- data/lib/sequel/dataset/prepared_statements.rb +1 -1
- data/lib/sequel/extensions/constraint_validations.rb +12 -12
- data/lib/sequel/extensions/date_arithmetic.rb +0 -4
- data/lib/sequel/extensions/pagination.rb +14 -2
- data/lib/sequel/extensions/pg_enum.rb +2 -2
- data/lib/sequel/extensions/pg_hstore.rb +1 -1
- data/lib/sequel/extensions/pg_json_ops.rb +2 -2
- data/lib/sequel/plugins/csv_serializer.rb +2 -0
- data/lib/sequel/plugins/delay_add_association.rb +50 -0
- data/lib/sequel/plugins/list.rb +2 -2
- data/lib/sequel/plugins/nested_attributes.rb +8 -28
- data/lib/sequel/plugins/update_refresh.rb +50 -0
- data/lib/sequel/plugins/validate_associated.rb +55 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +29 -29
- data/spec/adapters/firebird_spec.rb +97 -103
- data/spec/adapters/informix_spec.rb +25 -25
- data/spec/adapters/mssql_spec.rb +156 -172
- data/spec/adapters/mysql_spec.rb +334 -359
- data/spec/adapters/oracle_spec.rb +67 -69
- data/spec/adapters/postgres_spec.rb +1298 -1249
- data/spec/adapters/spec_helper.rb +2 -35
- data/spec/adapters/sqlanywhere_spec.rb +39 -39
- data/spec/adapters/sqlite_spec.rb +203 -200
- data/spec/bin_spec.rb +57 -59
- data/spec/core/connection_pool_spec.rb +402 -401
- data/spec/core/database_spec.rb +953 -944
- data/spec/core/dataset_spec.rb +2178 -2168
- data/spec/core/deprecated_spec.rb +19 -19
- data/spec/core/expression_filters_spec.rb +415 -415
- data/spec/core/mock_adapter_spec.rb +212 -212
- data/spec/core/object_graph_spec.rb +73 -73
- data/spec/core/placeholder_literalizer_spec.rb +71 -71
- data/spec/core/schema_generator_spec.rb +44 -44
- data/spec/core/schema_spec.rb +470 -472
- data/spec/core/spec_helper.rb +5 -20
- data/spec/core/version_spec.rb +2 -2
- data/spec/core_extensions_spec.rb +320 -320
- data/spec/extensions/accessed_columns_spec.rb +12 -12
- data/spec/extensions/active_model_spec.rb +3 -3
- data/spec/extensions/after_initialize_spec.rb +2 -2
- data/spec/extensions/arbitrary_servers_spec.rb +23 -23
- data/spec/extensions/association_dependencies_spec.rb +34 -34
- data/spec/extensions/association_pks_spec.rb +98 -98
- data/spec/extensions/association_proxies_spec.rb +33 -33
- data/spec/extensions/auto_validations_spec.rb +46 -46
- data/spec/extensions/blacklist_security_spec.rb +19 -18
- data/spec/extensions/blank_spec.rb +36 -36
- data/spec/extensions/boolean_readers_spec.rb +36 -36
- data/spec/extensions/caching_spec.rb +82 -82
- data/spec/extensions/class_table_inheritance_spec.rb +72 -72
- data/spec/extensions/column_conflicts_spec.rb +19 -14
- data/spec/extensions/column_select_spec.rb +19 -19
- data/spec/extensions/columns_introspection_spec.rb +43 -43
- data/spec/extensions/composition_spec.rb +64 -64
- data/spec/extensions/connection_validator_spec.rb +92 -90
- data/spec/extensions/constraint_validations_plugin_spec.rb +92 -92
- data/spec/extensions/constraint_validations_spec.rb +80 -80
- data/spec/extensions/core_refinements_spec.rb +220 -220
- data/spec/extensions/csv_serializer_spec.rb +44 -44
- data/spec/extensions/current_datetime_timestamp_spec.rb +8 -8
- data/spec/extensions/dataset_associations_spec.rb +65 -65
- data/spec/extensions/dataset_source_alias_spec.rb +16 -16
- data/spec/extensions/date_arithmetic_spec.rb +51 -58
- data/spec/extensions/defaults_setter_spec.rb +19 -19
- data/spec/extensions/delay_add_association_spec.rb +52 -0
- data/spec/extensions/dirty_spec.rb +51 -51
- data/spec/extensions/eager_each_spec.rb +8 -8
- data/spec/extensions/empty_array_ignore_nulls_spec.rb +10 -10
- data/spec/extensions/error_splitter_spec.rb +2 -2
- data/spec/extensions/error_sql_spec.rb +4 -4
- data/spec/extensions/eval_inspect_spec.rb +3 -3
- data/spec/extensions/filter_having_spec.rb +8 -8
- data/spec/extensions/force_encoding_spec.rb +30 -30
- data/spec/extensions/from_block_spec.rb +7 -7
- data/spec/extensions/graph_each_spec.rb +19 -19
- data/spec/extensions/hash_aliases_spec.rb +5 -5
- data/spec/extensions/hook_class_methods_spec.rb +100 -100
- data/spec/extensions/inflector_spec.rb +54 -54
- data/spec/extensions/input_transformer_spec.rb +10 -10
- data/spec/extensions/insert_returning_select_spec.rb +8 -8
- data/spec/extensions/instance_filters_spec.rb +26 -26
- data/spec/extensions/instance_hooks_spec.rb +85 -85
- data/spec/extensions/json_serializer_spec.rb +68 -68
- data/spec/extensions/lazy_attributes_spec.rb +49 -49
- data/spec/extensions/list_spec.rb +77 -75
- data/spec/extensions/looser_typecasting_spec.rb +16 -16
- data/spec/extensions/many_through_many_spec.rb +627 -627
- data/spec/extensions/meta_def_spec.rb +7 -7
- data/spec/extensions/migration_spec.rb +217 -217
- data/spec/extensions/modification_detection_spec.rb +20 -20
- data/spec/extensions/mssql_optimistic_locking_spec.rb +21 -21
- data/spec/extensions/named_timezones_spec.rb +18 -18
- data/spec/extensions/nested_attributes_spec.rb +107 -107
- data/spec/extensions/null_dataset_spec.rb +24 -24
- data/spec/extensions/optimistic_locking_spec.rb +21 -21
- data/spec/extensions/pagination_spec.rb +52 -52
- data/spec/extensions/pg_array_associations_spec.rb +273 -273
- data/spec/extensions/pg_array_ops_spec.rb +52 -52
- data/spec/extensions/pg_array_spec.rb +152 -152
- data/spec/extensions/pg_enum_spec.rb +13 -13
- data/spec/extensions/pg_hstore_ops_spec.rb +63 -63
- data/spec/extensions/pg_hstore_spec.rb +84 -84
- data/spec/extensions/pg_inet_spec.rb +15 -15
- data/spec/extensions/pg_interval_spec.rb +29 -29
- data/spec/extensions/pg_json_ops_spec.rb +86 -84
- data/spec/extensions/pg_json_spec.rb +104 -104
- data/spec/extensions/pg_loose_count_spec.rb +6 -6
- data/spec/extensions/pg_range_ops_spec.rb +24 -24
- data/spec/extensions/pg_range_spec.rb +143 -143
- data/spec/extensions/pg_row_ops_spec.rb +14 -14
- data/spec/extensions/pg_row_plugin_spec.rb +12 -12
- data/spec/extensions/pg_row_spec.rb +118 -118
- data/spec/extensions/pg_static_cache_updater_spec.rb +28 -28
- data/spec/extensions/pg_typecast_on_load_spec.rb +21 -21
- data/spec/extensions/prepared_statements_associations_spec.rb +42 -42
- data/spec/extensions/prepared_statements_safe_spec.rb +18 -18
- data/spec/extensions/prepared_statements_spec.rb +28 -28
- data/spec/extensions/prepared_statements_with_pk_spec.rb +11 -11
- data/spec/extensions/pretty_table_spec.rb +16 -16
- data/spec/extensions/query_literals_spec.rb +37 -37
- data/spec/extensions/query_spec.rb +32 -32
- data/spec/extensions/rcte_tree_spec.rb +141 -141
- data/spec/extensions/round_timestamps_spec.rb +21 -21
- data/spec/extensions/schema_caching_spec.rb +8 -8
- data/spec/extensions/schema_dumper_spec.rb +78 -78
- data/spec/extensions/schema_spec.rb +31 -27
- data/spec/extensions/scissors_spec.rb +3 -3
- data/spec/extensions/select_remove_spec.rb +14 -14
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +28 -28
- data/spec/extensions/serialization_modification_detection_spec.rb +33 -33
- data/spec/extensions/serialization_spec.rb +79 -78
- data/spec/extensions/server_block_spec.rb +17 -17
- data/spec/extensions/set_overrides_spec.rb +30 -30
- data/spec/extensions/sharding_spec.rb +65 -65
- data/spec/extensions/shared_caching_spec.rb +29 -29
- data/spec/extensions/single_table_inheritance_spec.rb +79 -79
- data/spec/extensions/skip_create_refresh_spec.rb +3 -3
- data/spec/extensions/spec_helper.rb +4 -29
- data/spec/extensions/split_array_nil_spec.rb +9 -9
- data/spec/extensions/split_values_spec.rb +7 -7
- data/spec/extensions/sql_expr_spec.rb +32 -32
- data/spec/extensions/static_cache_spec.rb +123 -123
- data/spec/extensions/string_date_time_spec.rb +34 -34
- data/spec/extensions/string_stripper_spec.rb +15 -15
- data/spec/extensions/subclasses_spec.rb +31 -31
- data/spec/extensions/table_select_spec.rb +15 -15
- data/spec/extensions/tactical_eager_loading_spec.rb +23 -23
- data/spec/extensions/thread_local_timezones_spec.rb +13 -13
- data/spec/extensions/timestamps_spec.rb +40 -40
- data/spec/extensions/to_dot_spec.rb +34 -34
- data/spec/extensions/touch_spec.rb +52 -52
- data/spec/extensions/tree_spec.rb +72 -72
- data/spec/extensions/typecast_on_load_spec.rb +25 -25
- data/spec/extensions/unlimited_update_spec.rb +2 -2
- data/spec/extensions/update_or_create_spec.rb +36 -36
- data/spec/extensions/update_primary_key_spec.rb +35 -35
- data/spec/extensions/update_refresh_spec.rb +41 -0
- data/spec/extensions/validate_associated_spec.rb +52 -0
- data/spec/extensions/validation_class_methods_spec.rb +314 -317
- data/spec/extensions/validation_helpers_spec.rb +195 -195
- data/spec/extensions/xml_serializer_spec.rb +48 -48
- data/spec/guards_helper.rb +55 -0
- data/spec/integration/associations_test.rb +1089 -1088
- data/spec/integration/database_test.rb +29 -29
- data/spec/integration/dataset_test.rb +661 -661
- data/spec/integration/eager_loader_test.rb +147 -147
- data/spec/integration/migrator_test.rb +122 -122
- data/spec/integration/model_test.rb +70 -70
- data/spec/integration/plugin_test.rb +682 -640
- data/spec/integration/prepared_statement_test.rb +172 -172
- data/spec/integration/schema_test.rb +245 -245
- data/spec/integration/spec_helper.rb +1 -64
- data/spec/integration/timezone_test.rb +17 -17
- data/spec/integration/transaction_test.rb +87 -87
- data/spec/integration/type_test.rb +33 -33
- data/spec/model/association_reflection_spec.rb +130 -121
- data/spec/model/associations_spec.rb +1112 -1113
- data/spec/model/base_spec.rb +197 -196
- data/spec/model/class_dataset_methods_spec.rb +118 -118
- data/spec/model/dataset_methods_spec.rb +49 -49
- data/spec/model/eager_loading_spec.rb +705 -702
- data/spec/model/hooks_spec.rb +169 -168
- data/spec/model/inflector_spec.rb +5 -5
- data/spec/model/model_spec.rb +287 -297
- data/spec/model/plugins_spec.rb +47 -47
- data/spec/model/record_spec.rb +534 -535
- data/spec/model/spec_helper.rb +3 -21
- data/spec/model/validations_spec.rb +72 -70
- data/spec/spec_config.rb +8 -0
- metadata +41 -9
- data/lib/sequel/adapters/fdbsql.rb +0 -286
- data/lib/sequel/adapters/jdbc/fdbsql.rb +0 -66
- data/lib/sequel/adapters/openbase.rb +0 -54
- data/lib/sequel/adapters/shared/fdbsql.rb +0 -550
- data/spec/adapters/fdbsql_spec.rb +0 -429
- data/spec/rspec_helper.rb +0 -22
|
@@ -13,11 +13,11 @@ DB.create_table :test do
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
describe "A Informix database" do
|
|
16
|
-
|
|
16
|
+
it "should provide disconnect functionality" do
|
|
17
17
|
DB.execute("select user from dual")
|
|
18
|
-
DB.pool.size.
|
|
18
|
+
DB.pool.size.must_equal 1
|
|
19
19
|
DB.disconnect
|
|
20
|
-
DB.pool.size.
|
|
20
|
+
DB.pool.size.must_equal 0
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
|
|
@@ -27,28 +27,28 @@ describe "A Informix dataset" do
|
|
|
27
27
|
@d.delete # remove all records
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
@d.count.
|
|
30
|
+
it "should return the correct record count" do
|
|
31
|
+
@d.count.must_equal 0
|
|
32
32
|
@d << {:name => 'abc', :value => 123}
|
|
33
33
|
@d << {:name => 'abc', :value => 456}
|
|
34
34
|
@d << {:name => 'def', :value => 789}
|
|
35
|
-
@d.count.
|
|
35
|
+
@d.count.must_equal 3
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
@d.to_a.
|
|
38
|
+
it "should return the correct records" do
|
|
39
|
+
@d.to_a.must_equal []
|
|
40
40
|
@d << {:name => 'abc', :value => 123}
|
|
41
41
|
@d << {:name => 'abc', :value => 456}
|
|
42
42
|
@d << {:name => 'def', :value => 789}
|
|
43
43
|
|
|
44
|
-
@d.order(:value).to_a.
|
|
44
|
+
@d.order(:value).to_a.must_equal [
|
|
45
45
|
{:name => 'abc', :value => 123},
|
|
46
46
|
{:name => 'abc', :value => 456},
|
|
47
47
|
{:name => 'def', :value => 789}
|
|
48
48
|
]
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
it "should update records correctly" do
|
|
52
52
|
@d << {:name => 'abc', :value => 123}
|
|
53
53
|
@d << {:name => 'abc', :value => 456}
|
|
54
54
|
@d << {:name => 'def', :value => 789}
|
|
@@ -56,45 +56,45 @@ describe "A Informix dataset" do
|
|
|
56
56
|
|
|
57
57
|
# the third record should stay the same
|
|
58
58
|
# floating-point precision bullshit
|
|
59
|
-
@d[:name => 'def'][:value].
|
|
60
|
-
@d.filter(:value => 530).count.
|
|
59
|
+
@d[:name => 'def'][:value].must_equal 789
|
|
60
|
+
@d.filter(:value => 530).count.must_equal 2
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
it "should delete records correctly" do
|
|
64
64
|
@d << {:name => 'abc', :value => 123}
|
|
65
65
|
@d << {:name => 'abc', :value => 456}
|
|
66
66
|
@d << {:name => 'def', :value => 789}
|
|
67
67
|
@d.filter(:name => 'abc').delete
|
|
68
68
|
|
|
69
|
-
@d.count.
|
|
70
|
-
@d.first[:name].
|
|
69
|
+
@d.count.must_equal 1
|
|
70
|
+
@d.first[:name].must_equal 'def'
|
|
71
71
|
end
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
it "should be able to literalize booleans" do
|
|
74
|
+
@d.literal(true)
|
|
75
|
+
@d.literal(false)
|
|
76
76
|
end
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
it "should support transactions" do
|
|
79
79
|
DB.transaction do
|
|
80
80
|
@d << {:name => 'abc', :value => 1}
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
-
@d.count.
|
|
83
|
+
@d.count.must_equal 1
|
|
84
84
|
end
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
it "should support #first and #last" do
|
|
87
87
|
@d << {:name => 'abc', :value => 123}
|
|
88
88
|
@d << {:name => 'abc', :value => 456}
|
|
89
89
|
@d << {:name => 'def', :value => 789}
|
|
90
90
|
|
|
91
|
-
@d.order(:value).first.
|
|
92
|
-
@d.order(:value).last.
|
|
91
|
+
@d.order(:value).first.must_equal(:name => 'abc', :value => 123)
|
|
92
|
+
@d.order(:value).last.must_equal(:name => 'def', :value => 789)
|
|
93
93
|
end
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
it "should return last inserted id" do
|
|
96
96
|
first = @d.insert :name => 'abc', :value => 123
|
|
97
97
|
second = @d.insert :name => 'abc', :value => 123
|
|
98
|
-
(second - first).
|
|
98
|
+
(second - first).must_equal 1
|
|
99
99
|
end
|
|
100
100
|
end
|
data/spec/adapters/mssql_spec.rb
CHANGED
|
@@ -16,19 +16,19 @@ describe "A MSSQL database" do
|
|
|
16
16
|
@db = DB
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
it "should be able to read fractional part of timestamp" do
|
|
20
20
|
rs = @db["select getutcdate() as full_date, cast(datepart(millisecond, getutcdate()) as int) as milliseconds"].first
|
|
21
|
-
rs[:milliseconds].
|
|
21
|
+
rs[:milliseconds].must_equal rs[:full_date].usec/1000
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
it "should be able to write fractional part of timestamp" do
|
|
25
25
|
t = Time.utc(2001, 12, 31, 23, 59, 59, 997000)
|
|
26
|
-
(t.usec/1000).
|
|
26
|
+
(t.usec/1000).must_equal @db["select cast(datepart(millisecond, ?) as int) as milliseconds", t].get
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
it "should not raise an error when getting the server version" do
|
|
30
|
+
@db.server_version
|
|
31
|
+
@db.dataset.server_version
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
34
|
|
|
@@ -44,8 +44,8 @@ describe "A MSSQL database" do
|
|
|
44
44
|
@db.drop_table?(:test3)
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
@db.transaction{@db[:test3].nolock.all.
|
|
47
|
+
it "should work with NOLOCK" do
|
|
48
|
+
@db.transaction{@db[:test3].nolock.all.must_equal []}
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
51
|
|
|
@@ -61,12 +61,12 @@ describe "MSSQL" do
|
|
|
61
61
|
@db.drop_table?(:test3, :test4)
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
@db[:test3].cross_apply(@db[:test4].where(:test3__v3=>:test4__v4)).select_order_map([:v3, :v4]).
|
|
64
|
+
it "should should support CROSS APPLY" do
|
|
65
|
+
@db[:test3].cross_apply(@db[:test4].where(:test3__v3=>:test4__v4)).select_order_map([:v3, :v4]).must_equal [[1,1]]
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
@db[:test3].outer_apply(@db[:test4].where(:test3__v3=>:test4__v4)).select_order_map([:v3, :v4]).
|
|
68
|
+
it "should should support OUTER APPLY" do
|
|
69
|
+
@db[:test3].outer_apply(@db[:test4].where(:test3__v3=>:test4__v4)).select_order_map([:v3, :v4]).must_equal [[1,1], [2, nil]]
|
|
70
70
|
end
|
|
71
71
|
end
|
|
72
72
|
|
|
@@ -83,31 +83,29 @@ describe "MSSQL full_text_search" do
|
|
|
83
83
|
@db.drop_table?(:posts)
|
|
84
84
|
end
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
it "should support fulltext indexes and full_text_search" do
|
|
87
87
|
log do
|
|
88
88
|
@db.create_table(:posts){Integer :id, :null=>false; String :title; String :body; index :id, :name=>:fts_id_idx, :unique=>true; full_text_index :title, :key_index=>:fts_id_idx; full_text_index [:title, :body], :key_index=>:fts_id_idx}
|
|
89
89
|
@db[:posts].insert(:title=>'ruby rails', :body=>'y')
|
|
90
90
|
@db[:posts].insert(:title=>'sequel', :body=>'ruby')
|
|
91
91
|
@db[:posts].insert(:title=>'ruby scooby', :body=>'x')
|
|
92
92
|
|
|
93
|
-
@db[:posts].full_text_search(:title, 'rails').all.
|
|
94
|
-
@db[:posts].full_text_search([:title, :body], ['sequel', 'ruby']).all.
|
|
93
|
+
@db[:posts].full_text_search(:title, 'rails').all.must_equal [{:title=>'ruby rails', :body=>'y'}]
|
|
94
|
+
@db[:posts].full_text_search([:title, :body], ['sequel', 'ruby']).all.must_equal [{:title=>'sequel', :body=>'ruby'}]
|
|
95
95
|
|
|
96
|
-
@db[:posts].full_text_search(:title, :$n).call(:select, :n=>'rails').
|
|
97
|
-
@db[:posts].full_text_search(:title, :$n).prepare(:select, :fts_select).call(:n=>'rails').
|
|
96
|
+
@db[:posts].full_text_search(:title, :$n).call(:select, :n=>'rails').must_equal [{:title=>'ruby rails', :body=>'y'}]
|
|
97
|
+
@db[:posts].full_text_search(:title, :$n).prepare(:select, :fts_select).call(:n=>'rails').must_equal [{:title=>'ruby rails', :body=>'y'}]
|
|
98
98
|
end
|
|
99
99
|
end
|
|
100
100
|
end if false
|
|
101
101
|
|
|
102
102
|
describe "MSSQL Dataset#join_table" do
|
|
103
|
-
|
|
104
|
-
DB[:items].join(:categories, [:id]).sql.
|
|
105
|
-
'SELECT * FROM [ITEMS] INNER JOIN [CATEGORIES] ON ([CATEGORIES].[ID] = [ITEMS].[ID])'
|
|
103
|
+
it "should emulate the USING clause with ON" do
|
|
104
|
+
DB[:items].join(:categories, [:id]).sql.must_equal 'SELECT * FROM [ITEMS] INNER JOIN [CATEGORIES] ON ([CATEGORIES].[ID] = [ITEMS].[ID])'
|
|
106
105
|
['SELECT * FROM [ITEMS] INNER JOIN [CATEGORIES] ON (([CATEGORIES].[ID1] = [ITEMS].[ID1]) AND ([CATEGORIES].[ID2] = [ITEMS].[ID2]))',
|
|
107
106
|
'SELECT * FROM [ITEMS] INNER JOIN [CATEGORIES] ON (([CATEGORIES].[ID2] = [ITEMS].[ID2]) AND ([CATEGORIES].[ID1] = [ITEMS].[ID1]))'].
|
|
108
|
-
|
|
109
|
-
DB[:items___i].join(:categories___c, [:id]).sql.
|
|
110
|
-
'SELECT * FROM [ITEMS] AS [I] INNER JOIN [CATEGORIES] AS [C] ON ([C].[ID] = [I].[ID])'
|
|
107
|
+
must_include(DB[:items].join(:categories, [:id1, :id2]).sql)
|
|
108
|
+
DB[:items___i].join(:categories___c, [:id]).sql.must_equal 'SELECT * FROM [ITEMS] AS [I] INNER JOIN [CATEGORIES] AS [C] ON ([C].[ID] = [I].[ID])'
|
|
111
109
|
end
|
|
112
110
|
end
|
|
113
111
|
|
|
@@ -122,70 +120,58 @@ describe "MSSQL Dataset#output" do
|
|
|
122
120
|
@db.drop_table?(:items, :out)
|
|
123
121
|
end
|
|
124
122
|
|
|
125
|
-
|
|
126
|
-
@ds.output(nil, [:deleted__name, :deleted__value]).delete_sql.
|
|
127
|
-
|
|
128
|
-
@ds.output(nil, [Sequel::SQL::ColumnAll.new(:deleted)]).delete_sql.should =~
|
|
129
|
-
/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].*/
|
|
123
|
+
it "should format OUTPUT clauses without INTO for DELETE statements" do
|
|
124
|
+
@ds.output(nil, [:deleted__name, :deleted__value]).delete_sql.must_match(/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].\[(NAME|VALUE)\], \[DELETED\].\[(NAME|VALUE)\]/)
|
|
125
|
+
@ds.output(nil, [Sequel::SQL::ColumnAll.new(:deleted)]).delete_sql.must_match(/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].*/)
|
|
130
126
|
end
|
|
131
127
|
|
|
132
|
-
|
|
133
|
-
@ds.output(:out, [:deleted__name, :deleted__value]).delete_sql.
|
|
134
|
-
|
|
135
|
-
@ds.output(:out, {:name => :deleted__name, :value => :deleted__value}).delete_sql.should =~
|
|
136
|
-
/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].\[(NAME|VALUE)\], \[DELETED\].\[(NAME|VALUE)\] INTO \[OUT\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\)/
|
|
128
|
+
it "should format OUTPUT clauses with INTO for DELETE statements" do
|
|
129
|
+
@ds.output(:out, [:deleted__name, :deleted__value]).delete_sql.must_match(/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].\[(NAME|VALUE)\], \[DELETED\].\[(NAME|VALUE)\] INTO \[OUT\]/)
|
|
130
|
+
@ds.output(:out, {:name => :deleted__name, :value => :deleted__value}).delete_sql.must_match(/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].\[(NAME|VALUE)\], \[DELETED\].\[(NAME|VALUE)\] INTO \[OUT\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\)/)
|
|
137
131
|
end
|
|
138
132
|
|
|
139
|
-
|
|
140
|
-
@ds.output(nil, [:inserted__name, :inserted__value]).insert_sql(:name => "name", :value => 1).
|
|
141
|
-
|
|
142
|
-
@ds.output(nil, [Sequel::SQL::ColumnAll.new(:inserted)]).insert_sql(:name => "name", :value => 1).should =~
|
|
143
|
-
/INSERT INTO \[ITEMS\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) OUTPUT \[INSERTED\].* VALUES \((N'name'|1), (N'name'|1)\)/
|
|
133
|
+
it "should format OUTPUT clauses without INTO for INSERT statements" do
|
|
134
|
+
@ds.output(nil, [:inserted__name, :inserted__value]).insert_sql(:name => "name", :value => 1).must_match(/INSERT INTO \[ITEMS\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) OUTPUT \[INSERTED\].\[(NAME|VALUE)\], \[INSERTED\].\[(NAME|VALUE)\] VALUES \((N'name'|1), (N'name'|1)\)/)
|
|
135
|
+
@ds.output(nil, [Sequel::SQL::ColumnAll.new(:inserted)]).insert_sql(:name => "name", :value => 1).must_match(/INSERT INTO \[ITEMS\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) OUTPUT \[INSERTED\].* VALUES \((N'name'|1), (N'name'|1)\)/)
|
|
144
136
|
end
|
|
145
137
|
|
|
146
|
-
|
|
147
|
-
@ds.output(:out, [:inserted__name, :inserted__value]).insert_sql(:name => "name", :value => 1).
|
|
148
|
-
|
|
149
|
-
@ds.output(:out, {:name => :inserted__name, :value => :inserted__value}).insert_sql(:name => "name", :value => 1).should =~
|
|
150
|
-
/INSERT INTO \[ITEMS\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) OUTPUT \[INSERTED\].\[(NAME|VALUE)\], \[INSERTED\].\[(NAME|VALUE)\] INTO \[OUT\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) VALUES \((N'name'|1), (N'name'|1)\)/
|
|
138
|
+
it "should format OUTPUT clauses with INTO for INSERT statements" do
|
|
139
|
+
@ds.output(:out, [:inserted__name, :inserted__value]).insert_sql(:name => "name", :value => 1).must_match(/INSERT INTO \[ITEMS\] \((\[NAME\]|\[VALUE\]), (\[NAME\]|\[VALUE\])\) OUTPUT \[INSERTED\].\[(NAME|VALUE)\], \[INSERTED\].\[(NAME|VALUE)\] INTO \[OUT\] VALUES \((N'name'|1), (N'name'|1)\)/)
|
|
140
|
+
@ds.output(:out, {:name => :inserted__name, :value => :inserted__value}).insert_sql(:name => "name", :value => 1).must_match(/INSERT INTO \[ITEMS\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) OUTPUT \[INSERTED\].\[(NAME|VALUE)\], \[INSERTED\].\[(NAME|VALUE)\] INTO \[OUT\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) VALUES \((N'name'|1), (N'name'|1)\)/)
|
|
151
141
|
end
|
|
152
142
|
|
|
153
|
-
|
|
154
|
-
@ds.output(nil, [:inserted__name, :deleted__value]).update_sql(:value => 2).
|
|
155
|
-
|
|
156
|
-
@ds.output(nil, [Sequel::SQL::ColumnAll.new(:inserted)]).update_sql(:value => 2).should =~
|
|
157
|
-
/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[INSERTED\].*/
|
|
143
|
+
it "should format OUTPUT clauses without INTO for UPDATE statements" do
|
|
144
|
+
@ds.output(nil, [:inserted__name, :deleted__value]).update_sql(:value => 2).must_match(/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\], \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\]/)
|
|
145
|
+
@ds.output(nil, [Sequel::SQL::ColumnAll.new(:inserted)]).update_sql(:value => 2).must_match(/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[INSERTED\].*/)
|
|
158
146
|
end
|
|
159
147
|
|
|
160
|
-
|
|
161
|
-
@ds.output(:out, [:inserted__name, :deleted__value]).update_sql(:value => 2).
|
|
162
|
-
|
|
163
|
-
@ds.output(:out, {:name => :inserted__name, :value => :deleted__value}).update_sql(:value => 2).should =~
|
|
164
|
-
/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\], \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\] INTO \[OUT\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\)/
|
|
148
|
+
it "should format OUTPUT clauses with INTO for UPDATE statements" do
|
|
149
|
+
@ds.output(:out, [:inserted__name, :deleted__value]).update_sql(:value => 2).must_match(/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\], \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\] INTO \[OUT\]/)
|
|
150
|
+
@ds.output(:out, {:name => :inserted__name, :value => :deleted__value}).update_sql(:value => 2).must_match(/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\], \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\] INTO \[OUT\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\)/)
|
|
165
151
|
end
|
|
166
152
|
|
|
167
|
-
|
|
153
|
+
it "should execute OUTPUT clauses in DELETE statements" do
|
|
168
154
|
@ds.insert(:name => "name", :value => 1)
|
|
169
155
|
@ds.output(:out, [:deleted__name, :deleted__value]).delete
|
|
170
|
-
@db[:out].all.
|
|
156
|
+
@db[:out].all.must_equal [{:name => "name", :value => 1}]
|
|
171
157
|
@ds.insert(:name => "name", :value => 2)
|
|
172
158
|
@ds.output(:out, {:name => :deleted__name, :value => :deleted__value}).delete
|
|
173
|
-
@db[:out].all.
|
|
159
|
+
@db[:out].all.must_equal [{:name => "name", :value => 1}, {:name => "name", :value => 2}]
|
|
174
160
|
end
|
|
175
161
|
|
|
176
|
-
|
|
162
|
+
it "should execute OUTPUT clauses in INSERT statements" do
|
|
177
163
|
@ds.output(:out, [:inserted__name, :inserted__value]).insert(:name => "name", :value => 1)
|
|
178
|
-
@db[:out].all.
|
|
164
|
+
@db[:out].all.must_equal [{:name => "name", :value => 1}]
|
|
179
165
|
@ds.output(:out, {:name => :inserted__name, :value => :inserted__value}).insert(:name => "name", :value => 2)
|
|
180
|
-
@db[:out].all.
|
|
166
|
+
@db[:out].all.must_equal [{:name => "name", :value => 1}, {:name => "name", :value => 2}]
|
|
181
167
|
end
|
|
182
168
|
|
|
183
|
-
|
|
169
|
+
it "should execute OUTPUT clauses in UPDATE statements" do
|
|
184
170
|
@ds.insert(:name => "name", :value => 1)
|
|
185
171
|
@ds.output(:out, [:inserted__name, :deleted__value]).update(:value => 2)
|
|
186
|
-
@db[:out].all.
|
|
172
|
+
@db[:out].all.must_equal [{:name => "name", :value => 1}]
|
|
187
173
|
@ds.output(:out, {:name => :inserted__name, :value => :deleted__value}).update(:value => 3)
|
|
188
|
-
@db[:out].all.
|
|
174
|
+
@db[:out].all.must_equal [{:name => "name", :value => 1}, {:name => "name", :value => 2}]
|
|
189
175
|
end
|
|
190
176
|
end
|
|
191
177
|
|
|
@@ -197,24 +183,24 @@ describe "MSSQL dataset using #with and #with_recursive" do
|
|
|
197
183
|
@ds2 = @ds.with_recursive(:t, @db[:x], @db[:t])
|
|
198
184
|
end
|
|
199
185
|
|
|
200
|
-
|
|
201
|
-
@ds1.update_sql(:x => :y).
|
|
202
|
-
@ds2.update_sql(:x => :y).
|
|
186
|
+
it "should prepend UPDATE statements with WITH clause" do
|
|
187
|
+
@ds1.update_sql(:x => :y).must_equal 'WITH [T] AS (SELECT * FROM [X]) UPDATE [T] SET [X] = [Y]'
|
|
188
|
+
@ds2.update_sql(:x => :y).must_equal 'WITH [T] AS (SELECT * FROM [X] UNION ALL SELECT * FROM [T]) UPDATE [T] SET [X] = [Y]'
|
|
203
189
|
end
|
|
204
190
|
|
|
205
|
-
|
|
206
|
-
@ds1.filter(:y => 1).delete_sql.
|
|
207
|
-
@ds2.filter(:y => 1).delete_sql.
|
|
191
|
+
it "should prepend DELETE statements with WITH clause" do
|
|
192
|
+
@ds1.filter(:y => 1).delete_sql.must_equal 'WITH [T] AS (SELECT * FROM [X]) DELETE FROM [T] WHERE ([Y] = 1)'
|
|
193
|
+
@ds2.filter(:y => 1).delete_sql.must_equal 'WITH [T] AS (SELECT * FROM [X] UNION ALL SELECT * FROM [T]) DELETE FROM [T] WHERE ([Y] = 1)'
|
|
208
194
|
end
|
|
209
195
|
|
|
210
|
-
|
|
211
|
-
@ds1.insert_sql(@db[:t]).
|
|
212
|
-
@ds2.insert_sql(@db[:t]).
|
|
196
|
+
it "should prepend INSERT statements with WITH clause" do
|
|
197
|
+
@ds1.insert_sql(@db[:t]).must_equal 'WITH [T] AS (SELECT * FROM [X]) INSERT INTO [T] SELECT * FROM [T]'
|
|
198
|
+
@ds2.insert_sql(@db[:t]).must_equal 'WITH [T] AS (SELECT * FROM [X] UNION ALL SELECT * FROM [T]) INSERT INTO [T] SELECT * FROM [T]'
|
|
213
199
|
end
|
|
214
200
|
|
|
215
|
-
|
|
216
|
-
@db[:s].inner_join(@ds1).sql.
|
|
217
|
-
@ds1.inner_join(@db[:s].with(:s, @db[:y])).sql.
|
|
201
|
+
it "should move WITH clause on joined dataset to top level" do
|
|
202
|
+
@db[:s].inner_join(@ds1).sql.must_equal "WITH [T] AS (SELECT * FROM [X]) SELECT * FROM [S] INNER JOIN (SELECT * FROM [T]) AS [T1]"
|
|
203
|
+
@ds1.inner_join(@db[:s].with(:s, @db[:y])).sql.must_equal "WITH [T] AS (SELECT * FROM [X]), [S] AS (SELECT * FROM [Y]) SELECT * FROM [T] INNER JOIN (SELECT * FROM [S]) AS [T1]"
|
|
218
204
|
end
|
|
219
205
|
end
|
|
220
206
|
|
|
@@ -228,16 +214,16 @@ describe "MSSQL::Dataset#import" do
|
|
|
228
214
|
@db.drop_table?(:test)
|
|
229
215
|
end
|
|
230
216
|
|
|
231
|
-
|
|
217
|
+
it "#import should work correctly with an arbitrary output value" do
|
|
232
218
|
@db.create_table!(:test){primary_key :x; Integer :y}
|
|
233
|
-
@ds.output(nil, [:inserted__y, :inserted__x]).import([:y], [[3], [4]]).
|
|
234
|
-
@ds.all.
|
|
219
|
+
@ds.output(nil, [:inserted__y, :inserted__x]).import([:y], [[3], [4]]).must_equal [{:y=>3, :x=>1}, {:y=>4, :x=>2}]
|
|
220
|
+
@ds.all.must_equal [{:x=>1, :y=>3}, {:x=>2, :y=>4}]
|
|
235
221
|
end
|
|
236
222
|
|
|
237
|
-
|
|
223
|
+
it "should handle WITH statements" do
|
|
238
224
|
@db.create_table!(:test){Integer :x; Integer :y}
|
|
239
225
|
@db[:testx].with(:testx, @db[:test]).import([:x, :y], [[1, 2], [3, 4], [5, 6]], :slice => 2)
|
|
240
|
-
@ds.select_order_map([:x, :y]).
|
|
226
|
+
@ds.select_order_map([:x, :y]).must_equal [[1, 2], [3, 4], [5, 6]]
|
|
241
227
|
end
|
|
242
228
|
end
|
|
243
229
|
|
|
@@ -246,14 +232,12 @@ describe "MSSQL joined datasets" do
|
|
|
246
232
|
@db = DB
|
|
247
233
|
end
|
|
248
234
|
|
|
249
|
-
|
|
250
|
-
@db[:t1].inner_join(:t2, :t1__pk => :t2__pk).delete_sql.
|
|
251
|
-
"DELETE FROM [T1] FROM [T1] INNER JOIN [T2] ON ([T1].[PK] = [T2].[PK])"
|
|
235
|
+
it "should format DELETE statements" do
|
|
236
|
+
@db[:t1].inner_join(:t2, :t1__pk => :t2__pk).delete_sql.must_equal "DELETE FROM [T1] FROM [T1] INNER JOIN [T2] ON ([T1].[PK] = [T2].[PK])"
|
|
252
237
|
end
|
|
253
238
|
|
|
254
|
-
|
|
255
|
-
@db[:t1].inner_join(:t2, :t1__pk => :t2__pk).update_sql(:pk => :t2__pk).
|
|
256
|
-
"UPDATE [T1] SET [PK] = [T2].[PK] FROM [T1] INNER JOIN [T2] ON ([T1].[PK] = [T2].[PK])"
|
|
239
|
+
it "should format UPDATE statements" do
|
|
240
|
+
@db[:t1].inner_join(:t2, :t1__pk => :t2__pk).update_sql(:pk => :t2__pk).must_equal "UPDATE [T1] SET [PK] = [T2].[PK] FROM [T1] INNER JOIN [T2] ON ([T1].[PK] = [T2].[PK])"
|
|
257
241
|
end
|
|
258
242
|
end
|
|
259
243
|
|
|
@@ -270,13 +254,13 @@ describe "Offset support" do
|
|
|
270
254
|
@db.drop_table?(:i)
|
|
271
255
|
end
|
|
272
256
|
|
|
273
|
-
|
|
274
|
-
@ds.limit(2, 2).all.
|
|
257
|
+
it "should return correct rows" do
|
|
258
|
+
@ds.limit(2, 2).all.must_equal [{:id=>6, :parent_id=>3}, {:id=>8, :parent_id=>3}]
|
|
275
259
|
end
|
|
276
260
|
|
|
277
|
-
|
|
261
|
+
it "should not include offset column in hashes passed to row_proc" do
|
|
278
262
|
@ds.limit(2, 2).all
|
|
279
|
-
@hs.
|
|
263
|
+
@hs.must_equal [{:id=>3, :parent_id=>1}, {:id=>4, :parent_id=>1}]
|
|
280
264
|
end
|
|
281
265
|
end
|
|
282
266
|
|
|
@@ -293,62 +277,62 @@ describe "Common Table Expressions" do
|
|
|
293
277
|
@db.drop_table?(:i1, :i2)
|
|
294
278
|
end
|
|
295
279
|
|
|
296
|
-
|
|
280
|
+
it "using #with should be able to update" do
|
|
297
281
|
@ds.insert(:id=>1)
|
|
298
282
|
@ds2.insert(:id=>2, :parent_id=>1)
|
|
299
283
|
@ds2.insert(:id=>3, :parent_id=>2)
|
|
300
284
|
@ds.with(:t, @ds2).filter(:id => @db[:t].select(:id)).update(:parent_id => @db[:t].filter(:id => :i1__id).select(:parent_id).limit(1))
|
|
301
|
-
@ds[:id => 1].
|
|
302
|
-
@ds[:id => 2].
|
|
303
|
-
@ds[:id => 3].
|
|
304
|
-
@ds[:id => 4].
|
|
285
|
+
@ds[:id => 1].must_equal(:id => 1, :parent_id => nil)
|
|
286
|
+
@ds[:id => 2].must_equal(:id => 2, :parent_id => 1)
|
|
287
|
+
@ds[:id => 3].must_equal(:id => 3, :parent_id => 2)
|
|
288
|
+
@ds[:id => 4].must_equal(:id => 4, :parent_id => 1)
|
|
305
289
|
end
|
|
306
290
|
|
|
307
|
-
|
|
291
|
+
it "using #with_recursive should be able to update" do
|
|
308
292
|
ds = @ds.with_recursive(:t, @ds.filter(:parent_id=>1).or(:id => 1), @ds.join(:t, :i=>:parent_id).select(:i1__id, :i1__parent_id), :args=>[:i, :pi])
|
|
309
293
|
ds.exclude(:id => @db[:t].select(:i)).update(:parent_id => 1)
|
|
310
|
-
@ds[:id => 1].
|
|
311
|
-
@ds[:id => 2].
|
|
312
|
-
@ds[:id => 5].
|
|
294
|
+
@ds[:id => 1].must_equal(:id => 1, :parent_id => nil)
|
|
295
|
+
@ds[:id => 2].must_equal(:id => 2, :parent_id => 1)
|
|
296
|
+
@ds[:id => 5].must_equal(:id => 5, :parent_id => 3)
|
|
313
297
|
end
|
|
314
298
|
|
|
315
|
-
|
|
299
|
+
it "using #with should be able to insert" do
|
|
316
300
|
@ds2.insert(:id=>7)
|
|
317
301
|
@ds.with(:t, @ds2).insert(@db[:t])
|
|
318
|
-
@ds[:id => 7].
|
|
302
|
+
@ds[:id => 7].must_equal(:id => 7, :parent_id => nil)
|
|
319
303
|
end
|
|
320
304
|
|
|
321
|
-
|
|
305
|
+
it "using #with_recursive should be able to insert" do
|
|
322
306
|
ds = @ds2.with_recursive(:t, @ds.filter(:parent_id=>1), @ds.join(:t, :i=>:parent_id).select(:i1__id, :i1__parent_id), :args=>[:i, :pi])
|
|
323
307
|
ds.insert @db[:t]
|
|
324
|
-
@ds2.all.
|
|
308
|
+
@ds2.all.must_equal [{:id => 3, :parent_id => 1}, {:id => 4, :parent_id => 1}, {:id => 5, :parent_id => 3}, {:id => 6, :parent_id => 5}]
|
|
325
309
|
end
|
|
326
310
|
|
|
327
|
-
|
|
311
|
+
it "using #with should be able to delete" do
|
|
328
312
|
@ds2.insert(:id=>6)
|
|
329
313
|
@ds2.insert(:id=>5)
|
|
330
314
|
@ds2.insert(:id=>4)
|
|
331
315
|
@ds.with(:t, @ds2).filter(:id => @db[:t].select(:id)).delete
|
|
332
|
-
@ds.all.
|
|
316
|
+
@ds.all.must_equal [{:id => 1, :parent_id => nil}, {:id => 2, :parent_id => nil}, {:id => 3, :parent_id => 1}]
|
|
333
317
|
end
|
|
334
318
|
|
|
335
|
-
|
|
319
|
+
it "using #with_recursive should be able to delete" do
|
|
336
320
|
@ds.insert(:id=>7, :parent_id=>2)
|
|
337
321
|
ds = @ds.with_recursive(:t, @ds.filter(:parent_id=>1), @ds.join(:t, :i=>:parent_id).select(:i1__id, :i1__parent_id), :args=>[:i, :pi])
|
|
338
322
|
ds.filter(:i1__id => @db[:t].select(:i)).delete
|
|
339
|
-
@ds.all.
|
|
323
|
+
@ds.all.must_equal [{:id => 1, :parent_id => nil}, {:id => 2, :parent_id => nil}, {:id => 7, :parent_id => 2}]
|
|
340
324
|
end
|
|
341
325
|
|
|
342
|
-
|
|
326
|
+
it "using #with should be able to import" do
|
|
343
327
|
@ds2.insert(:id=>7)
|
|
344
328
|
@ds.with(:t, @ds2).import [:id, :parent_id], @db[:t].select(:id, :parent_id)
|
|
345
|
-
@ds[:id => 7].
|
|
329
|
+
@ds[:id => 7].must_equal(:id => 7, :parent_id => nil)
|
|
346
330
|
end
|
|
347
331
|
|
|
348
|
-
|
|
332
|
+
it "using #with_recursive should be able to import" do
|
|
349
333
|
ds = @ds2.with_recursive(:t, @ds.filter(:parent_id=>1), @ds.join(:t, :i=>:parent_id).select(:i1__id, :i1__parent_id), :args=>[:i, :pi])
|
|
350
334
|
ds.import [:id, :parent_id], @db[:t].select(:i, :pi)
|
|
351
|
-
@ds2.all.
|
|
335
|
+
@ds2.all.must_equal [{:id => 3, :parent_id => 1}, {:id => 4, :parent_id => 1}, {:id => 5, :parent_id => 3}, {:id => 6, :parent_id => 5}]
|
|
352
336
|
end
|
|
353
337
|
end
|
|
354
338
|
|
|
@@ -367,31 +351,31 @@ describe "MSSSQL::Dataset#insert" do
|
|
|
367
351
|
@db.drop_table?(:test5, :test4)
|
|
368
352
|
end
|
|
369
353
|
|
|
370
|
-
|
|
371
|
-
@ds.disable_insert_output.insert_select(:value=>10).
|
|
354
|
+
it "should have insert_select return nil if disable_insert_output is used" do
|
|
355
|
+
@ds.disable_insert_output.insert_select(:value=>10).must_equal nil
|
|
372
356
|
end
|
|
373
357
|
|
|
374
|
-
|
|
358
|
+
it "should have insert_select return nil if the server version is not 2005+" do
|
|
375
359
|
def @ds.server_version() 8000760 end
|
|
376
|
-
@ds.insert_select(:value=>10).
|
|
360
|
+
@ds.insert_select(:value=>10).must_equal nil
|
|
377
361
|
end
|
|
378
362
|
|
|
379
|
-
|
|
363
|
+
it "should have insert_select insert the record and return the inserted record" do
|
|
380
364
|
h = @ds.insert_select(:value=>10)
|
|
381
|
-
h[:value].
|
|
382
|
-
@ds.first(:xid=>h[:xid])[:value].
|
|
365
|
+
h[:value].must_equal 10
|
|
366
|
+
@ds.first(:xid=>h[:xid])[:value].must_equal 10
|
|
383
367
|
end
|
|
384
368
|
|
|
385
|
-
cspecify "should allow large text and binary values", :odbc do
|
|
369
|
+
cspecify "should allow large text and binary values", [:odbc] do
|
|
386
370
|
blob = Sequel::SQL::Blob.new("0" * (65*1024))
|
|
387
371
|
@db[:test4].insert(:name => 'max varbinary test', :value => blob)
|
|
388
372
|
b = @db[:test4].where(:name => 'max varbinary test').get(:value)
|
|
389
|
-
b.length.
|
|
390
|
-
b.
|
|
373
|
+
b.length.must_equal blob.length
|
|
374
|
+
b.must_equal blob
|
|
391
375
|
end
|
|
392
376
|
|
|
393
|
-
|
|
394
|
-
DB[:test4].disable_insert_output.send(:simple_select_all?).
|
|
377
|
+
it "should play nicely with simple_select_all?" do
|
|
378
|
+
DB[:test4].disable_insert_output.send(:simple_select_all?).must_equal true
|
|
395
379
|
end
|
|
396
380
|
end
|
|
397
381
|
|
|
@@ -400,15 +384,15 @@ describe "MSSSQL::Dataset#into" do
|
|
|
400
384
|
@db = DB
|
|
401
385
|
end
|
|
402
386
|
|
|
403
|
-
|
|
404
|
-
@db[:t].into(:new).select_sql.
|
|
387
|
+
it "should format SELECT statement" do
|
|
388
|
+
@db[:t].into(:new).select_sql.must_equal "SELECT * INTO [NEW] FROM [T]"
|
|
405
389
|
end
|
|
406
390
|
|
|
407
|
-
|
|
391
|
+
it "should select rows into a new table" do
|
|
408
392
|
@db.create_table!(:t) {Integer :id; String :value}
|
|
409
393
|
@db[:t].insert(:id => 1, :value => "test")
|
|
410
394
|
@db << @db[:t].into(:new).select_sql
|
|
411
|
-
@db[:new].all.
|
|
395
|
+
@db[:new].all.must_equal [{:id => 1, :value => "test"}]
|
|
412
396
|
@db.drop_table?(:t, :new)
|
|
413
397
|
end
|
|
414
398
|
end
|
|
@@ -421,21 +405,21 @@ describe "A MSSQL database" do
|
|
|
421
405
|
@db.drop_table?(:a)
|
|
422
406
|
end
|
|
423
407
|
|
|
424
|
-
|
|
408
|
+
it "should handle many existing types for set_column_allow_null" do
|
|
425
409
|
@db.create_table!(:a){column :a, 'integer'}
|
|
426
410
|
@db.alter_table(:a){set_column_allow_null :a, false}
|
|
427
411
|
@db.create_table!(:a){column :a, 'decimal(24, 2)'}
|
|
428
412
|
@db.alter_table(:a){set_column_allow_null :a, false}
|
|
429
|
-
@db.schema(:a).first.last[:column_size].
|
|
430
|
-
@db.schema(:a).first.last[:scale].
|
|
413
|
+
@db.schema(:a).first.last[:column_size].must_equal 24
|
|
414
|
+
@db.schema(:a).first.last[:scale].must_equal 2
|
|
431
415
|
@db.create_table!(:a){column :a, 'decimal(10)'}
|
|
432
|
-
@db.schema(:a).first.last[:column_size].
|
|
433
|
-
@db.schema(:a).first.last[:scale].
|
|
416
|
+
@db.schema(:a).first.last[:column_size].must_equal 10
|
|
417
|
+
@db.schema(:a).first.last[:scale].must_equal 0
|
|
434
418
|
@db.alter_table(:a){set_column_allow_null :a, false}
|
|
435
419
|
@db.create_table!(:a){column :a, 'nchar(2)'}
|
|
436
420
|
@db.alter_table(:a){set_column_allow_null :a, false}
|
|
437
421
|
s = @db.schema(:a).first.last
|
|
438
|
-
(s[:max_chars] || s[:column_size]).
|
|
422
|
+
(s[:max_chars] || s[:column_size]).must_equal 2
|
|
439
423
|
end
|
|
440
424
|
end
|
|
441
425
|
|
|
@@ -444,16 +428,16 @@ describe "MSSQL::Database#rename_table" do
|
|
|
444
428
|
DB.drop_table?(:foo)
|
|
445
429
|
end
|
|
446
430
|
|
|
447
|
-
|
|
431
|
+
it "should work on non-schema bound tables which need escaping" do
|
|
448
432
|
DB.quote_identifiers = true
|
|
449
433
|
DB.create_table! :'foo bar' do
|
|
450
434
|
text :name
|
|
451
435
|
end
|
|
452
436
|
DB.drop_table? :foo
|
|
453
|
-
|
|
437
|
+
DB.rename_table 'foo bar', 'foo'
|
|
454
438
|
end
|
|
455
439
|
|
|
456
|
-
|
|
440
|
+
it "should work on schema bound tables" do
|
|
457
441
|
DB.execute(<<-SQL)
|
|
458
442
|
IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = 'MY')
|
|
459
443
|
EXECUTE sp_executesql N'create schema MY'
|
|
@@ -461,26 +445,26 @@ describe "MSSQL::Database#rename_table" do
|
|
|
461
445
|
DB.create_table! :MY__foo do
|
|
462
446
|
text :name
|
|
463
447
|
end
|
|
464
|
-
|
|
465
|
-
|
|
448
|
+
DB.rename_table :MY__foo, :MY__bar
|
|
449
|
+
DB.rename_table :MY__bar, :foo
|
|
466
450
|
end
|
|
467
451
|
end
|
|
468
452
|
|
|
469
453
|
describe "MSSQL::Dataset#count" do
|
|
470
|
-
|
|
454
|
+
it "should work with a distinct query with an order clause" do
|
|
471
455
|
DB.create_table!(:items){String :name; Integer :value}
|
|
472
456
|
DB[:items].insert(:name => "name", :value => 1)
|
|
473
457
|
DB[:items].insert(:name => "name", :value => 1)
|
|
474
|
-
DB[:items].select(:name, :value).distinct.order(:name).count.
|
|
475
|
-
DB[:items].select(:name, :value).group(:name, :value).order(:name).count.
|
|
458
|
+
DB[:items].select(:name, :value).distinct.order(:name).count.must_equal 1
|
|
459
|
+
DB[:items].select(:name, :value).group(:name, :value).order(:name).count.must_equal 1
|
|
476
460
|
end
|
|
477
461
|
end
|
|
478
462
|
|
|
479
463
|
describe "MSSQL::Database#create_table" do
|
|
480
|
-
|
|
464
|
+
it "should support collate with various other column options" do
|
|
481
465
|
DB.create_table!(:items){ String :name, :size => 128, :collate => :sql_latin1_general_cp1_ci_as, :default => 'foo', :null => false, :unique => true}
|
|
482
466
|
DB[:items].insert
|
|
483
|
-
DB[:items].select_map(:name).
|
|
467
|
+
DB[:items].select_map(:name).must_equal ["foo"]
|
|
484
468
|
end
|
|
485
469
|
end
|
|
486
470
|
|
|
@@ -493,21 +477,21 @@ describe "MSSQL::Database#mssql_unicode_strings = false" do
|
|
|
493
477
|
DB.mssql_unicode_strings = true
|
|
494
478
|
end
|
|
495
479
|
|
|
496
|
-
|
|
480
|
+
it "should work correctly" do
|
|
497
481
|
DB.create_table!(:items){String :name}
|
|
498
|
-
DB[:items].mssql_unicode_strings.
|
|
482
|
+
DB[:items].mssql_unicode_strings.must_equal false
|
|
499
483
|
DB[:items].insert(:name=>'foo')
|
|
500
|
-
DB[:items].select_map(:name).
|
|
484
|
+
DB[:items].select_map(:name).must_equal ['foo']
|
|
501
485
|
end
|
|
502
486
|
|
|
503
|
-
|
|
487
|
+
it "should be overridable at the dataset level" do
|
|
504
488
|
DB.create_table!(:items){String :name}
|
|
505
489
|
ds = DB[:items]
|
|
506
|
-
ds.mssql_unicode_strings.
|
|
490
|
+
ds.mssql_unicode_strings.must_equal false
|
|
507
491
|
ds.mssql_unicode_strings = true
|
|
508
|
-
ds.mssql_unicode_strings.
|
|
492
|
+
ds.mssql_unicode_strings.must_equal true
|
|
509
493
|
ds.insert(:name=>'foo')
|
|
510
|
-
ds.select_map(:name).
|
|
494
|
+
ds.select_map(:name).must_equal ['foo']
|
|
511
495
|
end
|
|
512
496
|
end
|
|
513
497
|
|
|
@@ -526,11 +510,11 @@ describe "A MSSQL database adds index with include" do
|
|
|
526
510
|
@db.drop_table? @table_name
|
|
527
511
|
end
|
|
528
512
|
|
|
529
|
-
|
|
513
|
+
it "should be able add index with include" do
|
|
530
514
|
@db.alter_table @table_name do
|
|
531
515
|
add_index [:col1], :include => [:col2,:col3]
|
|
532
516
|
end
|
|
533
|
-
@db.indexes(@table_name).
|
|
517
|
+
@db.indexes(@table_name).keys.must_include("#{@table_name}_col1_index".to_sym)
|
|
534
518
|
end
|
|
535
519
|
end
|
|
536
520
|
|
|
@@ -543,10 +527,10 @@ describe "MSSQL::Database#drop_column with a schema" do
|
|
|
543
527
|
DB.run "drop schema test" rescue nil
|
|
544
528
|
end
|
|
545
529
|
|
|
546
|
-
|
|
530
|
+
it "drops columns with a default value" do
|
|
547
531
|
DB.create_table!(:test__items){ Integer :id; String :name, :default => 'widget' }
|
|
548
532
|
DB.drop_column(:test__items, :name)
|
|
549
|
-
DB[:test__items].columns.
|
|
533
|
+
DB[:test__items].columns.must_equal [:id]
|
|
550
534
|
end
|
|
551
535
|
end
|
|
552
536
|
|
|
@@ -576,7 +560,7 @@ describe "Database#foreign_key_list" do
|
|
|
576
560
|
DB.drop_table :items
|
|
577
561
|
end
|
|
578
562
|
it "should support typical foreign keys" do
|
|
579
|
-
DB.foreign_key_list(:prices).
|
|
563
|
+
DB.foreign_key_list(:prices).must_equal [{:name => :fk_prices_items,
|
|
580
564
|
:table => :items,
|
|
581
565
|
:columns => [:item_id],
|
|
582
566
|
:key => [:id],
|
|
@@ -584,7 +568,7 @@ describe "Database#foreign_key_list" do
|
|
|
584
568
|
:on_delete => :no_action }]
|
|
585
569
|
end
|
|
586
570
|
it "should support a foreign key with multiple columns" do
|
|
587
|
-
DB.foreign_key_list(:sales).
|
|
571
|
+
DB.foreign_key_list(:sales).must_equal [{:name => :fk_sales_prices,
|
|
588
572
|
:table => :prices,
|
|
589
573
|
:columns => [:price_item_id, :price_valid_from],
|
|
590
574
|
:key => [:item_id, :valid_from],
|
|
@@ -592,7 +576,7 @@ describe "Database#foreign_key_list" do
|
|
|
592
576
|
:on_delete => :cascade }]
|
|
593
577
|
end
|
|
594
578
|
|
|
595
|
-
|
|
579
|
+
describe "with multiple schemas" do
|
|
596
580
|
before(:all) do
|
|
597
581
|
DB.execute_ddl "create schema vendor"
|
|
598
582
|
DB.create_table! :vendor__vendors do
|
|
@@ -612,7 +596,7 @@ describe "Database#foreign_key_list" do
|
|
|
612
596
|
DB.execute_ddl "drop schema vendor"
|
|
613
597
|
end
|
|
614
598
|
it "should support mixed schema bound tables" do
|
|
615
|
-
DB.foreign_key_list(:vendor__mapping).sort_by{|h| h[:name].to_s}.
|
|
599
|
+
DB.foreign_key_list(:vendor__mapping).sort_by{|h| h[:name].to_s}.must_equal [{:name => :fk_mapping_item, :table => :items, :columns => [:item_id], :key => [:id], :on_update => :no_action, :on_delete => :no_action }, {:name => :fk_mapping_vendor, :table => Sequel.qualify(:vendor, :vendors), :columns => [:vendor_id], :key => [:id], :on_update => :no_action, :on_delete => :no_action }]
|
|
616
600
|
end
|
|
617
601
|
end
|
|
618
602
|
end
|
|
@@ -636,11 +620,11 @@ describe "MSSQL optimistic locking plugin" do
|
|
|
636
620
|
o = c.create(:name=>'test')
|
|
637
621
|
o2 = c.first
|
|
638
622
|
ts = o.timestamp
|
|
639
|
-
ts.
|
|
623
|
+
ts.wont_equal nil
|
|
640
624
|
o.name = 'test2'
|
|
641
625
|
o.save
|
|
642
|
-
o.timestamp.
|
|
643
|
-
proc{o2.save}.
|
|
626
|
+
o.timestamp.wont_equal ts
|
|
627
|
+
proc{o2.save}.must_raise(Sequel::NoExistingObject)
|
|
644
628
|
end
|
|
645
629
|
end unless DB.adapter_scheme == :odbc
|
|
646
630
|
|
|
@@ -659,24 +643,24 @@ describe "MSSQL Stored Procedure support" do
|
|
|
659
643
|
describe "with unnamed parameters" do
|
|
660
644
|
it "should return a hash of output variables" do
|
|
661
645
|
r = @db.call_mssql_sproc(:SequelTest, {:args => [@now, 1, :output, :output]})
|
|
662
|
-
r.
|
|
663
|
-
r.values_at(:var2, :var3).
|
|
646
|
+
r.must_be_kind_of(Hash)
|
|
647
|
+
r.values_at(:var2, :var3).must_equal [@now, '1']
|
|
664
648
|
end
|
|
665
649
|
|
|
666
650
|
it "should support typed output variables" do
|
|
667
|
-
@db.call_mssql_sproc(:SequelTest, {:args => [@now, 1, :output, [:output, 'int']]})[:var3].
|
|
651
|
+
@db.call_mssql_sproc(:SequelTest, {:args => [@now, 1, :output, [:output, 'int']]})[:var3].must_equal 1
|
|
668
652
|
end
|
|
669
653
|
|
|
670
654
|
it "should support named output variables" do
|
|
671
|
-
@db.call_mssql_sproc(:SequelTest, {:args => [@now, 1, [:output, nil, 'output'], :output]})[:output].
|
|
655
|
+
@db.call_mssql_sproc(:SequelTest, {:args => [@now, 1, [:output, nil, 'output'], :output]})[:output].must_equal @now
|
|
672
656
|
end
|
|
673
657
|
|
|
674
658
|
it "should return the number of Affected Rows" do
|
|
675
|
-
@db.call_mssql_sproc(:SequelTest, {:args => [@now, 1, :output, :output]})[:numrows].
|
|
659
|
+
@db.call_mssql_sproc(:SequelTest, {:args => [@now, 1, :output, :output]})[:numrows].must_equal 1
|
|
676
660
|
end
|
|
677
661
|
|
|
678
662
|
it "should return the Result Code" do
|
|
679
|
-
@db.call_mssql_sproc(:SequelTest, {:args => [@now, 1, :output, :output]})[:result].
|
|
663
|
+
@db.call_mssql_sproc(:SequelTest, {:args => [@now, 1, :output, :output]})[:result].must_equal 1
|
|
680
664
|
end
|
|
681
665
|
end
|
|
682
666
|
|
|
@@ -688,8 +672,8 @@ describe "MSSQL Stored Procedure support" do
|
|
|
688
672
|
'Output' => [:output, nil, 'output'],
|
|
689
673
|
'IntegerOutput' => [:output, nil, 'integer_output']
|
|
690
674
|
})
|
|
691
|
-
r.
|
|
692
|
-
r.values_at(:output, :integer_output).
|
|
675
|
+
r.must_be_kind_of(Hash)
|
|
676
|
+
r.values_at(:output, :integer_output).must_equal [@now, '1']
|
|
693
677
|
end
|
|
694
678
|
|
|
695
679
|
it "should support typed output variables" do
|
|
@@ -698,7 +682,7 @@ describe "MSSQL Stored Procedure support" do
|
|
|
698
682
|
'IntegerInput' => 1,
|
|
699
683
|
'Output' => [:output, nil, 'output'],
|
|
700
684
|
'IntegerOutput' => [:output, 'int', 'integer_output']
|
|
701
|
-
})[:integer_output].
|
|
685
|
+
})[:integer_output].must_equal 1
|
|
702
686
|
end
|
|
703
687
|
|
|
704
688
|
it "should return the number of Affected Rows" do
|
|
@@ -707,7 +691,7 @@ describe "MSSQL Stored Procedure support" do
|
|
|
707
691
|
'IntegerInput' => 1,
|
|
708
692
|
'Output' => [:output, nil, 'output'],
|
|
709
693
|
'IntegerOutput' => [:output, nil, 'integer_output']
|
|
710
|
-
})[:numrows].
|
|
694
|
+
})[:numrows].must_equal 1
|
|
711
695
|
end
|
|
712
696
|
|
|
713
697
|
it "should return the Result Code" do
|
|
@@ -716,7 +700,7 @@ describe "MSSQL Stored Procedure support" do
|
|
|
716
700
|
'IntegerInput' => 1,
|
|
717
701
|
'Output' => [:output, nil, 'output'],
|
|
718
702
|
'IntegerOutput' => [:output, nil, 'integer_output']
|
|
719
|
-
})[:result].
|
|
703
|
+
})[:result].must_equal 1
|
|
720
704
|
end
|
|
721
705
|
end
|
|
722
706
|
end unless DB.adapter_scheme == :odbc
|