sequel 2.9.0 → 2.10.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.
Files changed (78) hide show
  1. data/CHANGELOG +56 -0
  2. data/{README → README.rdoc} +85 -57
  3. data/Rakefile +10 -5
  4. data/bin/sequel +7 -16
  5. data/doc/advanced_associations.rdoc +5 -17
  6. data/doc/cheat_sheet.rdoc +18 -20
  7. data/doc/dataset_filtering.rdoc +8 -32
  8. data/doc/schema.rdoc +20 -0
  9. data/lib/sequel_core.rb +35 -1
  10. data/lib/sequel_core/adapters/ado.rb +1 -1
  11. data/lib/sequel_core/adapters/db2.rb +2 -2
  12. data/lib/sequel_core/adapters/dbi.rb +2 -11
  13. data/lib/sequel_core/adapters/do.rb +205 -0
  14. data/lib/sequel_core/adapters/do/mysql.rb +38 -0
  15. data/lib/sequel_core/adapters/do/postgres.rb +92 -0
  16. data/lib/sequel_core/adapters/do/sqlite.rb +31 -0
  17. data/lib/sequel_core/adapters/firebird.rb +298 -0
  18. data/lib/sequel_core/adapters/informix.rb +10 -1
  19. data/lib/sequel_core/adapters/jdbc.rb +78 -19
  20. data/lib/sequel_core/adapters/jdbc/h2.rb +69 -0
  21. data/lib/sequel_core/adapters/jdbc/mysql.rb +10 -0
  22. data/lib/sequel_core/adapters/jdbc/postgresql.rb +7 -3
  23. data/lib/sequel_core/adapters/mysql.rb +53 -77
  24. data/lib/sequel_core/adapters/odbc.rb +1 -1
  25. data/lib/sequel_core/adapters/openbase.rb +1 -1
  26. data/lib/sequel_core/adapters/oracle.rb +2 -2
  27. data/lib/sequel_core/adapters/postgres.rb +16 -14
  28. data/lib/sequel_core/adapters/shared/mysql.rb +44 -9
  29. data/lib/sequel_core/adapters/shared/oracle.rb +4 -5
  30. data/lib/sequel_core/adapters/shared/postgres.rb +86 -82
  31. data/lib/sequel_core/adapters/shared/sqlite.rb +39 -24
  32. data/lib/sequel_core/adapters/sqlite.rb +11 -1
  33. data/lib/sequel_core/connection_pool.rb +10 -2
  34. data/lib/sequel_core/core_sql.rb +13 -3
  35. data/lib/sequel_core/database.rb +131 -30
  36. data/lib/sequel_core/database/schema.rb +5 -5
  37. data/lib/sequel_core/dataset.rb +31 -6
  38. data/lib/sequel_core/dataset/convenience.rb +11 -11
  39. data/lib/sequel_core/dataset/query.rb +2 -2
  40. data/lib/sequel_core/dataset/sql.rb +6 -6
  41. data/lib/sequel_core/exceptions.rb +4 -0
  42. data/lib/sequel_core/migration.rb +4 -4
  43. data/lib/sequel_core/schema/generator.rb +19 -3
  44. data/lib/sequel_core/schema/sql.rb +24 -20
  45. data/lib/sequel_core/sql.rb +13 -16
  46. data/lib/sequel_core/version.rb +11 -0
  47. data/lib/sequel_model.rb +2 -0
  48. data/lib/sequel_model/base.rb +2 -2
  49. data/lib/sequel_model/hooks.rb +46 -7
  50. data/lib/sequel_model/record.rb +11 -9
  51. data/lib/sequel_model/schema.rb +1 -1
  52. data/lib/sequel_model/validations.rb +72 -61
  53. data/spec/adapters/firebird_spec.rb +371 -0
  54. data/spec/adapters/mysql_spec.rb +118 -62
  55. data/spec/adapters/oracle_spec.rb +5 -5
  56. data/spec/adapters/postgres_spec.rb +33 -18
  57. data/spec/adapters/sqlite_spec.rb +2 -2
  58. data/spec/integration/dataset_test.rb +3 -3
  59. data/spec/integration/schema_test.rb +55 -5
  60. data/spec/integration/spec_helper.rb +11 -0
  61. data/spec/integration/type_test.rb +59 -16
  62. data/spec/sequel_core/connection_pool_spec.rb +14 -0
  63. data/spec/sequel_core/core_sql_spec.rb +24 -14
  64. data/spec/sequel_core/database_spec.rb +96 -11
  65. data/spec/sequel_core/dataset_spec.rb +97 -37
  66. data/spec/sequel_core/expression_filters_spec.rb +51 -40
  67. data/spec/sequel_core/object_graph_spec.rb +2 -2
  68. data/spec/sequel_core/schema_generator_spec.rb +31 -6
  69. data/spec/sequel_core/schema_spec.rb +25 -9
  70. data/spec/sequel_core/spec_helper.rb +4 -1
  71. data/spec/sequel_core/version_spec.rb +7 -0
  72. data/spec/sequel_model/associations_spec.rb +1 -1
  73. data/spec/sequel_model/hooks_spec.rb +68 -13
  74. data/spec/sequel_model/model_spec.rb +4 -4
  75. data/spec/sequel_model/record_spec.rb +22 -0
  76. data/spec/sequel_model/spec_helper.rb +2 -1
  77. data/spec/sequel_model/validations_spec.rb +107 -7
  78. metadata +15 -5
