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
|
@@ -25,107 +25,107 @@ describe "constraint_validations extension" do
|
|
|
25
25
|
|
|
26
26
|
it "should allow creating the sequel_constraint_validations table" do
|
|
27
27
|
@db.create_constraint_validations_table
|
|
28
|
-
@db.sqls.
|
|
28
|
+
@db.sqls.must_equal ["CREATE TABLE sequel_constraint_validations (table varchar(255) NOT NULL, constraint_name varchar(255), validation_type varchar(255) NOT NULL, column varchar(255) NOT NULL, argument varchar(255), message varchar(255), allow_nil boolean)"]
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
it "should allow creating the sequel_constraint_validations table with a non-default table name" do
|
|
32
32
|
@db.constraint_validations_table = :foo
|
|
33
33
|
@db.create_constraint_validations_table
|
|
34
|
-
@db.sqls.
|
|
34
|
+
@db.sqls.must_equal ["CREATE TABLE foo (table varchar(255) NOT NULL, constraint_name varchar(255), validation_type varchar(255) NOT NULL, column varchar(255) NOT NULL, argument varchar(255), message varchar(255), allow_nil boolean)"]
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
it "should allow dropping the sequel_constraint_validations table" do
|
|
38
38
|
@db.drop_constraint_validations_table
|
|
39
|
-
@db.sqls.
|
|
39
|
+
@db.sqls.must_equal ["DROP TABLE sequel_constraint_validations"]
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
it "should allow dropping the sequel_constraint_validations table with a non-default table name" do
|
|
43
43
|
@db.constraint_validations_table = :foo
|
|
44
44
|
@db.drop_constraint_validations_table
|
|
45
|
-
@db.sqls.
|
|
45
|
+
@db.sqls.must_equal ["DROP TABLE foo"]
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
it "should allow dropping validations for a given table" do
|
|
49
49
|
@db.drop_constraint_validations_for(:table=>:foo)
|
|
50
|
-
@db.sqls.
|
|
50
|
+
@db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE (table = 'foo')"]
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
it "should allow dropping validations for a given table and column" do
|
|
54
54
|
@db.drop_constraint_validations_for(:table=>:foo, :column=>:bar)
|
|
55
|
-
@db.sqls.
|
|
55
|
+
@db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE ((table = 'foo') AND (column = 'bar'))"]
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
it "should allow dropping validations for a given table and constraint" do
|
|
59
59
|
@db.drop_constraint_validations_for(:table=>:foo, :constraint=>:bar)
|
|
60
|
-
@db.sqls.
|
|
60
|
+
@db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE ((table = 'foo') AND (constraint_name = 'bar'))"]
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
it "should allow dropping validations for a non-default constraint_validations table" do
|
|
64
64
|
@db.constraint_validations_table = :cv
|
|
65
65
|
@db.drop_constraint_validations_for(:table=>:foo)
|
|
66
|
-
@db.sqls.
|
|
66
|
+
@db.sqls.must_equal ["DELETE FROM cv WHERE (table = 'foo')"]
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
it "should raise an error without deleting if attempting to drop validations without table, column, or constraint" do
|
|
70
|
-
proc{@db.drop_constraint_validations_for({})}.
|
|
71
|
-
@db.sqls.
|
|
70
|
+
proc{@db.drop_constraint_validations_for({})}.must_raise(Sequel::Error)
|
|
71
|
+
@db.sqls.must_equal []
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
it "should allow adding constraint validations via create_table validate" do
|
|
75
75
|
@db.create_table(:foo){String :name; validate{presence :name}}
|
|
76
76
|
sqls = @db.sqls
|
|
77
|
-
parse_insert(sqls.slice!(1)).
|
|
78
|
-
sqls.
|
|
77
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo")
|
|
78
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (trim(name) != '')))"]
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
it "should allow adding constraint validations via alter_table validate" do
|
|
82
82
|
@db.schema = [[:name, {:type=>:string}]]
|
|
83
83
|
@db.alter_table(:foo){validate{presence :name}}
|
|
84
84
|
sqls = @db.sqls
|
|
85
|
-
parse_insert(sqls.slice!(2)).
|
|
86
|
-
sqls.
|
|
85
|
+
parse_insert(sqls.slice!(2)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo")
|
|
86
|
+
sqls.must_equal ["parse schema for foo", "BEGIN", "COMMIT", "ALTER TABLE foo ADD CHECK ((name IS NOT NULL) AND (trim(name) != ''))"]
|
|
87
87
|
end
|
|
88
88
|
|
|
89
89
|
it "should handle :message option when adding validations" do
|
|
90
90
|
@db.create_table(:foo){String :name; validate{presence :name, :message=>'not there'}}
|
|
91
91
|
sqls = @db.sqls
|
|
92
|
-
parse_insert(sqls.slice!(1)).
|
|
93
|
-
sqls.
|
|
92
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo", :message=>'not there')
|
|
93
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (trim(name) != '')))"]
|
|
94
94
|
end
|
|
95
95
|
|
|
96
96
|
it "should handle :allow_nil option when adding validations" do
|
|
97
97
|
@db.create_table(:foo){String :name; validate{presence :name, :allow_nil=>true}}
|
|
98
98
|
sqls = @db.sqls
|
|
99
|
-
parse_insert(sqls.slice!(1)).
|
|
100
|
-
sqls.
|
|
99
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo", :allow_nil=>'t')
|
|
100
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NULL) OR (trim(name) != '')))"]
|
|
101
101
|
end
|
|
102
102
|
|
|
103
103
|
it "should handle :name option when adding validations" do
|
|
104
104
|
@db.create_table(:foo){String :name; validate{presence :name, :name=>'cons'}}
|
|
105
105
|
sqls = @db.sqls
|
|
106
|
-
parse_insert(sqls.slice!(1)).
|
|
107
|
-
sqls.
|
|
106
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo", :constraint_name=>'cons')
|
|
107
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CONSTRAINT cons CHECK ((name IS NOT NULL) AND (trim(name) != '')))"]
|
|
108
108
|
end
|
|
109
109
|
|
|
110
110
|
it "should handle multiple columns when adding validations" do
|
|
111
111
|
@db.create_table(:foo){String :name; String :bar; validate{presence [:name, :bar]}}
|
|
112
112
|
sqls = @db.sqls
|
|
113
|
-
parse_insert(sqls.slice!(1)).
|
|
114
|
-
parse_insert(sqls.slice!(1)).
|
|
115
|
-
sqls.
|
|
113
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo")
|
|
114
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"bar", :table=>"foo")
|
|
115
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), bar varchar(255), CHECK ((name IS NOT NULL) AND (bar IS NOT NULL) AND (trim(name) != '') AND (trim(bar) != '')))"]
|
|
116
116
|
end
|
|
117
117
|
|
|
118
118
|
it "should handle presence validation on non-String columns" do
|
|
119
119
|
@db.create_table(:foo){Integer :name; validate{presence :name}}
|
|
120
120
|
sqls = @db.sqls
|
|
121
|
-
parse_insert(sqls.slice!(1)).
|
|
122
|
-
sqls.
|
|
121
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo")
|
|
122
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name integer, CHECK (name IS NOT NULL))"]
|
|
123
123
|
|
|
124
124
|
@db.schema = [[:name, {:type=>:integer}]]
|
|
125
125
|
@db.alter_table(:foo){validate{presence :name}}
|
|
126
126
|
sqls = @db.sqls
|
|
127
|
-
parse_insert(sqls.slice!(2)).
|
|
128
|
-
sqls.
|
|
127
|
+
parse_insert(sqls.slice!(2)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo")
|
|
128
|
+
sqls.must_equal ["parse schema for foo", "BEGIN", "COMMIT", "ALTER TABLE foo ADD CHECK (name IS NOT NULL)"]
|
|
129
129
|
end
|
|
130
130
|
|
|
131
131
|
it "should handle presence validation on Oracle with IS NOT NULL instead of != ''" do
|
|
@@ -135,61 +135,61 @@ describe "constraint_validations extension" do
|
|
|
135
135
|
sqls = @db.sqls
|
|
136
136
|
s = sqls.slice!(1)
|
|
137
137
|
m = /\AINSERT INTO sequel_constraint_validations \((.*)\) SELECT (.*) FROM DUAL\z/.match(s)
|
|
138
|
-
Hash[*m[1].split(', ').map{|v| v.to_sym}.zip(m[2].split(', ').map{|v| parse_insert_value(v)}).reject{|k, v| v.nil?}.flatten].
|
|
139
|
-
sqls.
|
|
138
|
+
Hash[*m[1].split(', ').map{|v| v.to_sym}.zip(m[2].split(', ').map{|v| parse_insert_value(v)}).reject{|k, v| v.nil?}.flatten].must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo")
|
|
139
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (trim(name) IS NOT NULL)))"]
|
|
140
140
|
end
|
|
141
141
|
|
|
142
142
|
it "should assume column is not a String if it can't determine the type" do
|
|
143
143
|
@db.create_table(:foo){Integer :name; validate{presence :bar}}
|
|
144
144
|
sqls = @db.sqls
|
|
145
|
-
parse_insert(sqls.slice!(1)).
|
|
146
|
-
sqls.
|
|
145
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"bar", :table=>"foo")
|
|
146
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name integer, CHECK (bar IS NOT NULL))"]
|
|
147
147
|
|
|
148
148
|
@db.schema = [[:name, {:type=>:integer}]]
|
|
149
149
|
@db.alter_table(:foo){validate{presence :bar}}
|
|
150
150
|
sqls = @db.sqls
|
|
151
|
-
parse_insert(sqls.slice!(2)).
|
|
152
|
-
sqls.
|
|
151
|
+
parse_insert(sqls.slice!(2)).must_equal(:validation_type=>"presence", :column=>"bar", :table=>"foo")
|
|
152
|
+
sqls.must_equal ["parse schema for foo", "BEGIN", "COMMIT", "ALTER TABLE foo ADD CHECK (bar IS NOT NULL)"]
|
|
153
153
|
end
|
|
154
154
|
|
|
155
155
|
it "should handle presence validation on non-String columns with :allow_nil option" do
|
|
156
156
|
@db.create_table(:foo){Integer :name; validate{presence :name, :allow_nil=>true}}
|
|
157
157
|
sqls = @db.sqls
|
|
158
|
-
parse_insert(sqls.slice!(1)).
|
|
159
|
-
sqls.
|
|
158
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo", :allow_nil=>'t')
|
|
159
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name integer)"]
|
|
160
160
|
end
|
|
161
161
|
|
|
162
162
|
it "should support :exact_length constraint validation" do
|
|
163
163
|
@db.create_table(:foo){String :name; validate{exact_length 5, :name}}
|
|
164
164
|
sqls = @db.sqls
|
|
165
|
-
parse_insert(sqls.slice!(1)).
|
|
166
|
-
sqls.
|
|
165
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"exact_length", :column=>"name", :table=>"foo", :argument=>'5')
|
|
166
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (char_length(name) = 5)))"]
|
|
167
167
|
end
|
|
168
168
|
|
|
169
169
|
it "should support :min_length constraint validation" do
|
|
170
170
|
@db.create_table(:foo){String :name; validate{min_length 5, :name}}
|
|
171
171
|
sqls = @db.sqls
|
|
172
|
-
parse_insert(sqls.slice!(1)).
|
|
173
|
-
sqls.
|
|
172
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"min_length", :column=>"name", :table=>"foo", :argument=>'5')
|
|
173
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (char_length(name) >= 5)))"]
|
|
174
174
|
end
|
|
175
175
|
|
|
176
176
|
it "should support :max_length constraint validation" do
|
|
177
177
|
@db.create_table(:foo){String :name; validate{max_length 5, :name}}
|
|
178
178
|
sqls = @db.sqls
|
|
179
|
-
parse_insert(sqls.slice!(1)).
|
|
180
|
-
sqls.
|
|
179
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"max_length", :column=>"name", :table=>"foo", :argument=>'5')
|
|
180
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (char_length(name) <= 5)))"]
|
|
181
181
|
end
|
|
182
182
|
|
|
183
183
|
it "should support :length_range constraint validation" do
|
|
184
184
|
@db.create_table(:foo){String :name; validate{length_range 3..5, :name}}
|
|
185
185
|
sqls = @db.sqls
|
|
186
|
-
parse_insert(sqls.slice!(1)).
|
|
187
|
-
sqls.
|
|
186
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"length_range", :column=>"name", :table=>"foo", :argument=>'3..5')
|
|
187
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (char_length(name) >= 3) AND (char_length(name) <= 5)))"]
|
|
188
188
|
|
|
189
189
|
@db.create_table(:foo){String :name; validate{length_range 3...5, :name}}
|
|
190
190
|
sqls = @db.sqls
|
|
191
|
-
parse_insert(sqls.slice!(1)).
|
|
192
|
-
sqls.
|
|
191
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"length_range", :column=>"name", :table=>"foo", :argument=>'3...5')
|
|
192
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (char_length(name) >= 3) AND (char_length(name) < 5)))"]
|
|
193
193
|
end
|
|
194
194
|
|
|
195
195
|
it "should support :format constraint validation" do
|
|
@@ -197,8 +197,8 @@ describe "constraint_validations extension" do
|
|
|
197
197
|
@db.extension(:constraint_validations)
|
|
198
198
|
@db.create_table(:foo){String :name; validate{format(/^foo.*/, :name)}}
|
|
199
199
|
sqls = @db.sqls
|
|
200
|
-
parse_insert(sqls.slice!(1)).
|
|
201
|
-
sqls.
|
|
200
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"format", :column=>"name", :table=>"foo", :argument=>'^foo.*')
|
|
201
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name text, CHECK ((name IS NOT NULL) AND (name ~ '^foo.*')))"]
|
|
202
202
|
end
|
|
203
203
|
|
|
204
204
|
it "should support :format constraint validation with case insensitive format" do
|
|
@@ -206,120 +206,120 @@ describe "constraint_validations extension" do
|
|
|
206
206
|
@db.extension(:constraint_validations)
|
|
207
207
|
@db.create_table(:foo){String :name; validate{format(/^foo.*/i, :name)}}
|
|
208
208
|
sqls = @db.sqls
|
|
209
|
-
parse_insert(sqls.slice!(1)).
|
|
210
|
-
sqls.
|
|
209
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"iformat", :column=>"name", :table=>"foo", :argument=>'^foo.*')
|
|
210
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name text, CHECK ((name IS NOT NULL) AND (name ~* '^foo.*')))"]
|
|
211
211
|
end
|
|
212
212
|
|
|
213
213
|
it "should support :includes constraint validation with an array of strings" do
|
|
214
214
|
@db.create_table(:foo){String :name; validate{includes %w'a b c', :name}}
|
|
215
215
|
sqls = @db.sqls
|
|
216
|
-
parse_insert(sqls.slice!(1)).
|
|
217
|
-
sqls.
|
|
216
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"includes_str_array", :column=>"name", :table=>"foo", :argument=>'a,b,c')
|
|
217
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name IN ('a', 'b', 'c'))))"]
|
|
218
218
|
end
|
|
219
219
|
|
|
220
220
|
it "should support :includes constraint validation with an array of integers" do
|
|
221
221
|
@db.create_table(:foo){String :name; validate{includes [1, 2, 3], :name}}
|
|
222
222
|
sqls = @db.sqls
|
|
223
|
-
parse_insert(sqls.slice!(1)).
|
|
224
|
-
sqls.
|
|
223
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"includes_int_array", :column=>"name", :table=>"foo", :argument=>'1,2,3')
|
|
224
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name IN (1, 2, 3))))"]
|
|
225
225
|
end
|
|
226
226
|
|
|
227
227
|
it "should support :includes constraint validation with a inclusive range of integers" do
|
|
228
228
|
@db.create_table(:foo){String :name; validate{includes 3..5, :name}}
|
|
229
229
|
sqls = @db.sqls
|
|
230
|
-
parse_insert(sqls.slice!(1)).
|
|
231
|
-
sqls.
|
|
230
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"includes_int_range", :column=>"name", :table=>"foo", :argument=>'3..5')
|
|
231
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name >= 3) AND (name <= 5)))"]
|
|
232
232
|
end
|
|
233
233
|
|
|
234
234
|
it "should support :includes constraint validation with a exclusive range of integers" do
|
|
235
235
|
@db.create_table(:foo){String :name; validate{includes 3...5, :name}}
|
|
236
236
|
sqls = @db.sqls
|
|
237
|
-
parse_insert(sqls.slice!(1)).
|
|
238
|
-
sqls.
|
|
237
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"includes_int_range", :column=>"name", :table=>"foo", :argument=>'3...5')
|
|
238
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name >= 3) AND (name < 5)))"]
|
|
239
239
|
end
|
|
240
240
|
|
|
241
241
|
it "should support :like constraint validation" do
|
|
242
242
|
@db.create_table(:foo){String :name; validate{like 'foo%', :name}}
|
|
243
243
|
sqls = @db.sqls
|
|
244
|
-
parse_insert(sqls.slice!(1)).
|
|
245
|
-
sqls.
|
|
244
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"like", :column=>"name", :table=>"foo", :argument=>'foo%')
|
|
245
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name LIKE 'foo%' ESCAPE '\\')))"]
|
|
246
246
|
end
|
|
247
247
|
|
|
248
248
|
it "should support :ilike constraint validation" do
|
|
249
249
|
@db.create_table(:foo){String :name; validate{ilike 'foo%', :name}}
|
|
250
250
|
sqls = @db.sqls
|
|
251
|
-
parse_insert(sqls.slice!(1)).
|
|
252
|
-
sqls.
|
|
251
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"ilike", :column=>"name", :table=>"foo", :argument=>'foo%')
|
|
252
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (UPPER(name) LIKE UPPER('foo%') ESCAPE '\\')))"]
|
|
253
253
|
end
|
|
254
254
|
|
|
255
255
|
it "should support :unique constraint validation" do
|
|
256
256
|
@db.create_table(:foo){String :name; validate{unique :name}}
|
|
257
257
|
sqls = @db.sqls
|
|
258
|
-
parse_insert(sqls.slice!(1)).
|
|
259
|
-
sqls.
|
|
258
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"unique", :column=>"name", :table=>"foo")
|
|
259
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), UNIQUE (name))"]
|
|
260
260
|
end
|
|
261
261
|
|
|
262
262
|
it "should support :unique constraint validation with multiple columns" do
|
|
263
263
|
@db.create_table(:foo){String :name; Integer :id; validate{unique [:name, :id]}}
|
|
264
264
|
sqls = @db.sqls
|
|
265
|
-
parse_insert(sqls.slice!(1)).
|
|
266
|
-
sqls.
|
|
265
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"unique", :column=>"name,id", :table=>"foo")
|
|
266
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), id integer, UNIQUE (name, id))"]
|
|
267
267
|
end
|
|
268
268
|
|
|
269
269
|
it "should support :unique constraint validation in alter_table" do
|
|
270
270
|
@db.alter_table(:foo){validate{unique :name}}
|
|
271
271
|
sqls = @db.sqls
|
|
272
|
-
parse_insert(sqls.slice!(1)).
|
|
273
|
-
sqls.
|
|
272
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"unique", :column=>"name", :table=>"foo")
|
|
273
|
+
sqls.must_equal ["BEGIN", "COMMIT", "ALTER TABLE foo ADD UNIQUE (name)"]
|
|
274
274
|
end
|
|
275
275
|
|
|
276
276
|
it "should drop constraints and validations when dropping a constraint validation" do
|
|
277
277
|
@db.alter_table(:foo){String :name; validate{drop :bar}}
|
|
278
|
-
@db.sqls.
|
|
278
|
+
@db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE ((table, constraint_name) IN (('foo', 'bar')))", "ALTER TABLE foo DROP CONSTRAINT bar"]
|
|
279
279
|
end
|
|
280
280
|
|
|
281
281
|
it "should drop constraints and validations before adding new ones" do
|
|
282
282
|
@db.alter_table(:foo){String :name; validate{unique :name; drop :bar}}
|
|
283
283
|
sqls = @db.sqls
|
|
284
|
-
parse_insert(sqls.slice!(2)).
|
|
285
|
-
sqls.
|
|
284
|
+
parse_insert(sqls.slice!(2)).must_equal(:validation_type=>"unique", :column=>"name", :table=>"foo")
|
|
285
|
+
sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE ((table, constraint_name) IN (('foo', 'bar')))", "BEGIN", "COMMIT", "ALTER TABLE foo ADD UNIQUE (name)", "ALTER TABLE foo DROP CONSTRAINT bar"]
|
|
286
286
|
end
|
|
287
287
|
|
|
288
288
|
it "should raise an error if attempting to validate inclusion with a range of non-integers" do
|
|
289
|
-
proc{@db.create_table(:foo){String :name; validate{includes 'a'..'z', :name}}}.
|
|
289
|
+
proc{@db.create_table(:foo){String :name; validate{includes 'a'..'z', :name}}}.must_raise(Sequel::Error)
|
|
290
290
|
end
|
|
291
291
|
|
|
292
292
|
it "should raise an error if attempting to validate inclusion with a range of non-integers or strings" do
|
|
293
|
-
proc{@db.create_table(:foo){String :name; validate{includes [1.0, 2.0], :name}}}.
|
|
293
|
+
proc{@db.create_table(:foo){String :name; validate{includes [1.0, 2.0], :name}}}.must_raise(Sequel::Error)
|
|
294
294
|
end
|
|
295
295
|
|
|
296
296
|
it "should raise an error if attempting to validate inclusion with a unsupported object" do
|
|
297
|
-
proc{@db.create_table(:foo){String :name; validate{includes 'a', :name}}}.
|
|
297
|
+
proc{@db.create_table(:foo){String :name; validate{includes 'a', :name}}}.must_raise(Sequel::Error)
|
|
298
298
|
end
|
|
299
299
|
|
|
300
300
|
it "should raise an error if attempting to drop a constraint validation in a create_table generator" do
|
|
301
|
-
proc{@db.create_table(:foo){String :name; validate{drop :foo}}}.
|
|
301
|
+
proc{@db.create_table(:foo){String :name; validate{drop :foo}}}.must_raise(Sequel::Error)
|
|
302
302
|
end
|
|
303
303
|
|
|
304
304
|
it "should raise an error if attempting to drop a constraint validation without a name" do
|
|
305
|
-
proc{@db.alter_table(:foo){String :name; validate{drop nil}}}.
|
|
305
|
+
proc{@db.alter_table(:foo){String :name; validate{drop nil}}}.must_raise(Sequel::Error)
|
|
306
306
|
end
|
|
307
307
|
|
|
308
308
|
it "should raise an error if attempting attempting to process a constraint validation with an unsupported type" do
|
|
309
|
-
proc{@db.alter_table(:foo){String :name; validations << {:type=>:foo}}}.
|
|
309
|
+
proc{@db.alter_table(:foo){String :name; validations << {:type=>:foo}}}.must_raise(Sequel::Error)
|
|
310
310
|
end
|
|
311
311
|
|
|
312
312
|
it "should allow adding constraint validations for tables specified as a SQL::Identifier" do
|
|
313
313
|
@db.create_table(Sequel.identifier(:sch__foo)){String :name; validate{presence :name}}
|
|
314
314
|
sqls = @db.sqls
|
|
315
|
-
parse_insert(sqls.slice!(1)).
|
|
316
|
-
sqls.
|
|
315
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"sch__foo")
|
|
316
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE sch__foo (name varchar(255), CHECK ((name IS NOT NULL) AND (trim(name) != '')))"]
|
|
317
317
|
end
|
|
318
318
|
|
|
319
319
|
it "should allow adding constraint validations for tables specified as a SQL::QualifiedIdentifier" do
|
|
320
320
|
@db.create_table(Sequel.qualify(:sch, :foo)){String :name; validate{presence :name}}
|
|
321
321
|
sqls = @db.sqls
|
|
322
|
-
parse_insert(sqls.slice!(1)).
|
|
323
|
-
sqls.
|
|
322
|
+
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"sch.foo")
|
|
323
|
+
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE sch.foo (name varchar(255), CHECK ((name IS NOT NULL) AND (trim(name) != '')))"]
|
|
324
324
|
end
|
|
325
325
|
end
|
|
@@ -18,118 +18,118 @@ describe "Core refinements" do
|
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
it "should support NOT via Symbol#~" do
|
|
21
|
-
@d.l(~:x).
|
|
22
|
-
@d.l(~:x__y).
|
|
21
|
+
@d.l(~:x).must_equal 'NOT x'
|
|
22
|
+
@d.l(~:x__y).must_equal 'NOT x.y'
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
it "should support + - * / via Symbol#+,-,*,/" do
|
|
26
|
-
@d.l(:x + 1 > 100).
|
|
27
|
-
@d.l((:x * :y) < 100.01).
|
|
28
|
-
@d.l((:x - :y/2) >= 100000000000000000000000000000000000).
|
|
29
|
-
@d.l((((:x - :y)/(:x + :y))*:z) <= 100).
|
|
30
|
-
@d.l(~((((:x - :y)/(:x + :y))*:z) <= 100)).
|
|
26
|
+
@d.l(:x + 1 > 100).must_equal '((x + 1) > 100)'
|
|
27
|
+
@d.l((:x * :y) < 100.01).must_equal '((x * y) < 100.01)'
|
|
28
|
+
@d.l((:x - :y/2) >= 100000000000000000000000000000000000).must_equal '((x - (y / 2)) >= 100000000000000000000000000000000000)'
|
|
29
|
+
@d.l((((:x - :y)/(:x + :y))*:z) <= 100).must_equal '((((x - y) / (x + y)) * z) <= 100)'
|
|
30
|
+
@d.l(~((((:x - :y)/(:x + :y))*:z) <= 100)).must_equal '((((x - y) / (x + y)) * z) > 100)'
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
it "should support LIKE via Symbol#like" do
|
|
34
|
-
@d.l(:x.like('a')).
|
|
35
|
-
@d.l(:x.like(/a/)).
|
|
36
|
-
@d.l(:x.like('a', 'b')).
|
|
37
|
-
@d.l(:x.like(/a/, /b/i)).
|
|
38
|
-
@d.l(:x.like('a', /b/)).
|
|
34
|
+
@d.l(:x.like('a')).must_equal '(x LIKE \'a\' ESCAPE \'\\\')'
|
|
35
|
+
@d.l(:x.like(/a/)).must_equal '(x ~ \'a\')'
|
|
36
|
+
@d.l(:x.like('a', 'b')).must_equal '((x LIKE \'a\' ESCAPE \'\\\') OR (x LIKE \'b\' ESCAPE \'\\\'))'
|
|
37
|
+
@d.l(:x.like(/a/, /b/i)).must_equal '((x ~ \'a\') OR (x ~* \'b\'))'
|
|
38
|
+
@d.l(:x.like('a', /b/)).must_equal '((x LIKE \'a\' ESCAPE \'\\\') OR (x ~ \'b\'))'
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
it "should support NOT LIKE via Symbol#like and Symbol#~" do
|
|
42
|
-
@d.l(~:x.like('a')).
|
|
43
|
-
@d.l(~:x.like(/a/)).
|
|
44
|
-
@d.l(~:x.like('a', 'b')).
|
|
45
|
-
@d.l(~:x.like(/a/, /b/i)).
|
|
46
|
-
@d.l(~:x.like('a', /b/)).
|
|
42
|
+
@d.l(~:x.like('a')).must_equal '(x NOT LIKE \'a\' ESCAPE \'\\\')'
|
|
43
|
+
@d.l(~:x.like(/a/)).must_equal '(x !~ \'a\')'
|
|
44
|
+
@d.l(~:x.like('a', 'b')).must_equal '((x NOT LIKE \'a\' ESCAPE \'\\\') AND (x NOT LIKE \'b\' ESCAPE \'\\\'))'
|
|
45
|
+
@d.l(~:x.like(/a/, /b/i)).must_equal '((x !~ \'a\') AND (x !~* \'b\'))'
|
|
46
|
+
@d.l(~:x.like('a', /b/)).must_equal '((x NOT LIKE \'a\' ESCAPE \'\\\') AND (x !~ \'b\'))'
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
it "should support ILIKE via Symbol#ilike" do
|
|
50
|
-
@d.l(:x.ilike('a')).
|
|
51
|
-
@d.l(:x.ilike(/a/)).
|
|
52
|
-
@d.l(:x.ilike('a', 'b')).
|
|
53
|
-
@d.l(:x.ilike(/a/, /b/i)).
|
|
54
|
-
@d.l(:x.ilike('a', /b/)).
|
|
50
|
+
@d.l(:x.ilike('a')).must_equal '(UPPER(x) LIKE UPPER(\'a\') ESCAPE \'\\\')'
|
|
51
|
+
@d.l(:x.ilike(/a/)).must_equal '(x ~* \'a\')'
|
|
52
|
+
@d.l(:x.ilike('a', 'b')).must_equal '((UPPER(x) LIKE UPPER(\'a\') ESCAPE \'\\\') OR (UPPER(x) LIKE UPPER(\'b\') ESCAPE \'\\\'))'
|
|
53
|
+
@d.l(:x.ilike(/a/, /b/i)).must_equal '((x ~* \'a\') OR (x ~* \'b\'))'
|
|
54
|
+
@d.l(:x.ilike('a', /b/)).must_equal '((UPPER(x) LIKE UPPER(\'a\') ESCAPE \'\\\') OR (x ~* \'b\'))'
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
it "should support NOT ILIKE via Symbol#ilike and Symbol#~" do
|
|
58
|
-
@d.l(~:x.ilike('a')).
|
|
59
|
-
@d.l(~:x.ilike(/a/)).
|
|
60
|
-
@d.l(~:x.ilike('a', 'b')).
|
|
61
|
-
@d.l(~:x.ilike(/a/, /b/i)).
|
|
62
|
-
@d.l(~:x.ilike('a', /b/)).
|
|
58
|
+
@d.l(~:x.ilike('a')).must_equal '(UPPER(x) NOT LIKE UPPER(\'a\') ESCAPE \'\\\')'
|
|
59
|
+
@d.l(~:x.ilike(/a/)).must_equal '(x !~* \'a\')'
|
|
60
|
+
@d.l(~:x.ilike('a', 'b')).must_equal '((UPPER(x) NOT LIKE UPPER(\'a\') ESCAPE \'\\\') AND (UPPER(x) NOT LIKE UPPER(\'b\') ESCAPE \'\\\'))'
|
|
61
|
+
@d.l(~:x.ilike(/a/, /b/i)).must_equal '((x !~* \'a\') AND (x !~* \'b\'))'
|
|
62
|
+
@d.l(~:x.ilike('a', /b/)).must_equal '((UPPER(x) NOT LIKE UPPER(\'a\') ESCAPE \'\\\') AND (x !~* \'b\'))'
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
it "should support sql_expr on arrays with all two pairs" do
|
|
66
|
-
@d.l([[:x, 100],[:y, 'a']].sql_expr).
|
|
67
|
-
@d.l([[:x, true], [:y, false]].sql_expr).
|
|
68
|
-
@d.l([[:x, nil], [:y, [1,2,3]]].sql_expr).
|
|
66
|
+
@d.l([[:x, 100],[:y, 'a']].sql_expr).must_equal '((x = 100) AND (y = \'a\'))'
|
|
67
|
+
@d.l([[:x, true], [:y, false]].sql_expr).must_equal '((x IS TRUE) AND (y IS FALSE))'
|
|
68
|
+
@d.l([[:x, nil], [:y, [1,2,3]]].sql_expr).must_equal '((x IS NULL) AND (y IN (1, 2, 3)))'
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
it "should support sql_negate on arrays with all two pairs" do
|
|
72
|
-
@d.l([[:x, 100],[:y, 'a']].sql_negate).
|
|
73
|
-
@d.l([[:x, true], [:y, false]].sql_negate).
|
|
74
|
-
@d.l([[:x, nil], [:y, [1,2,3]]].sql_negate).
|
|
72
|
+
@d.l([[:x, 100],[:y, 'a']].sql_negate).must_equal '((x != 100) AND (y != \'a\'))'
|
|
73
|
+
@d.l([[:x, true], [:y, false]].sql_negate).must_equal '((x IS NOT TRUE) AND (y IS NOT FALSE))'
|
|
74
|
+
@d.l([[:x, nil], [:y, [1,2,3]]].sql_negate).must_equal '((x IS NOT NULL) AND (y NOT IN (1, 2, 3)))'
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
it "should support ~ on arrays with all two pairs" do
|
|
78
|
-
@d.l(~[[:x, 100],[:y, 'a']]).
|
|
79
|
-
@d.l(~[[:x, true], [:y, false]]).
|
|
80
|
-
@d.l(~[[:x, nil], [:y, [1,2,3]]]).
|
|
78
|
+
@d.l(~[[:x, 100],[:y, 'a']]).must_equal '((x != 100) OR (y != \'a\'))'
|
|
79
|
+
@d.l(~[[:x, true], [:y, false]]).must_equal '((x IS NOT TRUE) OR (y IS NOT FALSE))'
|
|
80
|
+
@d.l(~[[:x, nil], [:y, [1,2,3]]]).must_equal '((x IS NOT NULL) OR (y NOT IN (1, 2, 3)))'
|
|
81
81
|
end
|
|
82
82
|
|
|
83
83
|
it "should support sql_or on arrays with all two pairs" do
|
|
84
|
-
@d.l([[:x, 100],[:y, 'a']].sql_or).
|
|
85
|
-
@d.l([[:x, true], [:y, false]].sql_or).
|
|
86
|
-
@d.l([[:x, nil], [:y, [1,2,3]]].sql_or).
|
|
84
|
+
@d.l([[:x, 100],[:y, 'a']].sql_or).must_equal '((x = 100) OR (y = \'a\'))'
|
|
85
|
+
@d.l([[:x, true], [:y, false]].sql_or).must_equal '((x IS TRUE) OR (y IS FALSE))'
|
|
86
|
+
@d.l([[:x, nil], [:y, [1,2,3]]].sql_or).must_equal '((x IS NULL) OR (y IN (1, 2, 3)))'
|
|
87
87
|
end
|
|
88
88
|
|
|
89
89
|
it "should support Array#sql_string_join for concatenation of SQL strings" do
|
|
90
|
-
@d.lit([:x].sql_string_join).
|
|
91
|
-
@d.lit([:x].sql_string_join(', ')).
|
|
92
|
-
@d.lit([:x, :y].sql_string_join).
|
|
93
|
-
@d.lit([:x, :y].sql_string_join(', ')).
|
|
94
|
-
@d.lit([:x.sql_function(1), :y.sql_subscript(1)].sql_string_join).
|
|
95
|
-
@d.lit([:x.sql_function(1), 'y.z'.lit].sql_string_join(', ')).
|
|
96
|
-
@d.lit([:x, 1, :y].sql_string_join).
|
|
97
|
-
@d.lit([:x, 1, :y].sql_string_join(', ')).
|
|
98
|
-
@d.lit([:x, 1, :y].sql_string_join(:y__z)).
|
|
99
|
-
@d.lit([:x, 1, :y].sql_string_join(1)).
|
|
100
|
-
@d.lit([:x, :y].sql_string_join('y.x || x.y'.lit)).
|
|
101
|
-
@d.lit([[:x, :y].sql_string_join, [:a, :b].sql_string_join].sql_string_join).
|
|
90
|
+
@d.lit([:x].sql_string_join).must_equal '(x)'
|
|
91
|
+
@d.lit([:x].sql_string_join(', ')).must_equal '(x)'
|
|
92
|
+
@d.lit([:x, :y].sql_string_join).must_equal '(x || y)'
|
|
93
|
+
@d.lit([:x, :y].sql_string_join(', ')).must_equal "(x || ', ' || y)"
|
|
94
|
+
@d.lit([:x.sql_function(1), :y.sql_subscript(1)].sql_string_join).must_equal '(x(1) || y[1])'
|
|
95
|
+
@d.lit([:x.sql_function(1), 'y.z'.lit].sql_string_join(', ')).must_equal "(x(1) || ', ' || y.z)"
|
|
96
|
+
@d.lit([:x, 1, :y].sql_string_join).must_equal "(x || '1' || y)"
|
|
97
|
+
@d.lit([:x, 1, :y].sql_string_join(', ')).must_equal "(x || ', ' || '1' || ', ' || y)"
|
|
98
|
+
@d.lit([:x, 1, :y].sql_string_join(:y__z)).must_equal "(x || y.z || '1' || y.z || y)"
|
|
99
|
+
@d.lit([:x, 1, :y].sql_string_join(1)).must_equal "(x || '1' || '1' || '1' || y)"
|
|
100
|
+
@d.lit([:x, :y].sql_string_join('y.x || x.y'.lit)).must_equal "(x || y.x || x.y || y)"
|
|
101
|
+
@d.lit([[:x, :y].sql_string_join, [:a, :b].sql_string_join].sql_string_join).must_equal "(x || y || a || b)"
|
|
102
102
|
end
|
|
103
103
|
|
|
104
104
|
it "should support sql_expr on hashes" do
|
|
105
|
-
@d.l({:x => 100, :y => 'a'}.sql_expr)[1...-1].split(' AND ').sort.
|
|
106
|
-
@d.l({:x => true, :y => false}.sql_expr)[1...-1].split(' AND ').sort.
|
|
107
|
-
@d.l({:x => nil, :y => [1,2,3]}.sql_expr)[1...-1].split(' AND ').sort.
|
|
105
|
+
@d.l({:x => 100, :y => 'a'}.sql_expr)[1...-1].split(' AND ').sort.must_equal ['(x = 100)', '(y = \'a\')']
|
|
106
|
+
@d.l({:x => true, :y => false}.sql_expr)[1...-1].split(' AND ').sort.must_equal ['(x IS TRUE)', '(y IS FALSE)']
|
|
107
|
+
@d.l({:x => nil, :y => [1,2,3]}.sql_expr)[1...-1].split(' AND ').sort.must_equal ['(x IS NULL)', '(y IN (1, 2, 3))']
|
|
108
108
|
end
|
|
109
109
|
|
|
110
110
|
it "should support sql_negate on hashes" do
|
|
111
|
-
@d.l({:x => 100, :y => 'a'}.sql_negate)[1...-1].split(' AND ').sort.
|
|
112
|
-
@d.l({:x => true, :y => false}.sql_negate)[1...-1].split(' AND ').sort.
|
|
113
|
-
@d.l({:x => nil, :y => [1,2,3]}.sql_negate)[1...-1].split(' AND ').sort.
|
|
111
|
+
@d.l({:x => 100, :y => 'a'}.sql_negate)[1...-1].split(' AND ').sort.must_equal ['(x != 100)', '(y != \'a\')']
|
|
112
|
+
@d.l({:x => true, :y => false}.sql_negate)[1...-1].split(' AND ').sort.must_equal ['(x IS NOT TRUE)', '(y IS NOT FALSE)']
|
|
113
|
+
@d.l({:x => nil, :y => [1,2,3]}.sql_negate)[1...-1].split(' AND ').sort.must_equal ['(x IS NOT NULL)', '(y NOT IN (1, 2, 3))']
|
|
114
114
|
end
|
|
115
115
|
|
|
116
116
|
it "should support ~ on hashes" do
|
|
117
|
-
@d.l(~{:x => 100, :y => 'a'})[1...-1].split(' OR ').sort.
|
|
118
|
-
@d.l(~{:x => true, :y => false})[1...-1].split(' OR ').sort.
|
|
119
|
-
@d.l(~{:x => nil, :y => [1,2,3]})[1...-1].split(' OR ').sort.
|
|
117
|
+
@d.l(~{:x => 100, :y => 'a'})[1...-1].split(' OR ').sort.must_equal ['(x != 100)', '(y != \'a\')']
|
|
118
|
+
@d.l(~{:x => true, :y => false})[1...-1].split(' OR ').sort.must_equal ['(x IS NOT TRUE)', '(y IS NOT FALSE)']
|
|
119
|
+
@d.l(~{:x => nil, :y => [1,2,3]})[1...-1].split(' OR ').sort.must_equal ['(x IS NOT NULL)', '(y NOT IN (1, 2, 3))']
|
|
120
120
|
end
|
|
121
121
|
|
|
122
122
|
it "should support sql_or on hashes" do
|
|
123
|
-
@d.l({:x => 100, :y => 'a'}.sql_or)[1...-1].split(' OR ').sort.
|
|
124
|
-
@d.l({:x => true, :y => false}.sql_or)[1...-1].split(' OR ').sort.
|
|
125
|
-
@d.l({:x => nil, :y => [1,2,3]}.sql_or)[1...-1].split(' OR ').sort.
|
|
123
|
+
@d.l({:x => 100, :y => 'a'}.sql_or)[1...-1].split(' OR ').sort.must_equal ['(x = 100)', '(y = \'a\')']
|
|
124
|
+
@d.l({:x => true, :y => false}.sql_or)[1...-1].split(' OR ').sort.must_equal ['(x IS TRUE)', '(y IS FALSE)']
|
|
125
|
+
@d.l({:x => nil, :y => [1,2,3]}.sql_or)[1...-1].split(' OR ').sort.must_equal ['(x IS NULL)', '(y IN (1, 2, 3))']
|
|
126
126
|
end
|
|
127
127
|
|
|
128
128
|
it "should Hash#& and Hash#|" do
|
|
129
|
-
@d.l({:y => :z} & :x).
|
|
130
|
-
@d.l({:x => :a} & {:y => :z}).
|
|
131
|
-
@d.l({:y => :z} | :x).
|
|
132
|
-
@d.l({:x => :a} | {:y => :z}).
|
|
129
|
+
@d.l({:y => :z} & :x).must_equal '((y = z) AND x)'
|
|
130
|
+
@d.l({:x => :a} & {:y => :z}).must_equal '((x = a) AND (y = z))'
|
|
131
|
+
@d.l({:y => :z} | :x).must_equal '((y = z) OR x)'
|
|
132
|
+
@d.l({:x => :a} | {:y => :z}).must_equal '((x = a) OR (y = z))'
|
|
133
133
|
end
|
|
134
134
|
end
|
|
135
135
|
|
|
@@ -138,30 +138,30 @@ describe "Array#case and Hash#case" do
|
|
|
138
138
|
@d = Sequel.mock.dataset
|
|
139
139
|
end
|
|
140
140
|
|
|
141
|
-
|
|
142
|
-
@d.literal({:x=>:y}.case(:z)).
|
|
143
|
-
@d.literal({:x=>:y}.case(:z, :exp)).
|
|
141
|
+
it "should return SQL CASE expression" do
|
|
142
|
+
@d.literal({:x=>:y}.case(:z)).must_equal '(CASE WHEN x THEN y ELSE z END)'
|
|
143
|
+
@d.literal({:x=>:y}.case(:z, :exp)).must_equal '(CASE exp WHEN x THEN y ELSE z END)'
|
|
144
144
|
['(CASE WHEN x THEN y WHEN a THEN b ELSE z END)',
|
|
145
|
-
'(CASE WHEN a THEN b WHEN x THEN y ELSE z END)'].
|
|
146
|
-
@d.literal([[:x, :y]].case(:z)).
|
|
147
|
-
@d.literal([[:x, :y], [:a, :b]].case(:z)).
|
|
148
|
-
@d.literal([[:x, :y], [:a, :b]].case(:z, :exp)).
|
|
149
|
-
@d.literal([[:x, :y], [:a, :b]].case(:z, :exp__w)).
|
|
145
|
+
'(CASE WHEN a THEN b WHEN x THEN y ELSE z END)'].must_include(@d.literal({:x=>:y, :a=>:b}.case(:z)))
|
|
146
|
+
@d.literal([[:x, :y]].case(:z)).must_equal '(CASE WHEN x THEN y ELSE z END)'
|
|
147
|
+
@d.literal([[:x, :y], [:a, :b]].case(:z)).must_equal '(CASE WHEN x THEN y WHEN a THEN b ELSE z END)'
|
|
148
|
+
@d.literal([[:x, :y], [:a, :b]].case(:z, :exp)).must_equal '(CASE exp WHEN x THEN y WHEN a THEN b ELSE z END)'
|
|
149
|
+
@d.literal([[:x, :y], [:a, :b]].case(:z, :exp__w)).must_equal '(CASE exp.w WHEN x THEN y WHEN a THEN b ELSE z END)'
|
|
150
150
|
end
|
|
151
151
|
|
|
152
|
-
|
|
153
|
-
@d.literal({:x=>:y}.case(:z, nil)).
|
|
152
|
+
it "should return SQL CASE expression with expression even if nil" do
|
|
153
|
+
@d.literal({:x=>:y}.case(:z, nil)).must_equal '(CASE NULL WHEN x THEN y ELSE z END)'
|
|
154
154
|
end
|
|
155
155
|
|
|
156
|
-
|
|
157
|
-
proc{[:b].case(:a)}.
|
|
158
|
-
proc{[:b, :c].case(:a)}.
|
|
159
|
-
proc{[[:b, :c], :d].case(:a)}.
|
|
156
|
+
it "should raise an error if an array that isn't all two pairs is used" do
|
|
157
|
+
proc{[:b].case(:a)}.must_raise(Sequel::Error)
|
|
158
|
+
proc{[:b, :c].case(:a)}.must_raise(Sequel::Error)
|
|
159
|
+
proc{[[:b, :c], :d].case(:a)}.must_raise(Sequel::Error)
|
|
160
160
|
end
|
|
161
161
|
|
|
162
|
-
|
|
163
|
-
proc{[].case(:a)}.
|
|
164
|
-
proc{{}.case(:a)}.
|
|
162
|
+
it "should raise an error if an empty array/hash is used" do
|
|
163
|
+
proc{[].case(:a)}.must_raise(Sequel::Error)
|
|
164
|
+
proc{{}.case(:a)}.must_raise(Sequel::Error)
|
|
165
165
|
end
|
|
166
166
|
end
|
|
167
167
|
|
|
@@ -170,14 +170,14 @@ describe "Array#sql_value_list and #sql_array" do
|
|
|
170
170
|
@d = Sequel.mock.dataset
|
|
171
171
|
end
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
@d.filter("(a, b) IN ?", [[:x, 1], [:y, 2]]).sql.
|
|
175
|
-
@d.filter("(a, b) IN ?", [[:x, 1], [:y, 2]].sql_value_list).sql.
|
|
173
|
+
it "should treat the array as an SQL value list instead of conditions when used as a placeholder value" do
|
|
174
|
+
@d.filter("(a, b) IN ?", [[:x, 1], [:y, 2]]).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x = 1) AND (y = 2)))'
|
|
175
|
+
@d.filter("(a, b) IN ?", [[:x, 1], [:y, 2]].sql_value_list).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
|
|
176
176
|
end
|
|
177
177
|
|
|
178
|
-
|
|
179
|
-
@d.filter([:a, :b]=>[[:x, 1], [:y, 2]]).sql.
|
|
180
|
-
@d.filter([:a, :b]=>[[:x, 1], [:y, 2]].sql_value_list).sql.
|
|
178
|
+
it "should be no difference when used as a hash value" do
|
|
179
|
+
@d.filter([:a, :b]=>[[:x, 1], [:y, 2]]).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
|
|
180
|
+
@d.filter([:a, :b]=>[[:x, 1], [:y, 2]].sql_value_list).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
|
|
181
181
|
end
|
|
182
182
|
end
|
|
183
183
|
|
|
@@ -186,47 +186,47 @@ describe "String#lit" do
|
|
|
186
186
|
@ds = Sequel::Database.new[:t]
|
|
187
187
|
end
|
|
188
188
|
|
|
189
|
-
|
|
190
|
-
'xyz'.lit.
|
|
191
|
-
'xyz'.lit.to_s.
|
|
189
|
+
it "should return an LiteralString object" do
|
|
190
|
+
'xyz'.lit.must_be_kind_of(Sequel::LiteralString)
|
|
191
|
+
'xyz'.lit.to_s.must_equal 'xyz'
|
|
192
192
|
end
|
|
193
193
|
|
|
194
|
-
|
|
195
|
-
@ds.update_sql(:stamp => "NOW()".lit).
|
|
194
|
+
it "should inhibit string literalization" do
|
|
195
|
+
@ds.update_sql(:stamp => "NOW()".lit).must_equal "UPDATE t SET stamp = NOW()"
|
|
196
196
|
end
|
|
197
197
|
|
|
198
|
-
|
|
198
|
+
it "should return a PlaceholderLiteralString object if args are given" do
|
|
199
199
|
a = 'DISTINCT ?'.lit(:a)
|
|
200
|
-
a.
|
|
201
|
-
@ds.literal(a).
|
|
200
|
+
a.must_be_kind_of(Sequel::SQL::PlaceholderLiteralString)
|
|
201
|
+
@ds.literal(a).must_equal 'DISTINCT a'
|
|
202
202
|
@ds.quote_identifiers = true
|
|
203
|
-
@ds.literal(a).
|
|
203
|
+
@ds.literal(a).must_equal 'DISTINCT "a"'
|
|
204
204
|
end
|
|
205
205
|
|
|
206
|
-
|
|
206
|
+
it "should handle named placeholders if given a single argument hash" do
|
|
207
207
|
a = 'DISTINCT :b'.lit(:b=>:a)
|
|
208
|
-
a.
|
|
209
|
-
@ds.literal(a).
|
|
208
|
+
a.must_be_kind_of(Sequel::SQL::PlaceholderLiteralString)
|
|
209
|
+
@ds.literal(a).must_equal 'DISTINCT a'
|
|
210
210
|
@ds.quote_identifiers = true
|
|
211
|
-
@ds.literal(a).
|
|
211
|
+
@ds.literal(a).must_equal 'DISTINCT "a"'
|
|
212
212
|
end
|
|
213
213
|
|
|
214
|
-
|
|
214
|
+
it "should treat placeholder literal strings as generic expressions" do
|
|
215
215
|
a = ':b'.lit(:b=>:a)
|
|
216
|
-
@ds.literal(a + 1).
|
|
217
|
-
@ds.literal(a & :b).
|
|
218
|
-
@ds.literal(a.sql_string + :b).
|
|
216
|
+
@ds.literal(a + 1).must_equal "(a + 1)"
|
|
217
|
+
@ds.literal(a & :b).must_equal "(a AND b)"
|
|
218
|
+
@ds.literal(a.sql_string + :b).must_equal "(a || b)"
|
|
219
219
|
end
|
|
220
220
|
end
|
|
221
221
|
|
|
222
222
|
describe "String#to_sequel_blob" do
|
|
223
|
-
|
|
224
|
-
'xyz'.to_sequel_blob.
|
|
225
|
-
'xyz'.to_sequel_blob.
|
|
223
|
+
it "should return a Blob object" do
|
|
224
|
+
'xyz'.to_sequel_blob.must_be_kind_of(::Sequel::SQL::Blob)
|
|
225
|
+
'xyz'.to_sequel_blob.must_equal 'xyz'
|
|
226
226
|
end
|
|
227
227
|
|
|
228
|
-
|
|
229
|
-
"\1\2\3\4".to_sequel_blob.
|
|
228
|
+
it "should retain binary data" do
|
|
229
|
+
"\1\2\3\4".to_sequel_blob.must_equal "\1\2\3\4"
|
|
230
230
|
end
|
|
231
231
|
end
|
|
232
232
|
|
|
@@ -235,14 +235,14 @@ describe "#desc" do
|
|
|
235
235
|
@ds = Sequel.mock.dataset
|
|
236
236
|
end
|
|
237
237
|
|
|
238
|
-
|
|
239
|
-
@ds.literal(:test.desc).
|
|
238
|
+
it "should format a DESC clause for a column ref" do
|
|
239
|
+
@ds.literal(:test.desc).must_equal 'test DESC'
|
|
240
240
|
|
|
241
|
-
@ds.literal(:items__price.desc).
|
|
241
|
+
@ds.literal(:items__price.desc).must_equal 'items.price DESC'
|
|
242
242
|
end
|
|
243
243
|
|
|
244
|
-
|
|
245
|
-
@ds.literal(:avg.sql_function(:test).desc).
|
|
244
|
+
it "should format a DESC clause for a function" do
|
|
245
|
+
@ds.literal(:avg.sql_function(:test).desc).must_equal 'avg(test) DESC'
|
|
246
246
|
end
|
|
247
247
|
end
|
|
248
248
|
|
|
@@ -251,14 +251,14 @@ describe "#asc" do
|
|
|
251
251
|
@ds = Sequel.mock.dataset
|
|
252
252
|
end
|
|
253
253
|
|
|
254
|
-
|
|
255
|
-
@ds.literal(:test.asc).
|
|
254
|
+
it "should format a ASC clause for a column ref" do
|
|
255
|
+
@ds.literal(:test.asc).must_equal 'test ASC'
|
|
256
256
|
|
|
257
|
-
@ds.literal(:items__price.asc).
|
|
257
|
+
@ds.literal(:items__price.asc).must_equal 'items.price ASC'
|
|
258
258
|
end
|
|
259
259
|
|
|
260
|
-
|
|
261
|
-
@ds.literal(:avg.sql_function(:test).asc).
|
|
260
|
+
it "should format a ASC clause for a function" do
|
|
261
|
+
@ds.literal(:avg.sql_function(:test).asc).must_equal 'avg(test) ASC'
|
|
262
262
|
end
|
|
263
263
|
end
|
|
264
264
|
|
|
@@ -267,18 +267,18 @@ describe "#as" do
|
|
|
267
267
|
@ds = Sequel.mock.dataset
|
|
268
268
|
end
|
|
269
269
|
|
|
270
|
-
|
|
271
|
-
@ds.literal(:test.as(:t)).
|
|
270
|
+
it "should format a AS clause for a column ref" do
|
|
271
|
+
@ds.literal(:test.as(:t)).must_equal 'test AS t'
|
|
272
272
|
|
|
273
|
-
@ds.literal(:items__price.as(:p)).
|
|
273
|
+
@ds.literal(:items__price.as(:p)).must_equal 'items.price AS p'
|
|
274
274
|
end
|
|
275
275
|
|
|
276
|
-
|
|
277
|
-
@ds.literal(:avg.sql_function(:test).as(:avg)).
|
|
276
|
+
it "should format a AS clause for a function" do
|
|
277
|
+
@ds.literal(:avg.sql_function(:test).as(:avg)).must_equal 'avg(test) AS avg'
|
|
278
278
|
end
|
|
279
279
|
|
|
280
|
-
|
|
281
|
-
@ds.literal('abc'.as(:abc)).
|
|
280
|
+
it "should format a AS clause for a literal value" do
|
|
281
|
+
@ds.literal('abc'.as(:abc)).must_equal "'abc' AS abc"
|
|
282
282
|
end
|
|
283
283
|
end
|
|
284
284
|
|
|
@@ -291,38 +291,38 @@ describe "Column references" do
|
|
|
291
291
|
@ds.quote_identifiers = true
|
|
292
292
|
end
|
|
293
293
|
|
|
294
|
-
|
|
295
|
-
@ds.literal(:xyz).
|
|
296
|
-
@ds.literal(:xyz__abc).
|
|
294
|
+
it "should be quoted properly" do
|
|
295
|
+
@ds.literal(:xyz).must_equal "`xyz`"
|
|
296
|
+
@ds.literal(:xyz__abc).must_equal "`xyz`.`abc`"
|
|
297
297
|
|
|
298
|
-
@ds.literal(:xyz.as(:x)).
|
|
299
|
-
@ds.literal(:xyz__abc.as(:x)).
|
|
298
|
+
@ds.literal(:xyz.as(:x)).must_equal "`xyz` AS `x`"
|
|
299
|
+
@ds.literal(:xyz__abc.as(:x)).must_equal "`xyz`.`abc` AS `x`"
|
|
300
300
|
|
|
301
|
-
@ds.literal(:xyz___x).
|
|
302
|
-
@ds.literal(:xyz__abc___x).
|
|
301
|
+
@ds.literal(:xyz___x).must_equal "`xyz` AS `x`"
|
|
302
|
+
@ds.literal(:xyz__abc___x).must_equal "`xyz`.`abc` AS `x`"
|
|
303
303
|
end
|
|
304
304
|
|
|
305
|
-
|
|
306
|
-
@ds.literal(:avg.sql_function(:xyz)).
|
|
307
|
-
@ds.literal(:avg.sql_function(:xyz, 1)).
|
|
308
|
-
@ds.literal(:avg.sql_function(:xyz).as(:a)).
|
|
305
|
+
it "should be quoted properly in SQL functions" do
|
|
306
|
+
@ds.literal(:avg.sql_function(:xyz)).must_equal "avg(`xyz`)"
|
|
307
|
+
@ds.literal(:avg.sql_function(:xyz, 1)).must_equal "avg(`xyz`, 1)"
|
|
308
|
+
@ds.literal(:avg.sql_function(:xyz).as(:a)).must_equal "avg(`xyz`) AS `a`"
|
|
309
309
|
end
|
|
310
310
|
|
|
311
|
-
|
|
312
|
-
@ds.literal(:xyz.asc).
|
|
313
|
-
@ds.literal(:avg.sql_function(:xyz, 1).desc).
|
|
311
|
+
it "should be quoted properly in ASC/DESC clauses" do
|
|
312
|
+
@ds.literal(:xyz.asc).must_equal "`xyz` ASC"
|
|
313
|
+
@ds.literal(:avg.sql_function(:xyz, 1).desc).must_equal "avg(`xyz`, 1) DESC"
|
|
314
314
|
end
|
|
315
315
|
|
|
316
|
-
|
|
317
|
-
@ds.literal(:x.cast(:integer)).
|
|
318
|
-
@ds.literal(:x__y.cast('varchar(20)')).
|
|
316
|
+
it "should be quoted properly in a cast function" do
|
|
317
|
+
@ds.literal(:x.cast(:integer)).must_equal "CAST(`x` AS integer)"
|
|
318
|
+
@ds.literal(:x__y.cast('varchar(20)')).must_equal "CAST(`x`.`y` AS varchar(20))"
|
|
319
319
|
end
|
|
320
320
|
end
|
|
321
321
|
|
|
322
322
|
describe "Blob" do
|
|
323
|
-
|
|
323
|
+
it "#to_sequel_blob should return self" do
|
|
324
324
|
blob = "x".to_sequel_blob
|
|
325
|
-
blob.to_sequel_blob.object_id.
|
|
325
|
+
blob.to_sequel_blob.object_id.must_equal blob.object_id
|
|
326
326
|
end
|
|
327
327
|
end
|
|
328
328
|
|
|
@@ -331,18 +331,18 @@ describe "Symbol#*" do
|
|
|
331
331
|
@ds = Sequel.mock.dataset
|
|
332
332
|
end
|
|
333
333
|
|
|
334
|
-
|
|
335
|
-
@ds.literal(:xyz.*).
|
|
336
|
-
@ds.literal(:abc.*).
|
|
334
|
+
it "should format a qualified wildcard if no argument" do
|
|
335
|
+
@ds.literal(:xyz.*).must_equal 'xyz.*'
|
|
336
|
+
@ds.literal(:abc.*).must_equal 'abc.*'
|
|
337
337
|
end
|
|
338
338
|
|
|
339
|
-
|
|
340
|
-
@ds.literal(:xyz.*(3)).
|
|
341
|
-
@ds.literal(:abc.*(5)).
|
|
339
|
+
it "should format a filter expression if an argument" do
|
|
340
|
+
@ds.literal(:xyz.*(3)).must_equal '(xyz * 3)'
|
|
341
|
+
@ds.literal(:abc.*(5)).must_equal '(abc * 5)'
|
|
342
342
|
end
|
|
343
343
|
|
|
344
|
-
|
|
345
|
-
@ds.literal(:xyz__abc.*).
|
|
344
|
+
it "should support qualified symbols if no argument" do
|
|
345
|
+
@ds.literal(:xyz__abc.*).must_equal 'xyz.abc.*'
|
|
346
346
|
end
|
|
347
347
|
end
|
|
348
348
|
|
|
@@ -353,40 +353,40 @@ describe "Symbol" do
|
|
|
353
353
|
@ds.identifier_input_method = :upcase
|
|
354
354
|
end
|
|
355
355
|
|
|
356
|
-
|
|
357
|
-
@ds.literal(:xyz__abc.identifier).
|
|
356
|
+
it "#identifier should format an identifier" do
|
|
357
|
+
@ds.literal(:xyz__abc.identifier).must_equal '"XYZ__ABC"'
|
|
358
358
|
end
|
|
359
359
|
|
|
360
|
-
|
|
361
|
-
@ds.literal(:xyz.qualify(:abc)).
|
|
360
|
+
it "#qualify should format a qualified column" do
|
|
361
|
+
@ds.literal(:xyz.qualify(:abc)).must_equal '"ABC"."XYZ"'
|
|
362
362
|
end
|
|
363
363
|
|
|
364
|
-
|
|
365
|
-
@ds.literal(:xyz.qualify(:abc).qualify(:def)).
|
|
364
|
+
it "#qualify should work on QualifiedIdentifiers" do
|
|
365
|
+
@ds.literal(:xyz.qualify(:abc).qualify(:def)).must_equal '"DEF"."ABC"."XYZ"'
|
|
366
366
|
end
|
|
367
367
|
|
|
368
|
-
|
|
369
|
-
@ds.literal(:xyz.identifier.qualify(:xyz__abc)).
|
|
368
|
+
it "should be able to qualify an identifier" do
|
|
369
|
+
@ds.literal(:xyz.identifier.qualify(:xyz__abc)).must_equal '"XYZ"."ABC"."XYZ"'
|
|
370
370
|
end
|
|
371
371
|
|
|
372
|
-
|
|
373
|
-
@ds.literal(:column.qualify(:table.qualify(:schema))).
|
|
374
|
-
@ds.literal(:column.qualify(:table__name.identifier.qualify(:schema))).
|
|
372
|
+
it "should be able to specify a schema.table.column" do
|
|
373
|
+
@ds.literal(:column.qualify(:table.qualify(:schema))).must_equal '"SCHEMA"."TABLE"."COLUMN"'
|
|
374
|
+
@ds.literal(:column.qualify(:table__name.identifier.qualify(:schema))).must_equal '"SCHEMA"."TABLE__NAME"."COLUMN"'
|
|
375
375
|
end
|
|
376
376
|
|
|
377
|
-
|
|
377
|
+
it "should be able to specify order" do
|
|
378
378
|
@oe = :xyz.desc
|
|
379
|
-
@oe.class.
|
|
380
|
-
@oe.descending.
|
|
379
|
+
@oe.class.must_equal Sequel::SQL::OrderedExpression
|
|
380
|
+
@oe.descending.must_equal true
|
|
381
381
|
@oe = :xyz.asc
|
|
382
|
-
@oe.class.
|
|
383
|
-
@oe.descending.
|
|
382
|
+
@oe.class.must_equal Sequel::SQL::OrderedExpression
|
|
383
|
+
@oe.descending.must_equal false
|
|
384
384
|
end
|
|
385
385
|
|
|
386
|
-
|
|
386
|
+
it "should work correctly with objects" do
|
|
387
387
|
o = Object.new
|
|
388
388
|
def o.sql_literal(ds) "(foo)" end
|
|
389
|
-
@ds.literal(:column.qualify(o)).
|
|
389
|
+
@ds.literal(:column.qualify(o)).must_equal '(foo)."COLUMN"'
|
|
390
390
|
end
|
|
391
391
|
end
|
|
392
392
|
|
|
@@ -395,57 +395,57 @@ describe "Symbol" do
|
|
|
395
395
|
@ds = Sequel::Database.new.dataset
|
|
396
396
|
end
|
|
397
397
|
|
|
398
|
-
|
|
399
|
-
@ds.literal(:COUNT.sql_function('1')).
|
|
400
|
-
@ds.select(:COUNT.sql_function('1')).sql.
|
|
398
|
+
it "should support sql_function method" do
|
|
399
|
+
@ds.literal(:COUNT.sql_function('1')).must_equal "COUNT('1')"
|
|
400
|
+
@ds.select(:COUNT.sql_function('1')).sql.must_equal "SELECT COUNT('1')"
|
|
401
401
|
end
|
|
402
402
|
|
|
403
|
-
|
|
404
|
-
@ds.literal(:abc.cast(:integer)).
|
|
403
|
+
it "should support cast method" do
|
|
404
|
+
@ds.literal(:abc.cast(:integer)).must_equal "CAST(abc AS integer)"
|
|
405
405
|
end
|
|
406
406
|
|
|
407
|
-
|
|
408
|
-
@ds.literal(:abc.sql_subscript(1)).
|
|
409
|
-
@ds.literal(:abc__def.sql_subscript(1)).
|
|
410
|
-
@ds.literal(:abc.sql_subscript(1)|2).
|
|
411
|
-
@ds.literal(:abc.sql_subscript(1)[2]).
|
|
407
|
+
it "should support sql array accesses via sql_subscript" do
|
|
408
|
+
@ds.literal(:abc.sql_subscript(1)).must_equal "abc[1]"
|
|
409
|
+
@ds.literal(:abc__def.sql_subscript(1)).must_equal "abc.def[1]"
|
|
410
|
+
@ds.literal(:abc.sql_subscript(1)|2).must_equal "abc[1, 2]"
|
|
411
|
+
@ds.literal(:abc.sql_subscript(1)[2]).must_equal "abc[1][2]"
|
|
412
412
|
end
|
|
413
413
|
|
|
414
|
-
|
|
414
|
+
it "should support cast_numeric and cast_string" do
|
|
415
415
|
x = :abc.cast_numeric
|
|
416
|
-
x.
|
|
417
|
-
@ds.literal(x).
|
|
416
|
+
x.must_be_kind_of(Sequel::SQL::NumericExpression)
|
|
417
|
+
@ds.literal(x).must_equal "CAST(abc AS integer)"
|
|
418
418
|
|
|
419
419
|
x = :abc.cast_numeric(:real)
|
|
420
|
-
x.
|
|
421
|
-
@ds.literal(x).
|
|
420
|
+
x.must_be_kind_of(Sequel::SQL::NumericExpression)
|
|
421
|
+
@ds.literal(x).must_equal "CAST(abc AS real)"
|
|
422
422
|
|
|
423
423
|
x = :abc.cast_string
|
|
424
|
-
x.
|
|
425
|
-
@ds.literal(x).
|
|
424
|
+
x.must_be_kind_of(Sequel::SQL::StringExpression)
|
|
425
|
+
@ds.literal(x).must_equal "CAST(abc AS varchar(255))"
|
|
426
426
|
|
|
427
427
|
x = :abc.cast_string(:varchar)
|
|
428
|
-
x.
|
|
429
|
-
@ds.literal(x).
|
|
428
|
+
x.must_be_kind_of(Sequel::SQL::StringExpression)
|
|
429
|
+
@ds.literal(x).must_equal "CAST(abc AS varchar(255))"
|
|
430
430
|
end
|
|
431
431
|
|
|
432
|
-
|
|
432
|
+
it "should allow database independent types when casting" do
|
|
433
433
|
db = @ds.db
|
|
434
434
|
def db.cast_type_literal(type)
|
|
435
435
|
return :foo if type == Integer
|
|
436
436
|
return :bar if type == String
|
|
437
437
|
type
|
|
438
438
|
end
|
|
439
|
-
@ds.literal(:abc.cast(String)).
|
|
440
|
-
@ds.literal(:abc.cast(String)).
|
|
441
|
-
@ds.literal(:abc.cast_string).
|
|
442
|
-
@ds.literal(:abc.cast_string(Integer)).
|
|
443
|
-
@ds.literal(:abc.cast_numeric).
|
|
444
|
-
@ds.literal(:abc.cast_numeric(String)).
|
|
439
|
+
@ds.literal(:abc.cast(String)).must_equal "CAST(abc AS bar)"
|
|
440
|
+
@ds.literal(:abc.cast(String)).must_equal "CAST(abc AS bar)"
|
|
441
|
+
@ds.literal(:abc.cast_string).must_equal "CAST(abc AS bar)"
|
|
442
|
+
@ds.literal(:abc.cast_string(Integer)).must_equal "CAST(abc AS foo)"
|
|
443
|
+
@ds.literal(:abc.cast_numeric).must_equal "CAST(abc AS foo)"
|
|
444
|
+
@ds.literal(:abc.cast_numeric(String)).must_equal "CAST(abc AS bar)"
|
|
445
445
|
end
|
|
446
446
|
|
|
447
|
-
|
|
448
|
-
@ds.literal(:abc.extract(:year)).
|
|
447
|
+
it "should support SQL EXTRACT function via #extract " do
|
|
448
|
+
@ds.literal(:abc.extract(:year)).must_equal "extract(year FROM abc)"
|
|
449
449
|
end
|
|
450
450
|
end
|
|
451
451
|
|
|
@@ -455,63 +455,63 @@ describe "Postgres extensions integration" do
|
|
|
455
455
|
end
|
|
456
456
|
|
|
457
457
|
it "Symbol#pg_array should return an ArrayOp" do
|
|
458
|
-
@db.literal(:a.pg_array.unnest).
|
|
458
|
+
@db.literal(:a.pg_array.unnest).must_equal "unnest(a)"
|
|
459
459
|
end
|
|
460
460
|
|
|
461
461
|
it "Symbol#pg_row should return a PGRowOp" do
|
|
462
|
-
@db.literal(:a.pg_row[:a]).
|
|
462
|
+
@db.literal(:a.pg_row[:a]).must_equal "(a).a"
|
|
463
463
|
end
|
|
464
464
|
|
|
465
465
|
it "Symbol#hstore should return an HStoreOp" do
|
|
466
|
-
@db.literal(:a.hstore['a']).
|
|
466
|
+
@db.literal(:a.hstore['a']).must_equal "(a -> 'a')"
|
|
467
467
|
end
|
|
468
468
|
|
|
469
469
|
it "Symbol#pg_json should return an JSONOp" do
|
|
470
|
-
@db.literal(:a.pg_json[%w'a b']).
|
|
471
|
-
@db.literal(:a.pg_json.extract('a')).
|
|
470
|
+
@db.literal(:a.pg_json[%w'a b']).must_equal "(a #> ARRAY['a','b'])"
|
|
471
|
+
@db.literal(:a.pg_json.extract('a')).must_equal "json_extract_path(a, 'a')"
|
|
472
472
|
end
|
|
473
473
|
|
|
474
474
|
it "Symbol#pg_jsonb should return an JSONBOp" do
|
|
475
|
-
@db.literal(:a.pg_jsonb[%w'a b']).
|
|
476
|
-
@db.literal(:a.pg_jsonb.extract('a')).
|
|
475
|
+
@db.literal(:a.pg_jsonb[%w'a b']).must_equal "(a #> ARRAY['a','b'])"
|
|
476
|
+
@db.literal(:a.pg_jsonb.extract('a')).must_equal "jsonb_extract_path(a, 'a')"
|
|
477
477
|
end
|
|
478
478
|
|
|
479
479
|
it "Symbol#pg_range should return a RangeOp" do
|
|
480
|
-
@db.literal(:a.pg_range.lower).
|
|
480
|
+
@db.literal(:a.pg_range.lower).must_equal "lower(a)"
|
|
481
481
|
end
|
|
482
482
|
|
|
483
483
|
it "Array#pg_array should return a PGArray" do
|
|
484
|
-
@db.literal([1].pg_array.op.unnest).
|
|
485
|
-
@db.literal([1].pg_array(:int4).op.unnest).
|
|
484
|
+
@db.literal([1].pg_array.op.unnest).must_equal "unnest(ARRAY[1])"
|
|
485
|
+
@db.literal([1].pg_array(:int4).op.unnest).must_equal "unnest(ARRAY[1]::int4[])"
|
|
486
486
|
end
|
|
487
487
|
|
|
488
488
|
it "Array#pg_json should return a JSONArray" do
|
|
489
|
-
@db.literal([1].pg_json).
|
|
489
|
+
@db.literal([1].pg_json).must_equal "'[1]'::json"
|
|
490
490
|
end
|
|
491
491
|
|
|
492
492
|
it "Array#pg_jsonb should return a JSONBArray" do
|
|
493
|
-
@db.literal([1].pg_jsonb).
|
|
493
|
+
@db.literal([1].pg_jsonb).must_equal "'[1]'::jsonb"
|
|
494
494
|
end
|
|
495
495
|
|
|
496
496
|
it "Array#pg_row should return a ArrayRow" do
|
|
497
|
-
@db.literal([1].pg_row).
|
|
497
|
+
@db.literal([1].pg_row).must_equal "ROW(1)"
|
|
498
498
|
end
|
|
499
499
|
|
|
500
500
|
it "Hash#hstore should return an HStore" do
|
|
501
|
-
@db.literal({'a'=>1}.hstore.op['a']).
|
|
501
|
+
@db.literal({'a'=>1}.hstore.op['a']).must_equal '(\'"a"=>"1"\'::hstore -> \'a\')'
|
|
502
502
|
end
|
|
503
503
|
|
|
504
504
|
it "Hash#pg_json should return an JSONHash" do
|
|
505
|
-
@db.literal({'a'=>'b'}.pg_json).
|
|
505
|
+
@db.literal({'a'=>'b'}.pg_json).must_equal "'{\"a\":\"b\"}'::json"
|
|
506
506
|
end
|
|
507
507
|
|
|
508
508
|
it "Hash#pg_jsonb should return an JSONBHash" do
|
|
509
|
-
@db.literal({'a'=>'b'}.pg_jsonb).
|
|
509
|
+
@db.literal({'a'=>'b'}.pg_jsonb).must_equal "'{\"a\":\"b\"}'::jsonb"
|
|
510
510
|
end
|
|
511
511
|
|
|
512
512
|
it "Range#pg_range should return an PGRange" do
|
|
513
|
-
@db.literal((1..2).pg_range).
|
|
514
|
-
@db.literal((1..2).pg_range(:int4range)).
|
|
513
|
+
@db.literal((1..2).pg_range).must_equal "'[1,2]'"
|
|
514
|
+
@db.literal((1..2).pg_range(:int4range)).must_equal "'[1,2]'::int4range"
|
|
515
515
|
end
|
|
516
516
|
end
|
|
517
517
|
else
|