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.
- checksums.yaml +4 -4
- data/CHANGELOG +30 -5099
- data/Rakefile +1 -1
- data/doc/opening_databases.rdoc +0 -2
- data/doc/postgresql.rdoc +31 -0
- data/doc/querying.rdoc +2 -2
- data/doc/release_notes/5.7.0.txt +108 -0
- data/doc/testing.rdoc +1 -0
- data/lib/sequel/adapters/jdbc/derby.rb +1 -1
- data/lib/sequel/adapters/jdbc/oracle.rb +11 -0
- data/lib/sequel/adapters/postgres.rb +1 -0
- data/lib/sequel/adapters/shared/postgres.rb +117 -13
- data/lib/sequel/connection_pool/sharded_threaded.rb +7 -6
- data/lib/sequel/connection_pool/threaded.rb +6 -6
- data/lib/sequel/core.rb +20 -0
- data/lib/sequel/database/logging.rb +3 -2
- data/lib/sequel/database/schema_generator.rb +1 -2
- data/lib/sequel/dataset/actions.rb +15 -5
- data/lib/sequel/extensions/connection_expiration.rb +3 -3
- data/lib/sequel/extensions/connection_validator.rb +3 -3
- data/lib/sequel/extensions/integer64.rb +30 -0
- data/lib/sequel/extensions/migration.rb +2 -3
- data/lib/sequel/plugins/pg_array_associations.rb +5 -3
- data/lib/sequel/plugins/validate_associated.rb +18 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +6 -6
- data/spec/adapters/mysql_spec.rb +1 -1
- data/spec/adapters/oracle_spec.rb +15 -1
- data/spec/adapters/postgres_spec.rb +78 -1
- data/spec/adapters/spec_helper.rb +3 -1
- data/spec/bin_spec.rb +1 -0
- data/spec/core/dataset_spec.rb +10 -0
- data/spec/extensions/integer64_spec.rb +22 -0
- data/spec/extensions/pg_array_associations_spec.rb +14 -2
- data/spec/extensions/spec_helper.rb +1 -0
- data/spec/integration/associations_test.rb +4 -4
- data/spec/integration/dataset_test.rb +2 -0
- data/spec/integration/spec_helper.rb +5 -11
- data/spec/model/spec_helper.rb +1 -0
- metadata +35 -165
- data/doc/release_notes/1.0.txt +0 -38
- data/doc/release_notes/1.1.txt +0 -143
- data/doc/release_notes/1.3.txt +0 -101
- data/doc/release_notes/1.4.0.txt +0 -53
- data/doc/release_notes/1.5.0.txt +0 -155
- data/doc/release_notes/2.0.0.txt +0 -298
- data/doc/release_notes/2.1.0.txt +0 -271
- data/doc/release_notes/2.10.0.txt +0 -328
- data/doc/release_notes/2.11.0.txt +0 -215
- data/doc/release_notes/2.12.0.txt +0 -534
- data/doc/release_notes/2.2.0.txt +0 -253
- data/doc/release_notes/2.3.0.txt +0 -88
- data/doc/release_notes/2.4.0.txt +0 -106
- data/doc/release_notes/2.5.0.txt +0 -137
- data/doc/release_notes/2.6.0.txt +0 -157
- data/doc/release_notes/2.7.0.txt +0 -166
- data/doc/release_notes/2.8.0.txt +0 -171
- data/doc/release_notes/2.9.0.txt +0 -97
- data/doc/release_notes/3.0.0.txt +0 -221
- data/doc/release_notes/3.1.0.txt +0 -406
- data/doc/release_notes/3.10.0.txt +0 -286
- data/doc/release_notes/3.11.0.txt +0 -254
- data/doc/release_notes/3.12.0.txt +0 -304
- data/doc/release_notes/3.13.0.txt +0 -210
- data/doc/release_notes/3.14.0.txt +0 -118
- data/doc/release_notes/3.15.0.txt +0 -78
- data/doc/release_notes/3.16.0.txt +0 -45
- data/doc/release_notes/3.17.0.txt +0 -58
- data/doc/release_notes/3.18.0.txt +0 -120
- data/doc/release_notes/3.19.0.txt +0 -67
- data/doc/release_notes/3.2.0.txt +0 -268
- data/doc/release_notes/3.20.0.txt +0 -41
- data/doc/release_notes/3.21.0.txt +0 -87
- data/doc/release_notes/3.22.0.txt +0 -39
- data/doc/release_notes/3.23.0.txt +0 -172
- data/doc/release_notes/3.24.0.txt +0 -420
- data/doc/release_notes/3.25.0.txt +0 -88
- data/doc/release_notes/3.26.0.txt +0 -88
- data/doc/release_notes/3.27.0.txt +0 -82
- data/doc/release_notes/3.28.0.txt +0 -304
- data/doc/release_notes/3.29.0.txt +0 -459
- data/doc/release_notes/3.3.0.txt +0 -192
- data/doc/release_notes/3.30.0.txt +0 -135
- data/doc/release_notes/3.31.0.txt +0 -146
- data/doc/release_notes/3.32.0.txt +0 -202
- data/doc/release_notes/3.33.0.txt +0 -157
- data/doc/release_notes/3.34.0.txt +0 -671
- data/doc/release_notes/3.35.0.txt +0 -144
- data/doc/release_notes/3.36.0.txt +0 -245
- data/doc/release_notes/3.37.0.txt +0 -338
- data/doc/release_notes/3.38.0.txt +0 -234
- data/doc/release_notes/3.39.0.txt +0 -237
- data/doc/release_notes/3.4.0.txt +0 -325
- data/doc/release_notes/3.40.0.txt +0 -73
- data/doc/release_notes/3.41.0.txt +0 -155
- data/doc/release_notes/3.42.0.txt +0 -74
- data/doc/release_notes/3.43.0.txt +0 -105
- data/doc/release_notes/3.44.0.txt +0 -152
- data/doc/release_notes/3.45.0.txt +0 -179
- data/doc/release_notes/3.46.0.txt +0 -122
- data/doc/release_notes/3.47.0.txt +0 -270
- data/doc/release_notes/3.48.0.txt +0 -477
- data/doc/release_notes/3.5.0.txt +0 -510
- data/doc/release_notes/3.6.0.txt +0 -366
- data/doc/release_notes/3.7.0.txt +0 -179
- data/doc/release_notes/3.8.0.txt +0 -151
- 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
|
-
|
|
137
|
+
timeout = @timeout
|
|
138
|
+
timer = Sequel.start_timer
|
|
138
139
|
|
|
139
140
|
sync do
|
|
140
|
-
@waiter.wait(@mutex,
|
|
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
|
-
|
|
148
|
-
|
|
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,
|
|
155
|
+
@waiter.wait(@mutex, timeout - elapsed)
|
|
156
156
|
if conn = next_available
|
|
157
157
|
return(@allocated[thread] = conn)
|
|
158
158
|
end
|
data/lib/sequel/core.rb
CHANGED
|
@@ -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
|
-
|
|
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(
|
|
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,
|
|
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] =
|
|
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
|
-
(
|
|
73
|
-
|
|
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] =
|
|
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
|
-
(
|
|
100
|
-
|
|
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
|
-
|
|
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',
|
|
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
|
-
|
|
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)
|
data/lib/sequel/version.rb
CHANGED
|
@@ -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 =
|
|
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
|
data/spec/adapters/mssql_spec.rb
CHANGED
|
@@ -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
|
-
|
|
639
|
+
Integer :sku
|
|
640
640
|
end
|
|
641
641
|
DB.create_table! :prices do
|
|
642
|
-
|
|
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
|
-
|
|
650
|
-
|
|
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
|
-
|
|
686
|
-
|
|
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
|
data/spec/adapters/mysql_spec.rb
CHANGED
|
@@ -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, :
|
|
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]]}
|
|
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
|