sequel_core 1.5.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/CHANGELOG +116 -0
  2. data/COPYING +19 -19
  3. data/README +83 -32
  4. data/Rakefile +9 -20
  5. data/bin/sequel +43 -112
  6. data/doc/cheat_sheet.rdoc +225 -0
  7. data/doc/dataset_filtering.rdoc +257 -0
  8. data/lib/sequel_core/adapters/adapter_skeleton.rb +4 -2
  9. data/lib/sequel_core/adapters/ado.rb +3 -1
  10. data/lib/sequel_core/adapters/db2.rb +4 -2
  11. data/lib/sequel_core/adapters/dbi.rb +127 -113
  12. data/lib/sequel_core/adapters/informix.rb +4 -2
  13. data/lib/sequel_core/adapters/jdbc.rb +5 -3
  14. data/lib/sequel_core/adapters/mysql.rb +112 -46
  15. data/lib/sequel_core/adapters/odbc.rb +5 -7
  16. data/lib/sequel_core/adapters/odbc_mssql.rb +12 -3
  17. data/lib/sequel_core/adapters/openbase.rb +3 -1
  18. data/lib/sequel_core/adapters/oracle.rb +11 -9
  19. data/lib/sequel_core/adapters/postgres.rb +261 -262
  20. data/lib/sequel_core/adapters/sqlite.rb +72 -22
  21. data/lib/sequel_core/connection_pool.rb +140 -73
  22. data/lib/sequel_core/core_ext.rb +201 -66
  23. data/lib/sequel_core/core_sql.rb +123 -153
  24. data/lib/sequel_core/database/schema.rb +156 -0
  25. data/lib/sequel_core/database.rb +321 -338
  26. data/lib/sequel_core/dataset/callback.rb +11 -12
  27. data/lib/sequel_core/dataset/convenience.rb +213 -240
  28. data/lib/sequel_core/dataset/pagination.rb +58 -43
  29. data/lib/sequel_core/dataset/parse_tree_sequelizer.rb +331 -0
  30. data/lib/sequel_core/dataset/query.rb +41 -0
  31. data/lib/sequel_core/dataset/schema.rb +15 -0
  32. data/lib/sequel_core/dataset/sequelizer.rb +41 -373
  33. data/lib/sequel_core/dataset/sql.rb +741 -632
  34. data/lib/sequel_core/dataset.rb +183 -168
  35. data/lib/sequel_core/deprecated.rb +1 -169
  36. data/lib/sequel_core/exceptions.rb +24 -19
  37. data/lib/sequel_core/migration.rb +44 -52
  38. data/lib/sequel_core/object_graph.rb +43 -42
  39. data/lib/sequel_core/pretty_table.rb +71 -76
  40. data/lib/sequel_core/schema/generator.rb +163 -105
  41. data/lib/sequel_core/schema/sql.rb +250 -93
  42. data/lib/sequel_core/schema.rb +2 -8
  43. data/lib/sequel_core/sql.rb +394 -0
  44. data/lib/sequel_core/worker.rb +37 -27
  45. data/lib/sequel_core.rb +99 -45
  46. data/spec/adapters/informix_spec.rb +0 -1
  47. data/spec/adapters/mysql_spec.rb +177 -124
  48. data/spec/adapters/oracle_spec.rb +0 -1
  49. data/spec/adapters/postgres_spec.rb +98 -58
  50. data/spec/adapters/sqlite_spec.rb +45 -4
  51. data/spec/blockless_filters_spec.rb +269 -0
  52. data/spec/connection_pool_spec.rb +21 -18
  53. data/spec/core_ext_spec.rb +169 -19
  54. data/spec/core_sql_spec.rb +56 -49
  55. data/spec/database_spec.rb +78 -17
  56. data/spec/dataset_spec.rb +300 -428
  57. data/spec/migration_spec.rb +1 -1
  58. data/spec/object_graph_spec.rb +5 -11
  59. data/spec/rcov.opts +1 -1
  60. data/spec/schema_generator_spec.rb +16 -4
  61. data/spec/schema_spec.rb +89 -10
  62. data/spec/sequelizer_spec.rb +56 -56
  63. data/spec/spec.opts +0 -5
  64. data/spec/spec_config.rb +7 -0
  65. data/spec/spec_config.rb.example +5 -5
  66. data/spec/spec_helper.rb +6 -0
  67. data/spec/worker_spec.rb +1 -1
  68. metadata +78 -63
