sequel 5.6.0 → 5.7.0

Sign up to get free protection for your applications and to get access to all the features.
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