sequel 3.21.0 → 3.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +855 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +23 -7
- data/Rakefile +42 -24
- data/bin/sequel +26 -8
- data/doc/active_record.rdoc +1 -0
- data/doc/advanced_associations.rdoc +171 -11
- data/doc/association_basics.rdoc +293 -43
- data/doc/dataset_basics.rdoc +5 -5
- data/doc/dataset_filtering.rdoc +8 -0
- data/doc/mass_assignment.rdoc +56 -0
- data/doc/migration.rdoc +85 -552
- data/doc/model_hooks.rdoc +78 -27
- data/doc/object_model.rdoc +541 -0
- data/doc/opening_databases.rdoc +97 -50
- data/doc/prepared_statements.rdoc +40 -14
- data/doc/querying.rdoc +28 -4
- data/doc/reflection.rdoc +30 -4
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/release_notes/3.30.0.txt +135 -0
- data/doc/release_notes/3.31.0.txt +146 -0
- data/doc/release_notes/3.32.0.txt +202 -0
- data/doc/release_notes/3.33.0.txt +157 -0
- data/doc/release_notes/3.34.0.txt +671 -0
- data/doc/release_notes/3.35.0.txt +144 -0
- data/doc/release_notes/3.36.0.txt +245 -0
- data/doc/schema_modification.rdoc +572 -0
- data/doc/sharding.rdoc +95 -3
- data/doc/testing.rdoc +129 -0
- data/doc/thread_safety.rdoc +17 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/virtual_rows.rdoc +51 -2
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/ado.rb +40 -18
- data/lib/sequel/adapters/amalgalite.rb +17 -9
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do/mysql.rb +17 -11
- data/lib/sequel/adapters/do/postgres.rb +1 -57
- data/lib/sequel/adapters/do/sqlite.rb +0 -10
- data/lib/sequel/adapters/do.rb +18 -36
- data/lib/sequel/adapters/firebird.rb +27 -208
- data/lib/sequel/adapters/ibmdb.rb +453 -0
- data/lib/sequel/adapters/informix.rb +6 -23
- data/lib/sequel/adapters/jdbc/as400.rb +16 -34
- data/lib/sequel/adapters/jdbc/db2.rb +47 -0
- data/lib/sequel/adapters/jdbc/derby.rb +287 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
- data/lib/sequel/adapters/jdbc/h2.rb +73 -31
- data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
- data/lib/sequel/adapters/jdbc/informix.rb +21 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
- data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +58 -48
- data/lib/sequel/adapters/jdbc/progress.rb +21 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
- data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +265 -94
- data/lib/sequel/adapters/mock.rb +361 -0
- data/lib/sequel/adapters/mysql.rb +118 -222
- data/lib/sequel/adapters/mysql2.rb +58 -57
- data/lib/sequel/adapters/odbc/mssql.rb +15 -7
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +3 -5
- data/lib/sequel/adapters/oracle.rb +349 -53
- data/lib/sequel/adapters/postgres.rb +356 -107
- data/lib/sequel/adapters/shared/access.rb +32 -9
- data/lib/sequel/adapters/shared/db2.rb +342 -0
- data/lib/sequel/adapters/shared/firebird.rb +221 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +335 -118
- data/lib/sequel/adapters/shared/mysql.rb +340 -76
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
- data/lib/sequel/adapters/shared/oracle.rb +243 -45
- data/lib/sequel/adapters/shared/postgres.rb +524 -279
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +265 -89
- data/lib/sequel/adapters/sqlite.rb +101 -39
- data/lib/sequel/adapters/swift/mysql.rb +9 -12
- data/lib/sequel/adapters/swift/postgres.rb +9 -74
- data/lib/sequel/adapters/swift/sqlite.rb +8 -6
- data/lib/sequel/adapters/swift.rb +8 -7
- data/lib/sequel/adapters/tinytds.rb +161 -21
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- data/lib/sequel/ast_transformer.rb +194 -0
- data/lib/sequel/connection_pool/sharded_single.rb +11 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +28 -2
- data/lib/sequel/connection_pool/single.rb +5 -0
- data/lib/sequel/connection_pool/threaded.rb +38 -14
- data/lib/sequel/connection_pool.rb +10 -2
- data/lib/sequel/core.rb +118 -11
- data/lib/sequel/database/connecting.rb +38 -28
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +63 -2
- data/lib/sequel/database/logging.rb +7 -2
- data/lib/sequel/database/misc.rb +150 -46
- data/lib/sequel/database/query.rb +215 -65
- data/lib/sequel/database/schema_generator.rb +64 -20
- data/lib/sequel/database/schema_methods.rb +212 -54
- data/lib/sequel/dataset/actions.rb +322 -85
- data/lib/sequel/dataset/features.rb +96 -8
- data/lib/sequel/dataset/graph.rb +38 -11
- data/lib/sequel/dataset/misc.rb +50 -23
- data/lib/sequel/dataset/mutation.rb +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +68 -30
- data/lib/sequel/dataset/query.rb +237 -44
- data/lib/sequel/dataset/sql.rb +698 -278
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/_pretty_table.rb +79 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +108 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +16 -34
- data/lib/sequel/extensions/migration.rb +97 -11
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/null_dataset.rb +90 -0
- data/lib/sequel/extensions/pg_array.rb +460 -0
- data/lib/sequel/extensions/pg_array_ops.rb +220 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +169 -0
- data/lib/sequel/extensions/pg_hstore.rb +296 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +259 -0
- data/lib/sequel/extensions/pg_inet.rb +89 -0
- data/lib/sequel/extensions/pg_json.rb +178 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +316 -0
- data/lib/sequel/extensions/pretty_table.rb +5 -71
- data/lib/sequel/extensions/query.rb +1 -1
- data/lib/sequel/extensions/query_literals.rb +79 -0
- data/lib/sequel/extensions/schema_caching.rb +76 -0
- data/lib/sequel/extensions/schema_dumper.rb +251 -37
- data/lib/sequel/extensions/select_remove.rb +35 -0
- data/lib/sequel/extensions/server_block.rb +139 -0
- data/lib/sequel/extensions/sql_expr.rb +4 -110
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +1187 -393
- data/lib/sequel/model/base.rb +578 -170
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model.rb +30 -11
- data/lib/sequel/no_core_ext.rb +2 -0
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/caching.rb +25 -18
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/composition.rb +44 -12
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/dirty.rb +214 -0
- data/lib/sequel/plugins/eager_each.rb +59 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/hook_class_methods.rb +1 -1
- data/lib/sequel/plugins/identity_map.rb +123 -8
- data/lib/sequel/plugins/instance_filters.rb +10 -0
- data/lib/sequel/plugins/instance_hooks.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +58 -6
- data/lib/sequel/plugins/list.rb +12 -2
- data/lib/sequel/plugins/many_through_many.rb +79 -28
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
- data/lib/sequel/plugins/nested_attributes.rb +139 -63
- data/lib/sequel/plugins/optimistic_locking.rb +8 -0
- data/lib/sequel/plugins/prepared_statements.rb +167 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/schema.rb +7 -2
- data/lib/sequel/plugins/serialization.rb +98 -49
- data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
- data/lib/sequel/plugins/sharding.rb +21 -54
- data/lib/sequel/plugins/single_table_inheritance.rb +5 -3
- data/lib/sequel/plugins/static_cache.rb +99 -0
- data/lib/sequel/plugins/subclasses.rb +10 -2
- data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/plugins/xml_serializer.rb +15 -4
- data/lib/sequel/sql.rb +526 -59
- data/lib/sequel/timezones.rb +57 -38
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/firebird_spec.rb +1 -1
- data/spec/adapters/mssql_spec.rb +142 -40
- data/spec/adapters/mysql_spec.rb +380 -234
- data/spec/adapters/oracle_spec.rb +67 -77
- data/spec/adapters/postgres_spec.rb +1050 -212
- data/spec/adapters/spec_helper.rb +8 -5
- data/spec/adapters/sqlite_spec.rb +139 -27
- data/spec/core/connection_pool_spec.rb +196 -93
- data/spec/core/database_spec.rb +879 -510
- data/spec/core/dataset_spec.rb +1415 -1086
- data/spec/core/expression_filters_spec.rb +554 -109
- data/spec/core/mock_adapter_spec.rb +449 -0
- data/spec/core/object_graph_spec.rb +86 -114
- data/spec/core/schema_generator_spec.rb +4 -4
- data/spec/core/schema_spec.rb +482 -38
- data/spec/core/spec_helper.rb +6 -48
- data/spec/extensions/active_model_spec.rb +13 -0
- data/spec/extensions/arbitrary_servers_spec.rb +110 -0
- data/spec/extensions/association_autoreloading_spec.rb +18 -10
- data/spec/extensions/association_dependencies_spec.rb +15 -25
- data/spec/extensions/association_pks_spec.rb +66 -32
- data/spec/extensions/association_proxies_spec.rb +4 -4
- data/spec/extensions/caching_spec.rb +47 -51
- data/spec/extensions/class_table_inheritance_spec.rb +31 -83
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/composition_spec.rb +18 -13
- data/spec/{core/core_sql_spec.rb → extensions/core_extensions_spec.rb} +119 -139
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/dirty_spec.rb +155 -0
- data/spec/extensions/eager_each_spec.rb +34 -0
- data/spec/extensions/force_encoding_spec.rb +4 -2
- data/spec/extensions/hook_class_methods_spec.rb +69 -92
- data/spec/extensions/identity_map_spec.rb +131 -22
- data/spec/extensions/inflector_spec.rb +0 -4
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +72 -0
- data/spec/extensions/json_serializer_spec.rb +49 -6
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +48 -39
- data/spec/extensions/many_through_many_spec.rb +283 -250
- data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
- data/spec/extensions/migration_spec.rb +140 -35
- data/spec/extensions/named_timezones_spec.rb +29 -11
- data/spec/extensions/nested_attributes_spec.rb +251 -89
- data/spec/extensions/null_dataset_spec.rb +85 -0
- data/spec/extensions/optimistic_locking_spec.rb +24 -21
- data/spec/extensions/pg_array_ops_spec.rb +105 -0
- data/spec/extensions/pg_array_spec.rb +196 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
- data/spec/extensions/pg_hstore_ops_spec.rb +136 -0
- data/spec/extensions/pg_hstore_spec.rb +195 -0
- data/spec/extensions/pg_inet_spec.rb +44 -0
- data/spec/extensions/pg_json_spec.rb +101 -0
- data/spec/extensions/pg_statement_cache_spec.rb +209 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
- data/spec/extensions/prepared_statements_spec.rb +87 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +7 -6
- data/spec/extensions/query_literals_spec.rb +168 -0
- data/spec/extensions/query_spec.rb +6 -0
- data/spec/extensions/rcte_tree_spec.rb +50 -43
- data/spec/extensions/schema_caching_spec.rb +41 -0
- data/spec/extensions/schema_dumper_spec.rb +429 -22
- data/spec/extensions/schema_spec.rb +25 -21
- data/spec/extensions/select_remove_spec.rb +38 -0
- data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
- data/spec/extensions/serialization_spec.rb +85 -43
- data/spec/extensions/server_block_spec.rb +90 -0
- data/spec/extensions/sharding_spec.rb +69 -143
- data/spec/extensions/single_table_inheritance_spec.rb +23 -29
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +22 -61
- data/spec/extensions/sql_expr_spec.rb +29 -60
- data/spec/extensions/static_cache_spec.rb +145 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/timestamps_spec.rb +6 -6
- data/spec/extensions/to_dot_spec.rb +4 -7
- data/spec/extensions/touch_spec.rb +13 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +9 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +30 -51
- data/spec/extensions/validation_helpers_spec.rb +16 -35
- data/spec/extensions/xml_serializer_spec.rb +29 -4
- data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
- data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
- data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
- data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
- data/spec/integration/associations_test.rb +659 -21
- data/spec/integration/database_test.rb +9 -3
- data/spec/integration/dataset_test.rb +605 -91
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/migrator_test.rb +2 -3
- data/spec/integration/model_test.rb +81 -2
- data/spec/integration/plugin_test.rb +454 -143
- data/spec/integration/prepared_statement_test.rb +263 -128
- data/spec/integration/schema_test.rb +309 -43
- data/spec/integration/spec_helper.rb +40 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +183 -8
- data/spec/integration/type_test.rb +18 -4
- data/spec/model/association_reflection_spec.rb +201 -7
- data/spec/model/associations_spec.rb +1067 -661
- data/spec/model/base_spec.rb +329 -95
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +677 -676
- data/spec/model/hooks_spec.rb +349 -67
- data/spec/model/model_spec.rb +240 -168
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +490 -232
- data/spec/model/spec_helper.rb +14 -71
- data/spec/model/validations_spec.rb +11 -0
- data/spec/rcov.opts +2 -0
- metadata +178 -80
data/lib/sequel/timezones.rb
CHANGED
|
@@ -39,6 +39,48 @@ module Sequel
|
|
|
39
39
|
convert_output_timestamp(v, Sequel.database_timezone)
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
+
# Converts the object to the given +output_timezone+.
|
|
43
|
+
def convert_output_timestamp(v, output_timezone)
|
|
44
|
+
if output_timezone
|
|
45
|
+
if v.is_a?(DateTime)
|
|
46
|
+
case output_timezone
|
|
47
|
+
when :utc
|
|
48
|
+
v.new_offset(0)
|
|
49
|
+
when :local
|
|
50
|
+
v.new_offset(local_offset_for_datetime(v))
|
|
51
|
+
else
|
|
52
|
+
convert_output_datetime_other(v, output_timezone)
|
|
53
|
+
end
|
|
54
|
+
else
|
|
55
|
+
v.send(output_timezone == :utc ? :getutc : :getlocal)
|
|
56
|
+
end
|
|
57
|
+
else
|
|
58
|
+
v
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Converts the given object from the given input timezone to the
|
|
63
|
+
# +application_timezone+ using +convert_input_timestamp+ and
|
|
64
|
+
# +convert_output_timestamp+.
|
|
65
|
+
def convert_timestamp(v, input_timezone)
|
|
66
|
+
begin
|
|
67
|
+
if v.is_a?(Date) && !v.is_a?(DateTime)
|
|
68
|
+
# Dates handled specially as they are assumed to already be in the application_timezone
|
|
69
|
+
if datetime_class == DateTime
|
|
70
|
+
DateTime.civil(v.year, v.month, v.day, 0, 0, 0, application_timezone == :local ? (defined?(Rational) ? Rational(Time.local(v.year, v.month, v.day).utc_offset, 86400) : Time.local(v.year, v.month, v.day).utc_offset/86400.0) : 0)
|
|
71
|
+
else
|
|
72
|
+
Time.send(application_timezone == :utc ? :utc : :local, v.year, v.month, v.day)
|
|
73
|
+
end
|
|
74
|
+
else
|
|
75
|
+
convert_output_timestamp(convert_input_timestamp(v, input_timezone), application_timezone)
|
|
76
|
+
end
|
|
77
|
+
rescue InvalidValue
|
|
78
|
+
raise
|
|
79
|
+
rescue => e
|
|
80
|
+
raise convert_exception_class(e, InvalidValue)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
42
84
|
# Convert the given object into an object of <tt>Sequel.datetime_class</tt> in the
|
|
43
85
|
# +application_timezone+. Used when coverting datetime/timestamp columns
|
|
44
86
|
# returned by the database.
|
|
@@ -103,12 +145,24 @@ module Sequel
|
|
|
103
145
|
v2
|
|
104
146
|
end
|
|
105
147
|
when Array
|
|
106
|
-
y, mo, d, h, mi, s = v
|
|
148
|
+
y, mo, d, h, mi, s, ns, off = v
|
|
107
149
|
if datetime_class == DateTime
|
|
108
|
-
|
|
150
|
+
s += (defined?(Rational) ? Rational(ns, 1000000000) : ns/1000000000.0) if ns
|
|
151
|
+
if off
|
|
152
|
+
DateTime.civil(y, mo, d, h, mi, s, off)
|
|
153
|
+
else
|
|
154
|
+
convert_input_datetime_no_offset(DateTime.civil(y, mo, d, h, mi, s), input_timezone)
|
|
155
|
+
end
|
|
109
156
|
else
|
|
110
|
-
Time.send(input_timezone == :utc ? :utc : :local, y, mo, d, h, mi, s)
|
|
157
|
+
Time.send(input_timezone == :utc ? :utc : :local, y, mo, d, h, mi, s, (ns ? ns / 1000.0 : 0))
|
|
158
|
+
end
|
|
159
|
+
when Hash
|
|
160
|
+
ary = [:year, :month, :day, :hour, :minute, :second, :nanos].map{|x| (v[x] || v[x.to_s]).to_i}
|
|
161
|
+
if (offset = (v[:offset] || v['offset']))
|
|
162
|
+
ary << offset
|
|
111
163
|
end
|
|
164
|
+
convert_input_timestamp(ary, input_timezone)
|
|
165
|
+
convert_input_timestamp(ary, input_timezone)
|
|
112
166
|
when Time
|
|
113
167
|
if datetime_class == DateTime
|
|
114
168
|
v.respond_to?(:to_datetime) ? v.to_datetime : string_to_datetime(v.iso8601)
|
|
@@ -121,8 +175,6 @@ module Sequel
|
|
|
121
175
|
else
|
|
122
176
|
v.respond_to?(:to_time) ? v.to_time : string_to_datetime(v.to_s)
|
|
123
177
|
end
|
|
124
|
-
when Date
|
|
125
|
-
convert_input_timestamp(v.to_s, input_timezone)
|
|
126
178
|
else
|
|
127
179
|
raise InvalidValue, "Invalid convert_input_timestamp type: #{v.inspect}"
|
|
128
180
|
end
|
|
@@ -135,39 +187,6 @@ module Sequel
|
|
|
135
187
|
raise InvalidValue, "Invalid output_timezone: #{output_timezone.inspect}"
|
|
136
188
|
end
|
|
137
189
|
|
|
138
|
-
# Converts the object to the given +output_timezone+.
|
|
139
|
-
def convert_output_timestamp(v, output_timezone)
|
|
140
|
-
if output_timezone
|
|
141
|
-
if v.is_a?(DateTime)
|
|
142
|
-
case output_timezone
|
|
143
|
-
when :utc
|
|
144
|
-
v.new_offset(0)
|
|
145
|
-
when :local
|
|
146
|
-
v.new_offset(local_offset_for_datetime(v))
|
|
147
|
-
else
|
|
148
|
-
convert_output_datetime_other(v, output_timezone)
|
|
149
|
-
end
|
|
150
|
-
else
|
|
151
|
-
v.send(output_timezone == :utc ? :getutc : :getlocal)
|
|
152
|
-
end
|
|
153
|
-
else
|
|
154
|
-
v
|
|
155
|
-
end
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
# Converts the given object from the given input timezone to the
|
|
159
|
-
# +application_timezone+ using +convert_input_timestamp+ and
|
|
160
|
-
# +convert_output_timestamp+.
|
|
161
|
-
def convert_timestamp(v, input_timezone)
|
|
162
|
-
begin
|
|
163
|
-
convert_output_timestamp(convert_input_timestamp(v, input_timezone), Sequel.application_timezone)
|
|
164
|
-
rescue InvalidValue
|
|
165
|
-
raise
|
|
166
|
-
rescue => e
|
|
167
|
-
raise convert_exception_class(e, InvalidValue)
|
|
168
|
-
end
|
|
169
|
-
end
|
|
170
|
-
|
|
171
190
|
# Convert the timezone setter argument. Returns argument given by default,
|
|
172
191
|
# exists for easier overriding in extensions.
|
|
173
192
|
def convert_timezone_setter_arg(tz)
|
data/lib/sequel/version.rb
CHANGED
|
@@ -3,7 +3,7 @@ module Sequel
|
|
|
3
3
|
MAJOR = 3
|
|
4
4
|
# The minor version of Sequel. Bumped for every non-patch level
|
|
5
5
|
# release, generally around once a month.
|
|
6
|
-
MINOR =
|
|
6
|
+
MINOR = 36
|
|
7
7
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
|
8
8
|
# releases that fix regressions from previous versions.
|
|
9
9
|
TINY = 0
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# coding: utf-8
|
|
3
|
+
#Author: Roy L Zuo (roylzuo at gmail dot com)
|
|
4
|
+
#Description:
|
|
5
|
+
|
|
6
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
|
7
|
+
|
|
8
|
+
require ENV['SEQUEL_DB2_SPEC_REQUIRE'] if ENV['SEQUEL_DB2_SPEC_REQUIRE']
|
|
9
|
+
|
|
10
|
+
unless defined?(DB2_DB)
|
|
11
|
+
DB2_DB = Sequel.connect(ENV['SEQUEL_DB2_SPEC_DB']||DB2_URL)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
if DB2_DB.table_exists?(:test)
|
|
15
|
+
DB2_DB.drop_table :test
|
|
16
|
+
end
|
|
17
|
+
INTEGRATION_DB = DB2_DB unless defined?(INTEGRATION_DB)
|
|
18
|
+
|
|
19
|
+
describe Sequel::Database do
|
|
20
|
+
before do
|
|
21
|
+
@db = DB2_DB
|
|
22
|
+
@db.create_table(:test){String :a}
|
|
23
|
+
@ds = @db[:test]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
after do
|
|
27
|
+
@db.drop_table(:test)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
specify "should provide disconnect functionality after preparing a connection" do
|
|
31
|
+
@ds.prepare(:first, :a).call
|
|
32
|
+
@db.disconnect
|
|
33
|
+
@db.pool.size.should == 0
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
specify "should return version correctly" do
|
|
37
|
+
@db.db2_version.should match(/DB2 v/i)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe "Simple Dataset operations" do
|
|
42
|
+
before do
|
|
43
|
+
DB2_DB.create_table!(:items) do
|
|
44
|
+
Integer :id, :primary_key => true
|
|
45
|
+
Integer :number
|
|
46
|
+
end
|
|
47
|
+
@ds = DB2_DB[:items]
|
|
48
|
+
@ds.insert(:number=>10, :id => 1 )
|
|
49
|
+
end
|
|
50
|
+
after do
|
|
51
|
+
DB2_DB.drop_table(:items)
|
|
52
|
+
end
|
|
53
|
+
cspecify "should insert with a primary key specified", :mssql do
|
|
54
|
+
@ds.insert(:id=>100, :number=>20)
|
|
55
|
+
@ds.count.should == 2
|
|
56
|
+
@ds.order(:id).all.should == [{:id=>1, :number=>10}, {:id=>100, :number=>20}]
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe Sequel::Database do
|
|
61
|
+
before do
|
|
62
|
+
@db = DB2_DB
|
|
63
|
+
end
|
|
64
|
+
after do
|
|
65
|
+
@db.drop_table(:items)
|
|
66
|
+
end
|
|
67
|
+
specify "should parse primary keys from the schema properly" do
|
|
68
|
+
@db.create_table!(:items){Integer :number}
|
|
69
|
+
@db.schema(:items).collect{|k,v| k if v[:primary_key]}.compact.should == []
|
|
70
|
+
@db.create_table!(:items){primary_key :number}
|
|
71
|
+
@db.schema(:items).collect{|k,v| k if v[:primary_key]}.compact.should == [:number]
|
|
72
|
+
@db.create_table!(:items){Integer :number1, :null => false; Integer :number2, :null => false; primary_key [:number1, :number2]}
|
|
73
|
+
@db.schema(:items).collect{|k,v| k if v[:primary_key]}.compact.should == [:number1, :number2]
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
describe "Sequel::IBMDB.convert_smallint_to_bool" do
|
|
78
|
+
before do
|
|
79
|
+
@db = DB2_DB
|
|
80
|
+
@db.create_table!(:booltest){column :b, 'smallint'; column :i, 'integer'}
|
|
81
|
+
@ds = @db[:booltest]
|
|
82
|
+
end
|
|
83
|
+
after do
|
|
84
|
+
Sequel::IBMDB.convert_smallint_to_bool = true
|
|
85
|
+
@db.drop_table(:booltest)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
specify "should consider smallint datatypes as boolean if set, but not larger smallints" do
|
|
89
|
+
@db.schema(:booltest, :reload=>true).first.last[:type].should == :boolean
|
|
90
|
+
@db.schema(:booltest, :reload=>true).first.last[:db_type].should match /smallint/i
|
|
91
|
+
Sequel::IBMDB.convert_smallint_to_bool = false
|
|
92
|
+
@db.schema(:booltest, :reload=>true).first.last[:type].should == :integer
|
|
93
|
+
@db.schema(:booltest, :reload=>true).first.last[:db_type].should match /smallint/i
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
specify "should return smallints as bools and integers as integers when set" do
|
|
97
|
+
Sequel::IBMDB.convert_smallint_to_bool = true
|
|
98
|
+
@ds.delete
|
|
99
|
+
@ds << {:b=>true, :i=>10}
|
|
100
|
+
@ds.all.should == [{:b=>true, :i=>10}]
|
|
101
|
+
@ds.delete
|
|
102
|
+
@ds << {:b=>false, :i=>0}
|
|
103
|
+
@ds.all.should == [{:b=>false, :i=>0}]
|
|
104
|
+
@ds.delete
|
|
105
|
+
@ds << {:b=>true, :i=>1}
|
|
106
|
+
@ds.all.should == [{:b=>true, :i=>1}]
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
specify "should return all smallints as integers when unset" do
|
|
110
|
+
Sequel::IBMDB.convert_smallint_to_bool = false
|
|
111
|
+
@ds.delete
|
|
112
|
+
@ds << {:b=>true, :i=>10}
|
|
113
|
+
@ds.all.should == [{:b=>1, :i=>10}]
|
|
114
|
+
@ds.delete
|
|
115
|
+
@ds << {:b=>false, :i=>0}
|
|
116
|
+
@ds.all.should == [{:b=>0, :i=>0}]
|
|
117
|
+
|
|
118
|
+
@ds.delete
|
|
119
|
+
@ds << {:b=>1, :i=>10}
|
|
120
|
+
@ds.all.should == [{:b=>1, :i=>10}]
|
|
121
|
+
@ds.delete
|
|
122
|
+
@ds << {:b=>0, :i=>0}
|
|
123
|
+
@ds.all.should == [{:b=>0, :i=>0}]
|
|
124
|
+
end
|
|
125
|
+
end if DB2_DB.adapter_scheme == :ibmdb
|
|
126
|
+
|
|
127
|
+
describe "Simple Dataset operations in transactions" do
|
|
128
|
+
before do
|
|
129
|
+
DB2_DB.create_table!(:items_insert_in_transaction) do
|
|
130
|
+
Integer :id, :primary_key => true
|
|
131
|
+
integer :number
|
|
132
|
+
end
|
|
133
|
+
@ds = DB2_DB[:items_insert_in_transaction]
|
|
134
|
+
end
|
|
135
|
+
after do
|
|
136
|
+
DB2_DB.drop_table(:items_insert_in_transaction)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
specify "should insert correctly with a primary key specified inside a transaction" do
|
|
140
|
+
DB2_DB.transaction do
|
|
141
|
+
@ds.insert(:id=>100, :number=>20)
|
|
142
|
+
@ds.count.should == 1
|
|
143
|
+
@ds.order(:id).all.should == [{:id=>100, :number=>20}]
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
data/spec/adapters/mssql_spec.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
1
2
|
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
|
2
3
|
|
|
3
4
|
require ENV['SEQUEL_MSSQL_SPEC_REQUIRE'] if ENV['SEQUEL_MSSQL_SPEC_REQUIRE']
|
|
@@ -59,15 +60,44 @@ describe "A MSSQL database" do
|
|
|
59
60
|
end
|
|
60
61
|
end
|
|
61
62
|
|
|
63
|
+
# This spec is currently disabled as the SQL Server 2008 R2 Express doesn't support
|
|
64
|
+
# full text searching. Even if full text searching is supported,
|
|
65
|
+
# you may need to create a full text catalog on the database first via:
|
|
66
|
+
# CREATE FULLTEXT CATALOG ftscd AS DEFAULT
|
|
67
|
+
describe "MSSQL full_text_search" do
|
|
68
|
+
before do
|
|
69
|
+
@db = MSSQL_DB
|
|
70
|
+
@db.drop_table?(:posts)
|
|
71
|
+
end
|
|
72
|
+
after do
|
|
73
|
+
@db.drop_table?(:posts)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
specify "should support fulltext indexes and full_text_search" do
|
|
77
|
+
log do
|
|
78
|
+
@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}
|
|
79
|
+
@db[:posts].insert(:title=>'ruby rails', :body=>'y')
|
|
80
|
+
@db[:posts].insert(:title=>'sequel', :body=>'ruby')
|
|
81
|
+
@db[:posts].insert(:title=>'ruby scooby', :body=>'x')
|
|
82
|
+
|
|
83
|
+
@db[:posts].full_text_search(:title, 'rails').all.should == [{:title=>'ruby rails', :body=>'y'}]
|
|
84
|
+
@db[:posts].full_text_search([:title, :body], ['sequel', 'ruby']).all.should == [{:title=>'sequel', :body=>'ruby'}]
|
|
85
|
+
|
|
86
|
+
@db[:posts].full_text_search(:title, :$n).call(:select, :n=>'rails').should == [{:title=>'ruby rails', :body=>'y'}]
|
|
87
|
+
@db[:posts].full_text_search(:title, :$n).prepare(:select, :fts_select).call(:n=>'rails').should == [{:title=>'ruby rails', :body=>'y'}]
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end if false
|
|
91
|
+
|
|
62
92
|
describe "MSSQL Dataset#join_table" do
|
|
63
93
|
specify "should emulate the USING clause with ON" do
|
|
64
94
|
MSSQL_DB[:items].join(:categories, [:id]).sql.should ==
|
|
65
|
-
'SELECT * FROM ITEMS INNER JOIN CATEGORIES ON (CATEGORIES.ID = ITEMS.ID)'
|
|
66
|
-
['SELECT * FROM ITEMS INNER JOIN CATEGORIES ON ((CATEGORIES.ID1 = ITEMS.ID1) AND (CATEGORIES.ID2 = ITEMS.ID2))',
|
|
67
|
-
|
|
68
|
-
|
|
95
|
+
'SELECT * FROM [ITEMS] INNER JOIN [CATEGORIES] ON ([CATEGORIES].[ID] = [ITEMS].[ID])'
|
|
96
|
+
['SELECT * FROM [ITEMS] INNER JOIN [CATEGORIES] ON (([CATEGORIES].[ID1] = [ITEMS].[ID1]) AND ([CATEGORIES].[ID2] = [ITEMS].[ID2]))',
|
|
97
|
+
'SELECT * FROM [ITEMS] INNER JOIN [CATEGORIES] ON (([CATEGORIES].[ID2] = [ITEMS].[ID2]) AND ([CATEGORIES].[ID1] = [ITEMS].[ID1]))'].
|
|
98
|
+
should include(MSSQL_DB[:items].join(:categories, [:id1, :id2]).sql)
|
|
69
99
|
MSSQL_DB[:items___i].join(:categories___c, [:id]).sql.should ==
|
|
70
|
-
'SELECT * FROM ITEMS AS I INNER JOIN CATEGORIES AS C ON (C.ID = I.ID)'
|
|
100
|
+
'SELECT * FROM [ITEMS] AS [I] INNER JOIN [CATEGORIES] AS [C] ON ([C].[ID] = [I].[ID])'
|
|
71
101
|
end
|
|
72
102
|
end
|
|
73
103
|
|
|
@@ -79,50 +109,49 @@ describe "MSSQL Dataset#output" do
|
|
|
79
109
|
@ds = @db[:items]
|
|
80
110
|
end
|
|
81
111
|
after do
|
|
82
|
-
@db.drop_table(:items)
|
|
83
|
-
@db.drop_table(:out)
|
|
112
|
+
@db.drop_table?(:items, :out)
|
|
84
113
|
end
|
|
85
114
|
|
|
86
115
|
specify "should format OUTPUT clauses without INTO for DELETE statements" do
|
|
87
116
|
@ds.output(nil, [:deleted__name, :deleted__value]).delete_sql.should =~
|
|
88
|
-
/DELETE FROM ITEMS OUTPUT DELETED
|
|
117
|
+
/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].\[(NAME|VALUE)\], \[DELETED\].\[(NAME|VALUE)\]/
|
|
89
118
|
@ds.output(nil, [:deleted.*]).delete_sql.should =~
|
|
90
|
-
/DELETE FROM ITEMS OUTPUT DELETED.*/
|
|
119
|
+
/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].*/
|
|
91
120
|
end
|
|
92
121
|
|
|
93
122
|
specify "should format OUTPUT clauses with INTO for DELETE statements" do
|
|
94
123
|
@ds.output(:out, [:deleted__name, :deleted__value]).delete_sql.should =~
|
|
95
|
-
/DELETE FROM ITEMS OUTPUT DELETED
|
|
124
|
+
/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].\[(NAME|VALUE)\], \[DELETED\].\[(NAME|VALUE)\] INTO \[OUT\]/
|
|
96
125
|
@ds.output(:out, {:name => :deleted__name, :value => :deleted__value}).delete_sql.should =~
|
|
97
|
-
/DELETE FROM ITEMS OUTPUT DELETED
|
|
126
|
+
/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].\[(NAME|VALUE)\], \[DELETED\].\[(NAME|VALUE)\] INTO \[OUT\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\)/
|
|
98
127
|
end
|
|
99
128
|
|
|
100
129
|
specify "should format OUTPUT clauses without INTO for INSERT statements" do
|
|
101
130
|
@ds.output(nil, [:inserted__name, :inserted__value]).insert_sql(:name => "name", :value => 1).should =~
|
|
102
|
-
/INSERT INTO ITEMS \((NAME|VALUE), (NAME|VALUE)\) OUTPUT INSERTED
|
|
131
|
+
/INSERT INTO \[ITEMS\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) OUTPUT \[INSERTED\].\[(NAME|VALUE)\], \[INSERTED\].\[(NAME|VALUE)\] VALUES \((N'name'|1), (N'name'|1)\)/
|
|
103
132
|
@ds.output(nil, [:inserted.*]).insert_sql(:name => "name", :value => 1).should =~
|
|
104
|
-
/INSERT INTO ITEMS \((NAME|VALUE), (NAME|VALUE)\) OUTPUT INSERTED.* VALUES \((N'name'|1), (N'name'|1)\)/
|
|
133
|
+
/INSERT INTO \[ITEMS\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) OUTPUT \[INSERTED\].* VALUES \((N'name'|1), (N'name'|1)\)/
|
|
105
134
|
end
|
|
106
135
|
|
|
107
136
|
specify "should format OUTPUT clauses with INTO for INSERT statements" do
|
|
108
137
|
@ds.output(:out, [:inserted__name, :inserted__value]).insert_sql(:name => "name", :value => 1).should =~
|
|
109
|
-
/INSERT INTO ITEMS \((NAME
|
|
138
|
+
/INSERT INTO \[ITEMS\] \((\[NAME\]|\[VALUE\]), (\[NAME\]|\[VALUE\])\) OUTPUT \[INSERTED\].\[(NAME|VALUE)\], \[INSERTED\].\[(NAME|VALUE)\] INTO \[OUT\] VALUES \((N'name'|1), (N'name'|1)\)/
|
|
110
139
|
@ds.output(:out, {:name => :inserted__name, :value => :inserted__value}).insert_sql(:name => "name", :value => 1).should =~
|
|
111
|
-
/INSERT INTO ITEMS \((NAME|VALUE), (NAME|VALUE)\) OUTPUT INSERTED
|
|
140
|
+
/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)\)/
|
|
112
141
|
end
|
|
113
142
|
|
|
114
143
|
specify "should format OUTPUT clauses without INTO for UPDATE statements" do
|
|
115
144
|
@ds.output(nil, [:inserted__name, :deleted__value]).update_sql(:value => 2).should =~
|
|
116
|
-
/UPDATE ITEMS SET VALUE = 2 OUTPUT (INSERTED
|
|
145
|
+
/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\], \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\]/
|
|
117
146
|
@ds.output(nil, [:inserted.*]).update_sql(:value => 2).should =~
|
|
118
|
-
/UPDATE ITEMS SET VALUE = 2 OUTPUT INSERTED.*/
|
|
147
|
+
/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[INSERTED\].*/
|
|
119
148
|
end
|
|
120
149
|
|
|
121
150
|
specify "should format OUTPUT clauses with INTO for UPDATE statements" do
|
|
122
151
|
@ds.output(:out, [:inserted__name, :deleted__value]).update_sql(:value => 2).should =~
|
|
123
|
-
/UPDATE ITEMS SET VALUE = 2 OUTPUT (INSERTED
|
|
152
|
+
/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\], \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\] INTO \[OUT\]/
|
|
124
153
|
@ds.output(:out, {:name => :inserted__name, :value => :deleted__value}).update_sql(:value => 2).should =~
|
|
125
|
-
/UPDATE ITEMS SET VALUE = 2 OUTPUT (INSERTED
|
|
154
|
+
/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\], \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\] INTO \[OUT\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\)/
|
|
126
155
|
end
|
|
127
156
|
|
|
128
157
|
specify "should execute OUTPUT clauses in DELETE statements" do
|
|
@@ -163,23 +192,23 @@ describe "MSSQL dataset" do
|
|
|
163
192
|
end
|
|
164
193
|
|
|
165
194
|
specify "should prepend UPDATE statements with WITH clause" do
|
|
166
|
-
@ds1.update_sql(:x => :y).should == 'WITH T AS (SELECT * FROM X) UPDATE T SET X = Y'
|
|
167
|
-
@ds2.update_sql(:x => :y).should == 'WITH T AS (SELECT * FROM X UNION ALL SELECT * FROM T) UPDATE T SET X = Y'
|
|
195
|
+
@ds1.update_sql(:x => :y).should == 'WITH [T] AS (SELECT * FROM [X]) UPDATE [T] SET [X] = [Y]'
|
|
196
|
+
@ds2.update_sql(:x => :y).should == 'WITH [T] AS (SELECT * FROM [X] UNION ALL SELECT * FROM [T]) UPDATE [T] SET [X] = [Y]'
|
|
168
197
|
end
|
|
169
198
|
|
|
170
199
|
specify "should prepend DELETE statements with WITH clause" do
|
|
171
|
-
@ds1.filter(:y => 1).delete_sql.should == 'WITH T AS (SELECT * FROM X) DELETE FROM T WHERE (Y = 1)'
|
|
172
|
-
@ds2.filter(:y => 1).delete_sql.should == 'WITH T AS (SELECT * FROM X UNION ALL SELECT * FROM T) DELETE FROM T WHERE (Y = 1)'
|
|
200
|
+
@ds1.filter(:y => 1).delete_sql.should == 'WITH [T] AS (SELECT * FROM [X]) DELETE FROM [T] WHERE ([Y] = 1)'
|
|
201
|
+
@ds2.filter(:y => 1).delete_sql.should == 'WITH [T] AS (SELECT * FROM [X] UNION ALL SELECT * FROM [T]) DELETE FROM [T] WHERE ([Y] = 1)'
|
|
173
202
|
end
|
|
174
203
|
|
|
175
204
|
specify "should prepend INSERT statements with WITH clause" do
|
|
176
|
-
@ds1.insert_sql(@db[:t]).should == 'WITH T AS (SELECT * FROM X) INSERT INTO T SELECT * FROM T'
|
|
177
|
-
@ds2.insert_sql(@db[:t]).should == 'WITH T AS (SELECT * FROM X UNION ALL SELECT * FROM T) INSERT INTO T SELECT * FROM T'
|
|
205
|
+
@ds1.insert_sql(@db[:t]).should == 'WITH [T] AS (SELECT * FROM [X]) INSERT INTO [T] SELECT * FROM [T]'
|
|
206
|
+
@ds2.insert_sql(@db[:t]).should == 'WITH [T] AS (SELECT * FROM [X] UNION ALL SELECT * FROM [T]) INSERT INTO [T] SELECT * FROM [T]'
|
|
178
207
|
end
|
|
179
208
|
|
|
180
209
|
specify "should move WITH clause on joined dataset to top level" do
|
|
181
|
-
@db[:s].inner_join(@ds1).sql.should == "WITH T AS (SELECT * FROM X) SELECT * FROM S INNER JOIN (SELECT * FROM T) AS T1"
|
|
182
|
-
@ds1.inner_join(@db[:s].with(:s, @db[:y])).sql.should == "WITH T AS (SELECT * FROM X), S AS (SELECT * FROM Y) SELECT * FROM T INNER JOIN (SELECT * FROM S) AS T1"
|
|
210
|
+
@db[:s].inner_join(@ds1).sql.should == "WITH [T] AS (SELECT * FROM [X]) SELECT * FROM [S] INNER JOIN (SELECT * FROM [T]) AS [T1]"
|
|
211
|
+
@ds1.inner_join(@db[:s].with(:s, @db[:y])).sql.should == "WITH [T] AS (SELECT * FROM [X]), [S] AS (SELECT * FROM [Y]) SELECT * FROM [T] INNER JOIN (SELECT * FROM [S]) AS [T1]"
|
|
183
212
|
end
|
|
184
213
|
|
|
185
214
|
describe "on #import" do
|
|
@@ -207,10 +236,10 @@ describe "MSSQL dataset" do
|
|
|
207
236
|
@db[:items].with(:items, @db[:inventory].group(:type)).import([:x, :y], [[1, 2], [3, 4], [5, 6]], :slice => 2)
|
|
208
237
|
@db.import_sqls.should == [
|
|
209
238
|
'BEGIN',
|
|
210
|
-
"WITH ITEMS AS (SELECT * FROM INVENTORY GROUP BY TYPE) INSERT INTO ITEMS (X, Y) SELECT 1, 2 UNION ALL SELECT 3, 4",
|
|
239
|
+
"WITH [ITEMS] AS (SELECT * FROM [INVENTORY] GROUP BY [TYPE]) INSERT INTO [ITEMS] ([X], [Y]) SELECT 1, 2 UNION ALL SELECT 3, 4",
|
|
211
240
|
'COMMIT',
|
|
212
241
|
'BEGIN',
|
|
213
|
-
"WITH ITEMS AS (SELECT * FROM INVENTORY GROUP BY TYPE) INSERT INTO ITEMS (X, Y) SELECT 5, 6",
|
|
242
|
+
"WITH [ITEMS] AS (SELECT * FROM [INVENTORY] GROUP BY [TYPE]) INSERT INTO [ITEMS] ([X], [Y]) SELECT 5, 6",
|
|
214
243
|
'COMMIT'
|
|
215
244
|
]
|
|
216
245
|
end
|
|
@@ -218,6 +247,23 @@ describe "MSSQL dataset" do
|
|
|
218
247
|
end
|
|
219
248
|
end
|
|
220
249
|
|
|
250
|
+
describe "MSSQL::Dataset#import" do
|
|
251
|
+
before do
|
|
252
|
+
@db = MSSQL_DB
|
|
253
|
+
@db.create_table!(:test){primary_key :x; Integer :y}
|
|
254
|
+
@db.sqls.clear
|
|
255
|
+
@ds = @db[:test]
|
|
256
|
+
end
|
|
257
|
+
after do
|
|
258
|
+
@db.drop_table?(:test)
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
specify "#import should work correctly with an arbitrary output value" do
|
|
262
|
+
@ds.output(nil, [:inserted__y, :inserted__x]).import([:y], [[3], [4]]).should == [{:y=>3, :x=>1}, {:y=>4, :x=>2}]
|
|
263
|
+
@ds.all.should == [{:x=>1, :y=>3}, {:x=>2, :y=>4}]
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
221
267
|
describe "MSSQL joined datasets" do
|
|
222
268
|
before do
|
|
223
269
|
@db = MSSQL_DB
|
|
@@ -225,12 +271,12 @@ describe "MSSQL joined datasets" do
|
|
|
225
271
|
|
|
226
272
|
specify "should format DELETE statements" do
|
|
227
273
|
@db[:t1].inner_join(:t2, :t1__pk => :t2__pk).delete_sql.should ==
|
|
228
|
-
"DELETE FROM T1 FROM T1 INNER JOIN T2 ON (T1.PK = T2.PK)"
|
|
274
|
+
"DELETE FROM [T1] FROM [T1] INNER JOIN [T2] ON ([T1].[PK] = [T2].[PK])"
|
|
229
275
|
end
|
|
230
276
|
|
|
231
277
|
specify "should format UPDATE statements" do
|
|
232
278
|
@db[:t1].inner_join(:t2, :t1__pk => :t2__pk).update_sql(:pk => :t2__pk).should ==
|
|
233
|
-
"UPDATE T1 SET PK = T2.PK FROM T1 INNER JOIN T2 ON (T1.PK = T2.PK)"
|
|
279
|
+
"UPDATE [T1] SET [PK] = [T2].[PK] FROM [T1] INNER JOIN [T2] ON ([T1].[PK] = [T2].[PK])"
|
|
234
280
|
end
|
|
235
281
|
end
|
|
236
282
|
|
|
@@ -244,7 +290,7 @@ describe "Offset support" do
|
|
|
244
290
|
@ds.import [:id, :parent_id], [[1,nil],[2,nil],[3,1],[4,1],[5,3],[6,5]]
|
|
245
291
|
end
|
|
246
292
|
after do
|
|
247
|
-
@db.drop_table(:i)
|
|
293
|
+
@db.drop_table?(:i)
|
|
248
294
|
end
|
|
249
295
|
|
|
250
296
|
specify "should return correct rows" do
|
|
@@ -267,8 +313,7 @@ describe "Common Table Expressions" do
|
|
|
267
313
|
@ds.import [:id, :parent_id], [[1,nil],[2,nil],[3,1],[4,1],[5,3],[6,5]]
|
|
268
314
|
end
|
|
269
315
|
after do
|
|
270
|
-
@db.drop_table(:i1)
|
|
271
|
-
@db.drop_table(:i2)
|
|
316
|
+
@db.drop_table?(:i1, :i2)
|
|
272
317
|
end
|
|
273
318
|
|
|
274
319
|
specify "using #with should be able to update" do
|
|
@@ -338,7 +383,7 @@ describe "MSSSQL::Dataset#insert" do
|
|
|
338
383
|
@ds = @db[:test5]
|
|
339
384
|
end
|
|
340
385
|
after do
|
|
341
|
-
@db.drop_table(:test5)
|
|
386
|
+
@db.drop_table?(:test5)
|
|
342
387
|
end
|
|
343
388
|
|
|
344
389
|
specify "should have insert_select return nil if disable_insert_output is used" do
|
|
@@ -369,7 +414,7 @@ describe "MSSSQL::Dataset#into" do
|
|
|
369
414
|
end
|
|
370
415
|
|
|
371
416
|
specify "should format SELECT statement" do
|
|
372
|
-
@db[:t].into(:new).select_sql.should == "SELECT * INTO NEW FROM T"
|
|
417
|
+
@db[:t].into(:new).select_sql.should == "SELECT * INTO [NEW] FROM [T]"
|
|
373
418
|
end
|
|
374
419
|
|
|
375
420
|
specify "should select rows into a new table" do
|
|
@@ -377,8 +422,7 @@ describe "MSSSQL::Dataset#into" do
|
|
|
377
422
|
@db[:t].insert(:id => 1, :value => "test")
|
|
378
423
|
@db << @db[:t].into(:new).select_sql
|
|
379
424
|
@db[:new].all.should == [{:id => 1, :value => "test"}]
|
|
380
|
-
@db.drop_table(:t)
|
|
381
|
-
@db.drop_table(:new)
|
|
425
|
+
@db.drop_table?(:t, :new)
|
|
382
426
|
end
|
|
383
427
|
end
|
|
384
428
|
|
|
@@ -387,7 +431,7 @@ describe "A MSSQL database" do
|
|
|
387
431
|
@db = MSSQL_DB
|
|
388
432
|
end
|
|
389
433
|
after do
|
|
390
|
-
@db.drop_table(:a)
|
|
434
|
+
@db.drop_table?(:a)
|
|
391
435
|
end
|
|
392
436
|
|
|
393
437
|
specify "should handle many existing types for set_column_allow_null" do
|
|
@@ -414,7 +458,7 @@ describe "MSSQL::Database#rename_table" do
|
|
|
414
458
|
MSSQL_DB.create_table! :'foo bar' do
|
|
415
459
|
text :name
|
|
416
460
|
end
|
|
417
|
-
MSSQL_DB.drop_table :baz
|
|
461
|
+
MSSQL_DB.drop_table? :baz
|
|
418
462
|
proc { MSSQL_DB.rename_table 'foo bar', 'baz' }.should_not raise_error
|
|
419
463
|
end
|
|
420
464
|
|
|
@@ -440,3 +484,61 @@ describe "MSSQL::Dataset#count" do
|
|
|
440
484
|
MSSQL_DB[:items].select(:name, :value).group(:name, :value).order(:name).count.should == 1
|
|
441
485
|
end
|
|
442
486
|
end
|
|
487
|
+
|
|
488
|
+
describe "MSSQL::Database#create_table" do
|
|
489
|
+
specify "should support collate with various other column options" do
|
|
490
|
+
MSSQL_DB.create_table!(:items){ String :name, :size => 128, :collate => :sql_latin1_general_cp1_ci_as, :default => 'foo', :null => false, :unique => true}
|
|
491
|
+
MSSQL_DB[:items].insert
|
|
492
|
+
MSSQL_DB[:items].select_map(:name).should == ["foo"]
|
|
493
|
+
end
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
describe "MSSQL::Database#mssql_unicode_strings = false" do
|
|
497
|
+
before do
|
|
498
|
+
MSSQL_DB.mssql_unicode_strings = false
|
|
499
|
+
end
|
|
500
|
+
after do
|
|
501
|
+
MSSQL_DB.drop_table?(:items)
|
|
502
|
+
MSSQL_DB.mssql_unicode_strings = true
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
specify "should work correctly" do
|
|
506
|
+
MSSQL_DB.create_table!(:items){String :name}
|
|
507
|
+
MSSQL_DB[:items].mssql_unicode_strings.should == false
|
|
508
|
+
MSSQL_DB[:items].insert(:name=>'foo')
|
|
509
|
+
MSSQL_DB[:items].select_map(:name).should == ['foo']
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
specify "should be overridable at the dataset level" do
|
|
513
|
+
MSSQL_DB.create_table!(:items){String :name}
|
|
514
|
+
ds = MSSQL_DB[:items]
|
|
515
|
+
ds.mssql_unicode_strings.should == false
|
|
516
|
+
ds.mssql_unicode_strings = true
|
|
517
|
+
ds.mssql_unicode_strings.should == true
|
|
518
|
+
ds.insert(:name=>'foo')
|
|
519
|
+
ds.select_map(:name).should == ['foo']
|
|
520
|
+
end
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
describe "A MSSQL database adds index with include" do
|
|
524
|
+
before :all do
|
|
525
|
+
@table_name = :test_index_include
|
|
526
|
+
@db = MSSQL_DB
|
|
527
|
+
@db.create_table! @table_name do
|
|
528
|
+
integer :col1
|
|
529
|
+
integer :col2
|
|
530
|
+
integer :col3
|
|
531
|
+
end
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
after :all do
|
|
535
|
+
@db.drop_table? @table_name
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
cspecify "should be able add index with include" do
|
|
539
|
+
@db.alter_table @table_name do
|
|
540
|
+
add_index [:col1], :include => [:col2,:col3]
|
|
541
|
+
end
|
|
542
|
+
@db.indexes(@table_name).should have_key("#{@table_name}_col1_index".to_sym)
|
|
543
|
+
end
|
|
544
|
+
end
|