@@ -1,6 +1,4 @@
1
- require File.join(File.dirname(__FILE__), '../../lib/sequel_core')
2
1
  require File.join(File.dirname(__FILE__), '../spec_helper.rb')
3
- require 'logger'
4
2
 
5
3
  unless defined?(MYSQL_DB)
6
4
  MYSQL_URL = (ENV['SEQUEL_MY_SPEC_DB']||'mysql://root@localhost/sandbox') unless defined? MYSQL_URL
@@ -11,18 +9,28 @@ unless defined?(MYSQL_SOCKET_FILE)
11
9
  end
12
10
 
13
11
  MYSQL_URI = URI.parse(MYSQL_DB.uri)
14
- MYSQL_DB_NAME = MYSQL_URI.path =~ /\/(.*)/ && $1
12
+ MYSQL_DB_NAME = (m = /\/(.*)/.match(MYSQL_URI.path)) && m[1]
15
13
 
16
- MYSQL_DB.drop_table(:items) if MYSQL_DB.table_exists?(:items)
17
- MYSQL_DB.drop_table(:test2) if MYSQL_DB.table_exists?(:test2)
18
- MYSQL_DB.create_table :items do
14
+ MYSQL_DB.create_table! :items do
19
15
  text :name
20
16
  integer :value, :index => true
21
17
  end
22
- MYSQL_DB.create_table :test2 do
18
+ MYSQL_DB.create_table! :test2 do
23
19
  text :name
24
20
  integer :value
25
21
  end
22
+ MYSQL_DB.create_table! :booltest do
23
+ tinyint :value
24
+ end
25
+ class Sequel::MySQL::Database
26
+ attr_accessor :sqls
27
+ end
28
+ logger = Object.new
29
+ def logger.method_missing(m, msg)
30
+ MYSQL_DB.sqls << msg
31
+ end
32
+ MYSQL_DB.logger = logger
33
+ MYSQL_DB.sqls = []
26
34
 
27
35
  context "A MySQL database" do
28
36
  setup do
@@ -51,12 +59,25 @@ context "A MySQL database" do
51
59
  {:id => 3, :name => 'ghi'}
52
60
  ]
53
61
  end
62
+
63
+ specify "should convert Mysql::Errors to Sequel::Errors" do
64
+ proc{@db << "SELECT 1 + blah;"}.should raise_error(Sequel::Error)
65
+ end
66
+
67
+ specify "should correctly parse the schema" do
68
+ @db.schema(:booltest, :reload=>true).should == [[:value, {:type=>:boolean, :allow_null=>true, :max_chars=>nil, :default=>nil, :db_type=>"tinyint", :numeric_precision=>3}]]
69
+ end
70
+
71
+ specify "should get the schema all database tables if no table name is used" do
72
+ @db.schema(:booltest, :reload=>true).should == @db.schema(nil, :reload=>true)[:booltest]
73
+ end
54
74
  end
55
75
 
56
76
  context "A MySQL dataset" do
57
77
  setup do
58
78
  @d = MYSQL_DB[:items]
59
79
  @d.delete # remove all records
80
+ MYSQL_DB.sqls.clear
60
81
  end
61
82
 
62
83
  specify "should return the correct record count" do
@@ -107,72 +128,74 @@ context "A MySQL dataset" do
107
128
  proc {@d.literal(false)}.should_not raise_error
108
129
  end
109
130
 
110
- specify "should quote columns using back-ticks" do
131
+ specify "should quote columns and tables using back-ticks if quoting identifiers" do
132
+ @d.quote_identifiers = true
111
133
  @d.select(:name).sql.should == \
112
- 'SELECT `name` FROM items'
134
+ 'SELECT `name` FROM `items`'
113
135
 
114
136
  @d.select('COUNT(*)'.lit).sql.should == \
115
- 'SELECT COUNT(*) FROM items'
137
+ 'SELECT COUNT(*) FROM `items`'
116
138
 