@@ -33,6 +33,29 @@ def logger.method_missing(m, msg)
33
33
  end
34
34
  MYSQL_DB.logger = logger
35
35
 
36
+ if MYSQL_DB.class.adapter_scheme == :do
37
+ SQL_BEGIN = 'Transaction.begin'
38
+ SQL_ROLLBACK = 'Transaction.rollback'
39
+ SQL_COMMIT = 'Transaction.commit'
40
+ else
41
+ SQL_BEGIN = 'BEGIN'
42
+ SQL_ROLLBACK = 'ROLLBACK'
43
+ SQL_COMMIT = 'COMMIT'
44
+ end
45
+
46
+ context "MySQL", '#create_table' do
47
+ setup do
48
+ @db = MYSQL_DB
49
+ end
50
+ after(:each) do
51
+ @db.drop_table :dolls
52
+ end
53
+ specify "should allow to specify options for MySQL" do
54
+ @db.create_table(:dolls, :engine => 'MyISAM', :charset => 'latin2') { text :name }
55
+ @db.sqls.should == ["CREATE TABLE dolls (name text) ENGINE=MyISAM DEFAULT CHARSET=latin2"]
56
+ end
57
+ end
58
+
36
59
  context "A MySQL database" do
37
60
  setup do
38
61
  @db = MYSQL_DB
@@ -142,13 +165,13 @@ context "A MySQL dataset" do
142
165
  @d.select('COUNT(*)'.lit).sql.should == \
143
166
  'SELECT COUNT(*) FROM `items`'
144
167
 
145
- @d.select(:max[:value]).sql.should == \
168
+ @d.select(:max.sql_function(:value)).sql.should == \
146
169
  'SELECT max(`value`) FROM `items`'
147
170
 
148
- @d.select(:NOW[]).sql.should == \
171
+ @d.select(:NOW.sql_function).sql.should == \
149
172
  'SELECT NOW() FROM `items`'
150
173
 
151
- @d.select(:max[:items__value]).sql.should == \
174
+ @d.select(:max.sql_function(:items__value)).sql.should == \
152
175
  'SELECT max(`items`.`value`) FROM `items`'
153
176
 
154
177
  @d.order(:name.desc).sql.should == \
@@ -163,13 +186,13 @@ context "A MySQL dataset" do
163
186
  @d.select('max(items.`name`) AS `max_name`'.lit).sql.should == \
164
187
  'SELECT max(items.`name`) AS `max_name` FROM `items`'
165
188
 
166
- @d.select(:test[:abc, 'hello']).sql.should == \
189
+ @d.select(:test.sql_function(:abc, 'hello')).sql.should == \
167
190
  "SELECT test(`abc`, 'hello') FROM `items`"
168
191
 
