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
data/Rakefile CHANGED
@@ -49,7 +49,7 @@ task :website_rdoc=>[:website_rdoc_main, :website_rdoc_adapters, :website_rdoc_p
49
49
  RDoc::Task.new(:website_rdoc_main) do |rdoc|
50
50
  rdoc.rdoc_dir = "www/public/rdoc"
51
51
  rdoc.options += RDOC_OPTS + %w'--no-ignore-invalid'
52
- rdoc.rdoc_files.add %w"README.rdoc CHANGELOG MIT-LICENSE lib/*.rb lib/sequel/*.rb lib/sequel/{connection_pool,dataset,database,model}/*.rb doc/*.rdoc doc/release_notes/*.txt lib/sequel/extensions/migration.rb"
52
+ rdoc.rdoc_files.add %w"README.rdoc CHANGELOG doc/CHANGELOG.old MIT-LICENSE lib/*.rb lib/sequel/*.rb lib/sequel/{connection_pool,dataset,database,model}/*.rb doc/*.rdoc doc/release_notes/*.txt lib/sequel/extensions/migration.rb"
53
53
  end
54
54
 
55
55
  RDoc::Task.new(:website_rdoc_adapters) do |rdoc|
@@ -230,8 +230,6 @@ The following additional options are supported:
230
230
  There are a few issues with specific jdbc driver gems:
231
231
 
232
232
  jdbc-h2 :: jdbc-h2 versions greater than 1.3.175 have issues with ORDER BY not working correctly in some cases.
233
- jdbc-postgres :: jdbc-postgres 9.4.1204 has issues using PostgreSQL-specific types in bound variables.
234
- Use jdbc-postgres 9.4.1200 or below.
235
233
 
236
234
  === mysql
237
235
 
@@ -139,6 +139,21 @@ allows you do create an unlogged table by specifying the <tt>unlogged: true</tt>
139
139
  DB.create_table(:table, unlogged: true){Integer :i}
140
140
  # CREATE UNLOGGED TABLE "table" ("i" integer)
141
141
 
142
+ === Creating Identity Columns
143
+
144
+ You can use the +:identity+ option when creating columns to mark them as identity columns.
145
+ Identity columns are tied to a sequence for the default value. You can still override the
146
+ default value for the column when inserting:
147
+
148
+ DB.create_table(:table){Integer :id, identity: true}
149
+ # CREATE TABLE "table" ("id" integer GENERATED BY DEFAULT AS IDENTITY)
150
+
151
+ If you want to disallow using a user provided value when inserting, you can mark the
152
+ identity column using <tt>identity: :always</tt>:
153
+
154
+ DB.create_table(:table){Integer :id, identity: :always}
155
+ # CREATE TABLE "table" ("id" integer GENERATED ALWAYS AS IDENTITY)
156
+
142
157
  === Creating/Dropping Schemas, Languages, Functions, and Triggers
143
158
 
144
159
  Sequel has built in support for creating and dropping PostgreSQL schemas, procedural languages, functions, and triggers:
@@ -255,6 +270,22 @@ conditions, the constraint violation will be ignored, but the row will not be up
255
270
  # ON CONFLICT ON CONSTRAINT table_a_uidx
256
271
  # DO UPDATE SET b = excluded.b WHERE (table.status_id = 1)
257
272
 
273
+ === INSERT OVERRIDING SYSTEM|USER VALUE Support
274
+
275
+ PostgreSQL 10+ supports identity columns, which are designed to replace the serial
276
+ columns previously used for autoincrementing primary keys. You can use
277
+ Dataset#overriding_system_value and Dataset#overriding_user_value to use this new
278
+ syntax:
279
+
280
+ DB.create_table(:table){primary_key :id}
281
+ # Ignore the given value for id, using the identity's sequence value
282
+ DB[:table].overriding_user_value.insert(:id=>1)
283
+
284
+ DB.create_table(:table){primary_key :id, :identity=>:always}
285
+ # Force the use of the given value for id, because otherwise the insert will
286
+ # raise an error, since GENERATED ALWAYS was using when creating the column.
287
+ DB[:table].overriding_system_value.insert(:id=>1)
288
+
258
289
  === Distinct On Specific Columns
259
290
 
260
291
  Sequel allows passing columns to <tt>Dataset#distinct</tt>, which will make the dataset return
@@ -111,8 +111,8 @@ you want:
111
111
  If you want the value for multiple columns, you can pass an array to
112
112
  <tt>Sequel::Dataset#get</tt>:
113
113
 
114
- artist_id, artist_name, = Artist.get([:id, :name])
115
- # SELECT name FROM artists LIMIT 1
114
+ artist_id, artist_name = Artist.get([:id, :name])
115
+ # SELECT id, name FROM artists LIMIT 1
116
116
  # => [1, "YJM"]
117
117
 
118
118
  === Retrieving Multiple Objects
@@ -0,0 +1,108 @@
1
+ = New Features
2
+
3
+ * An integer64 extension has been added, which treats the Integer
4
+ class as a generic 64-bit integer type. Sequel's default behavior
5
+ for Integer is to use the integer type, which on most databases
6
+ is a 32-bit type.
7
+
8
+ This affects all internal use of the Integer class as a generic
9
+ database type, so that methods like primary_key and foreign_key
10
+ also default to using a 64-bit integer type when using this
11
+ extension.
12
+
13
+ * When using PostgreSQL 10+, you can use the :identity option when
14
+ creating columns to create identity columns:
15
+
16
+ DB.create_table(:table){Integer :id, identity: true}
17
+ # CREATE TABLE "table" ("id" integer GENERATED BY DEFAULT AS IDENTITY)
18
+
19
+ If you want to disallow using a user provided value when inserting,
20
+ or updating you can use a value of :always:
21
+
22
+ DB.create_table(:table){Integer :id, identity: :always}
23
+ # CREATE TABLE "table" ("id" integer GENERATED ALWAYS AS IDENTITY)
24
+
25
+ * Database#convert_serial_to_identity has been added on PostgreSQL 10.2+.
26
+ This method can convert existing serial columns to identity columns
27
+ in most cases, but it currently requires superuser permissions as it
28
+ modifies the system tables directly.
29
+
30
+ * Dataset#overriding_system_value and #overriding_user_value are
31
+ now supported on PostgreSQL to work with identity columns. You can
32
+ use #overriding_system_value to force the use of a user provided
33
+ value for identity columns that are GENERATED ALWAYS, and you can
34
+ use #overriding_user_value to ignore any user value for identity
35
+ columns and always use the next entry in the sequence.
36
+
37
+ = Other Improvements
38
+
39
+ * On PostgreSQL 10.2+, identity columns are now used instead of serial
40
+ columns as the default for auto incrementing primary keys:
41
+
42
+ DB.create_table(:table){primary_key :id}
43
+
44
+ # Sequel 5.7.0+ and PostgreSQL 10.2+
45
+ # CREATE TABLE "table" ("id" integer
46
+ # GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY)
47
+
48
+ # Older Sequel version or older PostgreSQL version
49
+ # CREATE TABLE "table" ("id" serial PRIMARY KEY)
50
+
51
+ Identity columns fix many issues that serial columns have, in
52
+ addition to being the SQL standard way to support auto incrementing
53
+ columns.
54
+
55
+ * PostgreSQL identity columns are now correctly recognized and the
56
+ :auto_increment schema entry is now populated for them.
57
+
58
+ * Dataset#with_sql_{all,each,first,single_value} now use a cached
59
+ dataset to avoid clobbering the current dataset's columns.
60
+ Previously, the clobbering of the current dataset's columns was
61
+ documented and the method warned against using SQL with
62
+ different columns. These methods are now safe to use in such
63
+ cases, but will not have the same performance advantages if the
64
+ current dataset is not cached.
65
+
66
+ * On ruby 2.1+, Sequel now uses Process::CLOCK_MONOTONIC when
67
+ performing elapsed time calculations so that it is not affected by
68
+ modifications to the system's time.
69
+
70
+ * In the postgres adapter, prepared statement errors related to
71
+ changing types are now treated as disconnect errors. While they
72
+ are not technically disconnect errors, treating them as such
73
+ will in general reduce the total number of exceptions generated
74
+ from 1 per affected statement per connection to 1 per
75
+ connection.
76
+
77
+ * In the pg_array_associations plugin, the array_type for
78
+ pg_array_to_many and many_to_pg_array association reflections is
79
+ now always the scalar type for the array (e.g. integer). Previously,
80
+ the array type (e.g. integer[]) was used in some cases. This didn't
81
+ previously result in issues as PostgreSQL considers integer[][] the
82
+ same type as integer[].
83
+
84
+ * In the pg_array_associations plugin, the many_to_pg_array
85
+ association remove_all_* method now uses the appropriate cast to
86
+ work for non-integer array types such as bigint[].
87
+
88
+ * Database#server_version on PostgreSQL 10.1+ now works correctly
89
+ when the connection does not support the server_version method.
90
+ Now the server_version_num database setting is always used to
91
+ ensure consistent behavior across adapters.
92
+
93
+ * In the jdbc/oracle adapter, temporary clobs are now manually
94
+ freed to prevent a memory leak, in line with the Oracle JDBC
95
+ driver recommendations.
96
+
97
+ * The Sequel <4 release notes and changelog are no longer shipped
98
+ with the gem, decreasing the size of the gem by 20%.
99
+
100
+ = Backwards Compatibility
101
+
102
+ * The switch to using identity columns instead of serial columns
103
+ by default on PostgreSQL 10.2+ may break backwards compatibilty
104
+ in some situations, such as code that relies on what are generally
105
+ considered bugs in serial columns, such as CREATE TABLE LIKE
106
+ using the same sequence for the column in both the existing table
107
+ and the new table, or that dropping the default value for the
108
+ column does not drop the related sequence.
@@ -159,6 +159,7 @@ SEQUEL_ERROR_SQL :: Use the error_sql extension when running the specs
159
159
  SEQUEL_INDEX_CACHING :: Use the index_caching extension when running the specs
160
160
  SEQUEL_FREEZE_DATABASE :: Freeze the database before running the integration specs
161
161
  SEQUEL_IDENTIFIER_MANGLING :: Use the identifier_mangling extension when running the specs
162
+ SEQUEL_INTEGER64 :: Use the integer64 extension when running the adapter or integration specs
162
163
  SEQUEL_MODEL_PREPARED_STATEMENTS :: Use the prepared_statements plugin when running the specs
163
164
  SEQUEL_NO_CACHE_ASSOCIATIONS :: Don't cache association metadata when running the specs
164
165
  SEQUEL_NO_CHECK_SQLS :: Don't check for specific SQL syntax when running the specs
@@ -36,7 +36,7 @@ module Sequel
36
36
 
37
37
  # Derby uses an IDENTITY sequence for autoincrementing columns.
38
38
  def serial_primary_key_options
39
- {:primary_key => true, :type => :integer, :identity=>true, :start_with=>1}
39
+ {:primary_key => true, :type => Integer, :identity=>true, :start_with=>1}
40
40
  end
41
41
 
42
42
  # The SVN version of the database.
@@ -28,6 +28,13 @@ module Sequel
28
28
  end
29
29
  end
30
30
 
31
+ def self.OracleClob(r, i)
32
+ return unless clob = r.getClob(i)
33
+ str = clob.getSubString(1, clob.length)
34
+ clob.freeTemporary if clob.isTemporary
35
+ str
36
+ end
37
+
31
38
  module DatabaseMethods
32
39
  include Sequel::Oracle::DatabaseMethods
33
40
  include Sequel::JDBC::Transactions
@@ -104,6 +111,7 @@ module Sequel
104
111
  def setup_type_convertor_map
105
112
  super
106
113
  @type_convertor_map[:OracleDecimal] = Oracle.method(:OracleDecimal)
114
+ @type_convertor_map[:OracleClob] = Oracle.method(:OracleClob)
107
115
  end
108
116
  end
109
117
 
@@ -112,6 +120,7 @@ module Sequel
112
120
 
113
121
  NUMERIC_TYPE = Java::JavaSQL::Types::NUMERIC
114
122
  TIMESTAMP_TYPE = Java::JavaSQL::Types::TIMESTAMP
123
+ CLOB_TYPE = Java::JavaSQL::Types::CLOB
115
124
  TIMESTAMPTZ_TYPES = [Java::oracle.jdbc.OracleTypes::TIMESTAMPTZ, Java::oracle.jdbc.OracleTypes::TIMESTAMPLTZ].freeze
116
125
 
117
126
  def type_convertor(map, meta, type, i)
@@ -124,6 +133,8 @@ module Sequel
124
133
  end
125
134
  when *TIMESTAMPTZ_TYPES
126
135
  map[TIMESTAMP_TYPE]
136
+ when CLOB_TYPE
137
+ map[:OracleClob]
127
138
  else
128
139
  super
129
140
  end
@@ -45,6 +45,7 @@ module Sequel
45
45
  DISCONNECT_ERROR_CLASSES.freeze
46
46
 
47
47
  disconnect_errors = [
48
+ 'ERROR: cached plan must not change result type',
48
49
  'could not receive data from server',
49
50
  'no connection to the server',
50
51
  'connection not open',
@@ -213,6 +213,76 @@ module Sequel
213
213
  run("COMMIT PREPARED #{literal(transaction_id)}", opts)
214
214
  end
215
215
 
216
+ # Convert the first primary key column in the +table+ from being a serial column to being an identity column.
217
+ # If the column is already an identity column, assume it was already converted and make no changes.
218
+ #
219
+ # Only supported on PostgreSQL 10.2+, since on those versions Sequel will use identity columns
220
+ # instead of serial columns for auto incrementing primary keys. Only supported when running as
221
+ # a superuser, since regular users cannot modify system tables, and there is no way to keep an
222
+ # existing sequence when changing an existing column to be an identity column.
223
+ #
224
+ # This method can raise an exception in at least the following cases where it may otherwise succeed
225
+ # (there may be additional cases not listed here):
226
+ #
227
+ # * The serial column was added after table creation using PostgreSQL <7.3
228
+ # * A regular index also exists on the column (such an index can probably be dropped as the
229
+ # primary key index should suffice)
230
+ #
231
+ # Options:
232
+ # :column :: Specify the column to convert instead of using the first primary key column
233
+ # :server :: Run the SQL on the given server
234
+ def convert_serial_to_identity(table, opts=OPTS)
235
+ raise Error, "convert_serial_to_identity is only supported on PostgreSQL 10.2+" unless server_version >= 100002
236
+
237
+ server = opts[:server]
238
+ server_hash = server ? {:server=>server} : {}
239
+ ds = dataset
240
+ ds = ds.server(server) if server
241
+
242
+ raise Error, "convert_serial_to_identity requires superuser permissions" unless ds.get{current_setting('is_superuser')} == 'on'
243
+
244
+ table_oid = regclass_oid(table)
245
+ im = input_identifier_meth
246
+ unless column = im.call(opts[:column] || ((sch = schema(table).find{|col, sch| sch[:primary_key] && sch[:auto_increment]}) && sch[0]))
247
+ raise Error, "could not determine column to convert from serial to identity automatically"
248
+ end
249
+
250
+ column_num = ds.from(:pg_attribute).
251
+ where(:attrelid=>table_oid, :attname=>column).
252
+ get(:attnum)
253
+
254
+ pg_class = Sequel.cast('pg_class', :regclass)
255
+ res = ds.from(:pg_depend).
256
+ where(:refclassid=>pg_class, :refobjid=>table_oid, :refobjsubid=>column_num, :classid=>pg_class, :objsubid=>0, :deptype=>%w'a i').
257
+ select_map([:objid, Sequel.as({:deptype=>'i'}, :v)])
258
+
259
+ case res.length
260
+ when 0
261
+ raise Error, "unable to find related sequence when converting serial to identity"
262
+ when 1
263
+ seq_oid, already_identity = res.first
264
+ else
265
+ raise Error, "more than one linked sequence found when converting serial to identity"
266
+ end
267
+
268
+ return if already_identity
269
+
270
+ transaction(server_hash) do
271
+ run("ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(column)} DROP DEFAULT", server_hash)
272
+
273
+ ds.from(:pg_depend).
274
+ where(:classid=>pg_class, :objid=>seq_oid, :objsubid=>0, :deptype=>'a').
275
+ update(:deptype=>'i')
276
+
277
+ ds.from(:pg_attribute).
278
+ where(:attrelid=>table_oid, :attname=>column).
279
+ update(:attidentity=>'d')
280
+ end
281
+
282
+ remove_cached_schema(table)
283
+ nil
284
+ end
285
+
216
286
  # Creates the function in the database. Arguments:
217
287
  # name :: name of the function to create
218
288
  # definition :: string definition of the function, or object file for a dynamically loaded C function.
@@ -528,23 +598,16 @@ module Sequel
528
598
  # PostgreSQL uses SERIAL psuedo-type instead of AUTOINCREMENT for
529
599
  # managing incrementing primary keys.
530
600
  def serial_primary_key_options
531
- {:primary_key => true, :serial => true, :type=>Integer}
601
+ auto_increment_key = server_version >= 100002 ? :identity : :serial
602
+ {:primary_key => true, auto_increment_key => true, :type=>Integer}
532
603
  end
533
604
 
534
605
  # The version of the PostgreSQL server, used for determining capability.
535
606
  def server_version(server=nil)
536
607
  return @server_version if @server_version
537
- @server_version = synchronize(server) do |conn|
538
- (conn.server_version rescue nil) if conn.respond_to?(:server_version)
539
- end
540
- unless @server_version
541
- @server_version = if m = /PostgreSQL (\d+)\.(\d+)(?:(?:rc\d+)|\.(\d+))?/.match(fetch('SELECT version()').single_value)
542
- (m[1].to_i * 10000) + (m[2].to_i * 100) + m[3].to_i
543
- else
544
- 0
545
- end
546
- end
547
- @server_version
608
+ ds = dataset
609
+ ds = ds.server(server) if server
610
+ @server_version ||= ds.with_sql("SELECT CAST(current_setting('server_version_num') AS integer) AS v").single_value rescue 0
548
611
  end
549
612
 
550
613
  # PostgreSQL supports CREATE TABLE IF NOT EXISTS on 9.1+
@@ -709,6 +772,17 @@ module Sequel
709
772
  end
710
773
  end
711
774
 
775
+ # Support identity columns, but only use the identity SQL syntax if no
776
+ # default value is given.
777
+ def column_definition_default_sql(sql, column)
778
+ super
779
+ if !column[:default] && (identity = column[:identity])
780
+ sql << " GENERATED "
781
+ sql << (identity == :always ? "ALWAYS" : "BY DEFAULT")
782
+ sql << " AS IDENTITY"
783
+ end
784
+ end
785
+
712
786
  # Handle PostgreSQL specific default format.
713
787
  def column_schema_normalize_default(default, type)
714
788
  if m = /\A(?:B?('.*')::[^']+|\((-?\d+(?:\.\d+)?)\))\z/.match(default)
@@ -1115,6 +1189,11 @@ module Sequel
1115
1189
  where{pg_attribute[:attnum] > 0}.
1116
1190
  where{{pg_class[:oid]=>oid}}.
1117
1191
  order{pg_attribute[:attnum]}
1192
+
1193
+ if server_version > 100000
1194
+ ds = ds.select_append{pg_attribute[:attidentity]}
1195
+ end
1196
+
1118
1197
  ds.map do |row|
1119
1198
  row[:default] = nil if blank_object?(row[:default])
1120
1199
  if row[:base_oid]
@@ -1127,8 +1206,9 @@ module Sequel
1127
1206
  row.delete(:db_base_type)
1128
1207
  end
1129
1208
  row[:type] = schema_column_type(row[:db_type])
1209
+ identity = row.delete(:attidentity)
1130
1210
  if row[:primary_key]
1131
- row[:auto_increment] = !!(row[:default] =~ /\Anextval/io)
1211
+ row[:auto_increment] = !!(row[:default] =~ /\A(?:nextval)/i) || identity == 'a' || identity == 'd'
1132
1212
  end
1133
1213
  [m.call(row.delete(:name)), row]
1134
1214
  end
@@ -1430,6 +1510,19 @@ module Sequel
1430
1510
  nil
1431
1511
  end
1432
1512
 
1513
+ # Use OVERRIDING USER VALUE for INSERT statements, so that identity columns
1514
+ # always use the user supplied value, and an error is not raised for identity
1515
+ # columns that are GENERATED ALWAYS.
1516
+ def overriding_system_value
1517
+ clone(:override=>:system)
1518
+ end
1519
+
1520
+ # Use OVERRIDING USER VALUE for INSERT statements, so that identity columns
1521
+ # always use the sequence value instead of the user supplied value.
1522
+ def overriding_user_value
1523
+ clone(:override=>:user)
1524
+ end
1525
+
1433
1526
  def supports_cte?(type=:select)
1434
1527
  if type == :select
1435
1528
  server_version >= 80400
@@ -1626,6 +1719,17 @@ module Sequel
1626
1719
  end
1627
1720
  end
1628
1721
 
1722
+ # Support OVERRIDING SYSTEM|USER VALUE in insert statements
1723
+ def insert_values_sql(sql)
1724
+ case opts[:override]
1725
+ when :system
1726
+ sql << " OVERRIDING SYSTEM VALUE"
1727
+ when :user
1728
+ sql << " OVERRIDING USER VALUE"
1729
+ end
1730
+ super
1731
+ end
1732
+
1629
1733
  # For multiple table support, PostgreSQL requires at least
1630
1734
  # two from tables, with joins allowed.
1631
1735
  def join_from_sql(type, sql)
@@ -185,24 +185,25 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
185
185
  return conn
186
186
  end
187
187
 
188
- time = Time.now
188
+ timeout = @timeout
189
+ timer = Sequel.start_timer
189
190
 
190
191
  sync do
191
- @waiters[server].wait(@mutex, @timeout)
192
+ @waiters[server].wait(@mutex, timeout)
192
193
  if conn = next_available(server)
193
194
  return(allocated(server)[thread] = conn)
194
195
  end
195
196
  end
196
197
 
197
198
  until conn = assign_connection(thread, server)
198
- deadline ||= time + @timeout
199
- current_time = Time.now
200
- raise_pool_timeout(current_time - time, server) if current_time > deadline
199
+ elapsed = Sequel.elapsed_seconds_since(timer)
200
+ raise_pool_timeout(elapsed, server) if elapsed > timeout
201
+
201
202
  # :nocov:
202
203
  # It's difficult to get to this point, it can only happen if there is a race condition
203
204
  # where a connection cannot be acquired even after the thread is signalled by the condition
204
205
  sync do
205
- @waiters[server].wait(@mutex, deadline - current_time)
206
+ @waiters[server].wait(@mutex, timeout - elapsed)
206
207
  if conn = next_available(server)
207
208
  return(allocated(server)[thread] = conn)
208
209
  end