117
139
  @d.select(:max[:value]).sql.should == \
118
- 'SELECT max(`value`) FROM items'
140
+ 'SELECT max(`value`) FROM `items`'
119
141
 
120
142
  @d.select(:NOW[]).sql.should == \
121
- 'SELECT NOW() FROM items'
143
+ 'SELECT NOW() FROM `items`'
122
144
 
123
145
  @d.select(:max[:items__value]).sql.should == \
124
- 'SELECT max(items.`value`) FROM items'
146
+ 'SELECT max(`items`.`value`) FROM `items`'
125
147
 
126
148
  @d.order(:name.desc).sql.should == \
127
- 'SELECT * FROM items ORDER BY `name` DESC'
149
+ 'SELECT * FROM `items` ORDER BY `name` DESC'
128
150
 
129
151
  @d.select('items.name AS item_name'.lit).sql.should == \
130
- 'SELECT items.name AS item_name FROM items'
152
+ 'SELECT items.name AS item_name FROM `items`'
131
153
 
132
154
  @d.select('`name`'.lit).sql.should == \
133
- 'SELECT `name` FROM items'
155
+ 'SELECT `name` FROM `items`'
134
156
 
135
157
  @d.select('max(items.`name`) AS `max_name`'.lit).sql.should == \
136
- 'SELECT max(items.`name`) AS `max_name` FROM items'
158
+ 'SELECT max(items.`name`) AS `max_name` FROM `items`'
137
159
 
138
160
  @d.select(:test[:abc, 'hello']).sql.should == \
139
- "SELECT test(`abc`, 'hello') FROM items"
161
+ "SELECT test(`abc`, 'hello') FROM `items`"
140
162
 
141
163
  @d.select(:test[:abc__def, 'hello']).sql.should == \
142
- "SELECT test(abc.`def`, 'hello') FROM items"
164
+ "SELECT test(`abc`.`def`, 'hello') FROM `items`"
143
165
 
144
166
  @d.select(:test[:abc__def, 'hello'].as(:x2)).sql.should == \
145
- "SELECT test(abc.`def`, 'hello') AS `x2` FROM items"
167
+ "SELECT test(`abc`.`def`, 'hello') AS `x2` FROM `items`"
146
168
 
147
169
  @d.insert_sql(:value => 333).should == \
148
- 'INSERT INTO items (`value`) VALUES (333)'
170
+ 'INSERT INTO `items` (`value`) VALUES (333)'
149
171
 
150
172
  @d.insert_sql(:x => :y).should == \
151
- 'INSERT INTO items (`x`) VALUES (`y`)'
173
+ 'INSERT INTO `items` (`x`) VALUES (`y`)'
152
174
  end
153
175
 
154
176
  specify "should quote fields correctly when reversing the order" do
177
+ @d.quote_identifiers = true
155
178
  @d.reverse_order(:name).sql.should == \
156
- 'SELECT * FROM items ORDER BY `name` DESC'
179
+ 'SELECT * FROM `items` ORDER BY `name` DESC'
157
180
 
158
181
  @d.reverse_order(:name.desc).sql.should == \
159
- 'SELECT * FROM items ORDER BY `name`'
182
+ 'SELECT * FROM `items` ORDER BY `name`'
160
183
 
161
184
  @d.reverse_order(:name, :test.desc).sql.should == \
162
- 'SELECT * FROM items ORDER BY `name` DESC, `test`'
185
+ 'SELECT * FROM `items` ORDER BY `name` DESC, `test`'
163
186
 
164
187
  @d.reverse_order(:name.desc, :test).sql.should == \
165
- 'SELECT * FROM items ORDER BY `name`, `test` DESC'
188
+ 'SELECT * FROM `items` ORDER BY `name`, `test` DESC'
166
189
  end
167
190
 
168
191
  specify "should support ORDER clause in UPDATE statements" do
169
192
  @d.order(:name).update_sql(:value => 1).should == \
170
- 'UPDATE items SET `value` = 1 ORDER BY `name`'
193
+ 'UPDATE items SET value = 1 ORDER BY name'
171
194
  end
172
195
 
173
196
  specify "should support LIMIT clause in UPDATE statements" do