169
- @d.select(:test[:abc__def, 'hello']).sql.should == \
192
+ @d.select(:test.sql_function(:abc__def, 'hello')).sql.should == \
170
193
  "SELECT test(`abc`.`def`, 'hello') FROM `items`"
171
194
 
172
- @d.select(:test[:abc__def, 'hello'].as(:x2)).sql.should == \
195
+ @d.select(:test.sql_function(:abc__def, 'hello').as(:x2)).sql.should == \
173
196
  "SELECT test(`abc`.`def`, 'hello') AS `x2` FROM `items`"
174
197
 
175
198
  @d.insert_sql(:value => 333).should == \
@@ -220,7 +243,7 @@ context "A MySQL dataset" do
220
243
  end
221
244
  end.should raise_error(Interrupt)
222
245
 
223
- MYSQL_DB.sqls.should == ['BEGIN', "INSERT INTO items (name) VALUES ('abc')", 'ROLLBACK']
246
+ MYSQL_DB.sqls.should == [SQL_BEGIN, "INSERT INTO items (name) VALUES ('abc')", SQL_ROLLBACK]
224
247
  end
225
248
 
226
249
  specify "should handle returning inside of the block by committing" do
@@ -232,7 +255,7 @@ context "A MySQL dataset" do
232
255
  end
233
256
  end
234
257
  MYSQL_DB.ret_commit
235
- MYSQL_DB.sqls.should == ['BEGIN', "INSERT INTO items (name) VALUES ('abc')", 'COMMIT']
258
+ MYSQL_DB.sqls.should == [SQL_BEGIN, "INSERT INTO items (name) VALUES ('abc')", SQL_COMMIT]
236
259
  end
237
260
 
238
261
  specify "should support regexps" do
@@ -263,9 +286,9 @@ context "MySQL datasets" do
263
286
  market = 'ICE'
264
287
  ack_stamp = Time.now - 15 * 60 # 15 minutes ago
265
288
  @d.query do
266
- select :market, :minute[:from_unixtime[:ack]].as(:minute)
267
- where {(:ack > ack_stamp) & {:market => market}}
268
- group_by :minute[:from_unixtime[:ack]]
289
+ select :market, :minute.sql_function(:from_unixtime.sql_function(:ack)).as(:minute)
290
+ where {(:ack.sql_number > ack_stamp) & {:market => market}}
291
+ group_by :minute.sql_function(:from_unixtime.sql_function(:ack))
269
292
  end.sql.should == \
270
293
  "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`))"
271
294
  end
@@ -295,21 +318,6 @@ context "MySQL datasets" do
295
318
  end
296
319
  end
297
320
 
298
- # # Commented out because it was causing subsequent examples to fail for some reason
299
- # context "Simple stored procedure test" do
300
- # setup do
301
- # # Create a simple stored procedure but drop it first if there
302
- # MYSQL_DB.execute("DROP PROCEDURE IF EXISTS sp_get_server_id;")
303
- # MYSQL_DB.execute("CREATE PROCEDURE sp_get_server_id() SQL SECURITY DEFINER SELECT @@SERVER_ID as server_id;")
304
- # end
305
- #
306
- # specify "should return the server-id via a stored procedure call" do
307
- # @server_id = MYSQL_DB["SELECT @@SERVER_ID as server_id;"].first[:server_id] # grab the server_id via a simple query
308
- # @server_id_by_sp = MYSQL_DB["CALL sp_get_server_id();"].first[:server_id]
309
- # @server_id_by_sp.should == @server_id # compare it to output from stored procedure
310
- # end
311
- # end
312
- #
313
321
  context "MySQL join expressions" do
314
322
  setup do
315
323
  @ds = MYSQL_DB[:nodes]
@@ -452,6 +460,52 @@ context "A MySQL database" do
452
460
  end
453
461
  end
454
462
 
