sequel 2.12.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. data/CHANGELOG +62 -0
  2. data/README.rdoc +3 -3
  3. data/Rakefile +7 -0
  4. data/doc/advanced_associations.rdoc +44 -0
  5. data/doc/release_notes/3.0.0.txt +221 -0
  6. data/lib/sequel/adapters/amalgalite.rb +208 -0
  7. data/lib/sequel/adapters/db2.rb +3 -0
  8. data/lib/sequel/adapters/dbi.rb +9 -0
  9. data/lib/sequel/adapters/do.rb +0 -4
  10. data/lib/sequel/adapters/firebird.rb +16 -18
  11. data/lib/sequel/adapters/informix.rb +5 -3
  12. data/lib/sequel/adapters/jdbc.rb +24 -20
  13. data/lib/sequel/adapters/jdbc/h2.rb +15 -4
  14. data/lib/sequel/adapters/mysql.rb +4 -8
  15. data/lib/sequel/adapters/odbc.rb +0 -4
  16. data/lib/sequel/adapters/oracle.rb +0 -4
  17. data/lib/sequel/adapters/shared/mssql.rb +16 -5
  18. data/lib/sequel/adapters/shared/mysql.rb +87 -86
  19. data/lib/sequel/adapters/shared/oracle.rb +92 -3
  20. data/lib/sequel/adapters/shared/postgres.rb +85 -29
  21. data/lib/sequel/adapters/shared/progress.rb +8 -3
  22. data/lib/sequel/adapters/shared/sqlite.rb +53 -23
  23. data/lib/sequel/adapters/sqlite.rb +4 -7
  24. data/lib/sequel/adapters/utils/unsupported.rb +3 -3
  25. data/lib/sequel/connection_pool.rb +18 -25
  26. data/lib/sequel/core.rb +2 -21
  27. data/lib/sequel/database.rb +60 -44
  28. data/lib/sequel/database/schema_generator.rb +26 -31
  29. data/lib/sequel/database/schema_methods.rb +8 -3
  30. data/lib/sequel/database/schema_sql.rb +114 -28
  31. data/lib/sequel/dataset.rb +14 -41
  32. data/lib/sequel/dataset/convenience.rb +31 -54
  33. data/lib/sequel/dataset/graph.rb +7 -13
  34. data/lib/sequel/dataset/sql.rb +43 -54
  35. data/lib/sequel/extensions/inflector.rb +0 -5
  36. data/lib/sequel/extensions/schema_dumper.rb +238 -0
  37. data/lib/sequel/metaprogramming.rb +0 -20
  38. data/lib/sequel/model.rb +1 -2
  39. data/lib/sequel/model/base.rb +18 -16
  40. data/lib/sequel/model/inflections.rb +6 -9
  41. data/lib/sequel/plugins/caching.rb +0 -6
  42. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  43. data/lib/sequel/sql.rb +2 -0
  44. data/lib/sequel/version.rb +2 -2
  45. data/spec/adapters/firebird_spec.rb +35 -8
  46. data/spec/adapters/mysql_spec.rb +173 -266
  47. data/spec/adapters/oracle_spec.rb +13 -0
  48. data/spec/adapters/postgres_spec.rb +127 -227
  49. data/spec/adapters/sqlite_spec.rb +13 -171
  50. data/spec/core/connection_pool_spec.rb +15 -4
  51. data/spec/core/core_sql_spec.rb +14 -170
  52. data/spec/core/database_spec.rb +50 -132
  53. data/spec/core/dataset_spec.rb +47 -930
  54. data/spec/core/expression_filters_spec.rb +12 -0
  55. data/spec/core/schema_generator_spec.rb +37 -45
  56. data/spec/core/schema_spec.rb +26 -16
  57. data/spec/core/spec_helper.rb +0 -25
  58. data/spec/extensions/inflector_spec.rb +0 -3
  59. data/spec/extensions/schema_dumper_spec.rb +292 -0
  60. data/spec/extensions/serialization_spec.rb +9 -0
  61. data/spec/extensions/single_table_inheritance_spec.rb +6 -1
  62. data/spec/extensions/spec_helper.rb +1 -3
  63. data/spec/extensions/validation_helpers_spec.rb +4 -4
  64. data/spec/integration/database_test.rb +18 -0
  65. data/spec/integration/dataset_test.rb +112 -1
  66. data/spec/integration/eager_loader_test.rb +70 -9
  67. data/spec/integration/prepared_statement_test.rb +2 -2
  68. data/spec/integration/schema_test.rb +76 -27
  69. data/spec/integration/spec_helper.rb +0 -14
  70. data/spec/integration/transaction_test.rb +27 -0
  71. data/spec/model/associations_spec.rb +0 -36
  72. data/spec/model/base_spec.rb +18 -123
  73. data/spec/model/hooks_spec.rb +2 -235
  74. data/spec/model/inflector_spec.rb +15 -115
  75. data/spec/model/model_spec.rb +0 -120
  76. data/spec/model/plugins_spec.rb +0 -70
  77. data/spec/model/record_spec.rb +35 -93
  78. data/spec/model/spec_helper.rb +0 -27
  79. data/spec/model/validations_spec.rb +0 -931
  80. metadata +9 -14
  81. data/lib/sequel/deprecated.rb +0 -593
  82. data/lib/sequel/deprecated_migration.rb +0 -91
  83. data/lib/sequel/model/deprecated.rb +0 -204
  84. data/lib/sequel/model/deprecated_hooks.rb +0 -103
  85. data/lib/sequel/model/deprecated_inflector.rb +0 -335
  86. data/lib/sequel/model/deprecated_validations.rb +0 -388
  87. data/spec/core/core_ext_spec.rb +0 -156
  88. data/spec/core/migration_spec.rb +0 -263
  89. data/spec/core/pretty_table_spec.rb +0 -58
  90. data/spec/model/caching_spec.rb +0 -217
  91. data/spec/model/schema_spec.rb +0 -92