174
197
  @d.limit(10).update_sql(:value => 1).should == \
175
- 'UPDATE items SET `value` = 1 LIMIT 10'
198
+ 'UPDATE items SET value = 1 LIMIT 10'
176
199
  end
177
200
 
178
201
  specify "should support transactions" do
@@ -183,6 +206,29 @@ context "A MySQL dataset" do
183
206
  @d.count.should == 1
184
207
  end
185
208
 
209
+ specify "should correctly rollback transactions" do
210
+ proc do
211
+ MYSQL_DB.transaction do
212
+ @d << {:name => 'abc'}
213
+ raise Interrupt, 'asdf'
214
+ end
215
+ end.should raise_error(Interrupt)
216
+
217
+ MYSQL_DB.sqls.should == ['BEGIN', "INSERT INTO items (name) VALUES ('abc')", 'ROLLBACK']
218
+ end
219
+
220
+ specify "should handle returning inside of the block by committing" do
221
+ def MYSQL_DB.ret_commit
222
+ transaction do
223
+ self[:items] << {:name => 'abc'}
224
+ return
225
+ self[:items] << {:name => 'd'}
226
+ end
227
+ end
228
+ MYSQL_DB.ret_commit
229
+ MYSQL_DB.sqls.should == ['BEGIN', "INSERT INTO items (name) VALUES ('abc')", 'COMMIT']
230
+ end
231
+
186
232
  specify "should support regexps" do
187
233
  @d << {:name => 'abc', :value => 1}
188
234
  @d << {:name => 'bcd', :value => 2}
@@ -204,6 +250,7 @@ context "MySQL datasets" do
204
250
  end
205
251
 
206
252
  specify "should correctly quote column references" do
253
+ @d.quote_identifiers = true
207
254
  market = 'ICE'
208
255
  ack_stamp = Time.now - 15 * 60 # 15 minutes ago
209
256
  @d.query do
@@ -214,7 +261,16 @@ context "MySQL datasets" do
214
261
  end
215
262
  group_by :minute[:from_unixtime[:ack]]
216
263
  end.sql.should == \
217
- "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`))"
264
+ "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`))"
265
+ end
266
+
267
+ specify "should accept and return tinyints as bools" do
268
+ MYSQL_DB[:booltest].delete
269
+ MYSQL_DB[:booltest] << {:value=>true}
270
+ MYSQL_DB[:booltest].all.should == [{:value=>true}]
271
+ MYSQL_DB[:booltest].delete
272
+ MYSQL_DB[:booltest] << {:value=>false}
273
+ MYSQL_DB[:booltest].all.should == [{:value=>false}]
218
274
  end
219
275
  end
220
276
 
@@ -240,67 +296,67 @@ context "MySQL join expressions" do
240
296
  end
241
297
 
242
298
  specify "should raise error for :full_outer join requests." do
243
- lambda{@ds.join_expr(:full_outer, :nodes)}.should raise_error(Sequel::Error::InvalidJoinType)
299
+ lambda{@ds.join_table(:full_outer, :nodes)}.should raise_error(Sequel::Error::InvalidJoinType)
244
300
  end
245
301
  specify "should support natural left joins" do
246
- @ds.join_expr(:natural_left, :nodes).should == \
247
- 'NATURAL LEFT JOIN nodes'
302
+ @ds.join_table(:natural_left, :nodes).sql.should == \
303
+ 'SELECT * FROM nodes NATURAL LEFT JOIN nodes'
248
304
  end
249
305
  specify "should support natural right joins" do
250
- @ds.join_expr(:natural_right, :nodes).should == \
251
- 'NATURAL RIGHT JOIN nodes'
306
+ @ds.join_table(:natural_right, :nodes).sql.should == \
307
+ 'SELECT * FROM nodes NATURAL RIGHT JOIN nodes'
252
308
  end
253
309
  specify "should support natural left outer joins" do
254
- @ds.join_expr(:natural_left_outer, :nodes).should == \
255
- 'NATURAL LEFT OUTER JOIN nodes'
310
+ @ds.join_table(:natural_left_outer, :nodes).sql.should == \
311
+ 'SELECT * FROM nodes NATURAL LEFT OUTER JOIN nodes'
256
312
  end
