sequel_core 2.2.0 → 3.8.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.
- metadata +30 -101
- data/CHANGELOG +0 -1519
- data/COPYING +0 -19
- data/README +0 -313
- data/Rakefile +0 -158
- data/bin/sequel +0 -117
- data/doc/cheat_sheet.rdoc +0 -225
- data/doc/dataset_filtering.rdoc +0 -182
- data/lib/sequel_core.rb +0 -136
- data/lib/sequel_core/adapters/adapter_skeleton.rb +0 -68
- data/lib/sequel_core/adapters/ado.rb +0 -90
- data/lib/sequel_core/adapters/db2.rb +0 -160
- data/lib/sequel_core/adapters/dbi.rb +0 -127
- data/lib/sequel_core/adapters/informix.rb +0 -89
- data/lib/sequel_core/adapters/jdbc.rb +0 -110
- data/lib/sequel_core/adapters/mysql.rb +0 -486
- data/lib/sequel_core/adapters/odbc.rb +0 -167
- data/lib/sequel_core/adapters/odbc_mssql.rb +0 -106
- data/lib/sequel_core/adapters/openbase.rb +0 -76
- data/lib/sequel_core/adapters/oracle.rb +0 -182
- data/lib/sequel_core/adapters/postgres.rb +0 -560
- data/lib/sequel_core/adapters/sqlite.rb +0 -270
- data/lib/sequel_core/connection_pool.rb +0 -194
- data/lib/sequel_core/core_ext.rb +0 -197
- data/lib/sequel_core/core_sql.rb +0 -184
- data/lib/sequel_core/database.rb +0 -462
- data/lib/sequel_core/database/schema.rb +0 -156
- data/lib/sequel_core/dataset.rb +0 -457
- data/lib/sequel_core/dataset/callback.rb +0 -13
- data/lib/sequel_core/dataset/convenience.rb +0 -245
- data/lib/sequel_core/dataset/pagination.rb +0 -96
- data/lib/sequel_core/dataset/query.rb +0 -41
- data/lib/sequel_core/dataset/schema.rb +0 -15
- data/lib/sequel_core/dataset/sql.rb +0 -889
- data/lib/sequel_core/deprecated.rb +0 -26
- data/lib/sequel_core/exceptions.rb +0 -42
- data/lib/sequel_core/migration.rb +0 -187
- data/lib/sequel_core/object_graph.rb +0 -216
- data/lib/sequel_core/pretty_table.rb +0 -71
- data/lib/sequel_core/schema.rb +0 -2
- data/lib/sequel_core/schema/generator.rb +0 -239
- data/lib/sequel_core/schema/sql.rb +0 -326
- data/lib/sequel_core/sql.rb +0 -812
- data/lib/sequel_core/worker.rb +0 -68
- data/spec/adapters/informix_spec.rb +0 -96
- data/spec/adapters/mysql_spec.rb +0 -765
- data/spec/adapters/oracle_spec.rb +0 -222
- data/spec/adapters/postgres_spec.rb +0 -441
- data/spec/adapters/sqlite_spec.rb +0 -413
- data/spec/connection_pool_spec.rb +0 -363
- data/spec/core_ext_spec.rb +0 -156
- data/spec/core_sql_spec.rb +0 -427
- data/spec/database_spec.rb +0 -963
- data/spec/dataset_spec.rb +0 -2933
- data/spec/expression_filters_spec.rb +0 -316
- data/spec/migration_spec.rb +0 -261
- data/spec/object_graph_spec.rb +0 -230
- data/spec/pretty_table_spec.rb +0 -58
- data/spec/rcov.opts +0 -6
- data/spec/schema_generator_spec.rb +0 -122
- data/spec/schema_spec.rb +0 -422
- data/spec/spec.opts +0 -0
- data/spec/spec_config.rb +0 -7
- data/spec/spec_config.rb.example +0 -8
- data/spec/spec_helper.rb +0 -55
- data/spec/worker_spec.rb +0 -96
data/lib/sequel_core/worker.rb
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
module Sequel
|
2
|
-
# A Worker is a thread that accepts jobs off a work queue and
|
3
|
-
# processes them in the background. It accepts an optional
|
4
|
-
# database where it wruns all of its work inside a transaction.
|
5
|
-
class Worker < Thread
|
6
|
-
attr_reader :queue
|
7
|
-
attr_reader :errors
|
8
|
-
|
9
|
-
# Setup the interal variables. If a database is given,
|
10
|
-
# run the thread inside a database transaction. Continue
|
11
|
-
# to work until #join is called.
|
12
|
-
def initialize(db = nil)
|
13
|
-
@queue = Queue.new
|
14
|
-
@errors = []
|
15
|
-
t = self
|
16
|
-
t.abort_on_exception = true
|
17
|
-
@transaction = !db.nil?
|
18
|
-
db ? super {db.transaction {t.work}} : super {t.work}
|
19
|
-
end
|
20
|
-
|
21
|
-
# Add a job to the queue, specified either as a proc argument
|
22
|
-
# or as a block.
|
23
|
-
def async(proc = nil, &block)
|
24
|
-
@queue << (proc || block)
|
25
|
-
self
|
26
|
-
end
|
27
|
-
alias_method :add, :async
|
28
|
-
alias_method :<<, :async
|
29
|
-
|
30
|
-
# Whether the worker is actively working and/or has work scheduled
|
31
|
-
def busy?
|
32
|
-
@cur || !@queue.empty?
|
33
|
-
end
|
34
|
-
|
35
|
-
# Wait until the worker is no longer busy and then stop working.
|
36
|
-
def join
|
37
|
-
sleep(0.1) while busy?
|
38
|
-
self.raise Error::WorkerStop
|
39
|
-
super
|
40
|
-
end
|
41
|
-
|
42
|
-
# Continually get jobs from the work queue and process them.
|
43
|
-
def work
|
44
|
-
begin
|
45
|
-
loop {next_job}
|
46
|
-
rescue Sequel::Error::WorkerStop # signals the worker thread to stop
|
47
|
-
ensure
|
48
|
-
raise Sequel::Error::Rollback if @transaction && !@errors.empty?
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
|
-
|
54
|
-
# Get the next job from the work queue and process it.
|
55
|
-
def next_job
|
56
|
-
begin
|
57
|
-
@cur = @queue.pop
|
58
|
-
@cur.call
|
59
|
-
rescue Error::WorkerStop => e
|
60
|
-
raise e
|
61
|
-
rescue Exception => e
|
62
|
-
@errors << e
|
63
|
-
ensure
|
64
|
-
@cur = nil
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
@@ -1,96 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), '../spec_helper.rb')
|
2
|
-
|
3
|
-
unless defined?(INFORMIX_DB)
|
4
|
-
INFORMIX_DB = Sequel.connect('informix://localhost/mydb')
|
5
|
-
end
|
6
|
-
|
7
|
-
if INFORMIX_DB.table_exists?(:test)
|
8
|
-
INFORMIX_DB.drop_table :test
|
9
|
-
end
|
10
|
-
INFORMIX_DB.create_table :test do
|
11
|
-
text :name
|
12
|
-
integer :value
|
13
|
-
|
14
|
-
index :value
|
15
|
-
end
|
16
|
-
|
17
|
-
context "A Informix database" do
|
18
|
-
specify "should provide disconnect functionality" do
|
19
|
-
INFORMIX_DB.execute("select user from dual")
|
20
|
-
INFORMIX_DB.pool.size.should == 1
|
21
|
-
INFORMIX_DB.disconnect
|
22
|
-
INFORMIX_DB.pool.size.should == 0
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
context "A Informix dataset" do
|
27
|
-
setup do
|
28
|
-
@d = INFORMIX_DB[:test]
|
29
|
-
@d.delete # remove all records
|
30
|
-
end
|
31
|
-
|
32
|
-
specify "should return the correct record count" do
|
33
|
-
@d.count.should == 0
|
34
|
-
@d << {:name => 'abc', :value => 123}
|
35
|
-
@d << {:name => 'abc', :value => 456}
|
36
|
-
@d << {:name => 'def', :value => 789}
|
37
|
-
@d.count.should == 3
|
38
|
-
end
|
39
|
-
|
40
|
-
specify "should return the correct records" do
|
41
|
-
@d.to_a.should == []
|
42
|
-
@d << {:name => 'abc', :value => 123}
|
43
|
-
@d << {:name => 'abc', :value => 456}
|
44
|
-
@d << {:name => 'def', :value => 789}
|
45
|
-
|
46
|
-
@d.order(:value).to_a.should == [
|
47
|
-
{:name => 'abc', :value => 123},
|
48
|
-
{:name => 'abc', :value => 456},
|
49
|
-
{:name => 'def', :value => 789}
|
50
|
-
]
|
51
|
-
end
|
52
|
-
|
53
|
-
specify "should update records correctly" do
|
54
|
-
@d << {:name => 'abc', :value => 123}
|
55
|
-
@d << {:name => 'abc', :value => 456}
|
56
|
-
@d << {:name => 'def', :value => 789}
|
57
|
-
@d.filter(:name => 'abc').update(:value => 530)
|
58
|
-
|
59
|
-
# the third record should stay the same
|
60
|
-
# floating-point precision bullshit
|
61
|
-
@d[:name => 'def'][:value].should == 789
|
62
|
-
@d.filter(:value => 530).count.should == 2
|
63
|
-
end
|
64
|
-
|
65
|
-
specify "should delete records correctly" do
|
66
|
-
@d << {:name => 'abc', :value => 123}
|
67
|
-
@d << {:name => 'abc', :value => 456}
|
68
|
-
@d << {:name => 'def', :value => 789}
|
69
|
-
@d.filter(:name => 'abc').delete
|
70
|
-
|
71
|
-
@d.count.should == 1
|
72
|
-
@d.first[:name].should == 'def'
|
73
|
-
end
|
74
|
-
|
75
|
-
specify "should be able to literalize booleans" do
|
76
|
-
proc {@d.literal(true)}.should_not raise_error
|
77
|
-
proc {@d.literal(false)}.should_not raise_error
|
78
|
-
end
|
79
|
-
|
80
|
-
specify "should support transactions" do
|
81
|
-
INFORMIX_DB.transaction do
|
82
|
-
@d << {:name => 'abc', :value => 1}
|
83
|
-
end
|
84
|
-
|
85
|
-
@d.count.should == 1
|
86
|
-
end
|
87
|
-
|
88
|
-
specify "should support #first and #last" do
|
89
|
-
@d << {:name => 'abc', :value => 123}
|
90
|
-
@d << {:name => 'abc', :value => 456}
|
91
|
-
@d << {:name => 'def', :value => 789}
|
92
|
-
|
93
|
-
@d.order(:value).first.should == {:name => 'abc', :value => 123}
|
94
|
-
@d.order(:value).last.should == {:name => 'def', :value => 789}
|
95
|
-
end
|
96
|
-
end
|
data/spec/adapters/mysql_spec.rb
DELETED
@@ -1,765 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), '../spec_helper.rb')
|
2
|
-
|
3
|
-
unless defined?(MYSQL_USER)
|
4
|
-
MYSQL_USER = 'root'
|
5
|
-
end
|
6
|
-
unless defined?(MYSQL_DB)
|
7
|
-
MYSQL_URL = (ENV['SEQUEL_MY_SPEC_DB']||"mysql://#{MYSQL_USER}@localhost/sandbox") unless defined? MYSQL_URL
|
8
|
-
MYSQL_DB = Sequel.connect(MYSQL_URL)
|
9
|
-
end
|
10
|
-
unless defined?(MYSQL_SOCKET_FILE)
|
11
|
-
MYSQL_SOCKET_FILE = '/tmp/mysql.sock'
|
12
|
-
end
|
13
|
-
|
14
|
-
MYSQL_URI = URI.parse(MYSQL_DB.uri)
|
15
|
-
MYSQL_DB_NAME = (m = /\/(.*)/.match(MYSQL_URI.path)) && m[1]
|
16
|
-
|
17
|
-
MYSQL_DB.create_table! :items do
|
18
|
-
text :name
|
19
|
-
integer :value, :index => true
|
20
|
-
end
|
21
|
-
MYSQL_DB.create_table! :test2 do
|
22
|
-
text :name
|
23
|
-
integer :value
|
24
|
-
end
|
25
|
-
MYSQL_DB.create_table! :booltest do
|
26
|
-
tinyint :value
|
27
|
-
end
|
28
|
-
class Sequel::MySQL::Database
|
29
|
-
attr_accessor :sqls
|
30
|
-
end
|
31
|
-
logger = Object.new
|
32
|
-
def logger.method_missing(m, msg)
|
33
|
-
MYSQL_DB.sqls << msg
|
34
|
-
end
|
35
|
-
MYSQL_DB.logger = logger
|
36
|
-
MYSQL_DB.sqls = []
|
37
|
-
|
38
|
-
context "A MySQL database" do
|
39
|
-
setup do
|
40
|
-
@db = MYSQL_DB
|
41
|
-
end
|
42
|
-
teardown do
|
43
|
-
Sequel.convert_tinyint_to_bool = true
|
44
|
-
end
|
45
|
-
|
46
|
-
specify "should provide disconnect functionality" do
|
47
|
-
@db.tables
|
48
|
-
@db.pool.size.should == 1
|
49
|
-
@db.disconnect
|
50
|
-
@db.pool.size.should == 0
|
51
|
-
end
|
52
|
-
|
53
|
-
specify "should provide the server version" do
|
54
|
-
@db.server_version.should >= 40000
|
55
|
-
end
|
56
|
-
|
57
|
-
specify "should support sequential primary keys" do
|
58
|
-
@db.create_table!(:with_pk) {primary_key :id; text :name}
|
59
|
-
@db[:with_pk] << {:name => 'abc'}
|
60
|
-
@db[:with_pk] << {:name => 'def'}
|
61
|
-
@db[:with_pk] << {:name => 'ghi'}
|
62
|
-
@db[:with_pk].order(:name).all.should == [
|
63
|
-
{:id => 1, :name => 'abc'},
|
64
|
-
{:id => 2, :name => 'def'},
|
65
|
-
{:id => 3, :name => 'ghi'}
|
66
|
-
]
|
67
|
-
end
|
68
|
-
|
69
|
-
specify "should convert Mysql::Errors to Sequel::Errors" do
|
70
|
-
proc{@db << "SELECT 1 + blah;"}.should raise_error(Sequel::Error)
|
71
|
-
end
|
72
|
-
|
73
|
-
specify "should correctly parse the schema" do
|
74
|
-
@db.schema(:booltest, :reload=>true).should == [[:value, {:type=>:boolean, :allow_null=>true, :max_chars=>nil, :default=>nil, :db_type=>"tinyint", :numeric_precision=>3}]]
|
75
|
-
|
76
|
-
Sequel.convert_tinyint_to_bool = false
|
77
|
-
@db.schema(:booltest, :reload=>true).should == [[:value, {:type=>:integer, :allow_null=>true, :max_chars=>nil, :default=>nil, :db_type=>"tinyint", :numeric_precision=>3}]]
|
78
|
-
end
|
79
|
-
|
80
|
-
specify "should get the schema all database tables if no table name is used" do
|
81
|
-
@db.schema(:booltest, :reload=>true).should == @db.schema(nil, :reload=>true)[:booltest]
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
context "A MySQL dataset" do
|
86
|
-
setup do
|
87
|
-
@d = MYSQL_DB[:items]
|
88
|
-
@d.delete # remove all records
|
89
|
-
MYSQL_DB.sqls.clear
|
90
|
-
end
|
91
|
-
|
92
|
-
specify "should return the correct record count" do
|
93
|
-
@d.count.should == 0
|
94
|
-
@d << {:name => 'abc', :value => 123}
|
95
|
-
@d << {:name => 'abc', :value => 456}
|
96
|
-
@d << {:name => 'def', :value => 789}
|
97
|
-
@d.count.should == 3
|
98
|
-
end
|
99
|
-
|
100
|
-
specify "should return the correct records" do
|
101
|
-
@d.to_a.should == []
|
102
|
-
@d << {:name => 'abc', :value => 123}
|
103
|
-
@d << {:name => 'abc', :value => 456}
|
104
|
-
@d << {:name => 'def', :value => 789}
|
105
|
-
|
106
|
-
@d.order(:value).to_a.should == [
|
107
|
-
{:name => 'abc', :value => 123},
|
108
|
-
{:name => 'abc', :value => 456},
|
109
|
-
{:name => 'def', :value => 789}
|
110
|
-
]
|
111
|
-
end
|
112
|
-
|
113
|
-
specify "should update records correctly" do
|
114
|
-
@d << {:name => 'abc', :value => 123}
|
115
|
-
@d << {:name => 'abc', :value => 456}
|
116
|
-
@d << {:name => 'def', :value => 789}
|
117
|
-
@d.filter(:name => 'abc').update(:value => 530)
|
118
|
-
|
119
|
-
# the third record should stay the same
|
120
|
-
# floating-point precision bullshit
|
121
|
-
@d[:name => 'def'][:value].should == 789
|
122
|
-
@d.filter(:value => 530).count.should == 2
|
123
|
-
end
|
124
|
-
|
125
|
-
specify "should delete records correctly" do
|
126
|
-
@d << {:name => 'abc', :value => 123}
|
127
|
-
@d << {:name => 'abc', :value => 456}
|
128
|
-
@d << {:name => 'def', :value => 789}
|
129
|
-
@d.filter(:name => 'abc').delete
|
130
|
-
|
131
|
-
@d.count.should == 1
|
132
|
-
@d.first[:name].should == 'def'
|
133
|
-
end
|
134
|
-
|
135
|
-
specify "should be able to literalize booleans" do
|
136
|
-
proc {@d.literal(true)}.should_not raise_error
|
137
|
-
proc {@d.literal(false)}.should_not raise_error
|
138
|
-
end
|
139
|
-
|
140
|
-
specify "should quote columns and tables using back-ticks if quoting identifiers" do
|
141
|
-
@d.quote_identifiers = true
|
142
|
-
@d.select(:name).sql.should == \
|
143
|
-
'SELECT `name` FROM `items`'
|
144
|
-
|
145
|
-
@d.select('COUNT(*)'.lit).sql.should == \
|
146
|
-
'SELECT COUNT(*) FROM `items`'
|
147
|
-
|
148
|
-
@d.select(:max[:value]).sql.should == \
|
149
|
-
'SELECT max(`value`) FROM `items`'
|
150
|
-
|
151
|
-
@d.select(:NOW[]).sql.should == \
|
152
|
-
'SELECT NOW() FROM `items`'
|
153
|
-
|
154
|
-
@d.select(:max[:items__value]).sql.should == \
|
155
|
-
'SELECT max(`items`.`value`) FROM `items`'
|
156
|
-
|
157
|
-
@d.order(:name.desc).sql.should == \
|
158
|
-
'SELECT * FROM `items` ORDER BY `name` DESC'
|
159
|
-
|
160
|
-
@d.select('items.name AS item_name'.lit).sql.should == \
|
161
|
-
'SELECT items.name AS item_name FROM `items`'
|
162
|
-
|
163
|
-
@d.select('`name`'.lit).sql.should == \
|
164
|
-
'SELECT `name` FROM `items`'
|
165
|
-
|
166
|
-
@d.select('max(items.`name`) AS `max_name`'.lit).sql.should == \
|
167
|
-
'SELECT max(items.`name`) AS `max_name` FROM `items`'
|
168
|
-
|
169
|
-
@d.select(:test[:abc, 'hello']).sql.should == \
|
170
|
-
"SELECT test(`abc`, 'hello') FROM `items`"
|
171
|
-
|
172
|
-
@d.select(:test[:abc__def, 'hello']).sql.should == \
|
173
|
-
"SELECT test(`abc`.`def`, 'hello') FROM `items`"
|
174
|
-
|
175
|
-
@d.select(:test[:abc__def, 'hello'].as(:x2)).sql.should == \
|
176
|
-
"SELECT test(`abc`.`def`, 'hello') AS `x2` FROM `items`"
|
177
|
-
|
178
|
-
@d.insert_sql(:value => 333).should == \
|
179
|
-
'INSERT INTO `items` (`value`) VALUES (333)'
|
180
|
-
|
181
|
-
@d.insert_sql(:x => :y).should == \
|
182
|
-
'INSERT INTO `items` (`x`) VALUES (`y`)'
|
183
|
-
end
|
184
|
-
|
185
|
-
specify "should quote fields correctly when reversing the order" do
|
186
|
-
@d.quote_identifiers = true
|
187
|
-
@d.reverse_order(:name).sql.should == \
|
188
|
-
'SELECT * FROM `items` ORDER BY `name` DESC'
|
189
|
-
|
190
|
-
@d.reverse_order(:name.desc).sql.should == \
|
191
|
-
'SELECT * FROM `items` ORDER BY `name` ASC'
|
192
|
-
|
193
|
-
@d.reverse_order(:name, :test.desc).sql.should == \
|
194
|
-
'SELECT * FROM `items` ORDER BY `name` DESC, `test` ASC'
|
195
|
-
|
196
|
-
@d.reverse_order(:name.desc, :test).sql.should == \
|
197
|
-
'SELECT * FROM `items` ORDER BY `name` ASC, `test` DESC'
|
198
|
-
end
|
199
|
-
|
200
|
-
specify "should support ORDER clause in UPDATE statements" do
|
201
|
-
@d.order(:name).update_sql(:value => 1).should == \
|
202
|
-
'UPDATE items SET value = 1 ORDER BY name'
|
203
|
-
end
|
204
|
-
|
205
|
-
specify "should support LIMIT clause in UPDATE statements" do
|
206
|
-
@d.limit(10).update_sql(:value => 1).should == \
|
207
|
-
'UPDATE items SET value = 1 LIMIT 10'
|
208
|
-
end
|
209
|
-
|
210
|
-
specify "should support transactions" do
|
211
|
-
MYSQL_DB.transaction do
|
212
|
-
@d << {:name => 'abc', :value => 1}
|
213
|
-
end
|
214
|
-
|
215
|
-
@d.count.should == 1
|
216
|
-
end
|
217
|
-
|
218
|
-
specify "should correctly rollback transactions" do
|
219
|
-
proc do
|
220
|
-
MYSQL_DB.transaction do
|
221
|
-
@d << {:name => 'abc'}
|
222
|
-
raise Interrupt, 'asdf'
|
223
|
-
end
|
224
|
-
end.should raise_error(Interrupt)
|
225
|
-
|
226
|
-
MYSQL_DB.sqls.should == ['BEGIN', "INSERT INTO items (name) VALUES ('abc')", 'ROLLBACK']
|
227
|
-
end
|
228
|
-
|
229
|
-
specify "should handle returning inside of the block by committing" do
|
230
|
-
def MYSQL_DB.ret_commit
|
231
|
-
transaction do
|
232
|
-
self[:items] << {:name => 'abc'}
|
233
|
-
return
|
234
|
-
self[:items] << {:name => 'd'}
|
235
|
-
end
|
236
|
-
end
|
237
|
-
MYSQL_DB.ret_commit
|
238
|
-
MYSQL_DB.sqls.should == ['BEGIN', "INSERT INTO items (name) VALUES ('abc')", 'COMMIT']
|
239
|
-
end
|
240
|
-
|
241
|
-
specify "should support regexps" do
|
242
|
-
@d << {:name => 'abc', :value => 1}
|
243
|
-
@d << {:name => 'bcd', :value => 2}
|
244
|
-
@d.filter(:name => /bc/).count.should == 2
|
245
|
-
@d.filter(:name => /^bc/).count.should == 1
|
246
|
-
end
|
247
|
-
|
248
|
-
specify "should correctly literalize strings with comment backslashes in them" do
|
249
|
-
@d.delete
|
250
|
-
proc {@d << {:name => ':\\'}}.should_not raise_error
|
251
|
-
|
252
|
-
@d.first[:name].should == ':\\'
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
|
-
context "MySQL datasets" do
|
257
|
-
setup do
|
258
|
-
@d = MYSQL_DB[:orders]
|
259
|
-
end
|
260
|
-
teardown do
|
261
|
-
Sequel.convert_tinyint_to_bool = true
|
262
|
-
end
|
263
|
-
|
264
|
-
specify "should correctly quote column references" do
|
265
|
-
@d.quote_identifiers = true
|
266
|
-
market = 'ICE'
|
267
|
-
ack_stamp = Time.now - 15 * 60 # 15 minutes ago
|
268
|
-
@d.query do
|
269
|
-
select :market, :minute[:from_unixtime[:ack]].as(:minute)
|
270
|
-
where {(:ack > ack_stamp) & {:market => market}}
|
271
|
-
group_by :minute[:from_unixtime[:ack]]
|
272
|
-
end.sql.should == \
|
273
|
-
"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`))"
|
274
|
-
end
|
275
|
-
|
276
|
-
specify "should accept and return tinyints as bools or integers when configured to do so" do
|
277
|
-
MYSQL_DB[:booltest].delete
|
278
|
-
MYSQL_DB[:booltest] << {:value=>true}
|
279
|
-
MYSQL_DB[:booltest].all.should == [{:value=>true}]
|
280
|
-
MYSQL_DB[:booltest].delete
|
281
|
-
MYSQL_DB[:booltest] << {:value=>false}
|
282
|
-
MYSQL_DB[:booltest].all.should == [{:value=>false}]
|
283
|
-
|
284
|
-
Sequel.convert_tinyint_to_bool = false
|
285
|
-
MYSQL_DB[:booltest].delete
|
286
|
-
MYSQL_DB[:booltest] << {:value=>true}
|
287
|
-
MYSQL_DB[:booltest].all.should == [{:value=>1}]
|
288
|
-
MYSQL_DB[:booltest].delete
|
289
|
-
MYSQL_DB[:booltest] << {:value=>false}
|
290
|
-
MYSQL_DB[:booltest].all.should == [{:value=>0}]
|
291
|
-
|
292
|
-
MYSQL_DB[:booltest].delete
|
293
|
-
MYSQL_DB[:booltest] << {:value=>1}
|
294
|
-
MYSQL_DB[:booltest].all.should == [{:value=>1}]
|
295
|
-
MYSQL_DB[:booltest].delete
|
296
|
-
MYSQL_DB[:booltest] << {:value=>0}
|
297
|
-
MYSQL_DB[:booltest].all.should == [{:value=>0}]
|
298
|
-
end
|
299
|
-
end
|
300
|
-
|
301
|
-
# # Commented out because it was causing subsequent examples to fail for some reason
|
302
|
-
# context "Simple stored procedure test" do
|
303
|
-
# setup do
|
304
|
-
# # Create a simple stored procedure but drop it first if there
|
305
|
-
# MYSQL_DB.execute("DROP PROCEDURE IF EXISTS sp_get_server_id;")
|
306
|
-
# MYSQL_DB.execute("CREATE PROCEDURE sp_get_server_id() SQL SECURITY DEFINER SELECT @@SERVER_ID as server_id;")
|
307
|
-
# end
|
308
|
-
#
|
309
|
-
# specify "should return the server-id via a stored procedure call" do
|
310
|
-
# @server_id = MYSQL_DB["SELECT @@SERVER_ID as server_id;"].first[:server_id] # grab the server_id via a simple query
|
311
|
-
# @server_id_by_sp = MYSQL_DB["CALL sp_get_server_id();"].first[:server_id]
|
312
|
-
# @server_id_by_sp.should == @server_id # compare it to output from stored procedure
|
313
|
-
# end
|
314
|
-
# end
|
315
|
-
#
|
316
|
-
context "MySQL join expressions" do
|
317
|
-
setup do
|
318
|
-
@ds = MYSQL_DB[:nodes]
|
319
|
-
@ds.db.meta_def(:server_version) {50014}
|
320
|
-
end
|
321
|
-
|
322
|
-
specify "should raise error for :full_outer join requests." do
|
323
|
-
lambda{@ds.join_table(:full_outer, :nodes)}.should raise_error(Sequel::Error::InvalidJoinType)
|
324
|
-
end
|
325
|
-
specify "should support natural left joins" do
|
326
|
-
@ds.join_table(:natural_left, :nodes).sql.should == \
|
327
|
-
'SELECT * FROM nodes NATURAL LEFT JOIN nodes'
|
328
|
-
end
|
329
|
-
specify "should support natural right joins" do
|
330
|
-
@ds.join_table(:natural_right, :nodes).sql.should == \
|
331
|
-
'SELECT * FROM nodes NATURAL RIGHT JOIN nodes'
|
332
|
-
end
|
333
|
-
specify "should support natural left outer joins" do
|
334
|
-
@ds.join_table(:natural_left_outer, :nodes).sql.should == \
|
335
|
-
'SELECT * FROM nodes NATURAL LEFT OUTER JOIN nodes'
|
336
|
-
end
|
337
|
-
specify "should support natural right outer joins" do
|
338
|
-
@ds.join_table(:natural_right_outer, :nodes).sql.should == \
|
339
|
-
'SELECT * FROM nodes NATURAL RIGHT OUTER JOIN nodes'
|
340
|
-
end
|
341
|
-
specify "should support natural inner joins" do
|
342
|
-
@ds.join_table(:natural_inner, :nodes).sql.should == \
|
343
|
-
'SELECT * FROM nodes NATURAL LEFT JOIN nodes'
|
344
|
-
end
|
345
|
-
specify "should support cross joins" do
|
346
|
-
@ds.join_table(:cross, :nodes).sql.should == \
|
347
|
-
'SELECT * FROM nodes CROSS JOIN nodes'
|
348
|
-
end
|
349
|
-
specify "should support cross joins as inner joins if conditions are used" do
|
350
|
-
@ds.join_table(:cross, :nodes, :id=>:id).sql.should == \
|
351
|
-
'SELECT * FROM nodes INNER JOIN nodes ON (nodes.id = nodes.id)'
|
352
|
-
end
|
353
|
-
specify "should support straight joins (force left table to be read before right)" do
|
354
|
-
@ds.join_table(:straight, :nodes).sql.should == \
|
355
|
-
'SELECT * FROM nodes STRAIGHT_JOIN nodes'
|
356
|
-
end
|
357
|
-
specify "should support natural joins on multiple tables." do
|
358
|
-
@ds.join_table(:natural_left_outer, [:nodes, :branches]).sql.should == \
|
359
|
-
'SELECT * FROM nodes NATURAL LEFT OUTER JOIN (nodes, branches)'
|
360
|
-
end
|
361
|
-
specify "should support straight joins on multiple tables." do
|
362
|
-
@ds.join_table(:straight, [:nodes,:branches]).sql.should == \
|
363
|
-
'SELECT * FROM nodes STRAIGHT_JOIN (nodes, branches)'
|
364
|
-
end
|
365
|
-
end
|
366
|
-
|
367
|
-
context "Joined MySQL dataset" do
|
368
|
-
setup do
|
369
|
-
@ds = MYSQL_DB[:nodes]
|
370
|
-
end
|
371
|
-
|
372
|
-
specify "should quote fields correctly" do
|
373
|
-
@ds.quote_identifiers = true
|
374
|
-
@ds.join(:attributes, :node_id => :id).sql.should == \
|
375
|
-
"SELECT * FROM `nodes` INNER JOIN `attributes` ON (`attributes`.`node_id` = `nodes`.`id`)"
|
376
|
-
end
|
377
|
-
|
378
|
-
specify "should allow a having clause on ungrouped datasets" do
|
379
|
-
proc {@ds.having('blah')}.should_not raise_error
|
380
|
-
|
381
|
-
@ds.having('blah').sql.should == \
|
382
|
-
"SELECT * FROM nodes HAVING (blah)"
|
383
|
-
end
|
384
|
-
|
385
|
-
specify "should put a having clause before an order by clause" do
|
386
|
-
@ds.order(:aaa).having(:bbb => :ccc).sql.should == \
|
387
|
-
"SELECT * FROM nodes HAVING (bbb = ccc) ORDER BY aaa"
|
388
|
-
end
|
389
|
-
end
|
390
|
-
|
391
|
-
context "A MySQL database" do
|
392
|
-
setup do
|
393
|
-
@db = MYSQL_DB
|
394
|
-
end
|
395
|
-
|
396
|
-
specify "should support add_column operations" do
|
397
|
-
@db.add_column :test2, :xyz, :text
|
398
|
-
|
399
|
-
@db[:test2].columns.should == [:name, :value, :xyz]
|
400
|
-
@db[:test2] << {:name => 'mmm', :value => 111, :xyz => '000'}
|
401
|
-
@db[:test2].first[:xyz].should == '000'
|
402
|
-
end
|
403
|
-
|
404
|
-
specify "should support drop_column operations" do
|
405
|
-
@db[:test2].columns.should == [:name, :value, :xyz]
|
406
|
-
@db.drop_column :test2, :xyz
|
407
|
-
|
408
|
-
@db[:test2].columns.should == [:name, :value]
|
409
|
-
end
|
410
|
-
|
411
|
-
specify "should support rename_column operations" do
|
412
|
-
@db[:test2].delete
|
413
|
-
@db.add_column :test2, :xyz, :text
|
414
|
-
@db[:test2] << {:name => 'mmm', :value => 111, :xyz => 'qqqq'}
|
415
|
-
|
416
|
-
@db[:test2].columns.should == [:name, :value, :xyz]
|
417
|
-
@db.rename_column :test2, :xyz, :zyx, :type => :text
|
418
|
-
@db[:test2].columns.should == [:name, :value, :zyx]
|
419
|
-
@db[:test2].first[:zyx].should == 'qqqq'
|
420
|
-
end
|
421
|
-
|
422
|
-
specify "should support rename_column operations with types like varchar(255)" do
|
423
|
-
@db[:test2].delete
|
424
|
-
@db.add_column :test2, :tre, :text
|
425
|
-
@db[:test2] << {:name => 'mmm', :value => 111, :tre => 'qqqq'}
|
426
|
-
|
427
|
-
@db[:test2].columns.should == [:name, :value, :zyx, :tre]
|
428
|
-
@db.rename_column :test2, :tre, :ert, :type => :varchar[255]
|
429
|
-
@db[:test2].columns.should == [:name, :value, :zyx, :ert]
|
430
|
-
@db[:test2].first[:ert].should == 'qqqq'
|
431
|
-
end
|
432
|
-
|
433
|
-
specify "should support set_column_type operations" do
|
434
|
-
@db.add_column :test2, :xyz, :float
|
435
|
-
@db[:test2].delete
|
436
|
-
@db[:test2] << {:name => 'mmm', :value => 111, :xyz => 56.78}
|
437
|
-
@db.set_column_type :test2, :xyz, :integer
|
438
|
-
|
439
|
-
@db[:test2].first[:xyz].should == 57
|
440
|
-
end
|
441
|
-
|
442
|
-
specify "should support add_index" do
|
443
|
-
@db.add_index :test2, :value
|
444
|
-
end
|
445
|
-
|
446
|
-
specify "should support drop_index" do
|
447
|
-
@db.drop_index :test2, :value
|
448
|
-
end
|
449
|
-
end
|
450
|
-
|
451
|
-
context "A MySQL database" do
|
452
|
-
setup do
|
453
|
-
@db = MYSQL_DB
|
454
|
-
end
|
455
|
-
|
456
|
-
specify "should support defaults for boolean columns" do
|
457
|
-
g = Sequel::Schema::Generator.new(@db) do
|
458
|
-
boolean :active1, :default => true
|
459
|
-
boolean :active2, :default => false
|
460
|
-
end
|
461
|
-
statements = @db.create_table_sql_list(:items, *g.create_info)
|
462
|
-
statements.should == [
|
463
|
-
"CREATE TABLE items (active1 boolean DEFAULT 1, active2 boolean DEFAULT 0)"
|
464
|
-
]
|
465
|
-
end
|
466
|
-
|
467
|
-
specify "should correctly format CREATE TABLE statements with foreign keys" do
|
468
|
-
g = Sequel::Schema::Generator.new(@db) do
|
469
|
-
foreign_key :p_id, :table => :users, :key => :id,
|
470
|
-
:null => false, :on_delete => :cascade
|
471
|
-
end
|
472
|
-
@db.create_table_sql_list(:items, *g.create_info).should == [
|
473
|
-
"CREATE TABLE items (p_id integer NOT NULL, FOREIGN KEY (p_id) REFERENCES users(id) ON DELETE CASCADE)"
|
474
|
-
]
|
475
|
-
end
|
476
|
-
|
477
|
-
specify "should accept repeated raw sql statements using Database#<<" do
|
478
|
-
@db << 'DELETE FROM items'
|
479
|
-
@db[:items].count.should == 0
|
480
|
-
|
481
|
-
@db << "INSERT INTO items (name, value) VALUES ('tutu', 1234)"
|
482
|
-
@db[:items].first.should == {:name => 'tutu', :value => 1234}
|
483
|
-
|
484
|
-
@db << 'DELETE FROM items'
|
485
|
-
@db[:items].first.should == nil
|
486
|
-
end
|
487
|
-
end
|
488
|
-
|
489
|
-
# Socket tests should only be run if the MySQL server is on localhost
|
490
|
-
if %w'localhost 127.0.0.1 ::1'.include? MYSQL_URI.host
|
491
|
-
context "A MySQL database" do
|
492
|
-
specify "should accept a socket option" do
|
493
|
-
db = Sequel.mysql(MYSQL_DB_NAME, :host => 'localhost', :user => MYSQL_USER, :socket => MYSQL_SOCKET_FILE)
|
494
|
-
proc {db.test_connection}.should_not raise_error
|
495
|
-
end
|
496
|
-
|
497
|
-
specify "should accept a socket option without host option" do
|
498
|
-
db = Sequel.mysql(MYSQL_DB_NAME, :user => MYSQL_USER, :socket => MYSQL_SOCKET_FILE)
|
499
|
-
proc {db.test_connection}.should_not raise_error
|
500
|
-
end
|
501
|
-
|
502
|
-
specify "should fail to connect with invalid socket" do
|
503
|
-
db = Sequel.mysql(MYSQL_DB_NAME, :host => 'localhost', :user => MYSQL_USER, :socket => 'blah')
|
504
|
-
proc {db.test_connection}.should raise_error
|
505
|
-
end
|
506
|
-
end
|
507
|
-
end
|
508
|
-
|
509
|
-
context "A grouped MySQL dataset" do
|
510
|
-
setup do
|
511
|
-
MYSQL_DB[:test2].delete
|
512
|
-
MYSQL_DB[:test2] << {:name => '11', :value => 10}
|
513
|
-
MYSQL_DB[:test2] << {:name => '11', :value => 20}
|
514
|
-
MYSQL_DB[:test2] << {:name => '11', :value => 30}
|
515
|
-
MYSQL_DB[:test2] << {:name => '12', :value => 10}
|
516
|
-
MYSQL_DB[:test2] << {:name => '12', :value => 20}
|
517
|
-
MYSQL_DB[:test2] << {:name => '13', :value => 10}
|
518
|
-
end
|
519
|
-
|
520
|
-
specify "should return the correct count for raw sql query" do
|
521
|
-
ds = MYSQL_DB["select name FROM test2 WHERE name = '11' GROUP BY name"]
|
522
|
-
ds.count.should == 1
|
523
|
-
end
|
524
|
-
|
525
|
-
specify "should return the correct count for a normal dataset" do
|
526
|
-
ds = MYSQL_DB[:test2].select(:name).where(:name => '11').group(:name)
|
527
|
-
ds.count.should == 1
|
528
|
-
end
|
529
|
-
end
|
530
|
-
|
531
|
-
context "A MySQL database" do
|
532
|
-
setup do
|
533
|
-
end
|
534
|
-
|
535
|
-
specify "should support fulltext indexes" do
|
536
|
-
g = Sequel::Schema::Generator.new(MYSQL_DB) do
|
537
|
-
text :title
|
538
|
-
text :body
|
539
|
-
full_text_index [:title, :body]
|
540
|
-
end
|
541
|
-
MYSQL_DB.create_table_sql_list(:posts, *g.create_info).should == [
|
542
|
-
"CREATE TABLE posts (title text, body text)",
|
543
|
-
"CREATE FULLTEXT INDEX posts_title_body_index ON posts (title, body)"
|
544
|
-
]
|
545
|
-
end
|
546
|
-
|
547
|
-
specify "should support full_text_search" do
|
548
|
-
MYSQL_DB[:posts].full_text_search(:title, 'ruby').sql.should ==
|
549
|
-
"SELECT * FROM posts WHERE (MATCH (title) AGAINST ('ruby'))"
|
550
|
-
|
551
|
-
MYSQL_DB[:posts].full_text_search([:title, :body], ['ruby', 'sequel']).sql.should ==
|
552
|
-
"SELECT * FROM posts WHERE (MATCH (title, body) AGAINST ('ruby', 'sequel'))"
|
553
|
-
|
554
|
-
MYSQL_DB[:posts].full_text_search(:title, '+ruby -rails', :boolean => true).sql.should ==
|
555
|
-
"SELECT * FROM posts WHERE (MATCH (title) AGAINST ('+ruby -rails' IN BOOLEAN MODE))"
|
556
|
-
end
|
557
|
-
|
558
|
-
specify "should support spatial indexes" do
|
559
|
-
g = Sequel::Schema::Generator.new(MYSQL_DB) do
|
560
|
-
point :geom
|
561
|
-
spatial_index [:geom]
|
562
|
-
end
|
563
|
-
MYSQL_DB.create_table_sql_list(:posts, *g.create_info).should == [
|
564
|
-
"CREATE TABLE posts (geom point)",
|
565
|
-
"CREATE SPATIAL INDEX posts_geom_index ON posts (geom)"
|
566
|
-
]
|
567
|
-
end
|
568
|
-
|
569
|
-
specify "should support indexes with index type" do
|
570
|
-
g = Sequel::Schema::Generator.new(MYSQL_DB) do
|
571
|
-
text :title
|
572
|
-
index :title, :type => :hash
|
573
|
-
end
|
574
|
-
MYSQL_DB.create_table_sql_list(:posts, *g.create_info).should == [
|
575
|
-
"CREATE TABLE posts (title text)",
|
576
|
-
"CREATE INDEX posts_title_index ON posts (title) USING hash"
|
577
|
-
]
|
578
|
-
end
|
579
|
-
|
580
|
-
specify "should support unique indexes with index type" do
|
581
|
-
g = Sequel::Schema::Generator.new(MYSQL_DB) do
|
582
|
-
text :title
|
583
|
-
index :title, :type => :hash, :unique => true
|
584
|
-
end
|
585
|
-
MYSQL_DB.create_table_sql_list(:posts, *g.create_info).should == [
|
586
|
-
"CREATE TABLE posts (title text)",
|
587
|
-
"CREATE UNIQUE INDEX posts_title_index ON posts (title) USING hash"
|
588
|
-
]
|
589
|
-
end
|
590
|
-
end
|
591
|
-
|
592
|
-
context "MySQL::Dataset#insert" do
|
593
|
-
setup do
|
594
|
-
@d = MYSQL_DB[:items]
|
595
|
-
@d.delete # remove all records
|
596
|
-
MYSQL_DB.sqls.clear
|
597
|
-
end
|
598
|
-
|
599
|
-
specify "should insert record with default values when no arguments given" do
|
600
|
-
@d.insert
|
601
|
-
|
602
|
-
MYSQL_DB.sqls.should == [
|
603
|
-
"INSERT INTO items () VALUES ()"
|
604
|
-
]
|
605
|
-
|
606
|
-
@d.all.should == [
|
607
|
-
{:name => nil, :value => nil}
|
608
|
-
]
|
609
|
-
end
|
610
|
-
|
611
|
-
specify "should insert record with default values when empty hash given" do
|
612
|
-
@d.insert({})
|
613
|
-
|
614
|
-
MYSQL_DB.sqls.should == [
|
615
|
-
"INSERT INTO items () VALUES ()"
|
616
|
-
]
|
617
|
-
|
618
|
-
@d.all.should == [
|
619
|
-
{:name => nil, :value => nil}
|
620
|
-
]
|
621
|
-
end
|
622
|
-
|
623
|
-
specify "should insert record with default values when empty array given" do
|
624
|
-
@d.insert []
|
625
|
-
|
626
|
-
MYSQL_DB.sqls.should == [
|
627
|
-
"INSERT INTO items () VALUES ()"
|
628
|
-
]
|
629
|
-
|
630
|
-
@d.all.should == [
|
631
|
-
{:name => nil, :value => nil}
|
632
|
-
]
|
633
|
-
end
|
634
|
-
end
|
635
|
-
|
636
|
-
context "MySQL::Dataset#multi_insert" do
|
637
|
-
setup do
|
638
|
-
@d = MYSQL_DB[:items]
|
639
|
-
@d.delete # remove all records
|
640
|
-
MYSQL_DB.sqls.clear
|
641
|
-
end
|
642
|
-
|
643
|
-
specify "should insert multiple records in a single statement" do
|
644
|
-
@d.multi_insert([{:name => 'abc'}, {:name => 'def'}])
|
645
|
-
|
646
|
-
MYSQL_DB.sqls.should == [
|
647
|
-
'BEGIN',
|
648
|
-
"INSERT INTO items (name) VALUES ('abc'), ('def')",
|
649
|
-
'COMMIT'
|
650
|
-
]
|
651
|
-
|
652
|
-
@d.all.should == [
|
653
|
-
{:name => 'abc', :value => nil}, {:name => 'def', :value => nil}
|
654
|
-
]
|
655
|
-
end
|
656
|
-
|
657
|
-
specify "should split the list of records into batches if :commit_every option is given" do
|
658
|
-
@d.multi_insert([{:value => 1}, {:value => 2}, {:value => 3}, {:value => 4}],
|
659
|
-
:commit_every => 2)
|
660
|
-
|
661
|
-
MYSQL_DB.sqls.should == [
|
662
|
-
'BEGIN',
|
663
|
-
"INSERT INTO items (value) VALUES (1), (2)",
|
664
|
-
'COMMIT',
|
665
|
-
'BEGIN',
|
666
|
-
"INSERT INTO items (value) VALUES (3), (4)",
|
667
|
-
'COMMIT'
|
668
|
-
]
|
669
|
-
|
670
|
-
@d.all.should == [
|
671
|
-
{:name => nil, :value => 1},
|
672
|
-
{:name => nil, :value => 2},
|
673
|
-
{:name => nil, :value => 3},
|
674
|
-
{:name => nil, :value => 4}
|
675
|
-
]
|
676
|
-
end
|
677
|
-
|
678
|
-
specify "should split the list of records into batches if :slice option is given" do
|
679
|
-
@d.multi_insert([{:value => 1}, {:value => 2}, {:value => 3}, {:value => 4}],
|
680
|
-
:slice => 2)
|
681
|
-
|
682
|
-
MYSQL_DB.sqls.should == [
|
683
|
-
'BEGIN',
|
684
|
-
"INSERT INTO items (value) VALUES (1), (2)",
|
685
|
-
'COMMIT',
|
686
|
-
'BEGIN',
|
687
|
-
"INSERT INTO items (value) VALUES (3), (4)",
|
688
|
-
'COMMIT'
|
689
|
-
]
|
690
|
-
|
691
|
-
@d.all.should == [
|
692
|
-
{:name => nil, :value => 1},
|
693
|
-
{:name => nil, :value => 2},
|
694
|
-
{:name => nil, :value => 3},
|
695
|
-
{:name => nil, :value => 4}
|
696
|
-
]
|
697
|
-
end
|
698
|
-
|
699
|
-
specify "should support inserting using columns and values arrays" do
|
700
|
-
@d.multi_insert([:name, :value], [['abc', 1], ['def', 2]])
|
701
|
-
|
702
|
-
MYSQL_DB.sqls.should == [
|
703
|
-
'BEGIN',
|
704
|
-
"INSERT INTO items (name, value) VALUES ('abc', 1), ('def', 2)",
|
705
|
-
'COMMIT'
|
706
|
-
]
|
707
|
-
|
708
|
-
@d.all.should == [
|
709
|
-
{:name => 'abc', :value => 1},
|
710
|
-
{:name => 'def', :value => 2}
|
711
|
-
]
|
712
|
-
end
|
713
|
-
end
|
714
|
-
|
715
|
-
context "MySQL::Dataset#replace" do
|
716
|
-
setup do
|
717
|
-
MYSQL_DB.drop_table(:items) if MYSQL_DB.table_exists?(:items)
|
718
|
-
MYSQL_DB.create_table :items do
|
719
|
-
integer :id, :unique => true
|
720
|
-
integer :value, :index => true
|
721
|
-
end
|
722
|
-
@d = MYSQL_DB[:items]
|
723
|
-
MYSQL_DB.sqls.clear
|
724
|
-
end
|
725
|
-
|
726
|
-
specify "should create a record if the condition is not met" do
|
727
|
-
@d.replace(:id => 111, :value => 333)
|
728
|
-
@d.all.should == [{:id => 111, :value => 333}]
|
729
|
-
end
|
730
|
-
|
731
|
-
specify "should update a record if the condition is met" do
|
732
|
-
@d << {:id => 111}
|
733
|
-
@d.all.should == [{:id => 111, :value => nil}]
|
734
|
-
@d.replace(:id => 111, :value => 333)
|
735
|
-
@d.all.should == [{:id => 111, :value => 333}]
|
736
|
-
end
|
737
|
-
end
|
738
|
-
|
739
|
-
context "MySQL::Dataset#complex_expression_sql" do
|
740
|
-
setup do
|
741
|
-
@d = MYSQL_DB.dataset
|
742
|
-
end
|
743
|
-
|
744
|
-
specify "should handle pattern matches correctly" do
|
745
|
-
@d.literal(:x.like('a')).should == "(x LIKE BINARY 'a')"
|
746
|
-
@d.literal(~:x.like('a')).should == "(x NOT LIKE BINARY 'a')"
|
747
|
-
@d.literal(:x.ilike('a')).should == "(x LIKE 'a')"
|
748
|
-
@d.literal(~:x.ilike('a')).should == "(x NOT LIKE 'a')"
|
749
|
-
@d.literal(:x.like(/a/)).should == "(x REGEXP BINARY 'a')"
|
750
|
-
@d.literal(~:x.like(/a/)).should == "(x NOT REGEXP BINARY 'a')"
|
751
|
-
@d.literal(:x.like(/a/i)).should == "(x REGEXP 'a')"
|
752
|
-
@d.literal(~:x.like(/a/i)).should == "(x NOT REGEXP 'a')"
|
753
|
-
end
|
754
|
-
|
755
|
-
specify "should handle string concatenation with CONCAT if more than one record" do
|
756
|
-
@d.literal([:x, :y].sql_string_join).should == "CONCAT(x, y)"
|
757
|
-
@d.literal([:x, :y].sql_string_join(' ')).should == "CONCAT(x, ' ', y)"
|
758
|
-
@d.literal([:x[:y], 1, 'z'.lit].sql_string_join(:y|1)).should == "CONCAT(x(y), y[1], '1', y[1], z)"
|
759
|
-
end
|
760
|
-
|
761
|
-
specify "should handle string concatenation as simple string if just one record" do
|
762
|
-
@d.literal([:x].sql_string_join).should == "x"
|
763
|
-
@d.literal([:x].sql_string_join(' ')).should == "x"
|
764
|
-
end
|
765
|
-
end
|