sequel 3.46.0 → 3.47.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +96 -0
- data/Rakefile +7 -1
- data/bin/sequel +6 -4
- data/doc/active_record.rdoc +1 -1
- data/doc/advanced_associations.rdoc +14 -35
- data/doc/association_basics.rdoc +66 -4
- data/doc/migration.rdoc +4 -0
- data/doc/opening_databases.rdoc +6 -0
- data/doc/postgresql.rdoc +302 -0
- data/doc/release_notes/3.47.0.txt +270 -0
- data/doc/security.rdoc +6 -0
- data/lib/sequel/adapters/ibmdb.rb +9 -9
- data/lib/sequel/adapters/jdbc.rb +22 -7
- data/lib/sequel/adapters/jdbc/postgresql.rb +7 -2
- data/lib/sequel/adapters/mock.rb +2 -0
- data/lib/sequel/adapters/postgres.rb +44 -13
- data/lib/sequel/adapters/shared/mssql.rb +1 -1
- data/lib/sequel/adapters/shared/mysql.rb +2 -2
- data/lib/sequel/adapters/shared/postgres.rb +94 -55
- data/lib/sequel/adapters/shared/sqlite.rb +3 -1
- data/lib/sequel/adapters/sqlite.rb +2 -2
- data/lib/sequel/adapters/utils/pg_types.rb +1 -14
- data/lib/sequel/adapters/utils/split_alter_table.rb +3 -3
- data/lib/sequel/connection_pool/threaded.rb +1 -1
- data/lib/sequel/core.rb +1 -1
- data/lib/sequel/database/connecting.rb +2 -2
- data/lib/sequel/database/features.rb +5 -0
- data/lib/sequel/database/misc.rb +47 -5
- data/lib/sequel/database/query.rb +2 -2
- data/lib/sequel/dataset/actions.rb +4 -2
- data/lib/sequel/dataset/misc.rb +1 -1
- data/lib/sequel/dataset/prepared_statements.rb +1 -1
- data/lib/sequel/dataset/query.rb +8 -6
- data/lib/sequel/dataset/sql.rb +8 -6
- data/lib/sequel/extensions/constraint_validations.rb +5 -2
- data/lib/sequel/extensions/migration.rb +10 -8
- data/lib/sequel/extensions/pagination.rb +3 -0
- data/lib/sequel/extensions/pg_array.rb +85 -25
- data/lib/sequel/extensions/pg_hstore.rb +8 -1
- data/lib/sequel/extensions/pg_hstore_ops.rb +4 -1
- data/lib/sequel/extensions/pg_inet.rb +16 -13
- data/lib/sequel/extensions/pg_interval.rb +6 -2
- data/lib/sequel/extensions/pg_json.rb +18 -11
- data/lib/sequel/extensions/pg_range.rb +17 -2
- data/lib/sequel/extensions/pg_range_ops.rb +7 -5
- data/lib/sequel/extensions/pg_row.rb +29 -12
- data/lib/sequel/extensions/pretty_table.rb +3 -0
- data/lib/sequel/extensions/query.rb +3 -0
- data/lib/sequel/extensions/schema_caching.rb +2 -0
- data/lib/sequel/extensions/schema_dumper.rb +3 -1
- data/lib/sequel/extensions/select_remove.rb +3 -0
- data/lib/sequel/model.rb +8 -2
- data/lib/sequel/model/associations.rb +39 -27
- data/lib/sequel/model/base.rb +99 -38
- data/lib/sequel/model/plugins.rb +25 -0
- data/lib/sequel/plugins/association_autoreloading.rb +27 -22
- data/lib/sequel/plugins/association_dependencies.rb +1 -7
- data/lib/sequel/plugins/auto_validations.rb +110 -0
- data/lib/sequel/plugins/boolean_readers.rb +1 -6
- data/lib/sequel/plugins/caching.rb +6 -13
- data/lib/sequel/plugins/class_table_inheritance.rb +1 -0
- data/lib/sequel/plugins/composition.rb +14 -7
- data/lib/sequel/plugins/constraint_validations.rb +2 -13
- data/lib/sequel/plugins/defaults_setter.rb +1 -6
- data/lib/sequel/plugins/dirty.rb +8 -0
- data/lib/sequel/plugins/error_splitter.rb +54 -0
- data/lib/sequel/plugins/force_encoding.rb +1 -5
- data/lib/sequel/plugins/hook_class_methods.rb +1 -6
- data/lib/sequel/plugins/input_transformer.rb +79 -0
- data/lib/sequel/plugins/instance_filters.rb +7 -1
- data/lib/sequel/plugins/instance_hooks.rb +7 -1
- data/lib/sequel/plugins/json_serializer.rb +5 -10
- data/lib/sequel/plugins/lazy_attributes.rb +20 -7
- data/lib/sequel/plugins/list.rb +1 -6
- data/lib/sequel/plugins/many_through_many.rb +1 -2
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +23 -39
- data/lib/sequel/plugins/optimistic_locking.rb +1 -5
- data/lib/sequel/plugins/pg_row.rb +4 -2
- data/lib/sequel/plugins/pg_typecast_on_load.rb +3 -7
- data/lib/sequel/plugins/prepared_statements.rb +1 -5
- data/lib/sequel/plugins/prepared_statements_safe.rb +2 -11
- data/lib/sequel/plugins/rcte_tree.rb +2 -2
- data/lib/sequel/plugins/serialization.rb +11 -13
- data/lib/sequel/plugins/serialization_modification_detection.rb +13 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/static_cache.rb +67 -19
- data/lib/sequel/plugins/string_stripper.rb +7 -27
- data/lib/sequel/plugins/subclasses.rb +3 -5
- data/lib/sequel/plugins/tactical_eager_loading.rb +2 -2
- data/lib/sequel/plugins/timestamps.rb +2 -7
- data/lib/sequel/plugins/touch.rb +5 -8
- data/lib/sequel/plugins/tree.rb +1 -6
- data/lib/sequel/plugins/typecast_on_load.rb +1 -5
- data/lib/sequel/plugins/update_primary_key.rb +26 -14
- data/lib/sequel/plugins/validation_class_methods.rb +31 -16
- data/lib/sequel/plugins/validation_helpers.rb +50 -26
- data/lib/sequel/plugins/xml_serializer.rb +3 -6
- data/lib/sequel/sql.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/postgres_spec.rb +131 -15
- data/spec/adapters/sqlite_spec.rb +1 -1
- data/spec/core/connection_pool_spec.rb +16 -17
- data/spec/core/database_spec.rb +111 -40
- data/spec/core/dataset_spec.rb +65 -74
- data/spec/core/expression_filters_spec.rb +6 -5
- data/spec/core/object_graph_spec.rb +0 -1
- data/spec/core/schema_spec.rb +23 -23
- data/spec/core/spec_helper.rb +5 -1
- data/spec/extensions/association_dependencies_spec.rb +1 -1
- data/spec/extensions/association_proxies_spec.rb +1 -1
- data/spec/extensions/auto_validations_spec.rb +90 -0
- data/spec/extensions/caching_spec.rb +6 -0
- data/spec/extensions/class_table_inheritance_spec.rb +8 -1
- data/spec/extensions/composition_spec.rb +12 -5
- data/spec/extensions/constraint_validations_spec.rb +4 -4
- data/spec/extensions/core_refinements_spec.rb +29 -79
- data/spec/extensions/dirty_spec.rb +14 -0
- data/spec/extensions/error_splitter_spec.rb +18 -0
- data/spec/extensions/identity_map_spec.rb +0 -1
- data/spec/extensions/input_transformer_spec.rb +54 -0
- data/spec/extensions/instance_filters_spec.rb +6 -0
- data/spec/extensions/instance_hooks_spec.rb +12 -1
- data/spec/extensions/json_serializer_spec.rb +0 -1
- data/spec/extensions/lazy_attributes_spec.rb +64 -55
- data/spec/extensions/looser_typecasting_spec.rb +1 -1
- data/spec/extensions/many_through_many_spec.rb +3 -4
- data/spec/extensions/many_to_one_pk_lookup_spec.rb +53 -15
- data/spec/extensions/migration_spec.rb +16 -0
- data/spec/extensions/null_dataset_spec.rb +1 -1
- data/spec/extensions/pg_array_spec.rb +48 -1
- data/spec/extensions/pg_hstore_ops_spec.rb +10 -2
- data/spec/extensions/pg_hstore_spec.rb +5 -0
- data/spec/extensions/pg_inet_spec.rb +5 -0
- data/spec/extensions/pg_interval_spec.rb +7 -3
- data/spec/extensions/pg_json_spec.rb +6 -1
- data/spec/extensions/pg_range_ops_spec.rb +4 -1
- data/spec/extensions/pg_range_spec.rb +5 -0
- data/spec/extensions/pg_row_plugin_spec.rb +13 -0
- data/spec/extensions/pg_row_spec.rb +28 -19
- data/spec/extensions/pg_typecast_on_load_spec.rb +6 -1
- data/spec/extensions/prepared_statements_associations_spec.rb +1 -1
- data/spec/extensions/query_literals_spec.rb +1 -1
- data/spec/extensions/rcte_tree_spec.rb +2 -2
- data/spec/extensions/schema_spec.rb +2 -2
- data/spec/extensions/serialization_modification_detection_spec.rb +8 -0
- data/spec/extensions/serialization_spec.rb +15 -1
- data/spec/extensions/sharding_spec.rb +1 -1
- data/spec/extensions/single_table_inheritance_spec.rb +1 -1
- data/spec/extensions/static_cache_spec.rb +59 -9
- data/spec/extensions/tactical_eager_loading_spec.rb +19 -4
- data/spec/extensions/update_primary_key_spec.rb +17 -1
- data/spec/extensions/validation_class_methods_spec.rb +25 -0
- data/spec/extensions/validation_helpers_spec.rb +59 -3
- data/spec/integration/associations_test.rb +5 -5
- data/spec/integration/eager_loader_test.rb +32 -63
- data/spec/integration/model_test.rb +2 -2
- data/spec/integration/plugin_test.rb +88 -56
- data/spec/integration/prepared_statement_test.rb +1 -1
- data/spec/integration/schema_test.rb +1 -1
- data/spec/integration/timezone_test.rb +0 -1
- data/spec/integration/transaction_test.rb +0 -1
- data/spec/model/association_reflection_spec.rb +1 -1
- data/spec/model/associations_spec.rb +106 -84
- data/spec/model/base_spec.rb +4 -4
- data/spec/model/eager_loading_spec.rb +8 -8
- data/spec/model/model_spec.rb +27 -9
- data/spec/model/plugins_spec.rb +71 -0
- data/spec/model/record_spec.rb +99 -13
- metadata +12 -2
data/lib/sequel/adapters/mock.rb
CHANGED
@@ -96,6 +96,15 @@ module Sequel
|
|
96
96
|
def bytea(s) ::Sequel::SQL::Blob.new(Adapter.unescape_bytea(s)) end
|
97
97
|
end.new.method(:bytea)
|
98
98
|
|
99
|
+
@use_iso_date_format = true
|
100
|
+
|
101
|
+
class << self
|
102
|
+
# As an optimization, Sequel sets the date style to ISO, so that PostgreSQL provides
|
103
|
+
# the date in a known format that Sequel can parse faster. This can be turned off
|
104
|
+
# if you require a date style other than ISO.
|
105
|
+
attr_accessor :use_iso_date_format
|
106
|
+
end
|
107
|
+
|
99
108
|
# PGconn subclass for connection specific methods used with the
|
100
109
|
# pg, postgres, or postgres-pr driver.
|
101
110
|
class Adapter < ::PGconn
|
@@ -160,18 +169,20 @@ module Sequel
|
|
160
169
|
|
161
170
|
set_adapter_scheme :postgres
|
162
171
|
|
163
|
-
# Whether infinite timestamps should be converted on retrieval. By default, no
|
172
|
+
# Whether infinite timestamps/dates should be converted on retrieval. By default, no
|
164
173
|
# conversion is done, so an error is raised if you attempt to retrieve an infinite
|
165
|
-
# timestamp. You can set this to :nil to convert to nil, :string to leave
|
174
|
+
# timestamp/date. You can set this to :nil to convert to nil, :string to leave
|
166
175
|
# as a string, or :float to convert to an infinite float.
|
167
176
|
attr_reader :convert_infinite_timestamps
|
168
|
-
|
177
|
+
|
169
178
|
# Add the primary_keys and primary_key_sequences instance variables,
|
170
179
|
# so we can get the correct return values for inserted rows.
|
171
180
|
def initialize(*args)
|
172
181
|
super
|
173
|
-
@
|
182
|
+
@use_iso_date_format = typecast_value_boolean(@opts.fetch(:use_iso_date_format, Postgres.use_iso_date_format))
|
174
183
|
initialize_postgres_adapter
|
184
|
+
conversion_procs[1082] = TYPE_TRANSLATOR.method(:date) if @use_iso_date_format
|
185
|
+
self.convert_infinite_timestamps = @opts[:convert_infinite_timestamps]
|
175
186
|
end
|
176
187
|
|
177
188
|
# Convert given argument so that it can be used directly by pg. Currently, pg doesn't
|
@@ -233,16 +244,32 @@ module Sequel
|
|
233
244
|
conn
|
234
245
|
end
|
235
246
|
|
247
|
+
# Set whether to allow infinite timestamps/dates. Make sure the
|
248
|
+
# conversion proc for date reflects that setting.
|
236
249
|
def convert_infinite_timestamps=(v)
|
237
|
-
@convert_infinite_timestamps = v
|
238
|
-
|
250
|
+
@convert_infinite_timestamps = case v
|
251
|
+
when Symbol
|
252
|
+
v
|
253
|
+
when 'nil'
|
254
|
+
:nil
|
255
|
+
when 'string'
|
256
|
+
:string
|
257
|
+
when 'float'
|
258
|
+
:float
|
259
|
+
when String
|
260
|
+
typecast_value_boolean(v)
|
261
|
+
else
|
262
|
+
false
|
263
|
+
end
|
264
|
+
|
265
|
+
pr = old_pr = @use_iso_date_format ? TYPE_TRANSLATOR.method(:date) : Sequel.method(:string_to_date)
|
239
266
|
if v
|
240
|
-
pr = lambda do |
|
241
|
-
case
|
267
|
+
pr = lambda do |val|
|
268
|
+
case val
|
242
269
|
when *INFINITE_TIMESTAMP_STRINGS
|
243
|
-
infinite_timestamp_value(
|
270
|
+
infinite_timestamp_value(val)
|
244
271
|
else
|
245
|
-
old_pr.call(
|
272
|
+
old_pr.call(val)
|
246
273
|
end
|
247
274
|
end
|
248
275
|
end
|
@@ -345,7 +372,7 @@ module Sequel
|
|
345
372
|
conn.put_copy_data(buf)
|
346
373
|
end
|
347
374
|
else
|
348
|
-
data.each{|
|
375
|
+
data.each{|buff| conn.put_copy_data(buff)}
|
349
376
|
end
|
350
377
|
rescue Exception => e
|
351
378
|
conn.put_copy_end("ruby exception occurred while copying data into PostgreSQL")
|
@@ -385,7 +412,11 @@ module Sequel
|
|
385
412
|
synchronize(opts[:server]) do |conn|
|
386
413
|
begin
|
387
414
|
channels = Array(channels)
|
388
|
-
channels.each
|
415
|
+
channels.each do |channel|
|
416
|
+
sql = "LISTEN "
|
417
|
+
dataset.send(:identifier_append, sql, channel)
|
418
|
+
conn.execute(sql)
|
419
|
+
end
|
389
420
|
opts[:after_listen].call(conn) if opts[:after_listen]
|
390
421
|
timeout = opts[:timeout] ? [opts[:timeout]] : []
|
391
422
|
if l = opts[:loop]
|
@@ -452,7 +483,7 @@ module Sequel
|
|
452
483
|
# Set the DateStyle to ISO if configured, for faster date parsing.
|
453
484
|
def connection_configuration_sqls
|
454
485
|
sqls = super
|
455
|
-
sqls << "SET DateStyle = 'ISO'" if
|
486
|
+
sqls << "SET DateStyle = 'ISO'" if @use_iso_date_format
|
456
487
|
sqls
|
457
488
|
end
|
458
489
|
|
@@ -203,7 +203,7 @@ module Sequel
|
|
203
203
|
opts.delete(:auto_increment) if op[:auto_increment] == false
|
204
204
|
"CHANGE COLUMN #{quote_identifier(op[:name])} #{column_definition_sql(opts)}"
|
205
205
|
when :drop_constraint
|
206
|
-
|
206
|
+
case op[:type]
|
207
207
|
when :primary_key
|
208
208
|
"DROP PRIMARY KEY"
|
209
209
|
when :foreign_key
|
@@ -881,7 +881,7 @@ module Sequel
|
|
881
881
|
def limit_sql(sql)
|
882
882
|
if l = @opts[:limit]
|
883
883
|
sql << LIMIT
|
884
|
-
literal_append(sql,
|
884
|
+
literal_append(sql, l)
|
885
885
|
end
|
886
886
|
end
|
887
887
|
alias delete_limit_sql limit_sql
|
@@ -11,25 +11,17 @@ module Sequel
|
|
11
11
|
# a per instance basis via the :client_min_messages option.
|
12
12
|
# force_standard_strings :: Set to false to not force the use of standard strings. Overridable
|
13
13
|
# on a per instance basis via the :force_standard_strings option.
|
14
|
-
# use_iso_date_format :: (only available when using the native adapter)
|
15
|
-
# Set to false to not change the date format to
|
16
|
-
# ISO. This disables one of Sequel's optimizations.
|
17
14
|
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
# after the Database object is instantiated and before a connection
|
21
|
-
# is actually made. For example, to use whatever the server defaults are:
|
15
|
+
# It is not recommened you use these module-level accessors. Instead,
|
16
|
+
# use the database option to make the setting per-Database.
|
22
17
|
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
# Sequel::Postgres.force_standard_strings = false
|
26
|
-
# Sequel::Postgres.use_iso_date_format = false
|
27
|
-
# # A connection to the server is not made until here
|
28
|
-
# DB[:t].all
|
18
|
+
# All adapters that connect to PostgreSQL support the following option in
|
19
|
+
# addition to those mentioned above:
|
29
20
|
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
21
|
+
# :search_path :: Set the schema search_path for this Database's connections.
|
22
|
+
# Allows to to set which schemas do not need explicit
|
23
|
+
# qualification, and in which order to check the schemas when
|
24
|
+
# an unqualified object is referenced.
|
33
25
|
module Postgres
|
34
26
|
# Array of exceptions that need to be converted. JDBC
|
35
27
|
# uses NativeExceptions, the native adapter uses PGError.
|
@@ -155,9 +147,6 @@ module Sequel
|
|
155
147
|
end_sql
|
156
148
|
).strip.gsub(/\s+/, ' ').freeze
|
157
149
|
|
158
|
-
# The Sequel extensions that require reseting of the conversion procs.
|
159
|
-
RESET_PROCS_EXTENSIONS = [:pg_array, :pg_hstore, :pg_inet, :pg_interval, :pg_json, :pg_range].freeze
|
160
|
-
|
161
150
|
# A hash of conversion procs, keyed by type integer (oid) and
|
162
151
|
# having callable values for the conversion proc for that type.
|
163
152
|
attr_reader :conversion_procs
|
@@ -276,17 +265,6 @@ module Sequel
|
|
276
265
|
self << drop_trigger_sql(table, name, opts)
|
277
266
|
end
|
278
267
|
|
279
|
-
# If any of the extensions that require reseting the conversion procs
|
280
|
-
# is loaded, reset them. This is done here so that if you load
|
281
|
-
# multiple pg_* extensions in the same call, the conversion procs are
|
282
|
-
# only reset once instead of once for every extension.
|
283
|
-
def extension(*exts)
|
284
|
-
super
|
285
|
-
unless (RESET_PROCS_EXTENSIONS & exts).empty?
|
286
|
-
reset_conversion_procs
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
268
|
# Return full foreign key information using the pg system tables, including
|
291
269
|
# :name, :on_delete, :on_update, and :deferrable entries in the hashes.
|
292
270
|
def foreign_key_list(table, opts={})
|
@@ -379,7 +357,13 @@ module Sequel
|
|
379
357
|
# :server :: The server to which to send the NOTIFY statement, if the sharding support
|
380
358
|
# is being used.
|
381
359
|
def notify(channel, opts={})
|
382
|
-
|
360
|
+
sql = "NOTIFY "
|
361
|
+
dataset.send(:identifier_append, sql, channel)
|
362
|
+
if payload = opts[:payload]
|
363
|
+
sql << ", "
|
364
|
+
dataset.literal_append(sql, payload.to_s)
|
365
|
+
end
|
366
|
+
execute_ddl(sql, opts)
|
383
367
|
end
|
384
368
|
|
385
369
|
# Return primary key for the given table.
|
@@ -530,6 +514,16 @@ module Sequel
|
|
530
514
|
|
531
515
|
private
|
532
516
|
|
517
|
+
# Do a type name-to-oid lookup using the database and update the procs
|
518
|
+
# with the related proc if the database supports the type.
|
519
|
+
def add_named_conversion_procs(procs, named_procs)
|
520
|
+
unless (named_procs).empty?
|
521
|
+
convert_named_procs_to_procs(named_procs).each do |oid, pr|
|
522
|
+
procs[oid] ||= pr
|
523
|
+
end
|
524
|
+
end
|
525
|
+
end
|
526
|
+
|
533
527
|
# Use a PostgreSQL-specific alter table generator
|
534
528
|
def alter_table_generator_class
|
535
529
|
Postgres::AlterTableGenerator
|
@@ -596,13 +590,29 @@ module Sequel
|
|
596
590
|
(super || op[:op] == :validate_constraint) && op[:op] != :rename_column
|
597
591
|
end
|
598
592
|
|
593
|
+
VALID_CLIENT_MIN_MESSAGES = %w'DEBUG5 DEBUG4 DEBUG3 DEBUG2 DEBUG1 LOG NOTICE WARNING ERROR FATAL PANIC'.freeze
|
599
594
|
# The SQL queries to execute when starting a new connection.
|
600
595
|
def connection_configuration_sqls
|
601
596
|
sqls = []
|
597
|
+
|
602
598
|
sqls << "SET standard_conforming_strings = ON" if typecast_value_boolean(@opts.fetch(:force_standard_strings, Postgres.force_standard_strings))
|
599
|
+
|
603
600
|
if (cmm = @opts.fetch(:client_min_messages, Postgres.client_min_messages)) && !cmm.to_s.empty?
|
604
601
|
sqls << "SET client_min_messages = '#{cmm.to_s.upcase}'"
|
605
602
|
end
|
603
|
+
|
604
|
+
if search_path = @opts[:search_path]
|
605
|
+
case search_path
|
606
|
+
when String
|
607
|
+
search_path = search_path.split(",").map{|s| s.strip}
|
608
|
+
when Array
|
609
|
+
# nil
|
610
|
+
else
|
611
|
+
raise Error, "unrecognized value for :search_path option: #{search_path.inspect}"
|
612
|
+
end
|
613
|
+
sqls << "SET search_path = #{search_path.map{|s| "\"#{s.gsub('"', '""')}\""}.join(',')}"
|
614
|
+
end
|
615
|
+
|
606
616
|
sqls
|
607
617
|
end
|
608
618
|
|
@@ -623,6 +633,24 @@ module Sequel
|
|
623
633
|
end
|
624
634
|
end
|
625
635
|
|
636
|
+
# Convert the hash of named conversion procs into a hash a oid conversion procs.
|
637
|
+
def convert_named_procs_to_procs(named_procs)
|
638
|
+
h = {}
|
639
|
+
from(:pg_type).where(:typtype=>'b', :typname=>named_procs.keys.map{|t| t.to_s}).select_map([:oid, :typname]).each do |oid, name|
|
640
|
+
h[oid.to_i] = named_procs[name.untaint.to_sym]
|
641
|
+
end
|
642
|
+
h
|
643
|
+
end
|
644
|
+
|
645
|
+
# Copy the conversion procs related to the given oids from PG_TYPES into
|
646
|
+
# the conversion procs for this instance.
|
647
|
+
def copy_conversion_procs(oids)
|
648
|
+
procs = conversion_procs
|
649
|
+
oids.each do |oid|
|
650
|
+
procs[oid] = PG_TYPES[oid]
|
651
|
+
end
|
652
|
+
end
|
653
|
+
|
626
654
|
EXCLUSION_CONSTRAINT_SQL_STATE = '23P01'.freeze
|
627
655
|
def database_specific_error_class_from_sqlstate(sqlstate)
|
628
656
|
if sqlstate == EXCLUSION_CONSTRAINT_SQL_STATE
|
@@ -665,23 +693,23 @@ module Sequel
|
|
665
693
|
|
666
694
|
# SQL for doing fast table output to stdout.
|
667
695
|
def copy_table_sql(table, opts)
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
696
|
+
if table.is_a?(String)
|
697
|
+
table
|
698
|
+
else
|
699
|
+
if opts[:options] || opts[:format]
|
700
|
+
options = " ("
|
701
|
+
options << "FORMAT #{opts[:format]}" if opts[:format]
|
702
|
+
options << "#{', ' if opts[:format]}#{opts[:options]}" if opts[:options]
|
703
|
+
options << ')'
|
704
|
+
end
|
705
|
+
table = if table.is_a?(::Sequel::Dataset)
|
706
|
+
"(#{table.sql})"
|
707
|
+
else
|
708
|
+
literal(table)
|
709
|
+
end
|
710
|
+
"COPY #{table} TO STDOUT#{options}"
|
711
|
+
end
|
712
|
+
end
|
685
713
|
|
686
714
|
# SQL statement to create database function.
|
687
715
|
def create_function_sql(name, definition, opts={})
|
@@ -786,11 +814,7 @@ module Sequel
|
|
786
814
|
def get_conversion_procs
|
787
815
|
procs = PG_TYPES.dup
|
788
816
|
procs[1184] = procs[1114] = method(:to_application_timestamp)
|
789
|
-
|
790
|
-
from(:pg_type).where(:typtype=>'b', :typname=>pgnt.keys.map{|t| t.to_s}).select_map([:oid, :typname]).each do |oid, name|
|
791
|
-
procs[oid.to_i] ||= pgnt[name.untaint.to_sym]
|
792
|
-
end
|
793
|
-
end
|
817
|
+
add_named_conversion_procs(procs, PG_NAMED_TYPES)
|
794
818
|
procs
|
795
819
|
end
|
796
820
|
|
@@ -915,6 +939,8 @@ module Sequel
|
|
915
939
|
m = output_identifier_meth(opts[:dataset])
|
916
940
|
ds = metadata_dataset.select(:pg_attribute__attname___name,
|
917
941
|
SQL::Cast.new(:pg_attribute__atttypid, :integer).as(:oid),
|
942
|
+
SQL::Cast.new(:basetype__oid, :integer).as(:base_oid),
|
943
|
+
SQL::Function.new(:format_type, :basetype__oid, :pg_type__typtypmod).as(:db_base_type),
|
918
944
|
SQL::Function.new(:format_type, :pg_type__oid, :pg_attribute__atttypmod).as(:db_type),
|
919
945
|
SQL::Function.new(:pg_get_expr, :pg_attrdef__adbin, :pg_class__oid).as(:default),
|
920
946
|
SQL::BooleanExpression.new(:NOT, :pg_attribute__attnotnull).as(:allow_null),
|
@@ -922,6 +948,7 @@ module Sequel
|
|
922
948
|
from(:pg_class).
|
923
949
|
join(:pg_attribute, :attrelid=>:oid).
|
924
950
|
join(:pg_type, :oid=>:atttypid).
|
951
|
+
left_outer_join(:pg_type___basetype, :oid=>:typbasetype).
|
925
952
|
left_outer_join(:pg_attrdef, :adrelid=>:pg_class__oid, :adnum=>:pg_attribute__attnum).
|
926
953
|
left_outer_join(:pg_index, :indrelid=>:pg_class__oid, :indisprimary=>true).
|
927
954
|
filter(:pg_attribute__attisdropped=>false).
|
@@ -930,6 +957,15 @@ module Sequel
|
|
930
957
|
order(:pg_attribute__attnum)
|
931
958
|
ds.map do |row|
|
932
959
|
row[:default] = nil if blank_object?(row[:default])
|
960
|
+
if row[:base_oid]
|
961
|
+
row[:domain_oid] = row[:oid]
|
962
|
+
row[:oid] = row.delete(:base_oid)
|
963
|
+
row[:db_domain_type] = row[:db_type]
|
964
|
+
row[:db_type] = row.delete(:db_base_type)
|
965
|
+
else
|
966
|
+
row.delete(:base_oid)
|
967
|
+
row.delete(:db_base_type)
|
968
|
+
end
|
933
969
|
row[:type] = schema_column_type(row[:db_type])
|
934
970
|
[m.call(row.delete(:name)), row]
|
935
971
|
end
|
@@ -1009,7 +1045,6 @@ module Sequel
|
|
1009
1045
|
FOR_SHARE = ' FOR SHARE'.freeze
|
1010
1046
|
INSERT_CLAUSE_METHODS = Dataset.clause_methods(:insert, %w'insert into columns values returning')
|
1011
1047
|
INSERT_CLAUSE_METHODS_91 = Dataset.clause_methods(:insert, %w'with insert into columns values returning')
|
1012
|
-
LOCK = 'LOCK TABLE %s IN %s MODE'.freeze
|
1013
1048
|
NULL = LiteralString.new('NULL').freeze
|
1014
1049
|
PG_TIMESTAMP_FORMAT = "TIMESTAMP '%Y-%m-%d %H:%M:%S".freeze
|
1015
1050
|
QUERY_PLAN = 'QUERY PLAN'.to_sym
|
@@ -1039,6 +1074,7 @@ module Sequel
|
|
1039
1074
|
BLOB_RE = /[\000-\037\047\134\177-\377]/n.freeze
|
1040
1075
|
WINDOW = " WINDOW ".freeze
|
1041
1076
|
EMPTY_STRING = ''.freeze
|
1077
|
+
LOCK_MODES = ['ACCESS SHARE', 'ROW SHARE', 'ROW EXCLUSIVE', 'SHARE UPDATE EXCLUSIVE', 'SHARE', 'SHARE ROW EXCLUSIVE', 'EXCLUSIVE', 'ACCESS EXCLUSIVE'].each{|s| s.freeze}
|
1042
1078
|
|
1043
1079
|
# Shared methods for prepared statements when used with PostgreSQL databases.
|
1044
1080
|
module PreparedStatementMethods
|
@@ -1140,7 +1176,10 @@ module Sequel
|
|
1140
1176
|
if block_given? # perform locking inside a transaction and yield to block
|
1141
1177
|
@db.transaction(opts){lock(mode, opts); yield}
|
1142
1178
|
else
|
1143
|
-
|
1179
|
+
sql = 'LOCK TABLE '
|
1180
|
+
source_list_append(sql, @opts[:from])
|
1181
|
+
sql << " IN #{mode} MODE"
|
1182
|
+
@db.execute(sql, opts) # lock without a transaction
|
1144
1183
|
end
|
1145
1184
|
nil
|
1146
1185
|
end
|
@@ -661,7 +661,9 @@ module Sequel
|
|
661
661
|
SELECT_CLAUSE_METHODS
|
662
662
|
end
|
663
663
|
|
664
|
-
#
|
664
|
+
# SQLite does not support FOR UPDATE, but silently ignore it
|
665
|
+
# instead of raising an error for compatibility with other
|
666
|
+
# databases.
|
665
667
|
def select_lock_sql(sql)
|
666
668
|
super unless @opts[:lock] == :update
|
667
669
|
end
|
@@ -356,8 +356,8 @@ module Sequel
|
|
356
356
|
@columns = cols.map{|c| c.first}
|
357
357
|
result.each do |values|
|
358
358
|
row = {}
|
359
|
-
cols.each do |name,
|
360
|
-
v = values[
|
359
|
+
cols.each do |name,id,type_proc|
|
360
|
+
v = values[id]
|
361
361
|
if type_proc && v
|
362
362
|
v = type_proc.call(v)
|
363
363
|
end
|
@@ -59,23 +59,10 @@ module Sequel
|
|
59
59
|
[700, 701] => tt.method(:float),
|
60
60
|
[1700] => ::BigDecimal.method(:new),
|
61
61
|
[1083, 1266] => ::Sequel.method(:string_to_time),
|
62
|
+
[1082] => ::Sequel.method(:string_to_date),
|
62
63
|
[1184, 1114] => ::Sequel.method(:database_to_application_timestamp),
|
63
64
|
}.each do |k,v|
|
64
65
|
k.each{|n| PG_TYPES[n] = v}
|
65
66
|
end
|
66
|
-
|
67
|
-
class << self
|
68
|
-
# As an optimization, Sequel sets the date style to ISO, so that PostgreSQL provides
|
69
|
-
# the date in a known format that Sequel can parse faster. This can be turned off
|
70
|
-
# if you require a date style other than ISO.
|
71
|
-
attr_reader :use_iso_date_format
|
72
|
-
end
|
73
|
-
|
74
|
-
# Modify the type translator for the date type depending on the value given.
|
75
|
-
def self.use_iso_date_format=(v)
|
76
|
-
PG_TYPES[1082] = v ? TYPE_TRANSLATOR.method(:date) : Sequel.method(:string_to_date)
|
77
|
-
@use_iso_date_format = v
|
78
|
-
end
|
79
|
-
self.use_iso_date_format = true
|
80
67
|
end
|
81
68
|
end
|