sequel 3.46.0 → 3.47.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (170) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +96 -0
  3. data/Rakefile +7 -1
  4. data/bin/sequel +6 -4
  5. data/doc/active_record.rdoc +1 -1
  6. data/doc/advanced_associations.rdoc +14 -35
  7. data/doc/association_basics.rdoc +66 -4
  8. data/doc/migration.rdoc +4 -0
  9. data/doc/opening_databases.rdoc +6 -0
  10. data/doc/postgresql.rdoc +302 -0
  11. data/doc/release_notes/3.47.0.txt +270 -0
  12. data/doc/security.rdoc +6 -0
  13. data/lib/sequel/adapters/ibmdb.rb +9 -9
  14. data/lib/sequel/adapters/jdbc.rb +22 -7
  15. data/lib/sequel/adapters/jdbc/postgresql.rb +7 -2
  16. data/lib/sequel/adapters/mock.rb +2 -0
  17. data/lib/sequel/adapters/postgres.rb +44 -13
  18. data/lib/sequel/adapters/shared/mssql.rb +1 -1
  19. data/lib/sequel/adapters/shared/mysql.rb +2 -2
  20. data/lib/sequel/adapters/shared/postgres.rb +94 -55
  21. data/lib/sequel/adapters/shared/sqlite.rb +3 -1
  22. data/lib/sequel/adapters/sqlite.rb +2 -2
  23. data/lib/sequel/adapters/utils/pg_types.rb +1 -14
  24. data/lib/sequel/adapters/utils/split_alter_table.rb +3 -3
  25. data/lib/sequel/connection_pool/threaded.rb +1 -1
  26. data/lib/sequel/core.rb +1 -1
  27. data/lib/sequel/database/connecting.rb +2 -2
  28. data/lib/sequel/database/features.rb +5 -0
  29. data/lib/sequel/database/misc.rb +47 -5
  30. data/lib/sequel/database/query.rb +2 -2
  31. data/lib/sequel/dataset/actions.rb +4 -2
  32. data/lib/sequel/dataset/misc.rb +1 -1
  33. data/lib/sequel/dataset/prepared_statements.rb +1 -1
  34. data/lib/sequel/dataset/query.rb +8 -6
  35. data/lib/sequel/dataset/sql.rb +8 -6
  36. data/lib/sequel/extensions/constraint_validations.rb +5 -2
  37. data/lib/sequel/extensions/migration.rb +10 -8
  38. data/lib/sequel/extensions/pagination.rb +3 -0
  39. data/lib/sequel/extensions/pg_array.rb +85 -25
  40. data/lib/sequel/extensions/pg_hstore.rb +8 -1
  41. data/lib/sequel/extensions/pg_hstore_ops.rb +4 -1
  42. data/lib/sequel/extensions/pg_inet.rb +16 -13
  43. data/lib/sequel/extensions/pg_interval.rb +6 -2
  44. data/lib/sequel/extensions/pg_json.rb +18 -11
  45. data/lib/sequel/extensions/pg_range.rb +17 -2
  46. data/lib/sequel/extensions/pg_range_ops.rb +7 -5
  47. data/lib/sequel/extensions/pg_row.rb +29 -12
  48. data/lib/sequel/extensions/pretty_table.rb +3 -0
  49. data/lib/sequel/extensions/query.rb +3 -0
  50. data/lib/sequel/extensions/schema_caching.rb +2 -0
  51. data/lib/sequel/extensions/schema_dumper.rb +3 -1
  52. data/lib/sequel/extensions/select_remove.rb +3 -0
  53. data/lib/sequel/model.rb +8 -2
  54. data/lib/sequel/model/associations.rb +39 -27
  55. data/lib/sequel/model/base.rb +99 -38
  56. data/lib/sequel/model/plugins.rb +25 -0
  57. data/lib/sequel/plugins/association_autoreloading.rb +27 -22
  58. data/lib/sequel/plugins/association_dependencies.rb +1 -7
  59. data/lib/sequel/plugins/auto_validations.rb +110 -0
  60. data/lib/sequel/plugins/boolean_readers.rb +1 -6
  61. data/lib/sequel/plugins/caching.rb +6 -13
  62. data/lib/sequel/plugins/class_table_inheritance.rb +1 -0
  63. data/lib/sequel/plugins/composition.rb +14 -7
  64. data/lib/sequel/plugins/constraint_validations.rb +2 -13
  65. data/lib/sequel/plugins/defaults_setter.rb +1 -6
  66. data/lib/sequel/plugins/dirty.rb +8 -0
  67. data/lib/sequel/plugins/error_splitter.rb +54 -0
  68. data/lib/sequel/plugins/force_encoding.rb +1 -5
  69. data/lib/sequel/plugins/hook_class_methods.rb +1 -6
  70. data/lib/sequel/plugins/input_transformer.rb +79 -0
  71. data/lib/sequel/plugins/instance_filters.rb +7 -1
  72. data/lib/sequel/plugins/instance_hooks.rb +7 -1
  73. data/lib/sequel/plugins/json_serializer.rb +5 -10
  74. data/lib/sequel/plugins/lazy_attributes.rb +20 -7
  75. data/lib/sequel/plugins/list.rb +1 -6
  76. data/lib/sequel/plugins/many_through_many.rb +1 -2
  77. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +23 -39
  78. data/lib/sequel/plugins/optimistic_locking.rb +1 -5
  79. data/lib/sequel/plugins/pg_row.rb +4 -2
  80. data/lib/sequel/plugins/pg_typecast_on_load.rb +3 -7
  81. data/lib/sequel/plugins/prepared_statements.rb +1 -5
  82. data/lib/sequel/plugins/prepared_statements_safe.rb +2 -11
  83. data/lib/sequel/plugins/rcte_tree.rb +2 -2
  84. data/lib/sequel/plugins/serialization.rb +11 -13
  85. data/lib/sequel/plugins/serialization_modification_detection.rb +13 -1
  86. data/lib/sequel/plugins/single_table_inheritance.rb +4 -4
  87. data/lib/sequel/plugins/static_cache.rb +67 -19
  88. data/lib/sequel/plugins/string_stripper.rb +7 -27
  89. data/lib/sequel/plugins/subclasses.rb +3 -5
  90. data/lib/sequel/plugins/tactical_eager_loading.rb +2 -2
  91. data/lib/sequel/plugins/timestamps.rb +2 -7
  92. data/lib/sequel/plugins/touch.rb +5 -8
  93. data/lib/sequel/plugins/tree.rb +1 -6
  94. data/lib/sequel/plugins/typecast_on_load.rb +1 -5
  95. data/lib/sequel/plugins/update_primary_key.rb +26 -14
  96. data/lib/sequel/plugins/validation_class_methods.rb +31 -16
  97. data/lib/sequel/plugins/validation_helpers.rb +50 -26
  98. data/lib/sequel/plugins/xml_serializer.rb +3 -6
  99. data/lib/sequel/sql.rb +1 -1
  100. data/lib/sequel/version.rb +1 -1
  101. data/spec/adapters/postgres_spec.rb +131 -15
  102. data/spec/adapters/sqlite_spec.rb +1 -1
  103. data/spec/core/connection_pool_spec.rb +16 -17
  104. data/spec/core/database_spec.rb +111 -40
  105. data/spec/core/dataset_spec.rb +65 -74
  106. data/spec/core/expression_filters_spec.rb +6 -5
  107. data/spec/core/object_graph_spec.rb +0 -1
  108. data/spec/core/schema_spec.rb +23 -23
  109. data/spec/core/spec_helper.rb +5 -1
  110. data/spec/extensions/association_dependencies_spec.rb +1 -1
  111. data/spec/extensions/association_proxies_spec.rb +1 -1
  112. data/spec/extensions/auto_validations_spec.rb +90 -0
  113. data/spec/extensions/caching_spec.rb +6 -0
  114. data/spec/extensions/class_table_inheritance_spec.rb +8 -1
  115. data/spec/extensions/composition_spec.rb +12 -5
  116. data/spec/extensions/constraint_validations_spec.rb +4 -4
  117. data/spec/extensions/core_refinements_spec.rb +29 -79
  118. data/spec/extensions/dirty_spec.rb +14 -0
  119. data/spec/extensions/error_splitter_spec.rb +18 -0
  120. data/spec/extensions/identity_map_spec.rb +0 -1
  121. data/spec/extensions/input_transformer_spec.rb +54 -0
  122. data/spec/extensions/instance_filters_spec.rb +6 -0
  123. data/spec/extensions/instance_hooks_spec.rb +12 -1
  124. data/spec/extensions/json_serializer_spec.rb +0 -1
  125. data/spec/extensions/lazy_attributes_spec.rb +64 -55
  126. data/spec/extensions/looser_typecasting_spec.rb +1 -1
  127. data/spec/extensions/many_through_many_spec.rb +3 -4
  128. data/spec/extensions/many_to_one_pk_lookup_spec.rb +53 -15
  129. data/spec/extensions/migration_spec.rb +16 -0
  130. data/spec/extensions/null_dataset_spec.rb +1 -1
  131. data/spec/extensions/pg_array_spec.rb +48 -1
  132. data/spec/extensions/pg_hstore_ops_spec.rb +10 -2
  133. data/spec/extensions/pg_hstore_spec.rb +5 -0
  134. data/spec/extensions/pg_inet_spec.rb +5 -0
  135. data/spec/extensions/pg_interval_spec.rb +7 -3
  136. data/spec/extensions/pg_json_spec.rb +6 -1
  137. data/spec/extensions/pg_range_ops_spec.rb +4 -1
  138. data/spec/extensions/pg_range_spec.rb +5 -0
  139. data/spec/extensions/pg_row_plugin_spec.rb +13 -0
  140. data/spec/extensions/pg_row_spec.rb +28 -19
  141. data/spec/extensions/pg_typecast_on_load_spec.rb +6 -1
  142. data/spec/extensions/prepared_statements_associations_spec.rb +1 -1
  143. data/spec/extensions/query_literals_spec.rb +1 -1
  144. data/spec/extensions/rcte_tree_spec.rb +2 -2
  145. data/spec/extensions/schema_spec.rb +2 -2
  146. data/spec/extensions/serialization_modification_detection_spec.rb +8 -0
  147. data/spec/extensions/serialization_spec.rb +15 -1
  148. data/spec/extensions/sharding_spec.rb +1 -1
  149. data/spec/extensions/single_table_inheritance_spec.rb +1 -1
  150. data/spec/extensions/static_cache_spec.rb +59 -9
  151. data/spec/extensions/tactical_eager_loading_spec.rb +19 -4
  152. data/spec/extensions/update_primary_key_spec.rb +17 -1
  153. data/spec/extensions/validation_class_methods_spec.rb +25 -0
  154. data/spec/extensions/validation_helpers_spec.rb +59 -3
  155. data/spec/integration/associations_test.rb +5 -5
  156. data/spec/integration/eager_loader_test.rb +32 -63
  157. data/spec/integration/model_test.rb +2 -2
  158. data/spec/integration/plugin_test.rb +88 -56
  159. data/spec/integration/prepared_statement_test.rb +1 -1
  160. data/spec/integration/schema_test.rb +1 -1
  161. data/spec/integration/timezone_test.rb +0 -1
  162. data/spec/integration/transaction_test.rb +0 -1
  163. data/spec/model/association_reflection_spec.rb +1 -1
  164. data/spec/model/associations_spec.rb +106 -84
  165. data/spec/model/base_spec.rb +4 -4
  166. data/spec/model/eager_loading_spec.rb +8 -8
  167. data/spec/model/model_spec.rb +27 -9
  168. data/spec/model/plugins_spec.rb +71 -0
  169. data/spec/model/record_spec.rb +99 -13
  170. metadata +12 -2