257
313
  specify "should support natural right outer joins" do
258
- @ds.join_expr(:natural_right_outer, :nodes).should == \
259
- 'NATURAL RIGHT OUTER JOIN nodes'
314
+ @ds.join_table(:natural_right_outer, :nodes).sql.should == \
315
+ 'SELECT * FROM nodes NATURAL RIGHT OUTER JOIN nodes'
260
316
  end
261
317
  specify "should support natural inner joins" do
262
- @ds.join_expr(:natural_inner, :nodes).should == \
263
- 'NATURAL LEFT JOIN nodes'
318
+ @ds.join_table(:natural_inner, :nodes).sql.should == \
319
+ 'SELECT * FROM nodes NATURAL LEFT JOIN nodes'
264
320
  end
265
321
  specify "should support cross joins (equivalent to inner join in MySQL, not in std SQL)" do
266
- @ds.join_expr(:cross, :nodes).should == \
267
- 'INNER JOIN nodes'
322
+ @ds.join_table(:cross, :nodes).sql.should == \
323
+ 'SELECT * FROM nodes INNER JOIN nodes'
268
324
  end
269
325
  specify "should support straight joins (force left table to be read before right)" do
270
- @ds.join_expr(:straight, :nodes).should == \
271
- 'STRAIGHT_JOIN nodes'
326
+ @ds.join_table(:straight, :nodes).sql.should == \
327
+ 'SELECT * FROM nodes STRAIGHT_JOIN nodes'
272
328
  end
273
329
  specify "should support natural joins on multiple tables." do
274
- @ds.join_expr(:natural_left_outer, [:nodes, :branches]).should == \
275
- 'NATURAL LEFT OUTER JOIN ( `nodes`, `branches` )'
330
+ @ds.join_table(:natural_left_outer, [:nodes, :branches]).sql.should == \
331
+ 'SELECT * FROM nodes NATURAL LEFT OUTER JOIN ( nodes, branches )'
276
332
  end
277
333
  specify "should support straight joins on multiple tables." do
278
- @ds.join_expr(:straight, [:nodes,:branches]).should == \
279
- 'STRAIGHT_JOIN ( `nodes`, `branches` )'
334
+ @ds.join_table(:straight, [:nodes,:branches]).sql.should == \
335
+ 'SELECT * FROM nodes STRAIGHT_JOIN ( nodes, branches )'
280
336
  end
281
337
  end
282
338
 
283
339
  context "Joined MySQL dataset" do
284
340
  setup do
285
- @ds = MYSQL_DB[:nodes].join(:attributes, :node_id => :id)
286
- @ds2 = MYSQL_DB[:nodes]
341
+ @ds = MYSQL_DB[:nodes]
287
342
  end
288
343
 
289
344
  specify "should quote fields correctly" do
290
- @ds.sql.should == \
291
- "SELECT * FROM nodes INNER JOIN attributes ON (attributes.`node_id` = nodes.`id`)"
345
+ @ds.quote_identifiers = true
346
+ @ds.join(:attributes, :node_id => :id).sql.should == \
347
+ "SELECT * FROM `nodes` INNER JOIN `attributes` ON (`attributes`.`node_id` = `nodes`.`id`)"
292
348
  end
293
349
 
294
350
  specify "should allow a having clause on ungrouped datasets" do
295
- proc {@ds2.having('blah')}.should_not raise_error
351
+ proc {@ds.having('blah')}.should_not raise_error
296
352
 
297
- @ds2.having('blah').sql.should == \
298
- "SELECT * FROM nodes HAVING blah"
353
+ @ds.having('blah').sql.should == \
354
+ "SELECT * FROM nodes HAVING (blah)"
299
355
  end
300
356
 
301
357
  specify "should put a having clause before an order by clause" do
302
- @ds2.order(:aaa).having(:bbb => :ccc).sql.should == \
303
- "SELECT * FROM nodes HAVING (`bbb` = `ccc`) ORDER BY `aaa`"
358
+ @ds.order(:aaa).having(:bbb => :ccc).sql.should == \
359
+ "SELECT * FROM nodes HAVING (bbb = ccc) ORDER BY aaa"
304
360
  end
