sequel 5.6.0 → 5.7.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 (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +30 -5099
  3. data/Rakefile +1 -1
  4. data/doc/opening_databases.rdoc +0 -2
  5. data/doc/postgresql.rdoc +31 -0
  6. data/doc/querying.rdoc +2 -2
  7. data/doc/release_notes/5.7.0.txt +108 -0
  8. data/doc/testing.rdoc +1 -0
  9. data/lib/sequel/adapters/jdbc/derby.rb +1 -1
  10. data/lib/sequel/adapters/jdbc/oracle.rb +11 -0
  11. data/lib/sequel/adapters/postgres.rb +1 -0
  12. data/lib/sequel/adapters/shared/postgres.rb +117 -13
  13. data/lib/sequel/connection_pool/sharded_threaded.rb +7 -6
  14. data/lib/sequel/connection_pool/threaded.rb +6 -6
  15. data/lib/sequel/core.rb +20 -0
  16. data/lib/sequel/database/logging.rb +3 -2
  17. data/lib/sequel/database/schema_generator.rb +1 -2
  18. data/lib/sequel/dataset/actions.rb +15 -5
  19. data/lib/sequel/extensions/connection_expiration.rb +3 -3
  20. data/lib/sequel/extensions/connection_validator.rb +3 -3
  21. data/lib/sequel/extensions/integer64.rb +30 -0
  22. data/lib/sequel/extensions/migration.rb +2 -3
  23. data/lib/sequel/plugins/pg_array_associations.rb +5 -3
  24. data/lib/sequel/plugins/validate_associated.rb +18 -0
  25. data/lib/sequel/version.rb +1 -1
  26. data/spec/adapters/mssql_spec.rb +6 -6
  27. data/spec/adapters/mysql_spec.rb +1 -1
  28. data/spec/adapters/oracle_spec.rb +15 -1
  29. data/spec/adapters/postgres_spec.rb +78 -1
  30. data/spec/adapters/spec_helper.rb +3 -1
  31. data/spec/bin_spec.rb +1 -0
  32. data/spec/core/dataset_spec.rb +10 -0
  33. data/spec/extensions/integer64_spec.rb +22 -0
  34. data/spec/extensions/pg_array_associations_spec.rb +14 -2
  35. data/spec/extensions/spec_helper.rb +1 -0
  36. data/spec/integration/associations_test.rb +4 -4
  37. data/spec/integration/dataset_test.rb +2 -0
  38. data/spec/integration/spec_helper.rb +5 -11
  39. data/spec/model/spec_helper.rb +1 -0
  40. metadata +35 -165
  41. data/doc/release_notes/1.0.txt +0 -38
  42. data/doc/release_notes/1.1.txt +0 -143
  43. data/doc/release_notes/1.3.txt +0 -101
  44. data/doc/release_notes/1.4.0.txt +0 -53
  45. data/doc/release_notes/1.5.0.txt +0 -155
  46. data/doc/release_notes/2.0.0.txt +0 -298
  47. data/doc/release_notes/2.1.0.txt +0 -271
  48. data/doc/release_notes/2.10.0.txt +0 -328
  49. data/doc/release_notes/2.11.0.txt +0 -215
  50. data/doc/release_notes/2.12.0.txt +0 -534
  51. data/doc/release_notes/2.2.0.txt +0 -253
  52. data/doc/release_notes/2.3.0.txt +0 -88
  53. data/doc/release_notes/2.4.0.txt +0 -106
  54. data/doc/release_notes/2.5.0.txt +0 -137
  55. data/doc/release_notes/2.6.0.txt +0 -157
  56. data/doc/release_notes/2.7.0.txt +0 -166
  57. data/doc/release_notes/2.8.0.txt +0 -171
  58. data/doc/release_notes/2.9.0.txt +0 -97
  59. data/doc/release_notes/3.0.0.txt +0 -221
  60. data/doc/release_notes/3.1.0.txt +0 -406
  61. data/doc/release_notes/3.10.0.txt +0 -286
  62. data/doc/release_notes/3.11.0.txt +0 -254
  63. data/doc/release_notes/3.12.0.txt +0 -304
  64. data/doc/release_notes/3.13.0.txt +0 -210
  65. data/doc/release_notes/3.14.0.txt +0 -118
  66. data/doc/release_notes/3.15.0.txt +0 -78
  67. data/doc/release_notes/3.16.0.txt +0 -45
  68. data/doc/release_notes/3.17.0.txt +0 -58
  69. data/doc/release_notes/3.18.0.txt +0 -120
  70. data/doc/release_notes/3.19.0.txt +0 -67
  71. data/doc/release_notes/3.2.0.txt +0 -268
  72. data/doc/release_notes/3.20.0.txt +0 -41
  73. data/doc/release_notes/3.21.0.txt +0 -87
  74. data/doc/release_notes/3.22.0.txt +0 -39
  75. data/doc/release_notes/3.23.0.txt +0 -172
  76. data/doc/release_notes/3.24.0.txt +0 -420
  77. data/doc/release_notes/3.25.0.txt +0 -88
  78. data/doc/release_notes/3.26.0.txt +0 -88
  79. data/doc/release_notes/3.27.0.txt +0 -82
  80. data/doc/release_notes/3.28.0.txt +0 -304
  81. data/doc/release_notes/3.29.0.txt +0 -459
  82. data/doc/release_notes/3.3.0.txt +0 -192
  83. data/doc/release_notes/3.30.0.txt +0 -135
  84. data/doc/release_notes/3.31.0.txt +0 -146
  85. data/doc/release_notes/3.32.0.txt +0 -202
  86. data/doc/release_notes/3.33.0.txt +0 -157
  87. data/doc/release_notes/3.34.0.txt +0 -671
  88. data/doc/release_notes/3.35.0.txt +0 -144
  89. data/doc/release_notes/3.36.0.txt +0 -245
  90. data/doc/release_notes/3.37.0.txt +0 -338
  91. data/doc/release_notes/3.38.0.txt +0 -234
  92. data/doc/release_notes/3.39.0.txt +0 -237
  93. data/doc/release_notes/3.4.0.txt +0 -325
  94. data/doc/release_notes/3.40.0.txt +0 -73
  95. data/doc/release_notes/3.41.0.txt +0 -155
  96. data/doc/release_notes/3.42.0.txt +0 -74
  97. data/doc/release_notes/3.43.0.txt +0 -105
  98. data/doc/release_notes/3.44.0.txt +0 -152
  99. data/doc/release_notes/3.45.0.txt +0 -179
  100. data/doc/release_notes/3.46.0.txt +0 -122
  101. data/doc/release_notes/3.47.0.txt +0 -270
  102. data/doc/release_notes/3.48.0.txt +0 -477
  103. data/doc/release_notes/3.5.0.txt +0 -510
  104. data/doc/release_notes/3.6.0.txt +0 -366
  105. data/doc/release_notes/3.7.0.txt +0 -179
  106. data/doc/release_notes/3.8.0.txt +0 -151
  107. data/doc/release_notes/3.9.0.txt +0 -233
@@ -134,25 +134,25 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
134
134
  return conn
135
135
  end
136
136
 
137
- time = Time.now
137
+ timeout = @timeout
138
+ timer = Sequel.start_timer
138
139
 
139
140
  sync do
140
- @waiter.wait(@mutex, @timeout)
141
+ @waiter.wait(@mutex, timeout)
141
142
  if conn = next_available
142
143
  return(@allocated[thread] = conn)
143
144
  end
144
145
  end
145
146
 
146
147
  until conn = assign_connection(thread)
147
- deadline ||= time + @timeout
148
- current_time = Time.now
149
- raise_pool_timeout(current_time - time) if current_time > deadline
148
+ elapsed = Sequel.elapsed_seconds_since(timer)
149
+ raise_pool_timeout(elapsed) if elapsed > timeout
150
150
 
151
151
  # :nocov:
152
152
  # It's difficult to get to this point, it can only happen if there is a race condition
153
153
  # where a connection cannot be acquired even after the thread is signalled by the condition
154
154
  sync do
155
- @waiter.wait(@mutex, deadline - current_time)
155
+ @waiter.wait(@mutex, timeout - elapsed)
156
156
  if conn = next_available
157
157
  return(@allocated[thread] = conn)
158
158
  end
@@ -303,6 +303,26 @@ module Sequel
303
303
  @single_threaded ? yield : @data_mutex.synchronize(&block)
304
304
  end
305
305
 
306
+ if RUBY_VERSION >= '2.1'
307
+ # A timer object that can be passed to Sequel.elapsed_seconds_since
308
+ # to return the number of seconds elapsed.
309
+ def self.start_timer
310
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
311
+ end
312
+ else
313
+ # :nocov:
314
+ def self.start_timer # :nodoc:
315
+ Time.now
316
+ end
317
+ # :nocov:
318
+ end
319
+
320
+ # The elapsed seconds since the given timer object was created. The
321
+ # timer object should have been created via Sequel.start_timer.
322
+ def self.elapsed_seconds_since(timer)
323
+ start_timer - timer
324
+ end
325
+
306
326
  # Uses a transaction on all given databases with the given options. This:
307
327
  #
308
328
  # Sequel.transaction([DB1, DB2, DB3]){}
@@ -37,14 +37,15 @@ module Sequel
37
37
  def log_connection_yield(sql, conn, args=nil)
38
38
  return yield if @loggers.empty?
39
39
  sql = "#{connection_info(conn) if conn && log_connection_info}#{sql}#{"; #{args.inspect}" if args}"
40
- start = Time.now
40
+ timer = Sequel.start_timer
41
+
41
42
  begin
42
43
  yield
43
44
  rescue => e
44
45
  log_exception(e, sql)
45
46
  raise
46
47
  ensure
47
- log_duration(Time.now - start, sql) unless e
48
+ log_duration(Sequel.elapsed_seconds_since(timer), sql) unless e
48
49
  end
49
50
  end
50
51
 
@@ -263,8 +263,7 @@ module Sequel
263
263
  #
264
264
  # Examples:
265
265
  # primary_key(:id)
266
- # primary_key(:id, Bigint)
267
- # primary_key(:id, Bigint, keep_order: true)
266
+ # primary_key(:id, type: :Bignum, keep_order: true)
268
267
  # primary_key([:street_number, :house_number], name: :some constraint_name)
269
268
  def primary_key(name, *args)
270
269
  return composite_primary_key(name, *args) if name.is_a?(Array)
@@ -929,14 +929,11 @@ module Sequel
929
929
  alias with_sql_update with_sql_delete
930
930
 
931
931
  # Run the given SQL and yield each returned row to the block.
932
- #
933
- # This method should not be called on a shared dataset if the columns selected
934
- # in the given SQL do not match the columns in the receiver.
935
932
  def with_sql_each(sql)
936
933
  if rp = row_proc
937
- fetch_rows(sql){|r| yield rp.call(r)}
934
+ _with_sql_dataset.fetch_rows(sql){|r| yield rp.call(r)}
938
935
  else
939
- fetch_rows(sql){|r| yield r}
936
+ _with_sql_dataset.fetch_rows(sql){|r| yield r}
940
937
  end
941
938
  self
942
939
  end
@@ -1219,5 +1216,18 @@ module Sequel
1219
1216
  c
1220
1217
  end
1221
1218
  end
1219
+
1220
+ # Cached dataset to use for with_sql_#{all,each,first,single_value}.
1221
+ # This is used so that the columns returned by the given SQL do not
1222
+ # affect the receiver of the with_sql_* method.
1223
+ def _with_sql_dataset
1224
+ if @opts[:_with_sql_ds]
1225
+ self
1226
+ else
1227
+ cached_dataset(:_with_sql_ds) do
1228
+ clone(:_with_sql_ds=>true)
1229
+ end
1230
+ end
1231
+ end
1222
1232
  end
1223
1233
  end
@@ -59,7 +59,7 @@ module Sequel
59
59
  # Record the time the connection was created.
60
60
  def make_new(*)
61
61
  conn = super
62
- @connection_expiration_timestamps[conn] = Time.now
62
+ @connection_expiration_timestamps[conn] = Sequel.start_timer
63
63
  conn
64
64
  end
65
65
 
@@ -69,8 +69,8 @@ module Sequel
69
69
  def acquire(*a)
70
70
  begin
71
71
  if (conn = super) &&
72
- (t = sync{@connection_expiration_timestamps[conn]}) &&
73
- Time.now - t > @connection_expiration_timeout
72
+ (timer = sync{@connection_expiration_timestamps[conn]}) &&
73
+ Sequel.elapsed_seconds_since(timer) > @connection_expiration_timeout
74
74
 
75
75
  if pool_type == :sharded_threaded
76
76
  sync{allocated(a.last).delete(Thread.current)}
@@ -79,7 +79,7 @@ module Sequel
79
79
  # Record the time the connection was checked back into the pool.
80
80
  def checkin_connection(*)
81
81
  conn = super
82
- @connection_timestamps[conn] = Time.now
82
+ @connection_timestamps[conn] = Sequel.start_timer
83
83
  conn
84
84
  end
85
85
 
@@ -96,8 +96,8 @@ module Sequel
96
96
  def acquire(*a)
97
97
  begin
98
98
  if (conn = super) &&
99
- (t = sync{@connection_timestamps.delete(conn)}) &&
100
- Time.now - t > @connection_validation_timeout &&
99
+ (timer = sync{@connection_timestamps.delete(conn)}) &&
100
+ Sequel.elapsed_seconds_since(timer) > @connection_validation_timeout &&
101
101
  !db.valid_connection?(conn)
102
102
 
103
103
  if pool_type == :sharded_threaded
@@ -0,0 +1,30 @@
1
+ # frozen-string-literal: true
2
+ #
3
+ # The integer64 extension changes the default type used for Integer
4
+ # to be the same type as used for :Bignum. In general, this means that
5
+ # instead of Integer resulting in a 32-bit database integer type, it will
6
+ # result in a 64-bit database integer type. This affects the default
7
+ # type used for primary_key and foreign_key when using the schema
8
+ # modification methods.
9
+ #
10
+ # Note that it doesn't make sense to use this extension on SQLite, since
11
+ # the integer type will automatically handle 64-bit integers, and it treats
12
+ # the integer type specially when the column is also the primary key.
13
+ #
14
+ # To load the extension into the database:
15
+ #
16
+ # DB.extension :integer64
17
+ #
18
+ # Related module: Sequel::Integer64
19
+
20
+ #
21
+ module Sequel
22
+ module Integer64
23
+ # Use timestamptz by default for generic timestamp value.
24
+ def type_literal_generic_integer(column)
25
+ type_literal_generic_bignum_symbol(column)
26
+ end
27
+ end
28
+
29
+ Database.register_extension(:integer64, Integer64)
30
+ end
@@ -548,13 +548,13 @@ module Sequel
548
548
  # Apply all migrations on the database
549
549
  def run
550
550
  migrations.zip(version_numbers).each do |m, v|
551
- t = Time.now
551
+ timer = Sequel.start_timer
552
552
  db.log_info("Begin applying migration version #{v}, direction: #{direction}")
553
553
  checked_transaction(m) do
554
554
  m.apply(db, direction)
555
555
  set_migration_version(up? ? v : v-1)
556
556
  end
557
- db.log_info("Finished applying migration version #{v}, direction: #{direction}, took #{sprintf('%0.6f', Time.now - t)} seconds")
557
+ db.log_info("Finished applying migration version #{v}, direction: #{direction}, took #{sprintf('%0.6f', Sequel.elapsed_seconds_since(timer))} seconds")
558
558
  end
559
559
 
560
560
  target
@@ -736,7 +736,6 @@ module Sequel
736
736
  def get_migration_tuples
737
737
  up_mts = []
738
738
  down_mts = []
739
- ms = Migration.descendants
740
739
  files.each do |path|
741
740
  f = File.basename(path)
742
741
  fi = f.downcase
@@ -80,7 +80,7 @@ module Sequel
80
80
  def array_type
81
81
  cached_fetch(:array_type) do
82
82
  if (sch = associated_class.db_schema) && (s = sch[self[:key]]) && (t = s[:db_type])
83
- t
83
+ t.sub(/\[\]\z/, '').freeze
84
84
  else
85
85
  :integer
86
86
  end
@@ -189,7 +189,7 @@ module Sequel
189
189
  def array_type
190
190
  cached_fetch(:array_type) do
191
191
  if (sch = self[:model].db_schema) && (s = sch[self[:key]]) && (t = s[:db_type])
192
- t
192
+ t.sub(/\[\]\z/, '').freeze
193
193
  else
194
194
  :integer
195
195
  end
@@ -400,7 +400,9 @@ module Sequel
400
400
  end
401
401
 
402
402
  opts[:clearer] ||= proc do
403
- opts.associated_dataset.where(Sequel.pg_array_op(key).contains([get_column_value(pk)])).update(key=>Sequel.function(:array_remove, key, get_column_value(pk)))
403
+ pk_value = get_column_value(pk)
404
+ db_type = opts.array_type
405
+ opts.associated_dataset.where(Sequel.pg_array_op(key).contains(Sequel.pg_array([pk_value], db_type))).update(key=>Sequel.function(:array_remove, key, Sequel.cast(pk_value, db_type)))
404
406
  end
405
407
  end
406
408
 
@@ -16,6 +16,24 @@ module Sequel
16
16
  #
17
17
  # # Make the Album class support validating associated objects
18
18
  # Album.plugin :validate_associated
19
+ #
20
+ # class Album
21
+ # many_to_one :artist
22
+ # many_to_many :tags
23
+ #
24
+ # # Always validate associated artist when saving the album
25
+ # def validate
26
+ # super
27
+ # if artist
28
+ # validate_associated_object(model.association_reflection(:artist), artist)
29
+ # end
30
+ # end
31
+ #
32
+ # # When saving after calling this method, validate the given tag as well.
33
+ # def check_tag!(tag)
34
+ # delay_validate_associated_object(model.association_reflection(:tags), tag)
35
+ # end
36
+ # end
19
37
  module ValidateAssociated
20
38
  # Depend on the instance_hooks plugin.
21
39
  def self.apply(mod)
@@ -5,7 +5,7 @@ module Sequel
5
5
  MAJOR = 5
6
6
  # The minor version of Sequel. Bumped for every non-patch level
7
7
  # release, generally around once a month.
8
- MINOR = 6
8
+ MINOR = 7
9
9
  # The tiny version of Sequel. Usually 0, only bumped for bugfix
10
10
  # releases that fix regressions from previous versions.
11
11
  TINY = 0
@@ -636,18 +636,18 @@ describe "Database#foreign_key_list" do
636
636
  before(:all) do
637
637
  DB.create_table! :items do
638
638
  primary_key :id
639
- integer :sku
639
+ Integer :sku
640
640
  end
641
641
  DB.create_table! :prices do
642
- integer :item_id
642
+ Integer :item_id
643
643
  datetime :valid_from
644
644
  float :price
645
645
  primary_key [:item_id, :valid_from]
646
646
  foreign_key [:item_id], :items, :key => :id, :name => :fk_prices_items
647
647
  end
648
648
  DB.create_table! :sales do
649
- integer :id
650
- integer :price_item_id
649
+ Integer :id
650
+ Integer :price_item_id
651
651
  datetime :price_valid_from
652
652
  foreign_key [:price_item_id, :price_valid_from], :prices, :key => [:item_id, :valid_from], :name => :fk_sales_prices, :on_delete => :cascade
653
653
  end
@@ -682,8 +682,8 @@ describe "Database#foreign_key_list" do
682
682
  varchar :name
683
683
  end
684
684
  DB.create_table! Sequel[:vendor][:mapping] do
685
- integer :vendor_id
686
- integer :item_id
685
+ Integer :vendor_id
686
+ Integer :item_id
687
687
  foreign_key [:vendor_id], Sequel[:vendor][:vendors], :name => :fk_mapping_vendor
688
688
  foreign_key [:item_id], :items, :name => :fk_mapping_item
689
689
  end
@@ -274,7 +274,7 @@ describe "A MySQL database" do
274
274
  @db = DB
275
275
  @db.create_table! :test2 do
276
276
  text :name
277
- integer :value
277
+ Integer :value
278
278
  end
279
279
  end
280
280
  after(:all) do
@@ -113,7 +113,7 @@ describe "An Oracle database" do
113
113
  it "should create a temporary table" do
114
114
  DB.create_table! :test_tmp, :temp => true do
115
115
  varchar2 :name, :size => 50
116
- primary_key :id, :integer, :null => false
116
+ primary_key :id, :null => false
117
117
  index :name, :unique => true
118
118
  end
119
119
  DB.drop_table?(:test_tmp)
@@ -311,3 +311,17 @@ describe "An Oracle database" do
311
311
  DB[:books].select(:title).group_by(:title).count.must_equal 2
312
312
  end
313
313
  end
314
+
315
+ describe "An Oracle database with xml types" do
316
+ before(:all) do
317
+ DB.create_table!(:xml_test){xmltype :xml_col}
318
+ end
319
+ after(:all) do
320
+ DB.drop_table(:xml_test)
321
+ end
322
+
323
+ it "should work correctly with temporary clobs" do
324
+ DB[:xml_test].insert("<a href='b'>c</a>")
325
+ DB.from(Sequel.lit('xml_test x')).select(Sequel.lit("x.xml_col.getCLOBVal() v")).all.must_equal [{:v=>"<a href=\"b\">c</a>\n"}]
326
+ end
327
+ end
@@ -107,6 +107,83 @@ describe "PostgreSQL", '#create_table' do
107
107
  end
108
108
  end if DB.server_version >= 90000
109
109
 
110
+ it "should support creating identity columns on non-primary key tables" do
111
+ @db.create_table(:tmp_dolls){Integer :a, :identity=>true}
112
+ 2.times do
113
+ @db[:tmp_dolls].insert
114
+ end
115
+ @db[:tmp_dolls].select_order_map(:a).must_equal [1, 2]
116
+ @db[:tmp_dolls].insert(:a=>2)
117
+ @db[:tmp_dolls].select_order_map(:a).must_equal [1, 2, 2]
118
+ @db[:tmp_dolls].insert(:a=>4)
119
+ @db[:tmp_dolls].select_order_map(:a).must_equal [1, 2, 2, 4]
120
+ @db[:tmp_dolls].overriding_user_value.insert(:a=>5)
121
+ @db[:tmp_dolls].select_order_map(:a).must_equal [1, 2, 2, 3, 4]
122
+ end if DB.server_version >= 100002
123
+
124
+ it "should support creating identity columns generated always" do
125
+ @db.create_table(:tmp_dolls){primary_key :id, :identity=>:always}
126
+ 2.times do
127
+ @db[:tmp_dolls].insert
128
+ end
129
+ @db[:tmp_dolls].select_order_map(:id).must_equal [1, 2]
130
+ proc{@db[:tmp_dolls].insert(:id=>2)}.must_raise Sequel::DatabaseError
131
+ @db[:tmp_dolls].overriding_system_value.insert(:id=>4)
132
+ @db[:tmp_dolls].select_order_map(:id).must_equal [1, 2, 4]
133
+ @db[:tmp_dolls].insert
134
+ @db[:tmp_dolls].select_order_map(:id).must_equal [1, 2, 3, 4]
135
+ end if DB.server_version >= 100002
136
+
137
+ it "should support converting serial columns to identity columns" do
138
+ @db.create_table(:tmp_dolls){primary_key :id, :identity=>false, :serial=>true}
139
+ sch = @db.schema(:tmp_dolls)[0][1]
140
+ sch[:default].must_match(/nextval/)
141
+ sch[:auto_increment].must_equal true
142
+
143
+ 2.times do
144
+ @db[:tmp_dolls].insert
145
+ end
146
+
147
+ @db.convert_serial_to_identity(:tmp_dolls)
148
+ sch = @db.schema(:tmp_dolls)[0][1]
149
+ sch[:default].must_be_nil
150
+ sch[:auto_increment].must_equal true
151
+
152
+ @db[:tmp_dolls].insert
153
+ @db[:tmp_dolls].insert(5)
154
+ @db[:tmp_dolls].select_order_map(:id).must_equal [1, 2, 3, 5]
155
+
156
+ # Make sure it doesn't break if already converted
157
+ @db.convert_serial_to_identity(:tmp_dolls)
158
+ end if DB.server_version >= 100002 && DB.get{current_setting('is_superuser')} == 'on'
159
+
160
+ it "should support converting serial columns to identity columns when using the :column option" do
161
+ @db.create_table(:tmp_dolls){Integer :i, :primary_key=>true; serial :id}
162
+ sch = @db.schema(:tmp_dolls)[1][1]
163
+ sch[:default].must_match(/nextval/)
164
+
165
+ 2.times do |i|
166
+ @db[:tmp_dolls].insert(:i=>-i)
167
+ end
168
+
169
+ # Automatic conversion should not work
170
+ proc{@db.convert_serial_to_identity(:tmp_dolls)}.must_raise Sequel::Error
171
+
172
+ # Conversion of type without related sequence should not work
173
+ proc{@db.convert_serial_to_identity(:tmp_dolls, :column=>:i)}.must_raise Sequel::Error
174
+
175
+ @db.convert_serial_to_identity(:tmp_dolls, :column=>:id)
176
+ sch = @db.schema(:tmp_dolls)[1][1]
177
+ sch[:default].must_be_nil
178
+
179
+ @db[:tmp_dolls].insert(:i=>200)
180
+ @db[:tmp_dolls].insert(:i=>300, :id=>5)
181
+ @db[:tmp_dolls].select_order_map(:id).must_equal [1, 2, 3, 5]
182
+
183
+ # Make sure it doesn't break if already converted
184
+ @db.convert_serial_to_identity(:tmp_dolls, :column=>:id)
185
+ end if DB.server_version >= 100002 && DB.get{current_setting('is_superuser')} == 'on'
186
+
110
187
  it "should support pg_loose_count extension" do
111
188
  @db.extension :pg_loose_count
112
189
  @db.create_table(:tmp_dolls){text :name}
@@ -324,7 +401,7 @@ describe "A PostgreSQL database" do
324
401
  end
325
402
 
326
403
  it "should correctly parse the schema" do
327
- @db.schema(Sequel[:public][:testfk], :reload=>true).map{|c,s| [c, s[:oid]]}.must_equal [[:id, 23], [:i, 23]]
404
+ [[[:id, 23], [:i, 23]], [[:id, 20], [:i, 20]]].must_include @db.schema(Sequel[:public][:testfk], :reload=>true).map{|c,s| [c, s[:oid]]}
328
405
  end
329
406
 
330
407
  it "should parse foreign keys for tables in a schema" do