@@ -151,6 +151,8 @@ module Sequel
151
151
  if pr = SHARED_ADAPTER_SETUP[opts[:host]]
152
152
  pr.call(self)
153
153
  end
154
+ else
155
+ @shared_adapter = false
154
156
  end
155
157
  self.autoid = opts[:autoid]
156
158
  self.columns = opts[:columns]
@@ -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
- @convert_infinite_timestamps = false
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
- pr = old_pr = Postgres.use_iso_date_format ? TYPE_TRANSLATOR.method(:date) : Sequel.method(:string_to_date)
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 |v|
241
- case v
267
+ pr = lambda do |val|
268
+ case val
242
269
  when *INFINITE_TIMESTAMP_STRINGS
243
- infinite_timestamp_value(v)
270
+ infinite_timestamp_value(val)
244
271
  else
245
- old_pr.call(v)
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{|buf| conn.put_copy_data(buf)}
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{|channel| conn.execute("LISTEN #{dataset.send(:table_ref, channel)}")}
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 Postgres.use_iso_date_format
486
+ sqls << "SET DateStyle = 'ISO'" if @use_iso_date_format
456
487
  sqls
457
488
  end
458
489
 
@@ -1,4 +1,4 @@
1
- Sequel.require %w'emulate_offset_with_row_number split_alter_table', 'adapters/utils/'
1
+ Sequel.require %w'emulate_offset_with_row_number split_alter_table', 'adapters/utils'
2
2
 