305
361
  end
306
362
 
@@ -376,7 +432,7 @@ context "A MySQL database" do
376
432
  end
377
433
  statements = @db.create_table_sql_list(:items, *g.create_info)
378
434
  statements.should == [
379
- "CREATE TABLE items (`active1` boolean DEFAULT 1, `active2` boolean DEFAULT 0)"
435
+ "CREATE TABLE items (active1 boolean DEFAULT 1, active2 boolean DEFAULT 0)"
380
436
  ]
381
437
  end
382
438
 
@@ -386,7 +442,7 @@ context "A MySQL database" do
386
442
  :null => false, :on_delete => :cascade
387
443
  end
388
444
  @db.create_table_sql_list(:items, *g.create_info).should == [
389
- "CREATE TABLE items (`p_id` integer NOT NULL, FOREIGN KEY (`p_id`) REFERENCES users(`id`) ON DELETE CASCADE)"
445
+ "CREATE TABLE items (p_id integer NOT NULL, FOREIGN KEY (p_id) REFERENCES users(id) ON DELETE CASCADE)"
390
446
  ]
391
447
  end
392
448
 
@@ -402,20 +458,23 @@ context "A MySQL database" do
402
458
  end
403
459
  end
404
460
 
405
- context "A MySQL database" do
406
- specify "should accept a socket option" do
407
- db = Sequel.mysql(MYSQL_DB_NAME, :host => 'localhost', :user => 'root', :socket => MYSQL_SOCKET_FILE)
408
- proc {db.test_connection}.should_not raise_error
409
- end
410
-
411
- specify "should accept a socket option without host option" do
412
- db = Sequel.mysql(MYSQL_DB_NAME, :user => 'root', :socket => MYSQL_SOCKET_FILE)
413
- proc {db.test_connection}.should_not raise_error
414
- end
415
-
416
- specify "should fail to connect with invalid socket" do
417
- db = Sequel.mysql(MYSQL_DB_NAME, :host => 'localhost', :user => 'root', :socket => 'blah')
418
- proc {db.test_connection}.should raise_error
461
+ # Socket tests should only be run if the MySQL server is on localhost
462
+ if %w'localhost 127.0.0.1 ::1'.include? MYSQL_URI.host
463
+ context "A MySQL database" do
464
+ specify "should accept a socket option" do
465
+ db = Sequel.mysql(MYSQL_DB_NAME, :host => 'localhost', :user => 'root', :socket => MYSQL_SOCKET_FILE)
466
+ proc {db.test_connection}.should_not raise_error
467
+ end
468
+
469
+ specify "should accept a socket option without host option" do
470
+ db = Sequel.mysql(MYSQL_DB_NAME, :user => 'root', :socket => MYSQL_SOCKET_FILE)
471
+ proc {db.test_connection}.should_not raise_error
472
+ end
473
+
474
+ specify "should fail to connect with invalid socket" do
475
+ db = Sequel.mysql(MYSQL_DB_NAME, :host => 'localhost', :user => 'root', :socket => 'blah')
476
+ proc {db.test_connection}.should raise_error
477
+ end
419
478
  end
420
479
  end
421
480
 
@@ -452,20 +511,20 @@ context "A MySQL database" do
452
511
  full_text_index [:title, :body]
453
512
  end
454
513
  MYSQL_DB.create_table_sql_list(:posts, *g.create_info).should == [
455
- "CREATE TABLE posts (`title` text, `body` text)",
456
- "CREATE FULLTEXT INDEX posts_title_body_index ON posts (`title`, `body`)"
514
+ "CREATE TABLE posts (title text, body text)",
515
+ "CREATE FULLTEXT INDEX posts_title_body_index ON posts (title, body)"
457
516
  ]
458
517
  end
459
518
 
460
519
  specify "should support full_text_search" do
461
520
  MYSQL_DB[:posts].full_text_search(:title, 'ruby').sql.should ==
462
- "SELECT * FROM posts WHERE (MATCH (`title`) AGAINST ('ruby'))"
521
+ "SELECT * FROM posts WHERE (MATCH (title) AGAINST ('ruby'))"
463
522
 
