sequel 2.12.0 → 3.0.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 +62 -0
- data/README.rdoc +3 -3
- data/Rakefile +7 -0
- data/doc/advanced_associations.rdoc +44 -0
- data/doc/release_notes/3.0.0.txt +221 -0
- data/lib/sequel/adapters/amalgalite.rb +208 -0
- data/lib/sequel/adapters/db2.rb +3 -0
- data/lib/sequel/adapters/dbi.rb +9 -0
- data/lib/sequel/adapters/do.rb +0 -4
- data/lib/sequel/adapters/firebird.rb +16 -18
- data/lib/sequel/adapters/informix.rb +5 -3
- data/lib/sequel/adapters/jdbc.rb +24 -20
- data/lib/sequel/adapters/jdbc/h2.rb +15 -4
- data/lib/sequel/adapters/mysql.rb +4 -8
- data/lib/sequel/adapters/odbc.rb +0 -4
- data/lib/sequel/adapters/oracle.rb +0 -4
- data/lib/sequel/adapters/shared/mssql.rb +16 -5
- data/lib/sequel/adapters/shared/mysql.rb +87 -86
- data/lib/sequel/adapters/shared/oracle.rb +92 -3
- data/lib/sequel/adapters/shared/postgres.rb +85 -29
- data/lib/sequel/adapters/shared/progress.rb +8 -3
- data/lib/sequel/adapters/shared/sqlite.rb +53 -23
- data/lib/sequel/adapters/sqlite.rb +4 -7
- data/lib/sequel/adapters/utils/unsupported.rb +3 -3
- data/lib/sequel/connection_pool.rb +18 -25
- data/lib/sequel/core.rb +2 -21
- data/lib/sequel/database.rb +60 -44
- data/lib/sequel/database/schema_generator.rb +26 -31
- data/lib/sequel/database/schema_methods.rb +8 -3
- data/lib/sequel/database/schema_sql.rb +114 -28
- data/lib/sequel/dataset.rb +14 -41
- data/lib/sequel/dataset/convenience.rb +31 -54
- data/lib/sequel/dataset/graph.rb +7 -13
- data/lib/sequel/dataset/sql.rb +43 -54
- data/lib/sequel/extensions/inflector.rb +0 -5
- data/lib/sequel/extensions/schema_dumper.rb +238 -0
- data/lib/sequel/metaprogramming.rb +0 -20
- data/lib/sequel/model.rb +1 -2
- data/lib/sequel/model/base.rb +18 -16
- data/lib/sequel/model/inflections.rb +6 -9
- data/lib/sequel/plugins/caching.rb +0 -6
- data/lib/sequel/plugins/hook_class_methods.rb +1 -1
- data/lib/sequel/sql.rb +2 -0
- data/lib/sequel/version.rb +2 -2
- data/spec/adapters/firebird_spec.rb +35 -8
- data/spec/adapters/mysql_spec.rb +173 -266
- data/spec/adapters/oracle_spec.rb +13 -0
- data/spec/adapters/postgres_spec.rb +127 -227
- data/spec/adapters/sqlite_spec.rb +13 -171
- data/spec/core/connection_pool_spec.rb +15 -4
- data/spec/core/core_sql_spec.rb +14 -170
- data/spec/core/database_spec.rb +50 -132
- data/spec/core/dataset_spec.rb +47 -930
- data/spec/core/expression_filters_spec.rb +12 -0
- data/spec/core/schema_generator_spec.rb +37 -45
- data/spec/core/schema_spec.rb +26 -16
- data/spec/core/spec_helper.rb +0 -25
- data/spec/extensions/inflector_spec.rb +0 -3
- data/spec/extensions/schema_dumper_spec.rb +292 -0
- data/spec/extensions/serialization_spec.rb +9 -0
- data/spec/extensions/single_table_inheritance_spec.rb +6 -1
- data/spec/extensions/spec_helper.rb +1 -3
- data/spec/extensions/validation_helpers_spec.rb +4 -4
- data/spec/integration/database_test.rb +18 -0
- data/spec/integration/dataset_test.rb +112 -1
- data/spec/integration/eager_loader_test.rb +70 -9
- data/spec/integration/prepared_statement_test.rb +2 -2
- data/spec/integration/schema_test.rb +76 -27
- data/spec/integration/spec_helper.rb +0 -14
- data/spec/integration/transaction_test.rb +27 -0
- data/spec/model/associations_spec.rb +0 -36
- data/spec/model/base_spec.rb +18 -123
- data/spec/model/hooks_spec.rb +2 -235
- data/spec/model/inflector_spec.rb +15 -115
- data/spec/model/model_spec.rb +0 -120
- data/spec/model/plugins_spec.rb +0 -70
- data/spec/model/record_spec.rb +35 -93
- data/spec/model/spec_helper.rb +0 -27
- data/spec/model/validations_spec.rb +0 -931
- metadata +9 -14
- data/lib/sequel/deprecated.rb +0 -593
- data/lib/sequel/deprecated_migration.rb +0 -91
- data/lib/sequel/model/deprecated.rb +0 -204
- data/lib/sequel/model/deprecated_hooks.rb +0 -103
- data/lib/sequel/model/deprecated_inflector.rb +0 -335
- data/lib/sequel/model/deprecated_validations.rb +0 -388
- data/spec/core/core_ext_spec.rb +0 -156
- data/spec/core/migration_spec.rb +0 -263
- data/spec/core/pretty_table_spec.rb +0 -58
- data/spec/model/caching_spec.rb +0 -217
- data/spec/model/schema_spec.rb +0 -92
@@ -8,26 +8,6 @@ module Sequel
|
|
8
8
|
|
9
9
|
private
|
10
10
|
|
11
|
-
# Make a singleton/class attribute accessor method(s).
|
12
|
-
# Replaces the construct:
|
13
|
-
#
|
14
|
-
# class << self
|
15
|
-
# attr_accessor *meths
|
16
|
-
# end
|
17
|
-
def metaattr_accessor(*meths)
|
18
|
-
meta_eval{attr_accessor(*meths)}
|
19
|
-
end
|
20
|
-
|
21
|
-
# Make a singleton/class attribute reader method(s).
|
22
|
-
# Replaces the construct:
|
23
|
-
#
|
24
|
-
# class << self
|
25
|
-
# attr_reader *meths
|
26
|
-
# end
|
27
|
-
def metaattr_reader(*meths)
|
28
|
-
meta_eval{attr_reader(*meths)}
|
29
|
-
end
|
30
|
-
|
31
11
|
# Evaluate the block in the context of the object's metaclass
|
32
12
|
def meta_eval(&block)
|
33
13
|
metaclass.instance_eval(&block)
|
data/lib/sequel/model.rb
CHANGED
@@ -45,7 +45,7 @@ module Sequel
|
|
45
45
|
last left_outer_join limit map multi_insert naked order order_by
|
46
46
|
order_more paginate print query range reverse_order right_outer_join
|
47
47
|
select select_all select_more server set set_graph_aliases
|
48
|
-
single_value to_csv to_hash
|
48
|
+
single_value to_csv to_hash union unfiltered unordered
|
49
49
|
update where with_sql'.map{|x| x.to_sym}
|
50
50
|
|
51
51
|
# Class instance variables to set to nil when a subclass is created, for -w compliance
|
@@ -106,5 +106,4 @@ module Sequel
|
|
106
106
|
require 'associations', 'model'
|
107
107
|
Model.plugin Model::Associations
|
108
108
|
end
|
109
|
-
require 'deprecated', 'model'
|
110
109
|
end
|
data/lib/sequel/model/base.rb
CHANGED
@@ -285,7 +285,6 @@ module Sequel
|
|
285
285
|
raise(Error, "Model.set_dataset takes a Symbol or a Sequel::Dataset")
|
286
286
|
end
|
287
287
|
@dataset.row_proc = Proc.new{|r| load(r)}
|
288
|
-
@dataset.transform(@transform) if @transform
|
289
288
|
if inherited
|
290
289
|
@simple_table = superclass.simple_table
|
291
290
|
@columns = @dataset.columns rescue nil
|
@@ -438,8 +437,6 @@ module Sequel
|
|
438
437
|
def set_columns(new_columns)
|
439
438
|
@columns = new_columns
|
440
439
|
def_column_accessor(*new_columns) if new_columns
|
441
|
-
# Deprecation.deprecated
|
442
|
-
@str_columns = nil
|
443
440
|
@columns
|
444
441
|
end
|
445
442
|
|
@@ -656,12 +653,9 @@ module Sequel
|
|
656
653
|
# cached association and changed_columns information. Raises an Error if the record no longer
|
657
654
|
# exists in the database.
|
658
655
|
def refresh
|
659
|
-
|
660
|
-
changed_columns.clear
|
661
|
-
associations.clear
|
662
|
-
self
|
656
|
+
_refresh(this)
|
663
657
|
end
|
664
|
-
|
658
|
+
|
665
659
|
# Alias of refresh, but not aliased directly to make overriding in a plugin easier.
|
666
660
|
def reload
|
667
661
|
refresh
|
@@ -677,7 +671,7 @@ module Sequel
|
|
677
671
|
#
|
678
672
|
# Takes the following options:
|
679
673
|
#
|
680
|
-
# * :changed - save all changed columns, instead of all columns or the columns
|
674
|
+
# * :changed - save all changed columns, instead of all columns or the columns given
|
681
675
|
# * :transaction - set to false not to use a transaction
|
682
676
|
# * :validate - set to false not to validate the model before saving
|
683
677
|
def save(*columns)
|
@@ -777,6 +771,15 @@ module Sequel
|
|
777
771
|
self
|
778
772
|
end
|
779
773
|
|
774
|
+
# Refresh using a particular dataset, used inside save to make sure the same server
|
775
|
+
# is used for reading newly inserted values from the database
|
776
|
+
def _refresh(dataset)
|
777
|
+
@values = dataset.first || raise(Error, "Record not found")
|
778
|
+
changed_columns.clear
|
779
|
+
associations.clear
|
780
|
+
self
|
781
|
+
end
|
782
|
+
|
780
783
|
# Internal version of save, split from save to allow running inside
|
781
784
|
# it's own transaction.
|
782
785
|
def _save(columns, opts)
|
@@ -801,7 +804,11 @@ module Sequel
|
|
801
804
|
after_create
|
802
805
|
after_save
|
803
806
|
@was_new = nil
|
804
|
-
|
807
|
+
if pk
|
808
|
+
ds = this
|
809
|
+
ds = ds.server(:default) unless ds.opts[:server]
|
810
|
+
_refresh(ds)
|
811
|
+
end
|
805
812
|
else
|
806
813
|
return save_failure(:update) if before_update == false
|
807
814
|
if columns.empty?
|
@@ -837,16 +844,12 @@ module Sequel
|
|
837
844
|
|
838
845
|
# Set the columns, filtered by the only and except arrays.
|
839
846
|
def set_restricted(hash, only, except)
|
840
|
-
columns_not_set = [nil, false, "", [], {}].include?(model.instance_variable_get(:@columns))
|
841
847
|
meths = setter_methods(only, except)
|
842
848
|
strict = strict_param_setting
|
843
849
|
hash.each do |k,v|
|
844
850
|
m = "#{k}="
|
845
851
|
if meths.include?(m)
|
846
852
|
send(m, v)
|
847
|
-
elsif columns_not_set && (Symbol === k)
|
848
|
-
Deprecation.deprecate('Calling Model#set_restricted for a column without a setter method when the model class does not have any columns', 'Use Model#[] for these columns')
|
849
|
-
self[k] = v
|
850
853
|
elsif strict
|
851
854
|
raise Error, "method #{m} doesn't exist or access is restricted to it"
|
852
855
|
end
|
@@ -887,8 +890,7 @@ module Sequel
|
|
887
890
|
# typecast_value method, so database adapters can override/augment the handling
|
888
891
|
# for database specific column types.
|
889
892
|
def typecast_value(column, value)
|
890
|
-
|
891
|
-
return value unless typecast_on_assignment && db_schema && (col_schema = db_schema[column]) && !model.serialized?(column)
|
893
|
+
return value unless typecast_on_assignment && db_schema && (col_schema = db_schema[column])
|
892
894
|
value = nil if value == '' and typecast_empty_string_to_nil and col_schema[:type] and ![:string, :blob].include?(col_schema[:type])
|
893
895
|
raise(InvalidValue, "nil/NULL is not allowed for the #{column} column") if raise_on_typecast_failure && value.nil? && (col_schema[:allow_null] == false)
|
894
896
|
begin
|
@@ -97,8 +97,6 @@ module Sequel
|
|
97
97
|
end
|
98
98
|
|
99
99
|
# Setup the default inflections
|
100
|
-
# Commented out until the deprecated inflector is removed
|
101
|
-
=begin
|
102
100
|
plural(/$/, 's')
|
103
101
|
plural(/s$/i, 's')
|
104
102
|
plural(/(ax|test)is$/i, '\1es')
|
@@ -149,14 +147,13 @@ module Sequel
|
|
149
147
|
irregular('move', 'moves')
|
150
148
|
|
151
149
|
uncountable(%w(equipment information rice money species series fish sheep))
|
152
|
-
=end
|
153
150
|
|
154
151
|
private
|
155
152
|
|
156
153
|
# Convert the given string to CamelCase. Will also convert '/' to '::' which is useful for converting paths to namespaces.
|
157
154
|
def camelize(s)
|
158
155
|
s = s.to_s
|
159
|
-
|
156
|
+
return s.camelize if s.respond_to?(:camelize)
|
160
157
|
s = s.gsub(CAMELIZE_MODULE_REGEXP){|x| "::#{x[-1..-1].upcase unless x == SLASH}"}.gsub(CAMELIZE_CONVERT_REGEXP){|x| x[-1..-1].upcase}
|
161
158
|
s
|
162
159
|
end
|
@@ -166,7 +163,7 @@ module Sequel
|
|
166
163
|
# or is not initialized.
|
167
164
|
def constantize(s)
|
168
165
|
s = s.to_s
|
169
|
-
|
166
|
+
return s.constantize if s.respond_to?(:constantize)
|
170
167
|
raise(NameError, "#{inspect} is not a valid constant name!") unless m = VALID_CONSTANT_NAME_REGEXP.match(s.to_s)
|
171
168
|
Object.module_eval("::#{m[1]}", __FILE__, __LINE__)
|
172
169
|
end
|
@@ -174,14 +171,14 @@ module Sequel
|
|
174
171
|
# Removes the module part from the expression in the string
|
175
172
|
def demodulize(s)
|
176
173
|
s = s.to_s
|
177
|
-
|
174
|
+
return s.demodulize if s.respond_to?(:demodulize)
|
178
175
|
s.gsub(DEMODULIZE_CONVERT_REGEXP, EMPTY_STRING)
|
179
176
|
end
|
180
177
|
|
181
178
|
# Returns the plural form of the word in the string.
|
182
179
|
def pluralize(s)
|
183
180
|
s = s.to_s
|
184
|
-
|
181
|
+
return s.pluralize if s.respond_to?(:pluralize)
|
185
182
|
result = s.dup
|
186
183
|
Inflections.plurals.each{|(rule, replacement)| break if result.gsub!(rule, replacement)} unless Inflections.uncountables.include?(s.downcase)
|
187
184
|
result
|
@@ -190,7 +187,7 @@ module Sequel
|
|
190
187
|
# The reverse of pluralize, returns the singular form of a word in a string.
|
191
188
|
def singularize(s)
|
192
189
|
s = s.to_s
|
193
|
-
|
190
|
+
return s.singularize if s.respond_to?(:singularize)
|
194
191
|
result = s.dup
|
195
192
|
Inflections.singulars.each{|(rule, replacement)| break if result.gsub!(rule, replacement)} unless Inflections.uncountables.include?(s.downcase)
|
196
193
|
result
|
@@ -200,7 +197,7 @@ module Sequel
|
|
200
197
|
# Also changes '::' to '/' to convert namespaces to paths.
|
201
198
|
def underscore(s)
|
202
199
|
s = s.to_s
|
203
|
-
|
200
|
+
return s.underscore if s.respond_to?(:underscore)
|
204
201
|
s.gsub(UNDERSCORE_MODULE_REGEXP, SLASH).gsub(UNDERSCORE_CONVERT_REGEXP1, UNDERSCORE_CONVERT_REPLACE).
|
205
202
|
gsub(UNDERSCORE_CONVERT_REGEXP2, UNDERSCORE_CONVERT_REPLACE).tr(DASH, UNDERSCORE).downcase
|
206
203
|
end
|
@@ -107,7 +107,7 @@ module Sequel
|
|
107
107
|
end
|
108
108
|
|
109
109
|
module InstanceMethods
|
110
|
-
Model::HOOKS.each{|h| class_eval("def #{h}; run_hooks(:#{h}); end", __FILE__, __LINE__)}
|
110
|
+
Model::HOOKS.each{|h| class_eval("def #{h}; return false if super == false; run_hooks(:#{h}); end", __FILE__, __LINE__)}
|
111
111
|
|
112
112
|
private
|
113
113
|
|
data/lib/sequel/sql.rb
CHANGED
data/lib/sequel/version.rb
CHANGED
@@ -25,6 +25,14 @@ FIREBIRD_DB.create_table! :test5 do
|
|
25
25
|
integer :val
|
26
26
|
end
|
27
27
|
|
28
|
+
FIREBIRD_DB.create_table! :test6 do
|
29
|
+
primary_key :xid
|
30
|
+
blob :val
|
31
|
+
String :val2
|
32
|
+
varchar :val3, :size=>200
|
33
|
+
text :val4
|
34
|
+
end
|
35
|
+
|
28
36
|
context "A Firebird database" do
|
29
37
|
before do
|
30
38
|
@db = FIREBIRD_DB
|
@@ -234,7 +242,7 @@ context "A Firebird database" do
|
|
234
242
|
g = Sequel::Schema::Generator.new(FIREBIRD_DB) do
|
235
243
|
primary_key :id, :sequence_name => "seq_test"
|
236
244
|
end
|
237
|
-
FIREBIRD_DB.
|
245
|
+
FIREBIRD_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [[
|
238
246
|
"CREATE TABLE POSTS (ID integer PRIMARY KEY )",
|
239
247
|
"CREATE SEQUENCE SEQ_TEST",
|
240
248
|
" CREATE TRIGGER BI_POSTS_ID for POSTS\n ACTIVE BEFORE INSERT position 0\n as begin\n if ((new.ID is null) or (new.ID = 0)) then\n begin\n new.ID = next value for seq_test;\n end\n end\n\n"
|
@@ -245,7 +253,7 @@ context "A Firebird database" do
|
|
245
253
|
g = Sequel::Schema::Generator.new(FIREBIRD_DB) do
|
246
254
|
primary_key :id, :sequence_start_position => 999
|
247
255
|
end
|
248
|
-
FIREBIRD_DB.
|
256
|
+
FIREBIRD_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [[
|
249
257
|
"CREATE TABLE POSTS (ID integer PRIMARY KEY )",
|
250
258
|
"CREATE SEQUENCE SEQ_POSTS_ID",
|
251
259
|
"ALTER SEQUENCE SEQ_POSTS_ID RESTART WITH 999",
|
@@ -257,7 +265,7 @@ context "A Firebird database" do
|
|
257
265
|
g = Sequel::Schema::Generator.new(FIREBIRD_DB) do
|
258
266
|
primary_key :id, :sequence_name => "seq_test", :sequence_start_position => 999
|
259
267
|
end
|
260
|
-
FIREBIRD_DB.
|
268
|
+
FIREBIRD_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [[
|
261
269
|
"CREATE TABLE POSTS (ID integer PRIMARY KEY )",
|
262
270
|
"CREATE SEQUENCE SEQ_TEST",
|
263
271
|
"ALTER SEQUENCE SEQ_TEST RESTART WITH 999",
|
@@ -269,7 +277,7 @@ context "A Firebird database" do
|
|
269
277
|
g = Sequel::Schema::Generator.new(FIREBIRD_DB) do
|
270
278
|
primary_key :id, :trigger_name => "trig_test"
|
271
279
|
end
|
272
|
-
FIREBIRD_DB.
|
280
|
+
FIREBIRD_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [[
|
273
281
|
"CREATE TABLE POSTS (ID integer PRIMARY KEY )",
|
274
282
|
"CREATE SEQUENCE SEQ_POSTS_ID",
|
275
283
|
" CREATE TRIGGER TRIG_TEST for POSTS\n ACTIVE BEFORE INSERT position 0\n as begin\n if ((new.ID is null) or (new.ID = 0)) then\n begin\n new.ID = next value for seq_posts_id;\n end\n end\n\n"
|
@@ -280,7 +288,7 @@ context "A Firebird database" do
|
|
280
288
|
g = Sequel::Schema::Generator.new(FIREBIRD_DB) do
|
281
289
|
primary_key :id, :create_sequence => false
|
282
290
|
end
|
283
|
-
FIREBIRD_DB.
|
291
|
+
FIREBIRD_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [[
|
284
292
|
"CREATE TABLE POSTS (ID integer PRIMARY KEY )",
|
285
293
|
" CREATE TRIGGER BI_POSTS_ID for POSTS\n ACTIVE BEFORE INSERT position 0\n as begin\n if ((new.ID is null) or (new.ID = 0)) then\n begin\n new.ID = next value for seq_posts_id;\n end\n end\n\n"
|
286
294
|
], nil]
|
@@ -290,7 +298,7 @@ context "A Firebird database" do
|
|
290
298
|
g = Sequel::Schema::Generator.new(FIREBIRD_DB) do
|
291
299
|
primary_key :id, :create_trigger => false
|
292
300
|
end
|
293
|
-
FIREBIRD_DB.
|
301
|
+
FIREBIRD_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [[
|
294
302
|
"CREATE TABLE POSTS (ID integer PRIMARY KEY )",
|
295
303
|
"CREATE SEQUENCE SEQ_POSTS_ID",
|
296
304
|
], "DROP SEQUENCE SEQ_POSTS_ID"]
|
@@ -300,7 +308,7 @@ context "A Firebird database" do
|
|
300
308
|
g = Sequel::Schema::Generator.new(FIREBIRD_DB) do
|
301
309
|
primary_key :id, :create_sequence => false, :create_trigger => false
|
302
310
|
end
|
303
|
-
FIREBIRD_DB.
|
311
|
+
FIREBIRD_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [[
|
304
312
|
"CREATE TABLE POSTS (ID integer PRIMARY KEY )"
|
305
313
|
], nil]
|
306
314
|
end
|
@@ -348,7 +356,8 @@ context "Postgres::Dataset#insert" do
|
|
348
356
|
end
|
349
357
|
|
350
358
|
specify "should using call insert_returning_sql" do
|
351
|
-
@ds.should_receive(:single_value).once.with(:sql=>'INSERT INTO TEST5 (VAL) VALUES (10) RETURNING XID', :server=> :default)
|
359
|
+
# @ds.should_receive(:single_value).once.with(:sql=>'INSERT INTO TEST5 (VAL) VALUES (10) RETURNING XID', :server=> :default)
|
360
|
+
@ds.should_receive(:single_value).once
|
352
361
|
@ds.insert(:val=>10)
|
353
362
|
end
|
354
363
|
|
@@ -374,3 +383,21 @@ context "Postgres::Dataset#insert" do
|
|
374
383
|
end
|
375
384
|
end
|
376
385
|
|
386
|
+
context "Postgres::Dataset#insert" do
|
387
|
+
before do
|
388
|
+
@ds = FIREBIRD_DB[:test6]
|
389
|
+
@ds.delete
|
390
|
+
end
|
391
|
+
|
392
|
+
specify "should insert and retrieve a blob successfully" do
|
393
|
+
value1 = "\1\2\2\2\2222\2\2\2"
|
394
|
+
value2 = "abcd"
|
395
|
+
value3 = "efgh"
|
396
|
+
value4 = "ijkl"
|
397
|
+
id1 = @ds.insert(:val=>value1, :val2=>value2, :val3=>value3, :val4=>value4)
|
398
|
+
@ds.first(:XID=>id1)[:val].should == value1
|
399
|
+
@ds.first(:XID=>id1)[:val2].should == value2
|
400
|
+
@ds.first(:XID=>id1)[:val3].should == value3
|
401
|
+
@ds.first(:XID=>id1)[:val4].should == value4
|
402
|
+
end
|
403
|
+
end
|
data/spec/adapters/mysql_spec.rb
CHANGED
@@ -13,17 +13,10 @@ end
|
|
13
13
|
|
14
14
|
MYSQL_URI = URI.parse(MYSQL_DB.uri)
|
15
15
|
|
16
|
-
MYSQL_DB.create_table! :items do
|
17
|
-
text :name
|
18
|
-
integer :value, :index => true
|
19
|
-
end
|
20
16
|
MYSQL_DB.create_table! :test2 do
|
21
17
|
text :name
|
22
18
|
integer :value
|
23
19
|
end
|
24
|
-
MYSQL_DB.create_table! :booltest do
|
25
|
-
tinyint :value
|
26
|
-
end
|
27
20
|
def MYSQL_DB.sqls
|
28
21
|
(@sqls ||= [])
|
29
22
|
end
|
@@ -32,6 +25,9 @@ def logger.method_missing(m, msg)
|
|
32
25
|
MYSQL_DB.sqls << msg
|
33
26
|
end
|
34
27
|
MYSQL_DB.logger = logger
|
28
|
+
MYSQL_DB.drop_table(:items) rescue nil
|
29
|
+
MYSQL_DB.drop_table(:dolls) rescue nil
|
30
|
+
MYSQL_DB.drop_table(:booltest) rescue nil
|
35
31
|
|
36
32
|
if MYSQL_DB.class.adapter_scheme == :do
|
37
33
|
SQL_BEGIN = 'Transaction.begin'
|
@@ -46,111 +42,77 @@ end
|
|
46
42
|
context "MySQL", '#create_table' do
|
47
43
|
before do
|
48
44
|
@db = MYSQL_DB
|
45
|
+
MYSQL_DB.sqls.clear
|
49
46
|
end
|
50
|
-
after
|
51
|
-
@db.drop_table
|
47
|
+
after do
|
48
|
+
@db.drop_table(:dolls) rescue nil
|
52
49
|
end
|
50
|
+
|
53
51
|
specify "should allow to specify options for MySQL" do
|
54
|
-
@db.create_table(:dolls, :engine => 'MyISAM', :charset => 'latin2')
|
52
|
+
@db.create_table(:dolls, :engine => 'MyISAM', :charset => 'latin2'){text :name}
|
55
53
|
@db.sqls.should == ["CREATE TABLE dolls (name text) ENGINE=MyISAM DEFAULT CHARSET=latin2"]
|
56
54
|
end
|
55
|
+
|
56
|
+
specify "should create a temporary table" do
|
57
|
+
@db.create_table(:tmp_dolls, :temp => true, :engine => 'MyISAM', :charset => 'latin2'){text :name}
|
58
|
+
@db.sqls.should == ["CREATE TEMPORARY TABLE tmp_dolls (name text) ENGINE=MyISAM DEFAULT CHARSET=latin2"]
|
59
|
+
end
|
57
60
|
end
|
58
61
|
|
59
62
|
context "A MySQL database" do
|
60
63
|
before do
|
61
64
|
@db = MYSQL_DB
|
65
|
+
@db.create_table(:booltest){TrueClass :value}
|
62
66
|
end
|
63
67
|
after do
|
64
68
|
Sequel.convert_tinyint_to_bool = true
|
69
|
+
@db.drop_table(:booltest)
|
65
70
|
end
|
66
71
|
|
67
72
|
specify "should provide the server version" do
|
68
73
|
@db.server_version.should >= 40000
|
69
74
|
end
|
70
75
|
|
71
|
-
specify "should support sequential primary keys" do
|
72
|
-
@db.create_table!(:with_pk) {primary_key :id; text :name}
|
73
|
-
@db[:with_pk] << {:name => 'abc'}
|
74
|
-
@db[:with_pk] << {:name => 'def'}
|
75
|
-
@db[:with_pk] << {:name => 'ghi'}
|
76
|
-
@db[:with_pk].order(:name).all.should == [
|
77
|
-
{:id => 1, :name => 'abc'},
|
78
|
-
{:id => 2, :name => 'def'},
|
79
|
-
{:id => 3, :name => 'ghi'}
|
80
|
-
]
|
81
|
-
end
|
82
|
-
|
83
|
-
specify "should provide disconnect functionality" do
|
84
|
-
@db.pool.size.should == 1
|
85
|
-
@db.disconnect
|
86
|
-
@db.pool.size.should == 0
|
87
|
-
end
|
88
|
-
|
89
|
-
specify "should convert Mysql::Errors to Sequel::Errors" do
|
90
|
-
proc{@db << "SELECT 1 + blah;"}.should raise_error(Sequel::Error)
|
91
|
-
end
|
92
|
-
|
93
76
|
specify "should correctly parse the schema" do
|
94
77
|
@db.schema(:booltest, :reload=>true).should == [[:value, {:type=>:boolean, :allow_null=>true, :primary_key=>false, :default=>nil, :db_type=>"tinyint(4)"}]]
|
95
78
|
|
96
79
|
Sequel.convert_tinyint_to_bool = false
|
97
80
|
@db.schema(:booltest, :reload=>true).should == [[:value, {:type=>:integer, :allow_null=>true, :primary_key=>false, :default=>nil, :db_type=>"tinyint(4)"}]]
|
98
81
|
end
|
82
|
+
|
83
|
+
specify "should accept and return tinyints as bools or integers when configured to do so" do
|
84
|
+
MYSQL_DB[:booltest].delete
|
85
|
+
MYSQL_DB[:booltest] << {:value=>true}
|
86
|
+
MYSQL_DB[:booltest].all.should == [{:value=>true}]
|
87
|
+
MYSQL_DB[:booltest].delete
|
88
|
+
MYSQL_DB[:booltest] << {:value=>false}
|
89
|
+
MYSQL_DB[:booltest].all.should == [{:value=>false}]
|
90
|
+
|
91
|
+
Sequel.convert_tinyint_to_bool = false
|
92
|
+
MYSQL_DB[:booltest].delete
|
93
|
+
MYSQL_DB[:booltest] << {:value=>true}
|
94
|
+
MYSQL_DB[:booltest].all.should == [{:value=>1}]
|
95
|
+
MYSQL_DB[:booltest].delete
|
96
|
+
MYSQL_DB[:booltest] << {:value=>false}
|
97
|
+
MYSQL_DB[:booltest].all.should == [{:value=>0}]
|
98
|
+
|
99
|
+
MYSQL_DB[:booltest].delete
|
100
|
+
MYSQL_DB[:booltest] << {:value=>1}
|
101
|
+
MYSQL_DB[:booltest].all.should == [{:value=>1}]
|
102
|
+
MYSQL_DB[:booltest].delete
|
103
|
+
MYSQL_DB[:booltest] << {:value=>0}
|
104
|
+
MYSQL_DB[:booltest].all.should == [{:value=>0}]
|
105
|
+
end
|
99
106
|
end
|
100
107
|
|
101
108
|
context "A MySQL dataset" do
|
102
109
|
before do
|
110
|
+
MYSQL_DB.create_table(:items){String :name; Integer :value}
|
103
111
|
@d = MYSQL_DB[:items]
|
104
|
-
@d.delete # remove all records
|
105
112
|
MYSQL_DB.sqls.clear
|
106
113
|
end
|
107
|
-
|
108
|
-
|
109
|
-
@d.count.should == 0
|
110
|
-
@d << {:name => 'abc', :value => 123}
|
111
|
-
@d << {:name => 'abc', :value => 456}
|
112
|
-
@d << {:name => 'def', :value => 789}
|
113
|
-
@d.count.should == 3
|
114
|
-
end
|
115
|
-
|
116
|
-
specify "should return the correct records" do
|
117
|
-
@d.to_a.should == []
|
118
|
-
@d << {:name => 'abc', :value => 123}
|
119
|
-
@d << {:name => 'abc', :value => 456}
|
120
|
-
@d << {:name => 'def', :value => 789}
|
121
|
-
|
122
|
-
@d.order(:value).to_a.should == [
|
123
|
-
{:name => 'abc', :value => 123},
|
124
|
-
{:name => 'abc', :value => 456},
|
125
|
-
{:name => 'def', :value => 789}
|
126
|
-
]
|
127
|
-
end
|
128
|
-
|
129
|
-
specify "should update records correctly" do
|
130
|
-
@d << {:name => 'abc', :value => 123}
|
131
|
-
@d << {:name => 'abc', :value => 456}
|
132
|
-
@d << {:name => 'def', :value => 789}
|
133
|
-
@d.filter(:name => 'abc').update(:value => 530)
|
134
|
-
|
135
|
-
# the third record should stay the same
|
136
|
-
# floating-point precision bullshit
|
137
|
-
@d[:name => 'def'][:value].should == 789
|
138
|
-
@d.filter(:value => 530).count.should == 2
|
139
|
-
end
|
140
|
-
|
141
|
-
specify "should delete records correctly" do
|
142
|
-
@d << {:name => 'abc', :value => 123}
|
143
|
-
@d << {:name => 'abc', :value => 456}
|
144
|
-
@d << {:name => 'def', :value => 789}
|
145
|
-
@d.filter(:name => 'abc').delete
|
146
|
-
|
147
|
-
@d.count.should == 1
|
148
|
-
@d.first[:name].should == 'def'
|
149
|
-
end
|
150
|
-
|
151
|
-
specify "should be able to literalize booleans" do
|
152
|
-
proc {@d.literal(true)}.should_not raise_error
|
153
|
-
proc {@d.literal(false)}.should_not raise_error
|
114
|
+
after do
|
115
|
+
MYSQL_DB.drop_table(:items)
|
154
116
|
end
|
155
117
|
|
156
118
|
specify "should quote columns and tables using back-ticks if quoting identifiers" do
|
@@ -223,37 +185,6 @@ context "A MySQL dataset" do
|
|
223
185
|
'UPDATE items SET value = 1 LIMIT 10'
|
224
186
|
end
|
225
187
|
|
226
|
-
specify "should support transactions" do
|
227
|
-
MYSQL_DB.transaction do
|
228
|
-
@d << {:name => 'abc', :value => 1}
|
229
|
-
end
|
230
|
-
|
231
|
-
@d.count.should == 1
|
232
|
-
end
|
233
|
-
|
234
|
-
specify "should correctly rollback transactions" do
|
235
|
-
proc do
|
236
|
-
MYSQL_DB.transaction do
|
237
|
-
@d << {:name => 'abc'}
|
238
|
-
raise Interrupt, 'asdf'
|
239
|
-
end
|
240
|
-
end.should raise_error(Interrupt)
|
241
|
-
|
242
|
-
MYSQL_DB.sqls.should == [SQL_BEGIN, "INSERT INTO items (name) VALUES ('abc')", SQL_ROLLBACK]
|
243
|
-
end
|
244
|
-
|
245
|
-
specify "should handle returning inside of the block by committing" do
|
246
|
-
def MYSQL_DB.ret_commit
|
247
|
-
transaction do
|
248
|
-
self[:items] << {:name => 'abc'}
|
249
|
-
return
|
250
|
-
self[:items] << {:name => 'd'}
|
251
|
-
end
|
252
|
-
end
|
253
|
-
MYSQL_DB.ret_commit
|
254
|
-
MYSQL_DB.sqls.should == [SQL_BEGIN, "INSERT INTO items (name) VALUES ('abc')", SQL_COMMIT]
|
255
|
-
end
|
256
|
-
|
257
188
|
specify "should support regexps" do
|
258
189
|
@d << {:name => 'abc', :value => 1}
|
259
190
|
@d << {:name => 'bcd', :value => 2}
|
@@ -273,9 +204,6 @@ context "MySQL datasets" do
|
|
273
204
|
before do
|
274
205
|
@d = MYSQL_DB[:orders]
|
275
206
|
end
|
276
|
-
after do
|
277
|
-
Sequel.convert_tinyint_to_bool = true
|
278
|
-
end
|
279
207
|
|
280
208
|
specify "should correctly quote column references" do
|
281
209
|
@d.quote_identifiers = true
|
@@ -286,30 +214,6 @@ context "MySQL datasets" do
|
|
286
214
|
group_by(:minute.sql_function(:from_unixtime.sql_function(:ack))).sql.should == \
|
287
215
|
"SELECT `market`, minute(from_unixtime(`ack`)) AS `minute` FROM `orders` WHERE ((`ack` > #{@d.literal(ack_stamp)}) AND (`market` = 'ICE')) GROUP BY minute(from_unixtime(`ack`))"
|
288
216
|
end
|
289
|
-
|
290
|
-
specify "should accept and return tinyints as bools or integers when configured to do so" do
|
291
|
-
MYSQL_DB[:booltest].delete
|
292
|
-
MYSQL_DB[:booltest] << {:value=>true}
|
293
|
-
MYSQL_DB[:booltest].all.should == [{:value=>true}]
|
294
|
-
MYSQL_DB[:booltest].delete
|
295
|
-
MYSQL_DB[:booltest] << {:value=>false}
|
296
|
-
MYSQL_DB[:booltest].all.should == [{:value=>false}]
|
297
|
-
|
298
|
-
Sequel.convert_tinyint_to_bool = false
|
299
|
-
MYSQL_DB[:booltest].delete
|
300
|
-
MYSQL_DB[:booltest] << {:value=>true}
|
301
|
-
MYSQL_DB[:booltest].all.should == [{:value=>1}]
|
302
|
-
MYSQL_DB[:booltest].delete
|
303
|
-
MYSQL_DB[:booltest] << {:value=>false}
|
304
|
-
MYSQL_DB[:booltest].all.should == [{:value=>0}]
|
305
|
-
|
306
|
-
MYSQL_DB[:booltest].delete
|
307
|
-
MYSQL_DB[:booltest] << {:value=>1}
|
308
|
-
MYSQL_DB[:booltest].all.should == [{:value=>1}]
|
309
|
-
MYSQL_DB[:booltest].delete
|
310
|
-
MYSQL_DB[:booltest] << {:value=>0}
|
311
|
-
MYSQL_DB[:booltest].all.should == [{:value=>0}]
|
312
|
-
end
|
313
217
|
end
|
314
218
|
|
315
219
|
context "MySQL join expressions" do
|
@@ -454,89 +358,109 @@ context "A MySQL database" do
|
|
454
358
|
end
|
455
359
|
end
|
456
360
|
|
457
|
-
context "A MySQL database
|
458
|
-
before
|
459
|
-
@options = {}
|
460
|
-
@options[:engine] = 'MyISAM'
|
461
|
-
@options[:charset] = 'latin2'
|
462
|
-
@options[:collate] = 'swedish'
|
361
|
+
context "A MySQL database with table options" do
|
362
|
+
before do
|
363
|
+
@options = {:engine=>'MyISAM', :charset=>'latin1', :collate => 'latin1_swedish_ci'}
|
463
364
|
|
464
365
|
Sequel::MySQL.default_engine = 'InnoDB'
|
465
366
|
Sequel::MySQL.default_charset = 'utf8'
|
466
|
-
Sequel::MySQL.default_collate = '
|
367
|
+
Sequel::MySQL.default_collate = 'utf8_general_ci'
|
467
368
|
|
468
369
|
@db = MYSQL_DB
|
469
|
-
@
|
470
|
-
|
471
|
-
|
472
|
-
end
|
370
|
+
@db.drop_table(:items) rescue nil
|
371
|
+
|
372
|
+
MYSQL_DB.sqls.clear
|
473
373
|
end
|
474
|
-
|
475
|
-
|
374
|
+
after do
|
375
|
+
@db.drop_table(:items) rescue nil
|
476
376
|
Sequel::MySQL.default_engine = nil
|
477
377
|
Sequel::MySQL.default_charset = nil
|
478
378
|
Sequel::MySQL.default_collate = nil
|
479
379
|
end
|
480
380
|
|
481
381
|
specify "should allow to pass custom options (engine, charset, collate) for table creation" do
|
482
|
-
|
483
|
-
|
484
|
-
"CREATE TABLE items (size integer, name text) ENGINE=MyISAM DEFAULT CHARSET=latin2 DEFAULT COLLATE=swedish"
|
485
|
-
]
|
382
|
+
@db.create_table(:items, @options){Integer :size; text :name}
|
383
|
+
@db.sqls.should == ["CREATE TABLE items (size integer, name text) ENGINE=MyISAM DEFAULT CHARSET=latin1 DEFAULT COLLATE=latin1_swedish_ci"]
|
486
384
|
end
|
487
385
|
|
488
386
|
specify "should use default options if specified (engine, charset, collate) for table creation" do
|
489
|
-
|
490
|
-
|
491
|
-
"CREATE TABLE items (size integer, name text) ENGINE=InnoDB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8"
|
492
|
-
]
|
387
|
+
@db.create_table(:items){Integer :size; text :name}
|
388
|
+
@db.sqls.should == ["CREATE TABLE items (size integer, name text) ENGINE=InnoDB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci"]
|
493
389
|
end
|
494
390
|
|
495
391
|
specify "should not use default if option has a nil value" do
|
496
|
-
|
497
|
-
|
498
|
-
"CREATE TABLE items (size integer, name text)"
|
499
|
-
]
|
392
|
+
@db.create_table(:items, :engine=>nil, :charset=>nil, :collate=>nil){Integer :size; text :name}
|
393
|
+
@db.sqls.should == ["CREATE TABLE items (size integer, name text)"]
|
500
394
|
end
|
501
395
|
end
|
502
396
|
|
503
397
|
context "A MySQL database" do
|
504
398
|
before do
|
505
399
|
@db = MYSQL_DB
|
400
|
+
@db.drop_table(:items) rescue nil
|
401
|
+
MYSQL_DB.sqls.clear
|
402
|
+
end
|
403
|
+
after do
|
404
|
+
@db.drop_table(:items) rescue nil
|
506
405
|
end
|
507
406
|
|
508
407
|
specify "should support defaults for boolean columns" do
|
509
|
-
|
510
|
-
|
511
|
-
boolean :active2, :default => false
|
512
|
-
end
|
513
|
-
statements = @db.send(:create_table_sql_list, :items, *g.create_info)
|
514
|
-
statements.should == [
|
515
|
-
"CREATE TABLE items (active1 boolean DEFAULT 1, active2 boolean DEFAULT 0)"
|
516
|
-
]
|
408
|
+
@db.create_table(:items){TrueClass :active1, :default=>true; FalseClass :active2, :default => false}
|
409
|
+
@db.sqls.should == ["CREATE TABLE items (active1 tinyint DEFAULT 1, active2 tinyint DEFAULT 0)"]
|
517
410
|
end
|
518
411
|
|
519
412
|
specify "should correctly format CREATE TABLE statements with foreign keys" do
|
520
|
-
|
521
|
-
|
522
|
-
:null => false, :on_delete => :cascade
|
523
|
-
end
|
524
|
-
@db.send(:create_table_sql_list, :items, *g.create_info).should == [
|
525
|
-
"CREATE TABLE items (p_id integer NOT NULL, FOREIGN KEY (p_id) REFERENCES users(id) ON DELETE CASCADE)"
|
526
|
-
]
|
413
|
+
@db.create_table(:items){Integer :id; foreign_key :p_id, :items, :key => :id, :null => false, :on_delete => :cascade}
|
414
|
+
@db.sqls.should == ["CREATE TABLE items (id integer, p_id integer NOT NULL, FOREIGN KEY (p_id) REFERENCES items(id) ON DELETE CASCADE)"]
|
527
415
|
end
|
528
416
|
|
529
|
-
specify "should correctly format ALTER TABLE statements with foreign keys" do
|
530
|
-
|
531
|
-
add_foreign_key :p_id, :users, :key => :id, :null => false, :on_delete => :cascade
|
417
|
+
specify "should correctly format ALTER TABLE statements with foreign keys" do
|
418
|
+
@db.create_table(:items){Integer :id}
|
419
|
+
@db.alter_table(:items){add_foreign_key :p_id, :users, :key => :id, :null => false, :on_delete => :cascade}
|
420
|
+
@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"]
|
421
|
+
end
|
422
|
+
|
423
|
+
specify "should have rename_column support keep existing options" do
|
424
|
+
@db.create_table(:items){Integer :id, :null=>false, :default=>5}
|
425
|
+
@db.alter_table(:items){rename_column :id, :nid}
|
426
|
+
@db.sqls.should == ["CREATE TABLE items (id integer NOT NULL DEFAULT 5)", "DESCRIBE items", "ALTER TABLE items CHANGE COLUMN id nid int(11) NOT NULL DEFAULT 5"]
|
427
|
+
@db[:items].insert
|
428
|
+
@db[:items].all.should == [{:nid=>5}]
|
429
|
+
proc{@db[:items].insert(:nid=>nil)}.should raise_error(Sequel::DatabaseError)
|
430
|
+
end
|
431
|
+
|
432
|
+
specify "should have set_column_type support keep existing options" do
|
433
|
+
@db.create_table(:items){Integer :id, :null=>false, :default=>5}
|
434
|
+
@db.alter_table(:items){set_column_type :id, Bignum}
|
435
|
+
@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"]
|
436
|
+
@db[:items].insert
|
437
|
+
@db[:items].all.should == [{:id=>5}]
|
438
|
+
proc{@db[:items].insert(:id=>nil)}.should raise_error(Sequel::DatabaseError)
|
439
|
+
@db[:items].delete
|
440
|
+
@db[:items].insert(2**40)
|
441
|
+
@db[:items].all.should == [{:id=>2**40}]
|
442
|
+
end
|
443
|
+
|
444
|
+
specify "should have set_column_default support keep existing options" do
|
445
|
+
@db.create_table(:items){Integer :id, :null=>false, :default=>5}
|
446
|
+
@db.alter_table(:items){set_column_default :id, 6}
|
447
|
+
@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"]
|
448
|
+
@db[:items].insert
|
449
|
+
@db[:items].all.should == [{:id=>6}]
|
450
|
+
proc{@db[:items].insert(:id=>nil)}.should raise_error(Sequel::DatabaseError)
|
451
|
+
end
|
452
|
+
|
453
|
+
specify "should have set_column_allow_null support keep existing options" do
|
454
|
+
@db.create_table(:items){Integer :id, :null=>false, :default=>5}
|
455
|
+
@db.alter_table(:items){set_column_allow_null :id, true}
|
456
|
+
@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"]
|
457
|
+
@db[:items].insert
|
458
|
+
@db[:items].all.should == [{:id=>5}]
|
459
|
+
proc{@db[:items].insert(:id=>nil)}.should_not
|
532
460
|
end
|
533
|
-
@db.send(:alter_table_sql_list, :items, g.operations).should == [[
|
534
|
-
"ALTER TABLE items ADD COLUMN p_id integer NOT NULL",
|
535
|
-
"ALTER TABLE items ADD FOREIGN KEY (p_id) REFERENCES users(id) ON DELETE CASCADE"
|
536
|
-
]]
|
537
|
-
end
|
538
461
|
|
539
462
|
specify "should accept repeated raw sql statements using Database#<<" do
|
463
|
+
@db.create_table(:items){String :name; Integer :value}
|
540
464
|
@db << 'DELETE FROM items'
|
541
465
|
@db[:items].count.should == 0
|
542
466
|
|
@@ -548,8 +472,7 @@ end
|
|
548
472
|
end
|
549
473
|
|
550
474
|
specify "should handle multiple select statements at once" do
|
551
|
-
@db
|
552
|
-
|
475
|
+
@db.create_table(:items){String :name; Integer :value}
|
553
476
|
@db[:items].delete
|
554
477
|
@db[:items].insert(:name => 'tutu', :value => 1234)
|
555
478
|
@db["SELECT * FROM items; SELECT * FROM items"].all.should == \
|
@@ -600,71 +523,73 @@ context "A grouped MySQL dataset" do
|
|
600
523
|
end
|
601
524
|
|
602
525
|
context "A MySQL database" do
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
526
|
+
before do
|
527
|
+
@db = MYSQL_DB
|
528
|
+
@db.drop_table(:posts) rescue nil
|
529
|
+
@db.sqls.clear
|
530
|
+
end
|
531
|
+
after do
|
532
|
+
@db.drop_table(:posts) rescue nil
|
533
|
+
end
|
534
|
+
|
535
|
+
specify "should support fulltext indexes and full_text_search" do
|
536
|
+
@db.create_table(:posts){text :title; text :body; full_text_index :title; full_text_index [:title, :body]}
|
537
|
+
@db.sqls.should == [
|
610
538
|
"CREATE TABLE posts (title text, body text)",
|
539
|
+
"CREATE FULLTEXT INDEX posts_title_index ON posts (title)",
|
611
540
|
"CREATE FULLTEXT INDEX posts_title_body_index ON posts (title, body)"
|
612
541
|
]
|
613
|
-
end
|
614
|
-
|
615
|
-
specify "should support full_text_search" do
|
616
|
-
MYSQL_DB[:posts].full_text_search(:title, 'ruby').sql.should ==
|
617
|
-
"SELECT * FROM posts WHERE (MATCH (title) AGAINST ('ruby'))"
|
618
542
|
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
543
|
+
@db[:posts].insert(:title=>'ruby rails', :body=>'y')
|
544
|
+
@db[:posts].insert(:title=>'sequel', :body=>'ruby')
|
545
|
+
@db[:posts].insert(:title=>'ruby scooby', :body=>'x')
|
546
|
+
@db.sqls.clear
|
547
|
+
|
548
|
+
@db[:posts].full_text_search(:title, 'rails').all.should == [{:title=>'ruby rails', :body=>'y'}]
|
549
|
+
@db[:posts].full_text_search([:title, :body], ['sequel', 'ruby']).all.should == [{:title=>'sequel', :body=>'ruby'}]
|
550
|
+
@db[:posts].full_text_search(:title, '+ruby -rails', :boolean => true).all.should == [{:title=>'ruby scooby', :body=>'x'}]
|
551
|
+
@db.sqls.should == [
|
552
|
+
"SELECT * FROM posts WHERE (MATCH (title) AGAINST ('rails'))",
|
553
|
+
"SELECT * FROM posts WHERE (MATCH (title, body) AGAINST ('sequel ruby'))",
|
554
|
+
"SELECT * FROM posts WHERE (MATCH (title) AGAINST ('+ruby -rails' IN BOOLEAN MODE))"]
|
624
555
|
end
|
625
556
|
|
626
557
|
specify "should support spatial indexes" do
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
end
|
631
|
-
MYSQL_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [
|
632
|
-
"CREATE TABLE posts (geom point)",
|
558
|
+
@db.create_table(:posts){point :geom, :null=>false; spatial_index [:geom]}
|
559
|
+
@db.sqls.should == [
|
560
|
+
"CREATE TABLE posts (geom point NOT NULL)",
|
633
561
|
"CREATE SPATIAL INDEX posts_geom_index ON posts (geom)"
|
634
562
|
]
|
635
563
|
end
|
636
564
|
|
637
565
|
specify "should support indexes with index type" do
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
MYSQL_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [
|
643
|
-
"CREATE TABLE posts (title text)",
|
644
|
-
"CREATE INDEX posts_title_index ON posts (title) USING hash"
|
566
|
+
@db.create_table(:posts){Integer :id; index :id, :type => :btree}
|
567
|
+
@db.sqls.should == [
|
568
|
+
"CREATE TABLE posts (id integer)",
|
569
|
+
"CREATE INDEX posts_id_index USING btree ON posts (id)"
|
645
570
|
]
|
646
571
|
end
|
647
572
|
|
648
573
|
specify "should support unique indexes with index type" do
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
MYSQL_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [
|
654
|
-
"CREATE TABLE posts (title text)",
|
655
|
-
"CREATE UNIQUE INDEX posts_title_index ON posts (title) USING hash"
|
574
|
+
@db.create_table(:posts){Integer :id; index :id, :type => :btree, :unique => true}
|
575
|
+
@db.sqls.should == [
|
576
|
+
"CREATE TABLE posts (id integer)",
|
577
|
+
"CREATE UNIQUE INDEX posts_id_index USING btree ON posts (id)"
|
656
578
|
]
|
657
579
|
end
|
658
580
|
end
|
659
581
|
|
660
|
-
context "MySQL::Dataset#insert" do
|
582
|
+
context "MySQL::Dataset#insert and related methods" do
|
661
583
|
before do
|
584
|
+
MYSQL_DB.create_table(:items){String :name; Integer :value}
|
662
585
|
@d = MYSQL_DB[:items]
|
663
|
-
@d.delete
|
664
586
|
MYSQL_DB.sqls.clear
|
665
587
|
end
|
588
|
+
after do
|
589
|
+
MYSQL_DB.drop_table(:items)
|
590
|
+
end
|
666
591
|
|
667
|
-
specify "should insert record with default values when no arguments given" do
|
592
|
+
specify "#insert should insert record with default values when no arguments given" do
|
668
593
|
@d.insert
|
669
594
|
|
670
595
|
MYSQL_DB.sqls.should == [
|
@@ -676,7 +601,7 @@ context "MySQL::Dataset#insert" do
|
|
676
601
|
]
|
677
602
|
end
|
678
603
|
|
679
|
-
specify "should insert record with default values when empty hash given" do
|
604
|
+
specify "#insert should insert record with default values when empty hash given" do
|
680
605
|
@d.insert({})
|
681
606
|
|
682
607
|
MYSQL_DB.sqls.should == [
|
@@ -688,7 +613,7 @@ context "MySQL::Dataset#insert" do
|
|
688
613
|
]
|
689
614
|
end
|
690
615
|
|
691
|
-
specify "should insert record with default values when empty array given" do
|
616
|
+
specify "#insert should insert record with default values when empty array given" do
|
692
617
|
@d.insert []
|
693
618
|
|
694
619
|
MYSQL_DB.sqls.should == [
|
@@ -699,16 +624,8 @@ context "MySQL::Dataset#insert" do
|
|
699
624
|
{:name => nil, :value => nil}
|
700
625
|
]
|
701
626
|
end
|
702
|
-
end
|
703
627
|
|
704
|
-
|
705
|
-
before do
|
706
|
-
@d = MYSQL_DB[:items]
|
707
|
-
@d.delete
|
708
|
-
MYSQL_DB.sqls.clear
|
709
|
-
end
|
710
|
-
|
711
|
-
specify "should insert multiple records in a single statement" do
|
628
|
+
specify "#multi_insert should insert multiple records in a single statement" do
|
712
629
|
@d.multi_insert([{:name => 'abc'}, {:name => 'def'}])
|
713
630
|
|
714
631
|
MYSQL_DB.sqls.should == [
|
@@ -722,7 +639,7 @@ context "MySQL::Dataset#multi_insert" do
|
|
722
639
|
]
|
723
640
|
end
|
724
641
|
|
725
|
-
specify "should split the list of records into batches if :commit_every option is given" do
|
642
|
+
specify "#multi_insert should split the list of records into batches if :commit_every option is given" do
|
726
643
|
@d.multi_insert([{:value => 1}, {:value => 2}, {:value => 3}, {:value => 4}],
|
727
644
|
:commit_every => 2)
|
728
645
|
|
@@ -743,7 +660,7 @@ context "MySQL::Dataset#multi_insert" do
|
|
743
660
|
]
|
744
661
|
end
|
745
662
|
|
746
|
-
specify "should split the list of records into batches if :slice option is given" do
|
663
|
+
specify "#multi_insert should split the list of records into batches if :slice option is given" do
|
747
664
|
@d.multi_insert([{:value => 1}, {:value => 2}, {:value => 3}, {:value => 4}],
|
748
665
|
:slice => 2)
|
749
666
|
|
@@ -764,7 +681,7 @@ context "MySQL::Dataset#multi_insert" do
|
|
764
681
|
]
|
765
682
|
end
|
766
683
|
|
767
|
-
specify "should support inserting using columns and values arrays" do
|
684
|
+
specify "#import should support inserting using columns and values arrays" do
|
768
685
|
@d.import([:name, :value], [['abc', 1], ['def', 2]])
|
769
686
|
|
770
687
|
MYSQL_DB.sqls.should == [
|
@@ -778,16 +695,8 @@ context "MySQL::Dataset#multi_insert" do
|
|
778
695
|
{:name => 'def', :value => 2}
|
779
696
|
]
|
780
697
|
end
|
781
|
-
end
|
782
|
-
|
783
|
-
context "MySQL::Dataset#insert_ignore" do
|
784
|
-
before do
|
785
|
-
@d = MYSQL_DB[:items]
|
786
|
-
@d.delete
|
787
|
-
MYSQL_DB.sqls.clear
|
788
|
-
end
|
789
698
|
|
790
|
-
specify "should add the IGNORE keyword when inserting" do
|
699
|
+
specify "#insert_ignore should add the IGNORE keyword when inserting" do
|
791
700
|
@d.insert_ignore.multi_insert([{:name => 'abc'}, {:name => 'def'}])
|
792
701
|
|
793
702
|
MYSQL_DB.sqls.should == [
|
@@ -800,16 +709,8 @@ context "MySQL::Dataset#insert_ignore" do
|
|
800
709
|
{:name => 'abc', :value => nil}, {:name => 'def', :value => nil}
|
801
710
|
]
|
802
711
|
end
|
803
|
-
end
|
804
|
-
|
805
|
-
context "MySQL::Dataset#on_duplicate_key_update" do
|
806
|
-
before do
|
807
|
-
@d = MYSQL_DB[:items]
|
808
|
-
@d.delete
|
809
|
-
MYSQL_DB.sqls.clear
|
810
|
-
end
|
811
712
|
|
812
|
-
specify "should add the ON DUPLICATE KEY UPDATE and ALL columns when no args given" do
|
713
|
+
specify "#on_duplicate_key_update should add the ON DUPLICATE KEY UPDATE and ALL columns when no args given" do
|
813
714
|
@d.on_duplicate_key_update.import([:name,:value],
|
814
715
|
[['abc', 1], ['def',2]]
|
815
716
|
)
|
@@ -824,7 +725,8 @@ context "MySQL::Dataset#on_duplicate_key_update" do
|
|
824
725
|
{:name => 'abc', :value => 1}, {:name => 'def', :value => 2}
|
825
726
|
]
|
826
727
|
end
|
827
|
-
|
728
|
+
|
729
|
+
specify "#on_duplicate_key_update should add the ON DUPLICATE KEY UPDATE and columns specified when args are given" do
|
828
730
|
@d.on_duplicate_key_update(:value).import([:name,:value],
|
829
731
|
[['abc', 1], ['def',2]]
|
830
732
|
)
|
@@ -844,14 +746,13 @@ end
|
|
844
746
|
|
845
747
|
context "MySQL::Dataset#replace" do
|
846
748
|
before do
|
847
|
-
MYSQL_DB.
|
848
|
-
MYSQL_DB.create_table :items do
|
849
|
-
integer :id, :unique => true
|
850
|
-
integer :value, :index => true
|
851
|
-
end
|
749
|
+
MYSQL_DB.create_table(:items){Integer :id, :unique=>true; Integer :value}
|
852
750
|
@d = MYSQL_DB[:items]
|
853
751
|
MYSQL_DB.sqls.clear
|
854
752
|
end
|
753
|
+
after do
|
754
|
+
MYSQL_DB.drop_table(:items)
|
755
|
+
end
|
855
756
|
|
856
757
|
specify "should create a record if the condition is not met" do
|
857
758
|
@d.replace(:id => 111, :value => 333)
|
@@ -896,7 +797,13 @@ end
|
|
896
797
|
|
897
798
|
unless MYSQL_DB.class.adapter_scheme == :do
|
898
799
|
context "MySQL Stored Procedures" do
|
800
|
+
before do
|
801
|
+
MYSQL_DB.create_table(:items){Integer :id; Integer :value}
|
802
|
+
@d = MYSQL_DB[:items]
|
803
|
+
MYSQL_DB.sqls.clear
|
804
|
+
end
|
899
805
|
after do
|
806
|
+
MYSQL_DB.drop_table(:items)
|
900
807
|
MYSQL_DB.execute('DROP PROCEDURE test_sproc')
|
901
808
|
end
|
902
809
|
|