463
+ context "A MySQL database", "with table options" do
464
+ before(:all) do
465
+ @options = {}
466
+ @options[:engine] = 'MyISAM'
467
+ @options[:charset] = 'latin2'
468
+ @options[:collate] = 'swedish'
469
+
470
+ Sequel::MySQL.default_engine = 'InnoDB'
471
+ Sequel::MySQL.default_charset = 'utf8'
472
+ Sequel::MySQL.default_collate = 'utf8'
473
+
474
+ @db = MYSQL_DB
475
+ @g = Sequel::Schema::Generator.new(@db) do
476
+ integer :size
477
+ text :name
478
+ end
479
+ end
480
+
481
+ after(:all) do
482
+ Sequel::MySQL.default_engine = nil
483
+ Sequel::MySQL.default_charset = nil
484
+ Sequel::MySQL.default_collate = nil
485
+ end
486
+
487
+ specify "should allow to pass custom options (engine, charset, collate) for table creation" do
488
+ statements = @db.create_table_sql_list(:items, *(@g.create_info << @options))
489
+ statements.should == [
490
+ "CREATE TABLE items (size integer, name text) ENGINE=MyISAM DEFAULT CHARSET=latin2 DEFAULT COLLATE=swedish"
491
+ ]
492
+ end
493
+
494
+ specify "should use default options if specified (engine, charset, collate) for table creation" do
495
+ statements = @db.create_table_sql_list(:items, *(@g.create_info))
496
+ statements.should == [
497
+ "CREATE TABLE items (size integer, name text) ENGINE=InnoDB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8"
498
+ ]
499
+ end
500
+
501
+ specify "should not use default if option has a nil value" do
502
+ statements = @db.create_table_sql_list(:items, *(@g.create_info << {:engine=>nil, :charset=>nil, :collate=>nil}))
503
+ statements.should == [
504
+ "CREATE TABLE items (size integer, name text)"
505
+ ]
506
+ end
507
+ end
508
+
455
509
  context "A MySQL database" do
456
510
  setup do
457
511
  @db = MYSQL_DB
@@ -510,7 +564,7 @@ end
510
564
  end
511
565
 
512
566
  # Socket tests should only be run if the MySQL server is on localhost
513
- if %w'localhost 127.0.0.1 ::1'.include? MYSQL_URI.host
567
+ if %w'localhost 127.0.0.1 ::1'.include?(MYSQL_URI.host) and MYSQL_DB.class.adapter_scheme == :mysql
514
568
  context "A MySQL database" do
515
569
  specify "should accept a socket option" do
516
570
  db = Sequel.mysql(MYSQL_DB.opts[:database], :host => 'localhost', :user => MYSQL_DB.opts[:user], :password => MYSQL_DB.opts[:password], :socket => MYSQL_SOCKET_FILE)
@@ -667,9 +721,9 @@ context "MySQL::Dataset#multi_insert" do
667
721
  @d.multi_insert([{:name => 'abc'}, {:name => 'def'}])
668
722
 
669
723
  MYSQL_DB.sqls.should == [
670
- 'BEGIN',
724
+ SQL_BEGIN,
671
725
  "INSERT INTO items (name) VALUES ('abc'), ('def')",
672
- 'COMMIT'
726
+ SQL_COMMIT
673
727
  ]
674
728
 
675
729
  @d.all.should == [
@@ -682,12 +736,12 @@ context "MySQL::Dataset#multi_insert" do
682
736
  :commit_every => 2)
683
737
 
684
738
  MYSQL_DB.sqls.should == [
685
- 'BEGIN',
739
+ SQL_BEGIN,
686
740
  "INSERT INTO items (value) VALUES (1), (2)",
687
- 'COMMIT',
688
- 'BEGIN',
741
+ SQL_COMMIT,
742
+ SQL_BEGIN,
689
743
  "INSERT INTO items (value) VALUES (3), (4)",
690
- 'COMMIT'
744
+ SQL_COMMIT
691
745
  ]
692
746
 
693
747
  @d.all.should == [
@@ -703,12 +757,12 @@ context "MySQL::Dataset#multi_insert" do
703
757
  :slice => 2)
704
758
 
705
759
  MYSQL_DB.sqls.should == [
706
- 'BEGIN',
760
+ SQL_BEGIN,
707
761
  "INSERT INTO items (value) VALUES (1), (2)",
708
- 'COMMIT',
709
- 'BEGIN',
762
+ SQL_COMMIT,
763
+ SQL_BEGIN,
710
764
  "INSERT INTO items (value) VALUES (3), (4)",
711
- 'COMMIT'
765
+ SQL_COMMIT
712
766
  ]