@@ -58,6 +58,19 @@ context "An Oracle database" do
58
58
  expected_schema.should == schema
59
59
  end
60
60
  end
61
+
62
+ specify "should create a temporary table" do
63
+ ORACLE_DB.create_table :test_tmp, :temporary => true do
64
+ primary_key :id, :integer, :null => false
65
+ column :name, :text
66
+ index :name, :unique => true
67
+ end
68
+
69
+ ORACLE_DB.sqls.should == [
70
+ 'CREATE GLOBAL TEMPORARY TABLE test_tmp (id integer NOT NULL PRIMARY KEY AUTOINCREMENT, name text)',
71
+ 'CREATE UNIQUE INDEX test_tmp_name_index ON test_tmp (name)'
72
+ ]
73
+ end
61
74
  end
62
75
 
63
76
  context "An Oracle dataset" do
@@ -4,6 +4,16 @@ unless defined?(POSTGRES_DB)
4
4
  POSTGRES_URL = 'postgres://postgres:postgres@localhost:5432/reality_spec' unless defined? POSTGRES_URL
5
5
  POSTGRES_DB = Sequel.connect(ENV['SEQUEL_PG_SPEC_DB']||POSTGRES_URL)
6
6
  end
7
+
8
+ def POSTGRES_DB.sqls
9
+ (@sqls ||= [])
10
+ end
11
+ logger = Object.new
12
+ def logger.method_missing(m, msg)
13
+ POSTGRES_DB.sqls << msg
14
+ end
15
+ POSTGRES_DB.logger = logger
16
+
7
17
  #POSTGRES_DB.instance_variable_set(:@server_version, 80100)
8
18
  POSTGRES_DB.create_table! :test do
9
19
  text :name
@@ -21,33 +31,17 @@ POSTGRES_DB.create_table! :test4 do
21
31
  varchar :name, :size => 20
22
32
  bytea :value
23
33
  end
24
- POSTGRES_DB.create_table! :test5 do
25
- primary_key :xid
26
- integer :value
27
- end
28
34
 
29
35
  context "A PostgreSQL database" do
30
36
  before do
31
37
  @db = POSTGRES_DB
32
38
  end
33
39
 
34
- specify "should provide disconnect functionality" do
35
- @db.tables
36
- @db.pool.size.should == 1
37
- @db.disconnect
38
- @db.pool.size.should == 0
39
- end
40
-
41
40
  specify "should provide the server version" do