464
523
  MYSQL_DB[:posts].full_text_search([:title, :body], ['ruby', 'sequel']).sql.should ==
465
- "SELECT * FROM posts WHERE (MATCH (`title`, `body`) AGAINST ('ruby', 'sequel'))"
524
+ "SELECT * FROM posts WHERE (MATCH (title, body) AGAINST ('ruby', 'sequel'))"
466
525
 
467
526
  MYSQL_DB[:posts].full_text_search(:title, '+ruby -rails', :boolean => true).sql.should ==
468
- "SELECT * FROM posts WHERE (MATCH (`title`) AGAINST ('+ruby -rails' IN BOOLEAN MODE))"
527
+ "SELECT * FROM posts WHERE (MATCH (title) AGAINST ('+ruby -rails' IN BOOLEAN MODE))"
469
528
  end
470
529
 
471
530
  specify "should support spatial indexes" do
@@ -474,8 +533,8 @@ context "A MySQL database" do
474
533
  spatial_index [:geom]
475
534
  end
476
535
  MYSQL_DB.create_table_sql_list(:posts, *g.create_info).should == [
477
- "CREATE TABLE posts (`geom` point)",
478
- "CREATE SPATIAL INDEX posts_geom_index ON posts (`geom`)"
536
+ "CREATE TABLE posts (geom point)",
537
+ "CREATE SPATIAL INDEX posts_geom_index ON posts (geom)"
479
538
  ]
480
539
  end
481
540
 
@@ -485,8 +544,8 @@ context "A MySQL database" do
485
544
  index :title, :type => :hash
486
545
  end
487
546
  MYSQL_DB.create_table_sql_list(:posts, *g.create_info).should == [
488
- "CREATE TABLE posts (`title` text)",
489
- "CREATE INDEX posts_title_index ON posts (`title`) USING hash"
547
+ "CREATE TABLE posts (title text)",
548
+ "CREATE INDEX posts_title_index ON posts (title) USING hash"
490
549
  ]
491
550
  end
492
551
 
@@ -496,45 +555,12 @@ context "A MySQL database" do
496
555
  index :title, :type => :hash, :unique => true
497
556
  end
498
557
  MYSQL_DB.create_table_sql_list(:posts, *g.create_info).should == [
499
- "CREATE TABLE posts (`title` text)",
500
- "CREATE UNIQUE INDEX posts_title_index ON posts (`title`) USING hash"
558
+ "CREATE TABLE posts (title text)",
559
+ "CREATE UNIQUE INDEX posts_title_index ON posts (title) USING hash"
501
560
  ]
502
561
  end
503
562
  end
504
563
 
505
- class Sequel::MySQL::Database
506
- alias_method :orig_execute, :execute
507
- attr_accessor :sqls
508
- def execute(sql, &block)
509
- @sqls ||= []; @sqls << sql
510
- orig_execute(sql, &block)
511
- end
512
-
513
- def transaction
514
- @pool.hold do |conn|
515
- @transactions ||= []
516
- if @transactions.include? Thread.current
517
- return yield(conn)
518
- end
519
- @sqls ||= []; @sqls << SQL_BEGIN
520
- conn.query(SQL_BEGIN)
521
- begin
522
- @transactions << Thread.current
523
- result = yield(conn)
524
- @sqls ||= []; @sqls << SQL_COMMIT
525
- conn.query(SQL_COMMIT)
526
- result
527
- rescue => e
528
- @sqls ||= []; @sqls << SQL_ROLLBACK
529
- conn.query(SQL_ROLLBACK)
530
- raise e unless Sequel::Error::Rollback === e
531
- ensure
532
- @transactions.delete(Thread.current)
533
- end
534
- end
535
- end
536
- end
537
-
538
564
  context "MySQL::Dataset#insert" do
539
565
  setup do
540
566
  @d = MYSQL_DB[:items]
@@ -555,7 +581,7 @@ context "MySQL::Dataset#insert" do
555
581
  end
556
582
 
557
583
  specify "should insert record with default values when empty hash given" do
558
- @d.insert {}
584
+ @d.insert({})
559
585
 