713
767
 
714
768
  @d.all.should == [
@@ -723,9 +777,9 @@ context "MySQL::Dataset#multi_insert" do
723
777
  @d.multi_insert([:name, :value], [['abc', 1], ['def', 2]])
724
778
 
725
779
  MYSQL_DB.sqls.should == [
726
- 'BEGIN',
780
+ SQL_BEGIN,
727
781
  "INSERT INTO items (name, value) VALUES ('abc', 1), ('def', 2)",
728
- 'COMMIT'
782
+ SQL_COMMIT
729
783
  ]
730
784
 
731
785
  @d.all.should == [
@@ -778,7 +832,7 @@ context "MySQL::Dataset#complex_expression_sql" do
778
832
  specify "should handle string concatenation with CONCAT if more than one record" do
779
833
  @d.literal([:x, :y].sql_string_join).should == "CONCAT(x, y)"
780
834
  @d.literal([:x, :y].sql_string_join(' ')).should == "CONCAT(x, ' ', y)"
781
- @d.literal([:x[:y], 1, 'z'.lit].sql_string_join(:y|1)).should == "CONCAT(x(y), y[1], '1', y[1], z)"
835
+ @d.literal([:x.sql_function(:y), 1, 'z'.lit].sql_string_join(:y|1)).should == "CONCAT(x(y), y[1], '1', y[1], z)"
782
836
  end
783
837
 
784
838
  specify "should handle string concatenation as simple string if just one record" do
@@ -787,27 +841,29 @@ context "MySQL::Dataset#complex_expression_sql" do
787
841
  end
788
842
  end
789
843
 
790
- context "MySQL Stored Procedures" do
791
- teardown do
792
- MYSQL_DB.execute('DROP PROCEDURE test_sproc')
793
- end
794
-
795
- specify "should be callable on the database object" do
796
- MYSQL_DB.execute('CREATE PROCEDURE test_sproc() BEGIN DELETE FROM items; END')
797
- MYSQL_DB[:items].delete
798
- MYSQL_DB[:items].insert(:value=>1)
799
- MYSQL_DB[:items].count.should == 1
800
- MYSQL_DB.call_sproc(:test_sproc)
801
- MYSQL_DB[:items].count.should == 0
802
- end
803
-
804
- specify "should be callable on the dataset object" do
805
- MYSQL_DB.execute('CREATE PROCEDURE test_sproc(a INTEGER) BEGIN SELECT *, a AS b FROM items; END')
806
- @d = MYSQL_DB[:items]
807
- @d.call_sproc(:select, :test_sproc, 3).should == []
808
- @d.insert(:value=>1)
809
- @d.call_sproc(:select, :test_sproc, 4).should == [{:id=>nil, :value=>1, :b=>4}]
810
- @d.row_proc = proc{|r| r.keys.each{|k| r[k] *= 2 if r[k].is_a?(Integer)}; r}
811
- @d.call_sproc(:select, :test_sproc, 3).should == [{:id=>nil, :value=>2, :b=>6}]
844
+ unless MYSQL_DB.class.adapter_scheme == :do
845
+ context "MySQL Stored Procedures" do
846
+ teardown do
847
+ MYSQL_DB.execute('DROP PROCEDURE test_sproc')
848
+ end
849
+
850
+ specify "should be callable on the database object" do
851
+ MYSQL_DB.execute('CREATE PROCEDURE test_sproc() BEGIN DELETE FROM items; END')
852
+ MYSQL_DB[:items].delete
853
+ MYSQL_DB[:items].insert(:value=>1)
854
+ MYSQL_DB[:items].count.should == 1
855
+ MYSQL_DB.call_sproc(:test_sproc)
856
+ MYSQL_DB[:items].count.should == 0
857
+ end
858
+
859
+ specify "should be callable on the dataset object" do
860
+ MYSQL_DB.execute('CREATE PROCEDURE test_sproc(a INTEGER) BEGIN SELECT *, a AS b FROM items; END')
861
+ @d = MYSQL_DB[:items]
862
+ @d.call_sproc(:select, :test_sproc, 3).should == []
863
+ @d.insert(:value=>1)
864
+ @d.call_sproc(:select, :test_sproc, 4).should == [{:id=>nil, :value=>1, :b=>4}]
865
+ @d.row_proc = proc{|r| r.keys.each{|k| r[k] *= 2 if r[k].is_a?(Integer)}; r}
866
+ @d.call_sproc(:select, :test_sproc, 3).should == [{:id=>nil, :value=>2, :b=>6}]
867
+ end
812
868
  end
813
869
  end
@@ -113,25 +113,25 @@ context "An Oracle dataset" do
113
113
 
114
114
  @d.max(:value).to_i.should == 789
115
115
 
116
- @d.select(:name, :AVG[:value]).filter(:name => 'abc').group(:name).to_a.should == [
116
+ @d.select(:name, :AVG.sql_function(:value)).filter(:name => 'abc').group(:name).to_a.should == [
117
117
  {:name => 'abc', :"avg(value)" => (456+123)/2.0}
118
118
  ]
119
119
 
120
- @d.select(:AVG[:value]).group(:name).order(:name).limit(1).to_a.should == [
120
+ @d.select(:AVG.sql_function(:value)).group(:name).order(:name).limit(1).to_a.should == [
121
121
  {:"avg(value)" => (456+123)/2.0}
122
122
  ]
123
123
 
124
- @d.select(:name, :AVG[:value]).group(:name).order(:name).to_a.should == [
124
+ @d.select(:name, :AVG.sql_function(:value)).group(:name).order(:name).to_a.should == [
125
125
  {:name => 'abc', :"avg(value)" => (456+123)/2.0},
126
126
  {:name => 'def', :"avg(value)" => 789*1.0}
127
127
  ]
128
128
 
129
- @d.select(:name, :AVG[:value]).group(:name).order(:name).to_a.should == [
129
+ @d.select(:name, :AVG.sql_function(:value)).group(:name).order(:name).to_a.should == [
130
130
  {:name => 'abc', :"avg(value)" => (456+123)/2.0},
131
131
  {:name => 'def', :"avg(value)" => 789*1.0}
132
132
  ]
133
133
 
134
- @d.select(:name, :AVG[:value]).group(:name).having(:name => ['abc', 'def']).order(:name).to_a.should == [
134
+ @d.select(:name, :AVG.sql_function(:value)).group(:name).having(:name => ['abc', 'def']).order(:name).to_a.should == [
135
135
  {:name => 'abc', :"avg(value)" => (456+123)/2.0},
136
136
  {:name => 'def', :"avg(value)" => 789*1.0}
137
137
  ]
@@ -4,7 +4,7 @@ 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
-
7
+ #POSTGRES_DB.instance_variable_set(:@server_version, 80100)
8
8
  POSTGRES_DB.create_table! :test do
9
9
  text :name
10
10
  integer :value, :index => true
@@ -125,13 +125,13 @@ context "A PostgreSQL dataset" do
125
125
  @d.select('COUNT(*)'.lit).sql.should == \
126
126
  'SELECT COUNT(*) FROM "test"'
127
127
 
128
- @d.select(:max[:value]).sql.should == \
128
+ @d.select(:max.sql_function(:value)).sql.should == \
129
129
  'SELECT max("value") FROM "test"'
130
130
 
131
- @d.select(:NOW[]).sql.should == \
131
+ @d.select(:NOW.sql_function).sql.should == \
132
132
  'SELECT NOW() FROM "test"'
133
133
 
134
- @d.select(:max[:items__value]).sql.should == \
134
+ @d.select(:max.sql_function(:items__value)).sql.should == \
135
135
  'SELECT max("items"."value") FROM "test"'
136
136
 
137
137
  @d.order(:name.desc).sql.should == \
@@ -146,13 +146,13 @@ context "A PostgreSQL dataset" do
146
146
  @d.select('max(test."name") AS "max_name"'.lit).sql.should == \
147
147
  'SELECT max(test."name") AS "max_name" FROM "test"'
148
148
 
149
- @d.select(:test[:abc, 'hello']).sql.should == \
149
+ @d.select(:test.sql_function(:abc, 'hello')).sql.should == \
150
150
  "SELECT test(\"abc\", 'hello') FROM \"test\""
151
151
 
152
- @d.select(:test[:abc__def, 'hello']).sql.should == \
152
+ @d.select(:test.sql_function(:abc__def, 'hello')).sql.should == \
153
153
  "SELECT test(\"abc\".\"def\", 'hello') FROM \"test\""
154
154
 
155
- @d.select(:test[:abc__def, 'hello'].as(:x2)).sql.should == \
155
+ @d.select(:test.sql_function(:abc__def, 'hello').as(:x2)).sql.should == \
156
156
  "SELECT test(\"abc\".\"def\", 'hello') AS \"x2\" FROM \"test\""
157
157
 
158
158
  @d.insert_sql(:value => 333).should =~ \
@@ -260,6 +260,10 @@ context "A PostgreSQL dataset" do
260
260
  POSTGRES_DB['SELECT ? AS a', "\\dingo"].get(:a) == "\\dingo"
261
261
  end
262
262
 
263
+ specify "should correctly escape strings with quotes" do
264
+ POSTGRES_DB['SELECT ? AS a', "\\'dingo"].get(:a) == "\\'dingo"
265
+ end
266
+
263
267
  specify "should properly escape binary data" do
264
268
  POSTGRES_DB['SELECT ? AS a', "\1\2\3".to_blob].get(:a) == "\1\2\3"
265
269
  end
@@ -343,7 +347,7 @@ context "A PostgreSQL database" do
343
347
  full_text_index [:title, :body]
344
348
  end
345
349
  POSTGRES_DB.create_table_sql_list(:posts, *g.create_info).should == [
346
- "CREATE TABLE public.posts (title text, body text)",
350
+ "CREATE TABLE posts (title text, body text)",
347
351
  "CREATE INDEX posts_title_body_index ON posts USING gin (to_tsvector('simple', (COALESCE(title, '') || ' ' || COALESCE(body, ''))))"
348
352
  ]
349
353
  end
@@ -355,7 +359,7 @@ context "A PostgreSQL database" do
355
359
  full_text_index [:title, :body], :language => 'french'
356
360
  end
357
361
  POSTGRES_DB.create_table_sql_list(:posts, *g.create_info).should == [
358
- "CREATE TABLE public.posts (title text, body text)",
362
+ "CREATE TABLE posts (title text, body text)",
359
363
  "CREATE INDEX posts_title_body_index ON posts USING gin (to_tsvector('french', (COALESCE(title, '') || ' ' || COALESCE(body, ''))))"
360
364
  ]
361
365
  end
@@ -377,7 +381,7 @@ context "A PostgreSQL database" do
377
381
  spatial_index [:geom]
378
382
  end
379
383
  POSTGRES_DB.create_table_sql_list(:posts, *g.create_info).should == [
380
- "CREATE TABLE public.posts (geom geometry)",
384
+ "CREATE TABLE posts (geom geometry)",
381
385
  "CREATE INDEX posts_geom_index ON posts USING gist (geom)"
382
386
  ]
383
387
  end
@@ -388,7 +392,7 @@ context "A PostgreSQL database" do
388
392
  index :title, :type => 'hash'
389
393
  end
390
394
  POSTGRES_DB.create_table_sql_list(:posts, *g.create_info).should == [
391
- "CREATE TABLE public.posts (title varchar(5))",
395
+ "CREATE TABLE posts (title varchar(5))",
392
396
  "CREATE INDEX posts_title_index ON posts USING hash (title)"
393
397
  ]
394
398
  end
@@ -399,7 +403,7 @@ context "A PostgreSQL database" do
399
403
  index :title, :type => 'hash', :unique => true
400
404
  end
401
405
  POSTGRES_DB.create_table_sql_list(:posts, *g.create_info).should == [
402
- "CREATE TABLE public.posts (title varchar(5))",
406
+ "CREATE TABLE posts (title varchar(5))",
403
407
  "CREATE UNIQUE INDEX posts_title_index ON posts USING hash (title)"
404
408
  ]
405
409
  end
@@ -410,10 +414,21 @@ context "A PostgreSQL database" do
410
414
  index :title, :where => {:something => 5}
411
415
  end
412
416
  POSTGRES_DB.create_table_sql_list(:posts, *g.create_info).should == [
413
- "CREATE TABLE public.posts (title varchar(5))",
417
+ "CREATE TABLE posts (title varchar(5))",
414
418
  "CREATE INDEX posts_title_index ON posts (title) WHERE (something = 5)"
415
419
  ]
416
420
  end
421
+
422
+ specify "should support identifiers for table names in indicies" do
423
+ g = Sequel::Schema::Generator.new(POSTGRES_DB) do
424
+ varchar :title, :size => 5
425
+ index :title, :where => {:something => 5}
426
+ end
427
+ POSTGRES_DB.create_table_sql_list(Sequel::SQL::Identifier.new(:posts__test), *g.create_info).should == [
428
+ "CREATE TABLE posts__test (title varchar(5))",
429
+ "CREATE INDEX posts__test_title_index ON posts__test (title) WHERE (something = 5)"
430
+ ]
431
+ end
417
432
  end
418
433
 
419
434
  context "Postgres::Dataset#multi_insert_sql / #import" do
@@ -542,18 +557,18 @@ context "Postgres::Database schema qualified tables" do
542
557
 
543
558
  specify "should be able to get primary keys for tables in a given schema" do
544
559
  POSTGRES_DB.create_table(:schema_test__schema_test){primary_key :i}
545
- POSTGRES_DB.synchronize{|c| POSTGRES_DB.send(:primary_key_for_table, c, :schema_test__schema_test).should == 'i'}
560
+ POSTGRES_DB.primary_key(:schema_test__schema_test).should == 'i'
546
561
  end
547
562
 
548
563
  specify "should be able to get serial sequences for tables in a given schema" do
549
564
  POSTGRES_DB.create_table(:schema_test__schema_test){primary_key :i}
550
- POSTGRES_DB.synchronize{|c| POSTGRES_DB.send(:primary_key_sequence_for_table, c, :schema_test__schema_test).should == '"schema_test"."schema_test_i_seq"'}
565
+ POSTGRES_DB.primary_key_sequence(:schema_test__schema_test).should == '"schema_test"."schema_test_i_seq"'
551
566
  end
552
567
 
553
568
  specify "should be able to get custom sequences for tables in a given schema" do
554
569
  POSTGRES_DB << "CREATE SEQUENCE schema_test.kseq"
555
570
  POSTGRES_DB.create_table(:schema_test__schema_test){integer :j; primary_key :k, :type=>:integer, :default=>"nextval('schema_test.kseq'::regclass)".lit}
556
- POSTGRES_DB.synchronize{|c| POSTGRES_DB.send(:primary_key_sequence_for_table, c, :schema_test__schema_test).should == '"schema_test"."kseq"'}
571
+ POSTGRES_DB.primary_key_sequence(:schema_test__schema_test).should == '"schema_test"."kseq"'
557
572
  end
558
573
 
559
574
  specify "#default_schema= should change the default schema used from public" do
@@ -561,8 +576,8 @@ context "Postgres::Database schema qualified tables" do
561
576
  POSTGRES_DB.default_schema = :schema_test
562
577
  POSTGRES_DB.table_exists?(:schema_test).should == true
563
578
  POSTGRES_DB.tables.should == [:schema_test]
564
- POSTGRES_DB.synchronize{|c| POSTGRES_DB.send(:primary_key_for_table, c, :schema_test).should == 'i'}
565
- POSTGRES_DB.synchronize{|c| POSTGRES_DB.send(:primary_key_sequence_for_table, c, :schema_test).should == '"schema_test"."schema_test_i_seq"'}
579
+ POSTGRES_DB.primary_key(:schema_test__schema_test).should == 'i'
580
+ POSTGRES_DB.primary_key_sequence(:schema_test__schema_test).should == '"schema_test"."schema_test_i_seq"'
566
581
  end
567
582
  end
568
583