sequel 3.28.0 → 3.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +119 -3
- data/Rakefile +5 -3
- data/bin/sequel +1 -5
- data/doc/model_hooks.rdoc +9 -1
- data/doc/opening_databases.rdoc +49 -40
- data/doc/prepared_statements.rdoc +27 -6
- data/doc/release_notes/3.28.0.txt +2 -2
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +18 -9
- data/doc/transactions.rdoc +41 -1
- data/lib/sequel/adapters/ado.rb +28 -17
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/amalgalite.rb +11 -7
- data/lib/sequel/adapters/db2.rb +122 -70
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do.rb +5 -36
- data/lib/sequel/adapters/do/mysql.rb +0 -5
- data/lib/sequel/adapters/do/postgres.rb +0 -5
- data/lib/sequel/adapters/do/sqlite.rb +0 -5
- data/lib/sequel/adapters/firebird.rb +3 -6
- data/lib/sequel/adapters/ibmdb.rb +24 -16
- data/lib/sequel/adapters/informix.rb +2 -4
- data/lib/sequel/adapters/jdbc.rb +47 -11
- data/lib/sequel/adapters/jdbc/as400.rb +5 -24
- data/lib/sequel/adapters/jdbc/db2.rb +0 -5
- data/lib/sequel/adapters/jdbc/derby.rb +217 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +0 -5
- data/lib/sequel/adapters/jdbc/h2.rb +10 -12
- data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
- data/lib/sequel/adapters/jdbc/informix.rb +0 -5
- data/lib/sequel/adapters/jdbc/jtds.rb +0 -5
- data/lib/sequel/adapters/jdbc/mysql.rb +0 -10
- data/lib/sequel/adapters/jdbc/oracle.rb +70 -3
- data/lib/sequel/adapters/jdbc/postgresql.rb +0 -11
- data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
- data/lib/sequel/adapters/jdbc/sqlserver.rb +0 -5
- data/lib/sequel/adapters/jdbc/transactions.rb +56 -7
- data/lib/sequel/adapters/mock.rb +315 -0
- data/lib/sequel/adapters/mysql.rb +64 -51
- data/lib/sequel/adapters/mysql2.rb +15 -9
- data/lib/sequel/adapters/odbc.rb +13 -6
- data/lib/sequel/adapters/odbc/db2.rb +0 -4
- data/lib/sequel/adapters/odbc/mssql.rb +0 -5
- data/lib/sequel/adapters/openbase.rb +2 -4
- data/lib/sequel/adapters/oracle.rb +333 -51
- data/lib/sequel/adapters/postgres.rb +80 -27
- data/lib/sequel/adapters/shared/access.rb +0 -6
- data/lib/sequel/adapters/shared/db2.rb +13 -15
- data/lib/sequel/adapters/shared/firebird.rb +6 -6
- data/lib/sequel/adapters/shared/mssql.rb +23 -18
- data/lib/sequel/adapters/shared/mysql.rb +6 -6
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +6 -0
- data/lib/sequel/adapters/shared/oracle.rb +185 -30
- data/lib/sequel/adapters/shared/postgres.rb +35 -18
- data/lib/sequel/adapters/shared/progress.rb +0 -6
- data/lib/sequel/adapters/shared/sqlite.rb +116 -37
- data/lib/sequel/adapters/sqlite.rb +16 -8
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/swift/mysql.rb +0 -5
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +6 -4
- data/lib/sequel/adapters/tinytds.rb +13 -10
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -0
- data/lib/sequel/core.rb +40 -0
- data/lib/sequel/database/connecting.rb +1 -2
- data/lib/sequel/database/dataset.rb +3 -3
- data/lib/sequel/database/dataset_defaults.rb +58 -0
- data/lib/sequel/database/misc.rb +62 -2
- data/lib/sequel/database/query.rb +113 -49
- data/lib/sequel/database/schema_methods.rb +7 -2
- data/lib/sequel/dataset/actions.rb +37 -19
- data/lib/sequel/dataset/features.rb +24 -0
- data/lib/sequel/dataset/graph.rb +7 -6
- data/lib/sequel/dataset/misc.rb +11 -3
- data/lib/sequel/dataset/mutation.rb +2 -3
- data/lib/sequel/dataset/prepared_statements.rb +6 -4
- data/lib/sequel/dataset/query.rb +46 -15
- data/lib/sequel/dataset/sql.rb +28 -4
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/model.rb +2 -1
- data/lib/sequel/model/associations.rb +115 -33
- data/lib/sequel/model/base.rb +91 -31
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +1 -1
- data/lib/sequel/plugins/many_through_many.rb +6 -10
- data/lib/sequel/plugins/prepared_statements.rb +12 -1
- data/lib/sequel/plugins/prepared_statements_associations.rb +1 -1
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/serialization.rb +6 -1
- data/lib/sequel/plugins/sharding.rb +0 -5
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +1 -1
- data/lib/sequel/timezones.rb +42 -42
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +29 -29
- data/spec/adapters/mysql_spec.rb +86 -104
- data/spec/adapters/oracle_spec.rb +48 -76
- data/spec/adapters/postgres_spec.rb +98 -33
- data/spec/adapters/spec_helper.rb +0 -5
- data/spec/adapters/sqlite_spec.rb +24 -21
- data/spec/core/connection_pool_spec.rb +9 -15
- data/spec/core/core_sql_spec.rb +20 -31
- data/spec/core/database_spec.rb +491 -227
- data/spec/core/dataset_spec.rb +638 -1051
- data/spec/core/expression_filters_spec.rb +0 -1
- data/spec/core/mock_adapter_spec.rb +378 -0
- data/spec/core/object_graph_spec.rb +48 -114
- data/spec/core/schema_generator_spec.rb +3 -3
- data/spec/core/schema_spec.rb +51 -114
- data/spec/core/spec_helper.rb +3 -90
- data/spec/extensions/class_table_inheritance_spec.rb +1 -1
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/instance_hooks_spec.rb +71 -0
- data/spec/extensions/named_timezones_spec.rb +22 -2
- data/spec/extensions/nested_attributes_spec.rb +3 -0
- data/spec/extensions/schema_spec.rb +1 -1
- data/spec/extensions/serialization_modification_detection_spec.rb +1 -0
- data/spec/extensions/serialization_spec.rb +5 -8
- data/spec/extensions/spec_helper.rb +4 -0
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/integration/associations_test.rb +123 -12
- data/spec/integration/dataset_test.rb +140 -47
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +179 -128
- data/spec/integration/prepared_statement_test.rb +92 -91
- data/spec/integration/schema_test.rb +42 -23
- data/spec/integration/spec_helper.rb +25 -31
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +161 -34
- data/spec/integration/type_test.rb +3 -3
- data/spec/model/association_reflection_spec.rb +83 -7
- data/spec/model/associations_spec.rb +393 -676
- data/spec/model/base_spec.rb +186 -116
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +343 -867
- data/spec/model/hooks_spec.rb +160 -79
- data/spec/model/model_spec.rb +118 -165
- data/spec/model/plugins_spec.rb +7 -13
- data/spec/model/record_spec.rb +138 -207
- data/spec/model/spec_helper.rb +10 -73
- metadata +14 -8
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.
|
|
@@ -135,48 +177,6 @@ module Sequel
|
|
|
135
177
|
raise InvalidValue, "Invalid output_timezone: #{output_timezone.inspect}"
|
|
136
178
|
end
|
|
137
179
|
|
|
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
|
-
if v.is_a?(Date) && !v.is_a?(DateTime)
|
|
164
|
-
# Dates handled specially as they are assumed to already be in the application_timezone
|
|
165
|
-
if datetime_class == DateTime
|
|
166
|
-
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)
|
|
167
|
-
else
|
|
168
|
-
Time.send(application_timezone == :utc ? :utc : :local, v.year, v.month, v.day)
|
|
169
|
-
end
|
|
170
|
-
else
|
|
171
|
-
convert_output_timestamp(convert_input_timestamp(v, input_timezone), application_timezone)
|
|
172
|
-
end
|
|
173
|
-
rescue InvalidValue
|
|
174
|
-
raise
|
|
175
|
-
rescue => e
|
|
176
|
-
raise convert_exception_class(e, InvalidValue)
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
|
|
180
180
|
# Convert the timezone setter argument. Returns argument given by default,
|
|
181
181
|
# exists for easier overriding in extensions.
|
|
182
182
|
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 = 29
|
|
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
|
data/spec/adapters/mssql_spec.rb
CHANGED
|
@@ -63,12 +63,12 @@ end
|
|
|
63
63
|
describe "MSSQL Dataset#join_table" do
|
|
64
64
|
specify "should emulate the USING clause with ON" do
|
|
65
65
|
MSSQL_DB[:items].join(:categories, [:id]).sql.should ==
|
|
66
|
-
'SELECT * FROM ITEMS INNER JOIN CATEGORIES ON (CATEGORIES.ID = ITEMS.ID)'
|
|
67
|
-
['SELECT * FROM ITEMS INNER JOIN CATEGORIES ON ((CATEGORIES.ID1 = ITEMS.ID1) AND (CATEGORIES.ID2 = ITEMS.ID2))',
|
|
68
|
-
'SELECT * FROM ITEMS INNER JOIN CATEGORIES ON ((CATEGORIES.ID2 = ITEMS.ID2) AND (CATEGORIES.ID1 = ITEMS.ID1))'].
|
|
66
|
+
'SELECT * FROM [ITEMS] INNER JOIN [CATEGORIES] ON ([CATEGORIES].[ID] = [ITEMS].[ID])'
|
|
67
|
+
['SELECT * FROM [ITEMS] INNER JOIN [CATEGORIES] ON (([CATEGORIES].[ID1] = [ITEMS].[ID1]) AND ([CATEGORIES].[ID2] = [ITEMS].[ID2]))',
|
|
68
|
+
'SELECT * FROM [ITEMS] INNER JOIN [CATEGORIES] ON (([CATEGORIES].[ID2] = [ITEMS].[ID2]) AND ([CATEGORIES].[ID1] = [ITEMS].[ID1]))'].
|
|
69
69
|
should include(MSSQL_DB[:items].join(:categories, [:id1, :id2]).sql)
|
|
70
70
|
MSSQL_DB[:items___i].join(:categories___c, [:id]).sql.should ==
|
|
71
|
-
'SELECT * FROM ITEMS AS I INNER JOIN CATEGORIES AS C ON (C.ID = I.ID)'
|
|
71
|
+
'SELECT * FROM [ITEMS] AS [I] INNER JOIN [CATEGORIES] AS [C] ON ([C].[ID] = [I].[ID])'
|
|
72
72
|
end
|
|
73
73
|
end
|
|
74
74
|
|
|
@@ -86,44 +86,44 @@ describe "MSSQL Dataset#output" do
|
|
|
86
86
|
|
|
87
87
|
specify "should format OUTPUT clauses without INTO for DELETE statements" do
|
|
88
88
|
@ds.output(nil, [:deleted__name, :deleted__value]).delete_sql.should =~
|
|
89
|
-
/DELETE FROM ITEMS OUTPUT DELETED
|
|
89
|
+
/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].\[(NAME|VALUE)\], \[DELETED\].\[(NAME|VALUE)\]/
|
|
90
90
|
@ds.output(nil, [:deleted.*]).delete_sql.should =~
|
|
91
|
-
/DELETE FROM ITEMS OUTPUT DELETED.*/
|
|
91
|
+
/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].*/
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
specify "should format OUTPUT clauses with INTO for DELETE statements" do
|
|
95
95
|
@ds.output(:out, [:deleted__name, :deleted__value]).delete_sql.should =~
|
|
96
|
-
/DELETE FROM ITEMS OUTPUT DELETED
|
|
96
|
+
/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].\[(NAME|VALUE)\], \[DELETED\].\[(NAME|VALUE)\] INTO \[OUT\]/
|
|
97
97
|
@ds.output(:out, {:name => :deleted__name, :value => :deleted__value}).delete_sql.should =~
|
|
98
|
-
/DELETE FROM ITEMS OUTPUT DELETED
|
|
98
|
+
/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].\[(NAME|VALUE)\], \[DELETED\].\[(NAME|VALUE)\] INTO \[OUT\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\)/
|
|
99
99
|
end
|
|
100
100
|
|
|
101
101
|
specify "should format OUTPUT clauses without INTO for INSERT statements" do
|
|
102
102
|
@ds.output(nil, [:inserted__name, :inserted__value]).insert_sql(:name => "name", :value => 1).should =~
|
|
103
|
-
/INSERT INTO ITEMS \((NAME|VALUE), (NAME|VALUE)\) OUTPUT INSERTED
|
|
103
|
+
/INSERT INTO \[ITEMS\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) OUTPUT \[INSERTED\].\[(NAME|VALUE)\], \[INSERTED\].\[(NAME|VALUE)\] VALUES \((N'name'|1), (N'name'|1)\)/
|
|
104
104
|
@ds.output(nil, [:inserted.*]).insert_sql(:name => "name", :value => 1).should =~
|
|
105
|
-
/INSERT INTO ITEMS \((NAME|VALUE), (NAME|VALUE)\) OUTPUT INSERTED.* VALUES \((N'name'|1), (N'name'|1)\)/
|
|
105
|
+
/INSERT INTO \[ITEMS\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) OUTPUT \[INSERTED\].* VALUES \((N'name'|1), (N'name'|1)\)/
|
|
106
106
|
end
|
|
107
107
|
|
|
108
108
|
specify "should format OUTPUT clauses with INTO for INSERT statements" do
|
|
109
109
|
@ds.output(:out, [:inserted__name, :inserted__value]).insert_sql(:name => "name", :value => 1).should =~
|
|
110
|
-
/INSERT INTO ITEMS \((NAME
|
|
110
|
+
/INSERT INTO \[ITEMS\] \((\[NAME\]|\[VALUE\]), (\[NAME\]|\[VALUE\])\) OUTPUT \[INSERTED\].\[(NAME|VALUE)\], \[INSERTED\].\[(NAME|VALUE)\] INTO \[OUT\] VALUES \((N'name'|1), (N'name'|1)\)/
|
|
111
111
|
@ds.output(:out, {:name => :inserted__name, :value => :inserted__value}).insert_sql(:name => "name", :value => 1).should =~
|
|
112
|
-
/INSERT INTO ITEMS \((NAME|VALUE), (NAME|VALUE)\) OUTPUT INSERTED
|
|
112
|
+
/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)\)/
|
|
113
113
|
end
|
|
114
114
|
|
|
115
115
|
specify "should format OUTPUT clauses without INTO for UPDATE statements" do
|
|
116
116
|
@ds.output(nil, [:inserted__name, :deleted__value]).update_sql(:value => 2).should =~
|
|
117
|
-
/UPDATE ITEMS SET VALUE = 2 OUTPUT (INSERTED
|
|
117
|
+
/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\], \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\]/
|
|
118
118
|
@ds.output(nil, [:inserted.*]).update_sql(:value => 2).should =~
|
|
119
|
-
/UPDATE ITEMS SET VALUE = 2 OUTPUT INSERTED.*/
|
|
119
|
+
/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[INSERTED\].*/
|
|
120
120
|
end
|
|
121
121
|
|
|
122
122
|
specify "should format OUTPUT clauses with INTO for UPDATE statements" do
|
|
123
123
|
@ds.output(:out, [:inserted__name, :deleted__value]).update_sql(:value => 2).should =~
|
|
124
|
-
/UPDATE ITEMS SET VALUE = 2 OUTPUT (INSERTED
|
|
124
|
+
/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\], \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\] INTO \[OUT\]/
|
|
125
125
|
@ds.output(:out, {:name => :inserted__name, :value => :deleted__value}).update_sql(:value => 2).should =~
|
|
126
|
-
/UPDATE ITEMS SET VALUE = 2 OUTPUT (INSERTED
|
|
126
|
+
/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\], \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\] INTO \[OUT\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\)/
|
|
127
127
|
end
|
|
128
128
|
|
|
129
129
|
specify "should execute OUTPUT clauses in DELETE statements" do
|
|
@@ -164,23 +164,23 @@ describe "MSSQL dataset" do
|
|
|
164
164
|
end
|
|
165
165
|
|
|
166
166
|
specify "should prepend UPDATE statements with WITH clause" do
|
|
167
|
-
@ds1.update_sql(:x => :y).should == 'WITH T AS (SELECT * FROM X) UPDATE T SET X = Y'
|
|
168
|
-
@ds2.update_sql(:x => :y).should == 'WITH T AS (SELECT * FROM X UNION ALL SELECT * FROM T) UPDATE T SET X = Y'
|
|
167
|
+
@ds1.update_sql(:x => :y).should == 'WITH [T] AS (SELECT * FROM [X]) UPDATE [T] SET [X] = [Y]'
|
|
168
|
+
@ds2.update_sql(:x => :y).should == 'WITH [T] AS (SELECT * FROM [X] UNION ALL SELECT * FROM [T]) UPDATE [T] SET [X] = [Y]'
|
|
169
169
|
end
|
|
170
170
|
|
|
171
171
|
specify "should prepend DELETE statements with WITH clause" do
|
|
172
|
-
@ds1.filter(:y => 1).delete_sql.should == 'WITH T AS (SELECT * FROM X) DELETE FROM T WHERE (Y = 1)'
|
|
173
|
-
@ds2.filter(:y => 1).delete_sql.should == 'WITH T AS (SELECT * FROM X UNION ALL SELECT * FROM T) DELETE FROM T WHERE (Y = 1)'
|
|
172
|
+
@ds1.filter(:y => 1).delete_sql.should == 'WITH [T] AS (SELECT * FROM [X]) DELETE FROM [T] WHERE ([Y] = 1)'
|
|
173
|
+
@ds2.filter(:y => 1).delete_sql.should == 'WITH [T] AS (SELECT * FROM [X] UNION ALL SELECT * FROM [T]) DELETE FROM [T] WHERE ([Y] = 1)'
|
|
174
174
|
end
|
|
175
175
|
|
|
176
176
|
specify "should prepend INSERT statements with WITH clause" do
|
|
177
|
-
@ds1.insert_sql(@db[:t]).should == 'WITH T AS (SELECT * FROM X) INSERT INTO T SELECT * FROM T'
|
|
178
|
-
@ds2.insert_sql(@db[:t]).should == 'WITH T AS (SELECT * FROM X UNION ALL SELECT * FROM T) INSERT INTO T SELECT * FROM T'
|
|
177
|
+
@ds1.insert_sql(@db[:t]).should == 'WITH [T] AS (SELECT * FROM [X]) INSERT INTO [T] SELECT * FROM [T]'
|
|
178
|
+
@ds2.insert_sql(@db[:t]).should == 'WITH [T] AS (SELECT * FROM [X] UNION ALL SELECT * FROM [T]) INSERT INTO [T] SELECT * FROM [T]'
|
|
179
179
|
end
|
|
180
180
|
|
|
181
181
|
specify "should move WITH clause on joined dataset to top level" do
|
|
182
|
-
@db[:s].inner_join(@ds1).sql.should == "WITH T AS (SELECT * FROM X) SELECT * FROM S INNER JOIN (SELECT * FROM T) AS T1"
|
|
183
|
-
@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"
|
|
182
|
+
@db[:s].inner_join(@ds1).sql.should == "WITH [T] AS (SELECT * FROM [X]) SELECT * FROM [S] INNER JOIN (SELECT * FROM [T]) AS [T1]"
|
|
183
|
+
@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]"
|
|
184
184
|
end
|
|
185
185
|
|
|
186
186
|
describe "on #import" do
|
|
@@ -208,10 +208,10 @@ describe "MSSQL dataset" do
|
|
|
208
208
|
@db[:items].with(:items, @db[:inventory].group(:type)).import([:x, :y], [[1, 2], [3, 4], [5, 6]], :slice => 2)
|
|
209
209
|
@db.import_sqls.should == [
|
|
210
210
|
'BEGIN',
|
|
211
|
-
"WITH ITEMS AS (SELECT * FROM INVENTORY GROUP BY TYPE) INSERT INTO ITEMS (X, Y) SELECT 1, 2 UNION ALL SELECT 3, 4",
|
|
211
|
+
"WITH [ITEMS] AS (SELECT * FROM [INVENTORY] GROUP BY [TYPE]) INSERT INTO [ITEMS] ([X], [Y]) SELECT 1, 2 UNION ALL SELECT 3, 4",
|
|
212
212
|
'COMMIT',
|
|
213
213
|
'BEGIN',
|
|
214
|
-
"WITH ITEMS AS (SELECT * FROM INVENTORY GROUP BY TYPE) INSERT INTO ITEMS (X, Y) SELECT 5, 6",
|
|
214
|
+
"WITH [ITEMS] AS (SELECT * FROM [INVENTORY] GROUP BY [TYPE]) INSERT INTO [ITEMS] ([X], [Y]) SELECT 5, 6",
|
|
215
215
|
'COMMIT'
|
|
216
216
|
]
|
|
217
217
|
end
|
|
@@ -226,12 +226,12 @@ describe "MSSQL joined datasets" do
|
|
|
226
226
|
|
|
227
227
|
specify "should format DELETE statements" do
|
|
228
228
|
@db[:t1].inner_join(:t2, :t1__pk => :t2__pk).delete_sql.should ==
|
|
229
|
-
"DELETE FROM T1 FROM T1 INNER JOIN T2 ON (T1.PK = T2.PK)"
|
|
229
|
+
"DELETE FROM [T1] FROM [T1] INNER JOIN [T2] ON ([T1].[PK] = [T2].[PK])"
|
|
230
230
|
end
|
|
231
231
|
|
|
232
232
|
specify "should format UPDATE statements" do
|
|
233
233
|
@db[:t1].inner_join(:t2, :t1__pk => :t2__pk).update_sql(:pk => :t2__pk).should ==
|
|
234
|
-
"UPDATE T1 SET PK = T2.PK FROM T1 INNER JOIN T2 ON (T1.PK = T2.PK)"
|
|
234
|
+
"UPDATE [T1] SET [PK] = [T2].[PK] FROM [T1] INNER JOIN [T2] ON ([T1].[PK] = [T2].[PK])"
|
|
235
235
|
end
|
|
236
236
|
end
|
|
237
237
|
|
|
@@ -370,7 +370,7 @@ describe "MSSSQL::Dataset#into" do
|
|
|
370
370
|
end
|
|
371
371
|
|
|
372
372
|
specify "should format SELECT statement" do
|
|
373
|
-
@db[:t].into(:new).select_sql.should == "SELECT * INTO NEW FROM T"
|
|
373
|
+
@db[:t].into(:new).select_sql.should == "SELECT * INTO [NEW] FROM [T]"
|
|
374
374
|
end
|
|
375
375
|
|
|
376
376
|
specify "should select rows into a new table" do
|
data/spec/adapters/mysql_spec.rb
CHANGED
|
@@ -45,22 +45,22 @@ describe "MySQL", '#create_table' do
|
|
|
45
45
|
|
|
46
46
|
specify "should allow to specify options for MySQL" do
|
|
47
47
|
@db.create_table(:dolls, :engine => 'MyISAM', :charset => 'latin2'){text :name}
|
|
48
|
-
@db.sqls.should == ["CREATE TABLE dolls (name text) ENGINE=MyISAM DEFAULT CHARSET=latin2"]
|
|
48
|
+
@db.sqls.should == ["CREATE TABLE `dolls` (`name` text) ENGINE=MyISAM DEFAULT CHARSET=latin2"]
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
specify "should create a temporary table" do
|
|
52
52
|
@db.create_table(:tmp_dolls, :temp => true, :engine => 'MyISAM', :charset => 'latin2'){text :name}
|
|
53
|
-
@db.sqls.should == ["CREATE TEMPORARY TABLE tmp_dolls (name text) ENGINE=MyISAM DEFAULT CHARSET=latin2"]
|
|
53
|
+
@db.sqls.should == ["CREATE TEMPORARY TABLE `tmp_dolls` (`name` text) ENGINE=MyISAM DEFAULT CHARSET=latin2"]
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
specify "should not use a default for a String :text=>true type" do
|
|
57
57
|
@db.create_table(:dolls){String :name, :text=>true, :default=>'blah'}
|
|
58
|
-
@db.sqls.should == ["CREATE TABLE dolls (name text)"]
|
|
58
|
+
@db.sqls.should == ["CREATE TABLE `dolls` (`name` text)"]
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
specify "should not use a default for a File type" do
|
|
62
62
|
@db.create_table(:dolls){File :name, :default=>'blah'}
|
|
63
|
-
@db.sqls.should == ["CREATE TABLE dolls (name blob)"]
|
|
63
|
+
@db.sqls.should == ["CREATE TABLE `dolls` (`name` blob)"]
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
specify "should respect the size option for File type" do
|
|
@@ -112,18 +112,18 @@ if MYSQL_DB.adapter_scheme == :mysql
|
|
|
112
112
|
@ds = @db[:booltest]
|
|
113
113
|
end
|
|
114
114
|
after do
|
|
115
|
-
|
|
115
|
+
@db.convert_tinyint_to_bool = true
|
|
116
116
|
@db.drop_table(:booltest)
|
|
117
117
|
end
|
|
118
118
|
|
|
119
119
|
specify "should consider tinyint(1) datatypes as boolean if set, but not larger tinyints" do
|
|
120
120
|
@db.schema(:booltest, :reload=>true).should == [[:b, {:type=>:boolean, :allow_null=>true, :primary_key=>false, :default=>nil, :ruby_default=>nil, :db_type=>"tinyint(1)"}, ], [:i, {:type=>:integer, :allow_null=>true, :primary_key=>false, :default=>nil, :ruby_default=>nil, :db_type=>"tinyint(4)"}, ]]
|
|
121
|
-
|
|
121
|
+
@db.convert_tinyint_to_bool = false
|
|
122
122
|
@db.schema(:booltest, :reload=>true).should == [[:b, {:type=>:integer, :allow_null=>true, :primary_key=>false, :default=>nil, :ruby_default=>nil, :db_type=>"tinyint(1)"}, ], [:i, {:type=>:integer, :allow_null=>true, :primary_key=>false, :default=>nil, :ruby_default=>nil, :db_type=>"tinyint(4)"}, ]]
|
|
123
123
|
end
|
|
124
124
|
|
|
125
125
|
specify "should return tinyint(1)s as bools and tinyint(4)s as integers when set" do
|
|
126
|
-
|
|
126
|
+
@db.convert_tinyint_to_bool = true
|
|
127
127
|
@ds.delete
|
|
128
128
|
@ds << {:b=>true, :i=>10}
|
|
129
129
|
@ds.all.should == [{:b=>true, :i=>10}]
|
|
@@ -136,7 +136,7 @@ if MYSQL_DB.adapter_scheme == :mysql
|
|
|
136
136
|
end
|
|
137
137
|
|
|
138
138
|
specify "should return all tinyints as integers when unset" do
|
|
139
|
-
|
|
139
|
+
@db.convert_tinyint_to_bool = false
|
|
140
140
|
@ds.delete
|
|
141
141
|
@ds << {:b=>true, :i=>10}
|
|
142
142
|
@ds.all.should == [{:b=>1, :i=>10}]
|
|
@@ -226,12 +226,12 @@ describe "A MySQL dataset" do
|
|
|
226
226
|
|
|
227
227
|
specify "should support ORDER clause in UPDATE statements" do
|
|
228
228
|
@d.order(:name).update_sql(:value => 1).should == \
|
|
229
|
-
'UPDATE items SET value = 1 ORDER BY name'
|
|
229
|
+
'UPDATE `items` SET `value` = 1 ORDER BY `name`'
|
|
230
230
|
end
|
|
231
231
|
|
|
232
232
|
specify "should support LIMIT clause in UPDATE statements" do
|
|
233
233
|
@d.limit(10).update_sql(:value => 1).should == \
|
|
234
|
-
'UPDATE items SET value = 1 LIMIT 10'
|
|
234
|
+
'UPDATE `items` SET `value` = 1 LIMIT 10'
|
|
235
235
|
end
|
|
236
236
|
|
|
237
237
|
specify "should support regexps" do
|
|
@@ -299,43 +299,43 @@ describe "MySQL join expressions" do
|
|
|
299
299
|
end
|
|
300
300
|
specify "should support natural left joins" do
|
|
301
301
|
@ds.join_table(:natural_left, :nodes).sql.should == \
|
|
302
|
-
'SELECT * FROM nodes NATURAL LEFT JOIN nodes'
|
|
302
|
+
'SELECT * FROM `nodes` NATURAL LEFT JOIN `nodes`'
|
|
303
303
|
end
|
|
304
304
|
specify "should support natural right joins" do
|
|
305
305
|
@ds.join_table(:natural_right, :nodes).sql.should == \
|
|
306
|
-
'SELECT * FROM nodes NATURAL RIGHT JOIN nodes'
|
|
306
|
+
'SELECT * FROM `nodes` NATURAL RIGHT JOIN `nodes`'
|
|
307
307
|
end
|
|
308
308
|
specify "should support natural left outer joins" do
|
|
309
309
|
@ds.join_table(:natural_left_outer, :nodes).sql.should == \
|
|
310
|
-
'SELECT * FROM nodes NATURAL LEFT OUTER JOIN nodes'
|
|
310
|
+
'SELECT * FROM `nodes` NATURAL LEFT OUTER JOIN `nodes`'
|
|
311
311
|
end
|
|
312
312
|
specify "should support natural right outer joins" do
|
|
313
313
|
@ds.join_table(:natural_right_outer, :nodes).sql.should == \
|
|
314
|
-
'SELECT * FROM nodes NATURAL RIGHT OUTER JOIN nodes'
|
|
314
|
+
'SELECT * FROM `nodes` NATURAL RIGHT OUTER JOIN `nodes`'
|
|
315
315
|
end
|
|
316
316
|
specify "should support natural inner joins" do
|
|
317
317
|
@ds.join_table(:natural_inner, :nodes).sql.should == \
|
|
318
|
-
'SELECT * FROM nodes NATURAL LEFT JOIN nodes'
|
|
318
|
+
'SELECT * FROM `nodes` NATURAL LEFT JOIN `nodes`'
|
|
319
319
|
end
|
|
320
320
|
specify "should support cross joins" do
|
|
321
321
|
@ds.join_table(:cross, :nodes).sql.should == \
|
|
322
|
-
'SELECT * FROM nodes CROSS JOIN nodes'
|
|
322
|
+
'SELECT * FROM `nodes` CROSS JOIN `nodes`'
|
|
323
323
|
end
|
|
324
324
|
specify "should support cross joins as inner joins if conditions are used" do
|
|
325
325
|
@ds.join_table(:cross, :nodes, :id=>:id).sql.should == \
|
|
326
|
-
'SELECT * FROM nodes INNER JOIN nodes ON (nodes
|
|
326
|
+
'SELECT * FROM `nodes` INNER JOIN `nodes` ON (`nodes`.`id` = `nodes`.`id`)'
|
|
327
327
|
end
|
|
328
328
|
specify "should support straight joins (force left table to be read before right)" do
|
|
329
329
|
@ds.join_table(:straight, :nodes).sql.should == \
|
|
330
|
-
'SELECT * FROM nodes STRAIGHT_JOIN nodes'
|
|
330
|
+
'SELECT * FROM `nodes` STRAIGHT_JOIN `nodes`'
|
|
331
331
|
end
|
|
332
332
|
specify "should support natural joins on multiple tables." do
|
|
333
333
|
@ds.join_table(:natural_left_outer, [:nodes, :branches]).sql.should == \
|
|
334
|
-
'SELECT * FROM nodes NATURAL LEFT OUTER JOIN (nodes
|
|
334
|
+
'SELECT * FROM `nodes` NATURAL LEFT OUTER JOIN (`nodes`, `branches`)'
|
|
335
335
|
end
|
|
336
336
|
specify "should support straight joins on multiple tables." do
|
|
337
337
|
@ds.join_table(:straight, [:nodes,:branches]).sql.should == \
|
|
338
|
-
'SELECT * FROM nodes STRAIGHT_JOIN (nodes
|
|
338
|
+
'SELECT * FROM `nodes` STRAIGHT_JOIN (`nodes`, `branches`)'
|
|
339
339
|
end
|
|
340
340
|
end
|
|
341
341
|
|
|
@@ -354,12 +354,12 @@ describe "Joined MySQL dataset" do
|
|
|
354
354
|
proc {@ds.having('blah')}.should_not raise_error
|
|
355
355
|
|
|
356
356
|
@ds.having('blah').sql.should == \
|
|
357
|
-
"SELECT * FROM nodes HAVING (blah)"
|
|
357
|
+
"SELECT * FROM `nodes` HAVING (blah)"
|
|
358
358
|
end
|
|
359
359
|
|
|
360
360
|
specify "should put a having clause before an order by clause" do
|
|
361
361
|
@ds.order(:aaa).having(:bbb => :ccc).sql.should == \
|
|
362
|
-
"SELECT * FROM nodes HAVING (bbb = ccc) ORDER BY aaa"
|
|
362
|
+
"SELECT * FROM `nodes` HAVING (`bbb` = `ccc`) ORDER BY `aaa`"
|
|
363
363
|
end
|
|
364
364
|
end
|
|
365
365
|
|
|
@@ -453,17 +453,17 @@ describe "A MySQL database with table options" do
|
|
|
453
453
|
|
|
454
454
|
specify "should allow to pass custom options (engine, charset, collate) for table creation" do
|
|
455
455
|
@db.create_table(:items, @options){Integer :size; text :name}
|
|
456
|
-
@db.sqls.should == ["CREATE TABLE items (size integer, name text) ENGINE=MyISAM DEFAULT CHARSET=latin1 DEFAULT COLLATE=latin1_swedish_ci"]
|
|
456
|
+
@db.sqls.should == ["CREATE TABLE `items` (`size` integer, `name` text) ENGINE=MyISAM DEFAULT CHARSET=latin1 DEFAULT COLLATE=latin1_swedish_ci"]
|
|
457
457
|
end
|
|
458
458
|
|
|
459
459
|
specify "should use default options if specified (engine, charset, collate) for table creation" do
|
|
460
460
|
@db.create_table(:items){Integer :size; text :name}
|
|
461
|
-
@db.sqls.should == ["CREATE TABLE items (size integer, name text) ENGINE=InnoDB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci"]
|
|
461
|
+
@db.sqls.should == ["CREATE TABLE `items` (`size` integer, `name` text) ENGINE=InnoDB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci"]
|
|
462
462
|
end
|
|
463
463
|
|
|
464
464
|
specify "should not use default if option has a nil value" do
|
|
465
465
|
@db.create_table(:items, :engine=>nil, :charset=>nil, :collate=>nil){Integer :size; text :name}
|
|
466
|
-
@db.sqls.should == ["CREATE TABLE items (size integer, name text)"]
|
|
466
|
+
@db.sqls.should == ["CREATE TABLE `items` (`size` integer, `name` text)"]
|
|
467
467
|
end
|
|
468
468
|
end
|
|
469
469
|
|
|
@@ -479,24 +479,24 @@ describe "A MySQL database" do
|
|
|
479
479
|
|
|
480
480
|
specify "should support defaults for boolean columns" do
|
|
481
481
|
@db.create_table(:items){TrueClass :active1, :default=>true; FalseClass :active2, :default => false}
|
|
482
|
-
@db.sqls.should == ["CREATE TABLE items (active1 tinyint(1) DEFAULT 1, active2 tinyint(1) DEFAULT 0)"]
|
|
482
|
+
@db.sqls.should == ["CREATE TABLE `items` (`active1` tinyint(1) DEFAULT 1, `active2` tinyint(1) DEFAULT 0)"]
|
|
483
483
|
end
|
|
484
484
|
|
|
485
485
|
specify "should correctly format CREATE TABLE statements with foreign keys" do
|
|
486
486
|
@db.create_table(:items){Integer :id; foreign_key :p_id, :items, :key => :id, :null => false, :on_delete => :cascade}
|
|
487
|
-
@db.sqls.should == ["CREATE TABLE items (id integer, p_id integer NOT NULL, FOREIGN KEY (p_id) REFERENCES items(id) ON DELETE CASCADE)"]
|
|
487
|
+
@db.sqls.should == ["CREATE TABLE `items` (`id` integer, `p_id` integer NOT NULL, FOREIGN KEY (`p_id`) REFERENCES `items`(`id`) ON DELETE CASCADE)"]
|
|
488
488
|
end
|
|
489
489
|
|
|
490
490
|
specify "should correctly format ALTER TABLE statements with foreign keys" do
|
|
491
491
|
@db.create_table(:items){Integer :id}
|
|
492
492
|
@db.alter_table(:items){add_foreign_key :p_id, :users, :key => :id, :null => false, :on_delete => :cascade}
|
|
493
|
-
@db.sqls.should == ["CREATE TABLE items (id integer)", "ALTER TABLE items ADD COLUMN p_id integer NOT NULL", "ALTER TABLE items ADD FOREIGN KEY (p_id) REFERENCES users(id) ON DELETE CASCADE"]
|
|
493
|
+
@db.sqls.should == ["CREATE TABLE `items` (`id` integer)", "ALTER TABLE `items` ADD COLUMN `p_id` integer NOT NULL", "ALTER TABLE `items` ADD FOREIGN KEY (`p_id`) REFERENCES `users`(`id`) ON DELETE CASCADE"]
|
|
494
494
|
end
|
|
495
495
|
|
|
496
496
|
specify "should have rename_column support keep existing options" do
|
|
497
497
|
@db.create_table(:items){String :id, :null=>false, :default=>'blah'}
|
|
498
498
|
@db.alter_table(:items){rename_column :id, :nid}
|
|
499
|
-
@db.sqls.should == ["CREATE TABLE items (id varchar(255) NOT NULL DEFAULT 'blah')", "DESCRIBE items", "ALTER TABLE items CHANGE COLUMN id nid varchar(255) NOT NULL DEFAULT 'blah'"]
|
|
499
|
+
@db.sqls.should == ["CREATE TABLE `items` (`id` varchar(255) NOT NULL DEFAULT 'blah')", "DESCRIBE `items`", "ALTER TABLE `items` CHANGE COLUMN `id` `nid` varchar(255) NOT NULL DEFAULT 'blah'"]
|
|
500
500
|
@db[:items].insert
|
|
501
501
|
@db[:items].all.should == [{:nid=>'blah'}]
|
|
502
502
|
proc{@db[:items].insert(:nid=>nil)}.should raise_error(Sequel::DatabaseError)
|
|
@@ -505,7 +505,7 @@ describe "A MySQL database" do
|
|
|
505
505
|
specify "should have set_column_type support keep existing options" do
|
|
506
506
|
@db.create_table(:items){Integer :id, :null=>false, :default=>5}
|
|
507
507
|
@db.alter_table(:items){set_column_type :id, Bignum}
|
|
508
|
-
@db.sqls.should == ["CREATE TABLE items (id integer NOT NULL DEFAULT 5)", "DESCRIBE items", "ALTER TABLE items CHANGE COLUMN id id bigint NOT NULL DEFAULT 5"]
|
|
508
|
+
@db.sqls.should == ["CREATE TABLE `items` (`id` integer NOT NULL DEFAULT 5)", "DESCRIBE `items`", "ALTER TABLE `items` CHANGE COLUMN `id` `id` bigint NOT NULL DEFAULT 5"]
|
|
509
509
|
@db[:items].insert
|
|
510
510
|
@db[:items].all.should == [{:id=>5}]
|
|
511
511
|
proc{@db[:items].insert(:id=>nil)}.should raise_error(Sequel::DatabaseError)
|
|
@@ -517,13 +517,13 @@ describe "A MySQL database" do
|
|
|
517
517
|
specify "should have set_column_type pass through options" do
|
|
518
518
|
@db.create_table(:items){integer :id; enum :list, :elements=>%w[one]}
|
|
519
519
|
@db.alter_table(:items){set_column_type :id, :int, :unsigned=>true, :size=>8; set_column_type :list, :enum, :elements=>%w[two]}
|
|
520
|
-
@db.sqls.should == ["CREATE TABLE items (id integer, list enum('one'))", "DESCRIBE items", "ALTER TABLE items CHANGE COLUMN id id int(8) UNSIGNED NULL", "ALTER TABLE items CHANGE COLUMN list list enum('two') NULL"]
|
|
520
|
+
@db.sqls.should == ["CREATE TABLE `items` (`id` integer, `list` enum('one'))", "DESCRIBE `items`", "ALTER TABLE `items` CHANGE COLUMN `id` `id` int(8) UNSIGNED NULL", "ALTER TABLE `items` CHANGE COLUMN `list` `list` enum('two') NULL"]
|
|
521
521
|
end
|
|
522
522
|
|
|
523
523
|
specify "should have set_column_default support keep existing options" do
|
|
524
524
|
@db.create_table(:items){Integer :id, :null=>false, :default=>5}
|
|
525
525
|
@db.alter_table(:items){set_column_default :id, 6}
|
|
526
|
-
@db.sqls.should == ["CREATE TABLE items (id integer NOT NULL DEFAULT 5)", "DESCRIBE items", "ALTER TABLE items CHANGE COLUMN id id int(11) NOT NULL DEFAULT 6"]
|
|
526
|
+
@db.sqls.should == ["CREATE TABLE `items` (`id` integer NOT NULL DEFAULT 5)", "DESCRIBE `items`", "ALTER TABLE `items` CHANGE COLUMN `id` `id` int(11) NOT NULL DEFAULT 6"]
|
|
527
527
|
@db[:items].insert
|
|
528
528
|
@db[:items].all.should == [{:id=>6}]
|
|
529
529
|
proc{@db[:items].insert(:id=>nil)}.should raise_error(Sequel::DatabaseError)
|
|
@@ -532,7 +532,7 @@ describe "A MySQL database" do
|
|
|
532
532
|
specify "should have set_column_allow_null support keep existing options" do
|
|
533
533
|
@db.create_table(:items){Integer :id, :null=>false, :default=>5}
|
|
534
534
|
@db.alter_table(:items){set_column_allow_null :id, true}
|
|
535
|
-
@db.sqls.should == ["CREATE TABLE items (id integer NOT NULL DEFAULT 5)", "DESCRIBE items", "ALTER TABLE items CHANGE COLUMN id id int(11) NULL DEFAULT 5"]
|
|
535
|
+
@db.sqls.should == ["CREATE TABLE `items` (`id` integer NOT NULL DEFAULT 5)", "DESCRIBE `items`", "ALTER TABLE `items` CHANGE COLUMN `id` `id` int(11) NULL DEFAULT 5"]
|
|
536
536
|
@db[:items].insert
|
|
537
537
|
@db[:items].all.should == [{:id=>5}]
|
|
538
538
|
proc{@db[:items].insert(:id=>nil)}.should_not
|
|
@@ -618,9 +618,9 @@ describe "A MySQL database" do
|
|
|
618
618
|
specify "should support fulltext indexes and full_text_search" do
|
|
619
619
|
@db.create_table(:posts){text :title; text :body; full_text_index :title; full_text_index [:title, :body]}
|
|
620
620
|
@db.sqls.should == [
|
|
621
|
-
"CREATE TABLE posts (title text, body text)",
|
|
622
|
-
"CREATE FULLTEXT INDEX posts_title_index ON posts (title)",
|
|
623
|
-
"CREATE FULLTEXT INDEX posts_title_body_index ON posts (title
|
|
621
|
+
"CREATE TABLE `posts` (`title` text, `body` text)",
|
|
622
|
+
"CREATE FULLTEXT INDEX `posts_title_index` ON `posts` (`title`)",
|
|
623
|
+
"CREATE FULLTEXT INDEX `posts_title_body_index` ON `posts` (`title`, `body`)"
|
|
624
624
|
]
|
|
625
625
|
|
|
626
626
|
@db[:posts].insert(:title=>'ruby rails', :body=>'y')
|
|
@@ -632,32 +632,32 @@ describe "A MySQL database" do
|
|
|
632
632
|
@db[:posts].full_text_search([:title, :body], ['sequel', 'ruby']).all.should == [{:title=>'sequel', :body=>'ruby'}]
|
|
633
633
|
@db[:posts].full_text_search(:title, '+ruby -rails', :boolean => true).all.should == [{:title=>'ruby scooby', :body=>'x'}]
|
|
634
634
|
@db.sqls.should == [
|
|
635
|
-
"SELECT * FROM posts WHERE (MATCH (title) AGAINST ('rails'))",
|
|
636
|
-
"SELECT * FROM posts WHERE (MATCH (title
|
|
637
|
-
"SELECT * FROM posts WHERE (MATCH (title) AGAINST ('+ruby -rails' IN BOOLEAN MODE))"]
|
|
635
|
+
"SELECT * FROM `posts` WHERE (MATCH (`title`) AGAINST ('rails'))",
|
|
636
|
+
"SELECT * FROM `posts` WHERE (MATCH (`title`, `body`) AGAINST ('sequel ruby'))",
|
|
637
|
+
"SELECT * FROM `posts` WHERE (MATCH (`title`) AGAINST ('+ruby -rails' IN BOOLEAN MODE))"]
|
|
638
638
|
end
|
|
639
639
|
|
|
640
640
|
specify "should support spatial indexes" do
|
|
641
641
|
@db.create_table(:posts){point :geom, :null=>false; spatial_index [:geom]}
|
|
642
642
|
@db.sqls.should == [
|
|
643
|
-
"CREATE TABLE posts (geom point NOT NULL)",
|
|
644
|
-
"CREATE SPATIAL INDEX posts_geom_index ON posts (geom)"
|
|
643
|
+
"CREATE TABLE `posts` (`geom` point NOT NULL)",
|
|
644
|
+
"CREATE SPATIAL INDEX `posts_geom_index` ON `posts` (`geom`)"
|
|
645
645
|
]
|
|
646
646
|
end
|
|
647
647
|
|
|
648
648
|
specify "should support indexes with index type" do
|
|
649
649
|
@db.create_table(:posts){Integer :id; index :id, :type => :btree}
|
|
650
650
|
@db.sqls.should == [
|
|
651
|
-
"CREATE TABLE posts (id integer)",
|
|
652
|
-
"CREATE INDEX posts_id_index USING btree ON posts (id)"
|
|
651
|
+
"CREATE TABLE `posts` (`id` integer)",
|
|
652
|
+
"CREATE INDEX `posts_id_index` USING btree ON `posts` (`id`)"
|
|
653
653
|
]
|
|
654
654
|
end
|
|
655
655
|
|
|
656
656
|
specify "should support unique indexes with index type" do
|
|
657
657
|
@db.create_table(:posts){Integer :id; index :id, :type => :btree, :unique => true}
|
|
658
658
|
@db.sqls.should == [
|
|
659
|
-
"CREATE TABLE posts (id integer)",
|
|
660
|
-
"CREATE UNIQUE INDEX posts_id_index USING btree ON posts (id)"
|
|
659
|
+
"CREATE TABLE `posts` (`id` integer)",
|
|
660
|
+
"CREATE UNIQUE INDEX `posts_id_index` USING btree ON `posts` (`id`)"
|
|
661
661
|
]
|
|
662
662
|
end
|
|
663
663
|
|
|
@@ -686,38 +686,20 @@ describe "MySQL::Dataset#insert and related methods" do
|
|
|
686
686
|
|
|
687
687
|
specify "#insert should insert record with default values when no arguments given" do
|
|
688
688
|
@d.insert
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
"INSERT INTO items () VALUES ()"
|
|
692
|
-
]
|
|
693
|
-
|
|
694
|
-
@d.all.should == [
|
|
695
|
-
{:name => nil, :value => nil}
|
|
696
|
-
]
|
|
689
|
+
MYSQL_DB.sqls.should == ["INSERT INTO `items` () VALUES ()"]
|
|
690
|
+
@d.all.should == [{:name => nil, :value => nil}]
|
|
697
691
|
end
|
|
698
692
|
|
|
699
693
|
specify "#insert should insert record with default values when empty hash given" do
|
|
700
694
|
@d.insert({})
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
"INSERT INTO items () VALUES ()"
|
|
704
|
-
]
|
|
705
|
-
|
|
706
|
-
@d.all.should == [
|
|
707
|
-
{:name => nil, :value => nil}
|
|
708
|
-
]
|
|
695
|
+
MYSQL_DB.sqls.should == ["INSERT INTO `items` () VALUES ()"]
|
|
696
|
+
@d.all.should == [{:name => nil, :value => nil}]
|
|
709
697
|
end
|
|
710
698
|
|
|
711
699
|
specify "#insert should insert record with default values when empty array given" do
|
|
712
700
|
@d.insert []
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
"INSERT INTO items () VALUES ()"
|
|
716
|
-
]
|
|
717
|
-
|
|
718
|
-
@d.all.should == [
|
|
719
|
-
{:name => nil, :value => nil}
|
|
720
|
-
]
|
|
701
|
+
MYSQL_DB.sqls.should == ["INSERT INTO `items` () VALUES ()"]
|
|
702
|
+
@d.all.should == [{:name => nil, :value => nil}]
|
|
721
703
|
end
|
|
722
704
|
|
|
723
705
|
specify "#on_duplicate_key_update should work with regular inserts" do
|
|
@@ -728,9 +710,9 @@ describe "MySQL::Dataset#insert and related methods" do
|
|
|
728
710
|
@d.on_duplicate_key_update(:name, :value => 6).insert(:name => 'def', :value => 2)
|
|
729
711
|
|
|
730
712
|
MYSQL_DB.sqls.length.should == 3
|
|
731
|
-
MYSQL_DB.sqls[0].should =~ /\AINSERT INTO items \((name|value)
|
|
732
|
-
MYSQL_DB.sqls[1].should =~ /\AINSERT INTO items \((name|value)
|
|
733
|
-
MYSQL_DB.sqls[2].should =~ /\AINSERT INTO items \((name|value)
|
|
713
|
+
MYSQL_DB.sqls[0].should =~ /\AINSERT INTO `items` \(`(name|value)`, `(name|value)`\) VALUES \(('abc'|1), (1|'abc')\)\z/
|
|
714
|
+
MYSQL_DB.sqls[1].should =~ /\AINSERT INTO `items` \(`(name|value)`, `(name|value)`\) VALUES \(('abc'|1), (1|'abc')\) ON DUPLICATE KEY UPDATE `name`=VALUES\(`name`\), `value`=6\z/
|
|
715
|
+
MYSQL_DB.sqls[2].should =~ /\AINSERT INTO `items` \(`(name|value)`, `(name|value)`\) VALUES \(('def'|2), (2|'def')\) ON DUPLICATE KEY UPDATE `name`=VALUES\(`name`\), `value`=6\z/
|
|
734
716
|
|
|
735
717
|
@d.all.should == [{:name => 'abc', :value => 6}, {:name => 'def', :value => 2}]
|
|
736
718
|
end
|
|
@@ -740,7 +722,7 @@ describe "MySQL::Dataset#insert and related methods" do
|
|
|
740
722
|
|
|
741
723
|
MYSQL_DB.sqls.should == [
|
|
742
724
|
SQL_BEGIN,
|
|
743
|
-
"INSERT INTO items (name) VALUES ('abc'), ('def')",
|
|
725
|
+
"INSERT INTO `items` (`name`) VALUES ('abc'), ('def')",
|
|
744
726
|
SQL_COMMIT
|
|
745
727
|
]
|
|
746
728
|
|
|
@@ -755,10 +737,10 @@ describe "MySQL::Dataset#insert and related methods" do
|
|
|
755
737
|
|
|
756
738
|
MYSQL_DB.sqls.should == [
|
|
757
739
|
SQL_BEGIN,
|
|
758
|
-
"INSERT INTO items (value) VALUES (1), (2)",
|
|
740
|
+
"INSERT INTO `items` (`value`) VALUES (1), (2)",
|
|
759
741
|
SQL_COMMIT,
|
|
760
742
|
SQL_BEGIN,
|
|
761
|
-
"INSERT INTO items (value) VALUES (3), (4)",
|
|
743
|
+
"INSERT INTO `items` (`value`) VALUES (3), (4)",
|
|
762
744
|
SQL_COMMIT
|
|
763
745
|
]
|
|
764
746
|
|
|
@@ -776,10 +758,10 @@ describe "MySQL::Dataset#insert and related methods" do
|
|
|
776
758
|
|
|
777
759
|
MYSQL_DB.sqls.should == [
|
|
778
760
|
SQL_BEGIN,
|
|
779
|
-
"INSERT INTO items (value) VALUES (1), (2)",
|
|
761
|
+
"INSERT INTO `items` (`value`) VALUES (1), (2)",
|
|
780
762
|
SQL_COMMIT,
|
|
781
763
|
SQL_BEGIN,
|
|
782
|
-
"INSERT INTO items (value) VALUES (3), (4)",
|
|
764
|
+
"INSERT INTO `items` (`value`) VALUES (3), (4)",
|
|
783
765
|
SQL_COMMIT
|
|
784
766
|
]
|
|
785
767
|
|
|
@@ -796,7 +778,7 @@ describe "MySQL::Dataset#insert and related methods" do
|
|
|
796
778
|
|
|
797
779
|
MYSQL_DB.sqls.should == [
|
|
798
780
|
SQL_BEGIN,
|
|
799
|
-
"INSERT INTO items (name
|
|
781
|
+
"INSERT INTO `items` (`name`, `value`) VALUES ('abc', 1), ('def', 2)",
|
|
800
782
|
SQL_COMMIT
|
|
801
783
|
]
|
|
802
784
|
|
|
@@ -811,7 +793,7 @@ describe "MySQL::Dataset#insert and related methods" do
|
|
|
811
793
|
|
|
812
794
|
MYSQL_DB.sqls.should == [
|
|
813
795
|
SQL_BEGIN,
|
|
814
|
-
"INSERT IGNORE INTO items (name) VALUES ('abc'), ('def')",
|
|
796
|
+
"INSERT IGNORE INTO `items` (`name`) VALUES ('abc'), ('def')",
|
|
815
797
|
SQL_COMMIT
|
|
816
798
|
]
|
|
817
799
|
|
|
@@ -822,7 +804,7 @@ describe "MySQL::Dataset#insert and related methods" do
|
|
|
822
804
|
|
|
823
805
|
specify "#insert_ignore should add the IGNORE keyword for single inserts" do
|
|
824
806
|
@d.insert_ignore.insert(:name => 'ghi')
|
|
825
|
-
MYSQL_DB.sqls.should == ["INSERT IGNORE INTO items (name) VALUES ('ghi')"]
|
|
807
|
+
MYSQL_DB.sqls.should == ["INSERT IGNORE INTO `items` (`name`) VALUES ('ghi')"]
|
|
826
808
|
@d.all.should == [{:name => 'ghi', :value => nil}]
|
|
827
809
|
end
|
|
828
810
|
|
|
@@ -830,9 +812,9 @@ describe "MySQL::Dataset#insert and related methods" do
|
|
|
830
812
|
@d.on_duplicate_key_update.import([:name,:value], [['abc', 1], ['def',2]])
|
|
831
813
|
|
|
832
814
|
MYSQL_DB.sqls.should == [
|
|
833
|
-
"SELECT * FROM items LIMIT 1",
|
|
815
|
+
"SELECT * FROM `items` LIMIT 1",
|
|
834
816
|
SQL_BEGIN,
|
|
835
|
-
"INSERT INTO items (name
|
|
817
|
+
"INSERT INTO `items` (`name`, `value`) VALUES ('abc', 1), ('def', 2) ON DUPLICATE KEY UPDATE `name`=VALUES(`name`), `value`=VALUES(`value`)",
|
|
836
818
|
SQL_COMMIT
|
|
837
819
|
]
|
|
838
820
|
|
|
@@ -848,7 +830,7 @@ describe "MySQL::Dataset#insert and related methods" do
|
|
|
848
830
|
|
|
849
831
|
MYSQL_DB.sqls.should == [
|
|
850
832
|
SQL_BEGIN,
|
|
851
|
-
"INSERT INTO items (name
|
|
833
|
+
"INSERT INTO `items` (`name`, `value`) VALUES ('abc', 1), ('def', 2) ON DUPLICATE KEY UPDATE `value`=VALUES(`value`)",
|
|
852
834
|
SQL_COMMIT
|
|
853
835
|
]
|
|
854
836
|
|
|
@@ -907,25 +889,25 @@ describe "MySQL::Dataset#complex_expression_sql" do
|
|
|
907
889
|
end
|
|
908
890
|
|
|
909
891
|
specify "should handle pattern matches correctly" do
|
|
910
|
-
@d.literal(:x.like('a')).should == "(x LIKE BINARY 'a')"
|
|
911
|
-
@d.literal(~:x.like('a')).should == "(x NOT LIKE BINARY 'a')"
|
|
912
|
-
@d.literal(:x.ilike('a')).should == "(x LIKE 'a')"
|
|
913
|
-
@d.literal(~:x.ilike('a')).should == "(x NOT LIKE 'a')"
|
|
914
|
-
@d.literal(:x.like(/a/)).should == "(x REGEXP BINARY 'a')"
|
|
915
|
-
@d.literal(~:x.like(/a/)).should == "(x NOT REGEXP BINARY 'a')"
|
|
916
|
-
@d.literal(:x.like(/a/i)).should == "(x REGEXP 'a')"
|
|
917
|
-
@d.literal(~:x.like(/a/i)).should == "(x NOT REGEXP 'a')"
|
|
892
|
+
@d.literal(:x.like('a')).should == "(`x` LIKE BINARY 'a')"
|
|
893
|
+
@d.literal(~:x.like('a')).should == "(`x` NOT LIKE BINARY 'a')"
|
|
894
|
+
@d.literal(:x.ilike('a')).should == "(`x` LIKE 'a')"
|
|
895
|
+
@d.literal(~:x.ilike('a')).should == "(`x` NOT LIKE 'a')"
|
|
896
|
+
@d.literal(:x.like(/a/)).should == "(`x` REGEXP BINARY 'a')"
|
|
897
|
+
@d.literal(~:x.like(/a/)).should == "(`x` NOT REGEXP BINARY 'a')"
|
|
898
|
+
@d.literal(:x.like(/a/i)).should == "(`x` REGEXP 'a')"
|
|
899
|
+
@d.literal(~:x.like(/a/i)).should == "(`x` NOT REGEXP 'a')"
|
|
918
900
|
end
|
|
919
901
|
|
|
920
902
|
specify "should handle string concatenation with CONCAT if more than one record" do
|
|
921
|
-
@d.literal([:x, :y].sql_string_join).should == "CONCAT(x
|
|
922
|
-
@d.literal([:x, :y].sql_string_join(' ')).should == "CONCAT(x
|
|
923
|
-
@d.literal([:x.sql_function(:y), 1, 'z'.lit].sql_string_join(:y.sql_subscript(1))).should == "CONCAT(x(y), y[1], '1', y[1], z)"
|
|
903
|
+
@d.literal([:x, :y].sql_string_join).should == "CONCAT(`x`, `y`)"
|
|
904
|
+
@d.literal([:x, :y].sql_string_join(' ')).should == "CONCAT(`x`, ' ', `y`)"
|
|
905
|
+
@d.literal([:x.sql_function(:y), 1, 'z'.lit].sql_string_join(:y.sql_subscript(1))).should == "CONCAT(x(`y`), `y`[1], '1', `y`[1], z)"
|
|
924
906
|
end
|
|
925
907
|
|
|
926
908
|
specify "should handle string concatenation as simple string if just one record" do
|
|
927
|
-
@d.literal([:x].sql_string_join).should == "x"
|
|
928
|
-
@d.literal([:x].sql_string_join(' ')).should == "x"
|
|
909
|
+
@d.literal([:x].sql_string_join).should == "`x`"
|
|
910
|
+
@d.literal([:x].sql_string_join(' ')).should == "`x`"
|
|
929
911
|
end
|
|
930
912
|
end
|
|
931
913
|
|
|
@@ -939,7 +921,7 @@ describe "MySQL::Dataset#calc_found_rows" do
|
|
|
939
921
|
|
|
940
922
|
specify "should add the SQL_CALC_FOUND_ROWS keyword when selecting" do
|
|
941
923
|
MYSQL_DB[:items].select(:a).calc_found_rows.limit(1).sql.should == \
|
|
942
|
-
'SELECT SQL_CALC_FOUND_ROWS a FROM items LIMIT 1'
|
|
924
|
+
'SELECT SQL_CALC_FOUND_ROWS `a` FROM `items` LIMIT 1'
|
|
943
925
|
end
|
|
944
926
|
|
|
945
927
|
specify "should count matching rows disregarding LIMIT clause" do
|
|
@@ -950,8 +932,8 @@ describe "MySQL::Dataset#calc_found_rows" do
|
|
|
950
932
|
MYSQL_DB.dataset.select(:FOUND_ROWS.sql_function.as(:rows)).all.should == [{:rows => 2 }]
|
|
951
933
|
|
|
952
934
|
MYSQL_DB.sqls.should == [
|
|
953
|
-
'SELECT SQL_CALC_FOUND_ROWS * FROM items WHERE (a = 1) LIMIT 1',
|
|
954
|
-
'SELECT FOUND_ROWS() AS rows',
|
|
935
|
+
'SELECT SQL_CALC_FOUND_ROWS * FROM `items` WHERE (`a` = 1) LIMIT 1',
|
|
936
|
+
'SELECT FOUND_ROWS() AS `rows`',
|
|
955
937
|
]
|
|
956
938
|
end
|
|
957
939
|
end
|
|
@@ -1015,29 +997,29 @@ end
|
|
|
1015
997
|
if MYSQL_DB.adapter_scheme == :mysql
|
|
1016
998
|
describe "MySQL bad date/time conversions" do
|
|
1017
999
|
after do
|
|
1018
|
-
|
|
1000
|
+
MYSQL_DB.convert_invalid_date_time = false
|
|
1019
1001
|
end
|
|
1020
1002
|
|
|
1021
1003
|
specify "should raise an exception when a bad date/time is used and convert_invalid_date_time is false" do
|
|
1022
|
-
|
|
1004
|
+
MYSQL_DB.convert_invalid_date_time = false
|
|
1023
1005
|
proc{MYSQL_DB["SELECT CAST('0000-00-00' AS date)"].single_value}.should raise_error(Sequel::InvalidValue)
|
|
1024
1006
|
proc{MYSQL_DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value}.should raise_error(Sequel::InvalidValue)
|
|
1025
1007
|
proc{MYSQL_DB["SELECT CAST('25:00:00' AS time)"].single_value}.should raise_error(Sequel::InvalidValue)
|
|
1026
1008
|
end
|
|
1027
1009
|
|
|
1028
1010
|
specify "should not use a nil value bad date/time is used and convert_invalid_date_time is nil or :nil" do
|
|
1029
|
-
|
|
1011
|
+
MYSQL_DB.convert_invalid_date_time = nil
|
|
1030
1012
|
MYSQL_DB["SELECT CAST('0000-00-00' AS date)"].single_value.should == nil
|
|
1031
1013
|
MYSQL_DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value.should == nil
|
|
1032
1014
|
MYSQL_DB["SELECT CAST('25:00:00' AS time)"].single_value.should == nil
|
|
1033
|
-
|
|
1015
|
+
MYSQL_DB.convert_invalid_date_time = :nil
|
|
1034
1016
|
MYSQL_DB["SELECT CAST('0000-00-00' AS date)"].single_value.should == nil
|
|
1035
1017
|
MYSQL_DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value.should == nil
|
|
1036
1018
|
MYSQL_DB["SELECT CAST('25:00:00' AS time)"].single_value.should == nil
|
|
1037
1019
|
end
|
|
1038
1020
|
|
|
1039
1021
|
specify "should not use a nil value bad date/time is used and convert_invalid_date_time is :string" do
|
|
1040
|
-
|
|
1022
|
+
MYSQL_DB.convert_invalid_date_time = :string
|
|
1041
1023
|
MYSQL_DB["SELECT CAST('0000-00-00' AS date)"].single_value.should == '0000-00-00'
|
|
1042
1024
|
MYSQL_DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value.should == '0000-00-00 00:00:00'
|
|
1043
1025
|
MYSQL_DB["SELECT CAST('25:00:00' AS time)"].single_value.should == '25:00:00'
|