42
41
  @db.server_version.should > 70000
43
42
  end
44
43
 
45
- specify "should raise Sequel::Error on error" do
46
- proc{@db << "SELECT 1 + 'a'"}.should raise_error(Sequel::Error)
47
- end
48
-
49
44
  specify "should correctly parse the schema" do
50
- require 'logger'
51
45
  @db.schema(:test3, :reload=>true).should == [
52
46
  [:value, {:type=>:integer, :allow_null=>true, :default=>nil, :db_type=>"integer", :primary_key=>false}],
53
47
  [:time, {:type=>:datetime, :allow_null=>true, :default=>nil, :db_type=>"timestamp without time zone", :primary_key=>false}]
@@ -65,54 +59,6 @@ context "A PostgreSQL dataset" do
65
59
  @d.delete # remove all records
66
60
  end
67
61
 
68
- specify "should return the correct record count" do
69
- @d.count.should == 0
70
- @d << {:name => 'abc', :value => 123}
71
- @d << {:name => 'abc', :value => 456}
72
- @d << {:name => 'def', :value => 789}
73
- @d.count.should == 3
74
- end
75
-
76
- specify "should return the correct records" do
77
- @d.to_a.should == []
78
- @d << {:name => 'abc', :value => 123}
79
- @d << {:name => 'abc', :value => 456}
80
- @d << {:name => 'def', :value => 789}
81
-
82
- @d.order(:value).to_a.should == [
83
- {:name => 'abc', :value => 123},
84
- {:name => 'abc', :value => 456},
85
- {:name => 'def', :value => 789}
86
- ]
87
- end
88
-
89
- specify "should update records correctly" do
90
- @d << {:name => 'abc', :value => 123}
91
- @d << {:name => 'abc', :value => 456}
92
- @d << {:name => 'def', :value => 789}
93
- @d.filter(:name => 'abc').update(:value => 530)
94
-
95
- # the third record should stay the same
96
- # floating-point precision bullshit
97
- @d[:name => 'def'][:value].should == 789
98
- @d.filter(:value => 530).count.should == 2
99
- end
100
-
101
- specify "should delete records correctly" do
102
- @d << {:name => 'abc', :value => 123}
103
- @d << {:name => 'abc', :value => 456}
104
- @d << {:name => 'def', :value => 789}
105
- @d.filter(:name => 'abc').delete
106
-
107
- @d.count.should == 1
108
- @d.first[:name].should == 'def'
109
- end
110
-
111
- specify "should be able to literalize booleans" do
112
- proc {@d.literal(true)}.should_not raise_error
113
- proc {@d.literal(false)}.should_not raise_error
114
- end
115
-
116
62
  specify "should quote columns and tables using double quotes if quoting identifiers" do
117
63
  @d.quote_identifiers = true
118
64
  @d.select(:name).sql.should == \
@@ -176,60 +122,6 @@ context "A PostgreSQL dataset" do
176
122
  'SELECT * FROM "test" ORDER BY "name" ASC, "test" DESC'
177
123
  end
178
124
 
179
- specify "should support transactions" do
180
- POSTGRES_DB.transaction do
181
- @d << {:name => 'abc', :value => 1}
182
- end
183
-
184
- @d.count.should == 1
185
- end
186
-
187
- specify "should have #transaction yield the connection" do
188
- POSTGRES_DB.transaction do |conn|
189
- conn.should_not == nil
190
- end
191
- end
192
-
193
- specify "should correctly rollback transactions" do
194
- proc do
195
- POSTGRES_DB.transaction do
196
- @d << {:name => 'abc', :value => 1}
197
- raise Interrupt, 'asdf'
198
- end
199
- end.should raise_error(Interrupt)
200
-
201
- proc do
202
- POSTGRES_DB.transaction do
203
- @d << {:name => 'abc', :value => 1}
204
- raise Sequel::Rollback
205
- end
206
- end.should_not raise_error
207
-
208
- @d.count.should == 0
209
- end
210
-
211
- specify "should handle returning inside of the block by committing" do
212
- def POSTGRES_DB.ret_commit
213
- transaction do
214
- self[:test] << {:name => 'abc'}
215
- return
216
- self[:test] << {:name => 'd'}
217
- end
218
- end
219
- @d.count.should == 0
220
- POSTGRES_DB.ret_commit
221
- @d.count.should == 1
222
- POSTGRES_DB.ret_commit
223
- @d.count.should == 2
224
- proc do
225
- POSTGRES_DB.transaction do
226
- raise Interrupt, 'asdf'
227
- end
228
- end.should raise_error(Interrupt)
229
-
230
- @d.count.should == 2
231
- end
232
-
233
125
  specify "should support nested transactions through savepoints using the savepoint option" do
234
126
  POSTGRES_DB.transaction do
235
127
  @d << {:name => '1'}
@@ -260,33 +152,6 @@ context "A PostgreSQL dataset" do
260
152
  @d.filter(:name => /bc/).count.should == 2
261
153
  @d.filter(:name => /^bc/).count.should == 1
262
154
  end
263
-
264
- specify "should correctly escape strings" do
265
- POSTGRES_DB['SELECT ? AS a', "\\dingo"].get(:a) == "\\dingo"
266
- end
267
-
268
- specify "should correctly escape strings with quotes" do
269
- POSTGRES_DB['SELECT ? AS a', "\\'dingo"].get(:a) == "\\'dingo"
270
- end
271
-
272
- specify "should properly escape binary data" do
273
- POSTGRES_DB['SELECT ? AS a', "\1\2\3".to_sequel_blob].get(:a) == "\1\2\3"
274
- end
275
-
276
- specify "should retrieve binary data as Blob object" do
277
- d = POSTGRES_DB[:test4]
278
- d << {:name => '123', :value => "\1\2\3".to_sequel_blob}
279
- retrieved_binary_value = d[:name => '123'][:value]
280
- retrieved_binary_value.should be_a_kind_of(::Sequel::SQL::Blob)
281
- retrieved_binary_value.should == "\1\2\3"
282
- retrieved_binary_value = d[:value => "\1\2\3".to_sequel_blob][:value]
283
- retrieved_binary_value.should be_a_kind_of(::Sequel::SQL::Blob)
284
- retrieved_binary_value.should == "\1\2\3"
285
- end
286
-
287
- specify "should properly receive binary data" do
288
- POSTGRES_DB['SELECT ?::bytea AS a', "a"].get(:a) == "a"
289
- end
290
155
  end
291
156
 
292
157
  context "A PostgreSQL dataset with a timestamp field" do
@@ -343,141 +208,161 @@ end
343
208
 
344
209
  context "A PostgreSQL database" do
345
210
  before do
211
+ @db = POSTGRES_DB
212
+ @db.drop_table(:posts) rescue nil
213
+ @db.sqls.clear
214
+ end
215
+ after do
216
+ @db.drop_table(:posts) rescue nil
346
217
  end
347
218
 
348
- specify "should support fulltext indexes" do
349
- g = Sequel::Schema::Generator.new(POSTGRES_DB) do
350
- text :title
351
- text :body
352
- full_text_index [:title, :body]
353
- end
354
- POSTGRES_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [
355
- "CREATE TABLE posts (title text, body text)",
356
- "CREATE INDEX posts_title_body_index ON posts USING gin (to_tsvector('simple', (COALESCE(title, '') || ' ' || COALESCE(body, ''))))"
357
- ]
219
+ specify "should support resetting the primary key sequence" do
220
+ @db.create_table(:posts){primary_key :a}
221
+ @db[:posts].insert(:a=>20).should == 20
222
+ @db[:posts].insert.should == 1
223
+ @db[:posts].insert.should == 2
224
+ @db[:posts].insert(:a=>10).should == 10
225
+ @db.reset_primary_key_sequence(:posts).should == 21
226
+ @db[:posts].insert.should == 21
227
+ @db[:posts].order(:a).map(:a).should == [1, 2, 10, 20, 21]
358
228
  end
359
229
 
360
- specify "should support fulltext indexes with a specific language" do
361
- g = Sequel::Schema::Generator.new(POSTGRES_DB) do
362
- text :title
363
- text :body
364
- full_text_index [:title, :body], :language => 'french'
365
- end
366
- POSTGRES_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [
230
+ specify "should support fulltext indexes and searching" do
231
+ @db.create_table(:posts){text :title; text :body; full_text_index [:title, :body]; full_text_index :title, :language => 'french'}
232
+ @db.sqls.should == [
367
233
  "CREATE TABLE posts (title text, body text)",
368
- "CREATE INDEX posts_title_body_index ON posts USING gin (to_tsvector('french', (COALESCE(title, '') || ' ' || COALESCE(body, ''))))"
234
+ "CREATE INDEX posts_title_body_index ON posts USING gin (to_tsvector('simple', (COALESCE(title, '') || ' ' || COALESCE(body, ''))))",
235
+ "CREATE INDEX posts_title_index ON posts USING gin (to_tsvector('french', (COALESCE(title, ''))))"
369
236
  ]
370
- end
371
-
372
- specify "should support full_text_search" do
373
- POSTGRES_DB[:posts].full_text_search(:title, 'ruby').sql.should ==
374
- "SELECT * FROM posts WHERE (to_tsvector('simple', (COALESCE(title, ''))) @@ to_tsquery('simple', 'ruby'))"
375
-
376
- POSTGRES_DB[:posts].full_text_search([:title, :body], ['ruby', 'sequel']).sql.should ==
377
- "SELECT * FROM posts WHERE (to_tsvector('simple', (COALESCE(title, '') || ' ' || COALESCE(body, ''))) @@ to_tsquery('simple', 'ruby | sequel'))"
378
-
379
- POSTGRES_DB[:posts].full_text_search(:title, 'ruby', :language => 'french').sql.should ==
380
- "SELECT * FROM posts WHERE (to_tsvector('french', (COALESCE(title, ''))) @@ to_tsquery('french', 'ruby'))"
237
+
238
+ @db[:posts].insert(:title=>'ruby rails', :body=>'yowsa')
239
+ @db[:posts].insert(:title=>'sequel', :body=>'ruby')
240
+ @db[:posts].insert(:title=>'ruby scooby', :body=>'x')
241
+ @db.sqls.clear
242
+
243
+ @db[:posts].full_text_search(:title, 'rails').all.should == [{:title=>'ruby rails', :body=>'yowsa'}]
244
+ @db[:posts].full_text_search([:title, :body], ['yowsa', 'rails']).all.should == [:title=>'ruby rails', :body=>'yowsa']
245
+ @db[:posts].full_text_search(:title, 'scooby', :language => 'french').all.should == [{:title=>'ruby scooby', :body=>'x'}]
246
+ @db.sqls.should == [
247
+ "SELECT * FROM posts WHERE (to_tsvector('simple', (COALESCE(title, ''))) @@ to_tsquery('simple', 'rails'))",
248
+ "SELECT * FROM posts WHERE (to_tsvector('simple', (COALESCE(title, '') || ' ' || COALESCE(body, ''))) @@ to_tsquery('simple', 'yowsa | rails'))",
249
+ "SELECT * FROM posts WHERE (to_tsvector('french', (COALESCE(title, ''))) @@ to_tsquery('french', 'scooby'))"]
381
250
  end
382
251
 
383
252
  specify "should support spatial indexes" do
384
- g = Sequel::Schema::Generator.new(POSTGRES_DB) do
385
- geometry :geom
386
- spatial_index [:geom]
387
- end
388
- POSTGRES_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [
389
- "CREATE TABLE posts (geom geometry)",
253
+ @db.create_table(:posts){box :geom; spatial_index [:geom]}
254
+ @db.sqls.should == [
255
+ "CREATE TABLE posts (geom box)",
390
256
  "CREATE INDEX posts_geom_index ON posts USING gist (geom)"
391
257
  ]
392
258
  end
393
259
 
394
260
  specify "should support indexes with index type" do
395
- g = Sequel::Schema::Generator.new(POSTGRES_DB) do
396
- varchar :title, :size => 5
397
- index :title, :type => 'hash'
398
- end
399
- POSTGRES_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [
261
+ @db.create_table(:posts){varchar :title, :size => 5; index :title, :type => 'hash'}
262
+ @db.sqls.should == [
400
263
  "CREATE TABLE posts (title varchar(5))",
401
264
  "CREATE INDEX posts_title_index ON posts USING hash (title)"
402
265
  ]
403
266
  end
404
267
 
405
268
  specify "should support unique indexes with index type" do
406
- g = Sequel::Schema::Generator.new(POSTGRES_DB) do
407
- varchar :title, :size => 5
408
- index :title, :type => 'hash', :unique => true
409
- end
410
- POSTGRES_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [
269
+ @db.create_table(:posts){varchar :title, :size => 5; index :title, :type => 'btree', :unique => true}
270
+ @db.sqls.should == [
411
271
  "CREATE TABLE posts (title varchar(5))",
412
- "CREATE UNIQUE INDEX posts_title_index ON posts USING hash (title)"
272
+ "CREATE UNIQUE INDEX posts_title_index ON posts USING btree (title)"
413
273
  ]
414
274
  end
415
275
 
416
276
  specify "should support partial indexes" do
417
- g = Sequel::Schema::Generator.new(POSTGRES_DB) do
418
- varchar :title, :size => 5
419
- index :title, :where => {:something => 5}
420
- end
421
- POSTGRES_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [
277
+ @db.create_table(:posts){varchar :title, :size => 5; index :title, :where => {:title => '5'}}
278
+ @db.sqls.should == [
422
279
  "CREATE TABLE posts (title varchar(5))",
423
- "CREATE INDEX posts_title_index ON posts (title) WHERE (something = 5)"
280
+ "CREATE INDEX posts_title_index ON posts (title) WHERE (title = '5')"
424
281
  ]
425
282
  end
426
283
 
427
284
  specify "should support identifiers for table names in indicies" do
428
- g = Sequel::Schema::Generator.new(POSTGRES_DB) do
429
- varchar :title, :size => 5
430
- index :title, :where => {:something => 5}
431
- end
432
- POSTGRES_DB.send(:create_table_sql_list, Sequel::SQL::Identifier.new(:posts__test), *g.create_info).should == [
433
- "CREATE TABLE posts__test (title varchar(5))",
434
- "CREATE INDEX posts__test_title_index ON posts__test (title) WHERE (something = 5)"
285
+ @db.create_table(Sequel::SQL::Identifier.new(:posts)){varchar :title, :size => 5; index :title, :where => {:title => '5'}}
286
+ @db.sqls.should == [
287
+ "CREATE TABLE posts (title varchar(5))",
288
+ "CREATE INDEX posts_title_index ON posts (title) WHERE (title = '5')"
435
289
  ]
436
290
  end
437
291
  end
438
292
 
439
- context "Postgres::Dataset#multi_insert_sql" do
293
+ context "Postgres::Dataset#import" do
440
294
  before do
441
- @ds = POSTGRES_DB[:test]
295
+ @db = POSTGRES_DB
296
+ @db.create_table!(:test){Integer :x; Integer :y}
297
+ @db.sqls.clear
298
+ @ds = @db[:test]
299
+ end
300
+ after do
301
+ @db.drop_table(:test) rescue nil
442
302
  end
443
303
 
444
- specify "should return separate insert statements if server_version < 80200" do
304
+ specify "#import should return separate insert statements if server_version < 80200" do
445
305
  @ds.meta_def(:server_version){80199}
446
306
 
447
- @ds.multi_insert_sql([:x, :y], [[1, 2], [3, 4]]).should == [
307
+ @ds.import([:x, :y], [[1, 2], [3, 4]])
308
+
309
+ @db.sqls.should == [
310
+ 'BEGIN',
448
311
  'INSERT INTO test (x, y) VALUES (1, 2)',
449
- 'INSERT INTO test (x, y) VALUES (3, 4)'
312
+ 'INSERT INTO test (x, y) VALUES (3, 4)',
313
+ 'COMMIT'
450
314
  ]
315
+ @ds.all.should == [{:x=>1, :y=>2}, {:x=>3, :y=>4}]
451
316
  end
452
317
 
453
- specify "should a single insert statement if server_version >= 80200" do
318
+ specify "#import should a single insert statement if server_version >= 80200" do
454
319
  @ds.meta_def(:server_version){80200}
455
-
456
- @ds.multi_insert_sql([:x, :y], [[1, 2], [3, 4]]).should == [
457
- 'INSERT INTO test (x, y) VALUES (1, 2), (3, 4)'
458
- ]
459
-
460
- @ds.meta_def(:server_version){80201}
461
320
 
462
- @ds.multi_insert_sql([:x, :y], [[1, 2], [3, 4]]).should == [
463
- 'INSERT INTO test (x, y) VALUES (1, 2), (3, 4)'
321
+ @ds.import([:x, :y], [[1, 2], [3, 4]])
322
+
323
+ @db.sqls.should == [
324
+ 'BEGIN',
325
+ 'INSERT INTO test (x, y) VALUES (1, 2), (3, 4)',
326
+ 'COMMIT'
464
327
  ]
328
+ @ds.all.should == [{:x=>1, :y=>2}, {:x=>3, :y=>4}]
465
329
  end
466
330
  end
467
331
 
468
332
  context "Postgres::Dataset#insert" do
469
333
  before do
470
- @ds = POSTGRES_DB[:test5]
471
- @ds.delete
334
+ @db = POSTGRES_DB
335
+ @db.create_table!(:test5){primary_key :xid; Integer :value}
336
+ @db.sqls.clear
337
+ @ds = @db[:test5]
338
+ end
339
+ after do
340
+ @db.drop_table(:test5) rescue nil
341
+ end
342
+
343
+ specify "should work regardless of how it is used" do
344
+ @ds.insert(:value=>10).should == 1
345
+ @ds.disable_insert_returning.insert(:value=>20).should == 2
346
+ @ds.meta_def(:server_version){80100}
347
+ @ds.insert(:value=>13).should == 3
348
+
349
+ @db.sqls.reject{|x| x =~ /pg_class/}.should == [
350
+ 'INSERT INTO test5 (value) VALUES (10) RETURNING xid',
351
+ 'INSERT INTO test5 (value) VALUES (20)',
352
+ "SELECT currval('\"public\".test5_xid_seq')",
353
+ 'INSERT INTO test5 (value) VALUES (13)',
354
+ "SELECT currval('\"public\".test5_xid_seq')"
355
+ ]
356
+ @ds.all.should == [{:xid=>1, :value=>10}, {:xid=>2, :value=>20}, {:xid=>3, :value=>13}]
472
357
  end
473
358
 
474
- specify "should call insert_sql if server_version < 80200" do
359
+ specify "should call execute_insert if server_version < 80200" do
475
360
  @ds.meta_def(:server_version){80100}
476
361
  @ds.should_receive(:execute_insert).once.with('INSERT INTO test5 (value) VALUES (10)', :table=>:test5, :values=>{:value=>10})
477
362
  @ds.insert(:value=>10)
478
363
  end
479
364
 
480
- specify "should call insert_sql if disabling insert returning" do
365
+ specify "should call execute_insert if disabling insert returning" do
481
366
  @ds.disable_insert_returning!
482
367
  @ds.should_receive(:execute_insert).once.with('INSERT INTO test5 (value) VALUES (10)', :table=>:test5, :values=>{:value=>10})
483
368
  @ds.insert(:value=>10)
@@ -530,6 +415,7 @@ context "Postgres::Database schema qualified tables" do
530
415
  POSTGRES_DB.instance_variable_set(:@primary_key_sequences, {})
531
416
  end
532
417
  after do
418
+ POSTGRES_DB.quote_identifiers = false
533
419
  POSTGRES_DB << "DROP SCHEMA schema_test CASCADE"
534
420
  POSTGRES_DB.default_schema = :public
535
421
  end
@@ -574,13 +460,26 @@ context "Postgres::Database schema qualified tables" do
574
460
 
575
461
  specify "should be able to get serial sequences for tables in a given schema" do
576
462
  POSTGRES_DB.create_table(:schema_test__schema_test){primary_key :i}
577
- POSTGRES_DB.primary_key_sequence(:schema_test__schema_test).should == '"schema_test"."schema_test_i_seq"'
463
+ POSTGRES_DB.primary_key_sequence(:schema_test__schema_test).should == '"schema_test".schema_test_i_seq'
464
+ end
465
+
466
+ specify "should be able to get serial sequences for tables that have spaces in the name in a given schema" do
467
+ POSTGRES_DB.quote_identifiers = true
468
+ POSTGRES_DB.create_table(:"schema_test__schema test"){primary_key :i}
469
+ POSTGRES_DB.primary_key_sequence(:"schema_test__schema test").should == '"schema_test"."schema test_i_seq"'
578
470
  end
579
471
 
580
472
  specify "should be able to get custom sequences for tables in a given schema" do
581
473
  POSTGRES_DB << "CREATE SEQUENCE schema_test.kseq"
582
474
  POSTGRES_DB.create_table(:schema_test__schema_test){integer :j; primary_key :k, :type=>:integer, :default=>"nextval('schema_test.kseq'::regclass)".lit}
583
- POSTGRES_DB.primary_key_sequence(:schema_test__schema_test).should == '"schema_test"."kseq"'
475
+ POSTGRES_DB.primary_key_sequence(:schema_test__schema_test).should == '"schema_test".kseq'
476
+ end
477
+
478
+ specify "should be able to get custom sequences for tables that have spaces in the name in a given schema" do
479
+ POSTGRES_DB.quote_identifiers = true
480
+ POSTGRES_DB << "CREATE SEQUENCE schema_test.\"ks eq\""
481
+ POSTGRES_DB.create_table(:"schema_test__schema test"){integer :j; primary_key :k, :type=>:integer, :default=>"nextval('schema_test.\"ks eq\"'::regclass)".lit}
482
+ POSTGRES_DB.primary_key_sequence(:"schema_test__schema test").should == '"schema_test"."ks eq"'
584
483
  end
585
484
 
586
485
  specify "#default_schema= should change the default schema used from public" do
@@ -589,7 +488,7 @@ context "Postgres::Database schema qualified tables" do
589
488
  POSTGRES_DB.table_exists?(:schema_test).should == true
590
489
  POSTGRES_DB.tables.should == [:schema_test]
591
490
  POSTGRES_DB.primary_key(:schema_test__schema_test).should == 'i'
592
- POSTGRES_DB.primary_key_sequence(:schema_test__schema_test).should == '"schema_test"."schema_test_i_seq"'
491
+ POSTGRES_DB.primary_key_sequence(:schema_test__schema_test).should == '"schema_test".schema_test_i_seq'
593
492
  end
594
493
  end
595
494
 
@@ -637,9 +536,9 @@ context "Postgres::Database functions, languages, and triggers" do
637
536
  @d.drop_function('tf', :if_exists=>true, :cascade=>true)
638
537
  @d.drop_function('tf', :if_exists=>true, :cascade=>true, :args=>%w'integer integer')
639
538
  @d.drop_language(:plpgsql, :if_exists=>true, :cascade=>true)
640
- @d.drop_trigger(:test5, :identity, :if_exists=>true, :cascade=>true)
539
+ @d.drop_table(:test) rescue nil
641
540
  end
642
-
541
+
643
542
  specify "#create_function and #drop_function should create and drop functions" do
644
543
  proc{@d['SELECT tf()'].all}.should raise_error(Sequel::DatabaseError)
645
544
  args = ['tf', 'SELECT 1', {:returns=>:integer}]
@@ -682,6 +581,7 @@ context "Postgres::Database functions, languages, and triggers" do
682
581
  @d.create_language(:plpgsql)
683
582
  @d.create_function(:tf, 'BEGIN IF NEW.value IS NULL THEN RAISE EXCEPTION \'Blah\'; END IF; RETURN NEW; END;', :language=>:plpgsql, :returns=>:trigger)
684
583
  @d.send(:create_trigger_sql, :test, :identity, :tf, :each_row=>true).should == 'CREATE TRIGGER identity BEFORE INSERT OR UPDATE OR DELETE ON public.test FOR EACH ROW EXECUTE PROCEDURE tf()'
584
+ @d.create_table(:test){String :name; Integer :value}
685
585
  @d.create_trigger(:test, :identity, :tf, :each_row=>true)
686
586
  @d[:test].insert(:name=>'a', :value=>1)
687
587
  @d[:test].filter(:name=>'a').all.should == [{:name=>'a', :value=>1}]