560
586
  MYSQL_DB.sqls.should == [
561
587
  "INSERT INTO items () VALUES ()"
@@ -591,7 +617,7 @@ context "MySQL::Dataset#multi_insert" do
591
617
 
592
618
  MYSQL_DB.sqls.should == [
593
619
  'BEGIN',
594
- "INSERT INTO items (`name`) VALUES ('abc'), ('def')",
620
+ "INSERT INTO items (name) VALUES ('abc'), ('def')",
595
621
  'COMMIT'
596
622
  ]
597
623
 
@@ -606,10 +632,10 @@ context "MySQL::Dataset#multi_insert" do
606
632
 
607
633
  MYSQL_DB.sqls.should == [
608
634
  'BEGIN',
609
- "INSERT INTO items (`value`) VALUES (1), (2)",
635
+ "INSERT INTO items (value) VALUES (1), (2)",
610
636
  'COMMIT',
611
637
  'BEGIN',
612
- "INSERT INTO items (`value`) VALUES (3), (4)",
638
+ "INSERT INTO items (value) VALUES (3), (4)",
613
639
  'COMMIT'
614
640
  ]
615
641
 
@@ -627,10 +653,10 @@ context "MySQL::Dataset#multi_insert" do
627
653
 
628
654
  MYSQL_DB.sqls.should == [
629
655
  'BEGIN',
630
- "INSERT INTO items (`value`) VALUES (1), (2)",
656
+ "INSERT INTO items (value) VALUES (1), (2)",
631
657
  'COMMIT',
632
658
  'BEGIN',
633
- "INSERT INTO items (`value`) VALUES (3), (4)",
659
+ "INSERT INTO items (value) VALUES (3), (4)",
634
660
  'COMMIT'
635
661
  ]
636
662
 
@@ -647,7 +673,7 @@ context "MySQL::Dataset#multi_insert" do
647
673
 
648
674
  MYSQL_DB.sqls.should == [
649
675
  'BEGIN',
650
- "INSERT INTO items (`name`, `value`) VALUES ('abc', 1), ('def', 2)",
676
+ "INSERT INTO items (name, value) VALUES ('abc', 1), ('def', 2)",
651
677
  'COMMIT'
652
678
  ]
653
679
 
@@ -681,3 +707,30 @@ context "MySQL::Dataset#replace" do
681
707
  @d.all.should == [{:id => 111, :value => 333}]
682
708
  end
683
709
  end
710
+
711
+ context "MySQL::Dataset#complex_expression_sql" do
712
+ setup do
713
+ @d = MYSQL_DB.dataset
714
+ end
715
+
716
+ specify "should handle case insensitive regular expressions with REGEXP" do
717
+ @d.literal(:x.like(/a/i)).should == "(x REGEXP 'a')"
718
+ @d.literal(~:x.like(/a/i)).should == "NOT (x REGEXP 'a')"
719
+ end
720
+
721
+ specify "should handle case sensitive regular expressions with REGEXP BINARY" do
722
+ @d.literal(:x.like(/a/)).should == "(x REGEXP BINARY 'a')"
723
+ @d.literal(~:x.like(/a/)).should == "NOT (x REGEXP BINARY 'a')"
724
+ end
725
+
726
+ specify "should handle string concatenation with CONCAT if more than one record" do
727
+ @d.literal([:x, :y].sql_string_join).should == "CONCAT(x, y)"
728
+ @d.literal([:x, :y].sql_string_join(' ')).should == "CONCAT(x, ' ', y)"
729
+ @d.literal([:x[:y], 1, 'z'.lit].sql_string_join(:y|1)).should == "CONCAT(x(y), y[1], '1', y[1], z)"
730
+ end
731
+
732
+ specify "should handle string concatenation as simple string if just one record" do
733
+ @d.literal([:x].sql_string_join).should == "x"
734
+ @d.literal([:x].sql_string_join(' ')).should == "x"
735
+ end
736
+ end
@@ -1,4 +1,3 @@
1
- require File.join(File.dirname(__FILE__), '../../lib/sequel_core')
2
1
  require File.join(File.dirname(__FILE__), '../spec_helper.rb')
3
2
 
4
3
  unless defined?(ORACLE_DB)