3
3
  module Sequel
4
4
  Dataset::NON_SQL_OPTIONS << :disable_insert_output
@@ -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
- type = case op[:type]
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, @opts[:limit])
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
- # Changes in these settings only affect future connections. To make
19
- # sure that they are applied, they should generally be called right
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
- # DB = Sequel.postgres(...)
24
- # Sequel::Postgres.client_min_messages = nil
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
- # The reason they can't be done earlier is that the Sequel::Postgres
31
- # module is not loaded until a Database object which uses PostgreSQL
32
- # is created.
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
- execute_ddl("NOTIFY #{dataset.send(:table_ref, channel)}#{", #{literal(opts[:payload].to_s)}" if opts[:payload]}", opts)
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
- if table.is_a?(String)
669
- return table
670
- else
671
- if opts[:options] || opts[:format]
672
- options = " ("
673
- options << "FORMAT #{opts[:format]}" if opts[:format]
674
- options << "#{', ' if opts[:format]}#{opts[:options]}" if opts[:options]
675
- options << ')'
676
- end
677
- table = if table.is_a?(::Sequel::Dataset)
678
- "(#{table.sql})"
679
- else
680
- literal(table)
681
- end
682
- return "COPY #{table} TO STDOUT#{options}"
683
- end
684
- end
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
- unless (pgnt = PG_NAMED_TYPES).empty?
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
- @db.execute(LOCK % [source_list(@opts[:from]), mode], opts) # lock without a transaction
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
- # Support FOR SHARE locking when using the :share lock style.
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,i,type_proc|
360
- v = values[i]
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