sequel 4.46.0 → 4.49.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 (228) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +210 -0
  3. data/Rakefile +1 -1
  4. data/doc/advanced_associations.rdoc +1 -1
  5. data/doc/opening_databases.rdoc +3 -2
  6. data/doc/release_notes/4.47.0.txt +56 -0
  7. data/doc/release_notes/4.48.0.txt +293 -0
  8. data/doc/release_notes/4.49.0.txt +222 -0
  9. data/lib/sequel/adapters/ado/access.rb +2 -1
  10. data/lib/sequel/adapters/do/postgres.rb +5 -2
  11. data/lib/sequel/adapters/ibmdb.rb +30 -8
  12. data/lib/sequel/adapters/jdbc/as400.rb +1 -1
  13. data/lib/sequel/adapters/jdbc/db2.rb +12 -3
  14. data/lib/sequel/adapters/jdbc/derby.rb +4 -5
  15. data/lib/sequel/adapters/jdbc/h2.rb +10 -1
  16. data/lib/sequel/adapters/jdbc/oracle.rb +16 -2
  17. data/lib/sequel/adapters/jdbc/postgresql.rb +46 -20
  18. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +9 -7
  19. data/lib/sequel/adapters/jdbc/sqlserver.rb +20 -6
  20. data/lib/sequel/adapters/jdbc.rb +39 -23
  21. data/lib/sequel/adapters/mock.rb +27 -19
  22. data/lib/sequel/adapters/mysql.rb +17 -16
  23. data/lib/sequel/adapters/mysql2.rb +5 -6
  24. data/lib/sequel/adapters/oracle.rb +5 -9
  25. data/lib/sequel/adapters/postgres.rb +91 -103
  26. data/lib/sequel/adapters/shared/db2.rb +22 -6
  27. data/lib/sequel/adapters/shared/mssql.rb +5 -4
  28. data/lib/sequel/adapters/shared/mysql.rb +79 -25
  29. data/lib/sequel/adapters/shared/oracle.rb +26 -3
  30. data/lib/sequel/adapters/shared/postgres.rb +199 -95
  31. data/lib/sequel/adapters/shared/sqlanywhere.rb +23 -10
  32. data/lib/sequel/adapters/shared/sqlite.rb +72 -82
  33. data/lib/sequel/adapters/sqlanywhere.rb +4 -1
  34. data/lib/sequel/adapters/sqlite.rb +5 -3
  35. data/lib/sequel/adapters/swift/postgres.rb +5 -2
  36. data/lib/sequel/adapters/tinytds.rb +0 -5
  37. data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -1
  38. data/lib/sequel/adapters/utils/pg_types.rb +2 -76
  39. data/lib/sequel/ast_transformer.rb +1 -1
  40. data/lib/sequel/connection_pool/sharded_single.rb +1 -1
  41. data/lib/sequel/connection_pool/sharded_threaded.rb +1 -1
  42. data/lib/sequel/connection_pool/single.rb +2 -2
  43. data/lib/sequel/connection_pool/threaded.rb +2 -2
  44. data/lib/sequel/connection_pool.rb +9 -2
  45. data/lib/sequel/core.rb +2 -2
  46. data/lib/sequel/database/connecting.rb +8 -8
  47. data/lib/sequel/database/dataset.rb +6 -3
  48. data/lib/sequel/database/dataset_defaults.rb +14 -1
  49. data/lib/sequel/database/misc.rb +1 -1
  50. data/lib/sequel/database/query.rb +3 -0
  51. data/lib/sequel/database/schema_methods.rb +1 -1
  52. data/lib/sequel/dataset/actions.rb +72 -10
  53. data/lib/sequel/dataset/dataset_module.rb +58 -0
  54. data/lib/sequel/dataset/graph.rb +1 -1
  55. data/lib/sequel/dataset/misc.rb +1 -0
  56. data/lib/sequel/dataset/prepared_statements.rb +3 -3
  57. data/lib/sequel/dataset/query.rb +22 -11
  58. data/lib/sequel/dataset.rb +1 -1
  59. data/lib/sequel/exceptions.rb +8 -0
  60. data/lib/sequel/extensions/_model_pg_row.rb +5 -2
  61. data/lib/sequel/extensions/core_extensions.rb +4 -1
  62. data/lib/sequel/extensions/current_datetime_timestamp.rb +2 -1
  63. data/lib/sequel/extensions/date_arithmetic.rb +1 -0
  64. data/lib/sequel/extensions/duplicate_columns_handler.rb +3 -3
  65. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +3 -0
  66. data/lib/sequel/extensions/filter_having.rb +2 -0
  67. data/lib/sequel/extensions/freeze_datasets.rb +2 -0
  68. data/lib/sequel/extensions/from_block.rb +1 -1
  69. data/lib/sequel/extensions/graph_each.rb +2 -2
  70. data/lib/sequel/extensions/hash_aliases.rb +2 -0
  71. data/lib/sequel/extensions/identifier_mangling.rb +0 -7
  72. data/lib/sequel/extensions/meta_def.rb +2 -0
  73. data/lib/sequel/extensions/migration.rb +11 -8
  74. data/lib/sequel/extensions/no_auto_literal_strings.rb +1 -1
  75. data/lib/sequel/extensions/null_dataset.rb +1 -0
  76. data/lib/sequel/extensions/pagination.rb +1 -1
  77. data/lib/sequel/extensions/pg_array.rb +207 -130
  78. data/lib/sequel/extensions/pg_hstore.rb +38 -20
  79. data/lib/sequel/extensions/pg_inet.rb +18 -6
  80. data/lib/sequel/extensions/pg_interval.rb +19 -12
  81. data/lib/sequel/extensions/pg_json.rb +25 -14
  82. data/lib/sequel/extensions/pg_json_ops.rb +2 -2
  83. data/lib/sequel/extensions/pg_range.rb +133 -100
  84. data/lib/sequel/extensions/pg_range_ops.rb +4 -3
  85. data/lib/sequel/extensions/pg_row.rb +68 -39
  86. data/lib/sequel/extensions/pg_row_ops.rb +11 -5
  87. data/lib/sequel/extensions/query_literals.rb +2 -0
  88. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +2 -0
  89. data/lib/sequel/extensions/s.rb +1 -1
  90. data/lib/sequel/extensions/schema_dumper.rb +29 -25
  91. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +3 -1
  92. data/lib/sequel/extensions/sequel_4_dataset_methods.rb +83 -0
  93. data/lib/sequel/extensions/server_block.rb +32 -15
  94. data/lib/sequel/extensions/set_overrides.rb +2 -2
  95. data/lib/sequel/extensions/string_agg.rb +0 -1
  96. data/lib/sequel/extensions/symbol_aref.rb +0 -4
  97. data/lib/sequel/model/associations.rb +35 -7
  98. data/lib/sequel/model/base.rb +113 -87
  99. data/lib/sequel/model/dataset_module.rb +5 -43
  100. data/lib/sequel/model/errors.rb +2 -1
  101. data/lib/sequel/model/inflections.rb +17 -5
  102. data/lib/sequel/model.rb +26 -58
  103. data/lib/sequel/plugins/active_model.rb +2 -2
  104. data/lib/sequel/plugins/association_autoreloading.rb +2 -0
  105. data/lib/sequel/plugins/association_dependencies.rb +3 -3
  106. data/lib/sequel/plugins/association_pks.rb +73 -46
  107. data/lib/sequel/plugins/association_proxies.rb +1 -1
  108. data/lib/sequel/plugins/auto_validations.rb +6 -2
  109. data/lib/sequel/plugins/boolean_readers.rb +2 -2
  110. data/lib/sequel/plugins/boolean_subsets.rb +1 -1
  111. data/lib/sequel/plugins/caching.rb +19 -13
  112. data/lib/sequel/plugins/class_table_inheritance.rb +24 -13
  113. data/lib/sequel/plugins/column_conflicts.rb +7 -2
  114. data/lib/sequel/plugins/column_select.rb +3 -3
  115. data/lib/sequel/plugins/composition.rb +2 -2
  116. data/lib/sequel/plugins/csv_serializer.rb +8 -8
  117. data/lib/sequel/plugins/dataset_associations.rb +25 -13
  118. data/lib/sequel/plugins/defaults_setter.rb +13 -1
  119. data/lib/sequel/plugins/eager_each.rb +1 -1
  120. data/lib/sequel/plugins/force_encoding.rb +2 -2
  121. data/lib/sequel/plugins/hook_class_methods.rb +9 -12
  122. data/lib/sequel/plugins/identifier_columns.rb +2 -0
  123. data/lib/sequel/plugins/instance_filters.rb +3 -1
  124. data/lib/sequel/plugins/instance_hooks.rb +17 -9
  125. data/lib/sequel/plugins/json_serializer.rb +19 -12
  126. data/lib/sequel/plugins/lazy_attributes.rb +8 -7
  127. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +2 -0
  128. data/lib/sequel/plugins/modification_detection.rb +3 -0
  129. data/lib/sequel/plugins/nested_attributes.rb +6 -2
  130. data/lib/sequel/plugins/pg_array_associations.rb +5 -0
  131. data/lib/sequel/plugins/pg_row.rb +4 -2
  132. data/lib/sequel/plugins/pg_typecast_on_load.rb +2 -0
  133. data/lib/sequel/plugins/prepared_statements.rb +1 -0
  134. data/lib/sequel/plugins/rcte_tree.rb +4 -24
  135. data/lib/sequel/plugins/serialization.rb +9 -15
  136. data/lib/sequel/plugins/single_table_inheritance.rb +8 -3
  137. data/lib/sequel/plugins/split_values.rb +6 -5
  138. data/lib/sequel/plugins/static_cache.rb +31 -25
  139. data/lib/sequel/plugins/subset_conditions.rb +3 -1
  140. data/lib/sequel/plugins/table_select.rb +1 -1
  141. data/lib/sequel/plugins/touch.rb +4 -2
  142. data/lib/sequel/plugins/validation_class_methods.rb +5 -6
  143. data/lib/sequel/plugins/validation_helpers.rb +14 -8
  144. data/lib/sequel/plugins/xml_serializer.rb +4 -4
  145. data/lib/sequel/sql.rb +18 -9
  146. data/lib/sequel/version.rb +1 -1
  147. data/spec/adapters/db2_spec.rb +115 -14
  148. data/spec/adapters/mssql_spec.rb +4 -4
  149. data/spec/adapters/mysql_spec.rb +83 -29
  150. data/spec/adapters/oracle_spec.rb +28 -24
  151. data/spec/adapters/postgres_spec.rb +40 -24
  152. data/spec/adapters/sqlanywhere_spec.rb +88 -86
  153. data/spec/adapters/sqlite_spec.rb +29 -24
  154. data/spec/bin_spec.rb +7 -1
  155. data/spec/core/connection_pool_spec.rb +45 -14
  156. data/spec/core/database_spec.rb +155 -0
  157. data/spec/core/dataset_spec.rb +219 -36
  158. data/spec/core/schema_spec.rb +16 -0
  159. data/spec/core/spec_helper.rb +1 -0
  160. data/spec/core_extensions_spec.rb +6 -2
  161. data/spec/extensions/active_model_spec.rb +1 -1
  162. data/spec/extensions/arbitrary_servers_spec.rb +1 -1
  163. data/spec/extensions/association_pks_spec.rb +34 -2
  164. data/spec/extensions/auto_literal_strings_spec.rb +5 -1
  165. data/spec/extensions/auto_validations_spec.rb +2 -0
  166. data/spec/extensions/boolean_readers_spec.rb +1 -1
  167. data/spec/extensions/boolean_subsets_spec.rb +1 -1
  168. data/spec/extensions/class_table_inheritance_spec.rb +106 -19
  169. data/spec/extensions/column_conflicts_spec.rb +11 -0
  170. data/spec/extensions/column_select_spec.rb +1 -0
  171. data/spec/extensions/composition_spec.rb +13 -0
  172. data/spec/extensions/connection_validator_spec.rb +1 -1
  173. data/spec/extensions/dataset_associations_spec.rb +20 -8
  174. data/spec/extensions/defaults_setter_spec.rb +15 -1
  175. data/spec/extensions/filter_having_spec.rb +5 -3
  176. data/spec/extensions/hash_aliases_spec.rb +3 -1
  177. data/spec/extensions/identifier_columns_spec.rb +3 -1
  178. data/spec/extensions/implicit_subquery_spec.rb +4 -2
  179. data/spec/extensions/json_serializer_spec.rb +18 -0
  180. data/spec/extensions/lazy_attributes_spec.rb +3 -3
  181. data/spec/extensions/many_through_many_spec.rb +4 -4
  182. data/spec/extensions/meta_def_spec.rb +9 -0
  183. data/spec/extensions/migration_spec.rb +3 -3
  184. data/spec/extensions/nested_attributes_spec.rb +14 -3
  185. data/spec/extensions/no_auto_literal_strings_spec.rb +8 -4
  186. data/spec/extensions/null_dataset_spec.rb +1 -1
  187. data/spec/extensions/pg_array_associations_spec.rb +29 -18
  188. data/spec/extensions/pg_array_spec.rb +44 -25
  189. data/spec/extensions/pg_hstore_spec.rb +10 -0
  190. data/spec/extensions/pg_inet_spec.rb +26 -0
  191. data/spec/extensions/pg_interval_spec.rb +20 -0
  192. data/spec/extensions/pg_json_spec.rb +24 -0
  193. data/spec/extensions/pg_range_spec.rb +98 -14
  194. data/spec/extensions/pg_row_spec.rb +14 -4
  195. data/spec/extensions/pg_typecast_on_load_spec.rb +11 -9
  196. data/spec/extensions/prepared_statements_safe_spec.rb +1 -1
  197. data/spec/extensions/query_literals_spec.rb +3 -1
  198. data/spec/extensions/schema_dumper_spec.rb +108 -94
  199. data/spec/extensions/sequel_3_dataset_methods_spec.rb +10 -6
  200. data/spec/extensions/sequel_4_dataset_methods_spec.rb +121 -0
  201. data/spec/extensions/serialization_spec.rb +1 -1
  202. data/spec/extensions/server_block_spec.rb +7 -0
  203. data/spec/extensions/single_table_inheritance_spec.rb +17 -1
  204. data/spec/extensions/spec_helper.rb +7 -1
  205. data/spec/extensions/static_cache_spec.rb +75 -24
  206. data/spec/extensions/string_agg_spec.rb +1 -1
  207. data/spec/extensions/touch_spec.rb +9 -0
  208. data/spec/extensions/validation_helpers_spec.rb +10 -5
  209. data/spec/extensions/whitelist_security_spec.rb +26 -0
  210. data/spec/integration/associations_test.rb +8 -0
  211. data/spec/integration/dataset_test.rb +45 -44
  212. data/spec/integration/model_test.rb +53 -4
  213. data/spec/integration/plugin_test.rb +28 -4
  214. data/spec/integration/prepared_statement_test.rb +3 -0
  215. data/spec/integration/schema_test.rb +21 -1
  216. data/spec/integration/transaction_test.rb +40 -40
  217. data/spec/model/association_reflection_spec.rb +43 -1
  218. data/spec/model/associations_spec.rb +29 -9
  219. data/spec/model/class_dataset_methods_spec.rb +20 -4
  220. data/spec/model/dataset_methods_spec.rb +12 -3
  221. data/spec/model/eager_loading_spec.rb +8 -8
  222. data/spec/model/model_spec.rb +45 -1
  223. data/spec/model/plugins_spec.rb +34 -0
  224. data/spec/model/record_spec.rb +1 -1
  225. data/spec/spec_config.rb +2 -0
  226. metadata +11 -4
  227. data/spec/adapters/firebird_spec.rb +0 -405
  228. data/spec/adapters/informix_spec.rb +0 -100
@@ -18,11 +18,14 @@
18
18
  # for HashRow and ArrayRow using the standard Sequel literalization callbacks, so
19
19
  # they work with on all adapters.
20
20
  #
21
- # The first thing you are going to want to do is to load the extension into
22
- # your Database object. Make sure you load the :pg_array extension first
23
- # if you plan to use composite types in bound variables:
21
+ # To use this extension, first load it into the Database instance:
22
+ #
23
+ # DB.extension :pg_row
24
+ #
25
+ # If you plan to use arrays of composite types, make sure you load the
26
+ # pg_array extension first:
24
27
  #
25
- # DB.extension(:pg_array, :pg_row)
28
+ # DB.extension :pg_array, :pg_row
26
29
  #
27
30
  # You can create an anonymous row type by calling the Sequel.pg_row with
28
31
  # an array:
@@ -85,13 +88,15 @@
85
88
 
86
89
  require 'delegate'
87
90
  require 'strscan'
88
- Sequel.require 'adapters/utils/pg_types'
91
+ Sequel.require 'adapters/shared/postgres'
89
92
 
90
93
  module Sequel
91
94
  module Postgres
92
95
  module PGRow
93
96
  ROW = 'ROW'.freeze
97
+ Sequel::Deprecation.deprecate_constant(self, :ROW)
94
98
  CAST = '::'.freeze
99
+ Sequel::Deprecation.deprecate_constant(self, :CAST)
95
100
 
96
101
  # Class for row-valued/composite types that are treated as arrays. By default,
97
102
  # this is only used for generic PostgreSQL record types, as registered
@@ -130,10 +135,10 @@ module Sequel
130
135
 
131
136
  # Append SQL fragment related to this object to the sql.
132
137
  def sql_literal_append(ds, sql)
133
- sql << ROW
138
+ sql << 'ROW'
134
139
  ds.literal_append(sql, to_a)
135
140
  if db_type
136
- sql << CAST
141
+ sql << '::'
137
142
  ds.quote_schema_table_append(sql, db_type)
138
143
  end
139
144
  end
@@ -202,16 +207,16 @@ module Sequel
202
207
  # Append SQL fragment related to this object to the sql.
203
208
  def sql_literal_append(ds, sql)
204
209
  check_columns!
205
- sql << ROW
210
+ sql << 'ROW'
206
211
  ds.literal_append(sql, values_at(*columns))
207
212
  if db_type
208
- sql << CAST
213
+ sql << '::'
209
214
  ds.quote_schema_table_append(sql, db_type)
210
215
  end
211
216
  end
212
217
  end
213
218
 
214
- ROW_TYPE_CLASSES = [HashRow, ArrayRow]
219
+ ROW_TYPE_CLASSES = [HashRow, ArrayRow]#.freeze # SEQUEL5
215
220
 
216
221
  # This parser-like class splits the PostgreSQL
217
222
  # row-valued/composite type output string format
@@ -221,32 +226,41 @@ module Sequel
221
226
  # PostgreSQL uses.
222
227
  class Splitter < StringScanner
223
228
  OPEN_PAREN = /\(/.freeze
229
+ Sequel::Deprecation.deprecate_constant(self, :OPEN_PAREN)
224
230
  CLOSE_PAREN = /\)/.freeze
231
+ Sequel::Deprecation.deprecate_constant(self, :CLOSE_PAREN)
225
232
  UNQUOTED_RE = /[^,)]*/.freeze
233
+ Sequel::Deprecation.deprecate_constant(self, :UNQUOTED_RE)
226
234
  SEP_RE = /[,)]/.freeze
235
+ Sequel::Deprecation.deprecate_constant(self, :SEP_RE)
227
236
  QUOTE_RE = /"/.freeze
237
+ Sequel::Deprecation.deprecate_constant(self, :QUOTE_RE)
228
238
  QUOTE_SEP_RE = /"[,)]/.freeze
239
+ Sequel::Deprecation.deprecate_constant(self, :QUOTE_SEP_RE)
229
240
  QUOTED_RE = /(\\.|""|[^"])*/.freeze
241
+ Sequel::Deprecation.deprecate_constant(self, :QUOTED_RE)
230
242
  REPLACE_RE = /\\(.)|"(")/.freeze
243
+ Sequel::Deprecation.deprecate_constant(self, :REPLACE_RE)
231
244
  REPLACE_WITH = '\1\2'.freeze
245
+ Sequel::Deprecation.deprecate_constant(self, :REPLACE_WITH)
232
246
 
233
247
  # Split the stored string into an array of strings, handling
234
248
  # the different types of quoting.
235
249
  def parse
236
250
  return @result if @result
237
251
  values = []
238
- skip(OPEN_PAREN)
239
- if skip(CLOSE_PAREN)
252
+ skip(/\(/)
253
+ if skip(/\)/)
240
254
  values << nil
241
255
  else
242
256
  until eos?
243
- if skip(QUOTE_RE)
244
- values << scan(QUOTED_RE).gsub(REPLACE_RE, REPLACE_WITH)
245
- skip(QUOTE_SEP_RE)
257
+ if skip(/"/)
258
+ values << scan(/(\\.|""|[^"])*/).gsub(/\\(.)|"(")/, '\1\2')
259
+ skip(/"[,)]/)
246
260
  else
247
- v = scan(UNQUOTED_RE)
261
+ v = scan(/[^,)]*/)
248
262
  values << (v unless v.empty?)
249
- skip(SEP_RE)
263
+ skip(/[,)]/)
250
264
  end
251
265
  end
252
266
  end
@@ -374,8 +388,11 @@ module Sequel
374
388
 
375
389
  module DatabaseMethods
376
390
  ESCAPE_RE = /("|\\)/.freeze
391
+ Sequel::Deprecation.deprecate_constant(self, :ESCAPE_RE)
377
392
  ESCAPE_REPLACEMENT = '\\\\\1'.freeze
393
+ Sequel::Deprecation.deprecate_constant(self, :ESCAPE_REPLACEMENT)
378
394
  COMMA = ','.freeze
395
+ Sequel::Deprecation.deprecate_constant(self, :COMMA)
379
396
 
380
397
  # A hash mapping row type keys (usually symbols), to option
381
398
  # hashes. At the least, the values will contain the :parser
@@ -384,17 +401,14 @@ module Sequel
384
401
 
385
402
  # Do some setup for the data structures the module uses.
386
403
  def self.extended(db)
387
- # Return right away if row_types has already been set. This
388
- # makes things not break if a user extends the database with
389
- # this module more than once (since extended is called every
390
- # time).
391
- return if db.row_types
392
-
393
404
  db.instance_eval do
394
405
  @row_types = {}
395
406
  @row_schema_types = {}
396
407
  extend(@row_type_method_module = Module.new)
397
- copy_conversion_procs([2249, 2287])
408
+ add_conversion_proc(2249, PGRow::Parser.new(:converter=>PGRow::ArrayRow))
409
+ if respond_to?(:register_array_type)
410
+ register_array_type('record', :oid=>2287, :scalar_oid=>2249)
411
+ end
398
412
  end
399
413
  end
400
414
 
@@ -402,10 +416,10 @@ module Sequel
402
416
  def bound_variable_arg(arg, conn)
403
417
  case arg
404
418
  when ArrayRow
405
- "(#{arg.map{|v| bound_variable_array(v) if v}.join(COMMA)})"
419
+ "(#{arg.map{|v| bound_variable_array(v) if v}.join(',')})"
406
420
  when HashRow
407
421
  arg.check_columns!
408
- "(#{arg.values_at(*arg.columns).map{|v| bound_variable_array(v) if v}.join(COMMA)})"
422
+ "(#{arg.values_at(*arg.columns).map{|v| bound_variable_array(v) if v}.join(',')})"
409
423
  else
410
424
  super
411
425
  end
@@ -419,6 +433,8 @@ module Sequel
419
433
  super
420
434
  end
421
435
 
436
+ STRING_TYPES = [18, 19, 25, 1042, 1043].freeze
437
+
422
438
  # Register a new row type for the Database instance. db_type should be the type
423
439
  # symbol. This parses the PostgreSQL system tables to get information the
424
440
  # composite type, and by default has the type return instances of a subclass
@@ -471,12 +487,22 @@ module Sequel
471
487
 
472
488
  # Using the conversion_procs, lookup converters for each member of the composite type
473
489
  parser_opts[:column_converters] = parser_opts[:column_oids].map do |oid|
490
+ # procs[oid] # SEQUEL5
491
+
492
+ # SEQUEL5: Remove
474
493
  if pr = procs[oid]
475
494
  pr
476
- elsif !Sequel::Postgres::STRING_TYPES.include?(oid)
495
+ elsif !STRING_TYPES.include?(oid)
477
496
  # It's not a string type, and it's possible a conversion proc for this
478
497
  # oid will be added later, so do a runtime check for it.
479
- lambda{|s| (pr = procs[oid]) ? pr.call(s) : s}
498
+ lambda do |s|
499
+ if (pr = procs[oid])
500
+ Sequel::Deprecation.deprecate("Calling conversion proc for subtype (oid: #{oid}) of composite type (oid: #{parser_opts[:oid]}) not added until after composite type registration", "Register subtype conversion procs before registering composite type")
501
+ pr.call(s)
502
+ else
503
+ s
504
+ end
505
+ end
480
506
  end
481
507
  end
482
508
 
@@ -485,15 +511,15 @@ module Sequel
485
511
  parser_opts[:typecaster] = opts.fetch(:typecaster, parser_opts[:converter])
486
512
 
487
513
  parser = Parser.new(parser_opts)
488
- @conversion_procs[parser.oid] = parser
514
+ add_conversion_proc(parser.oid, parser)
489
515
 
490
- if defined?(PGArray) && PGArray.respond_to?(:register) && array_oid && array_oid > 0
516
+ if respond_to?(:register_array_type) && array_oid && array_oid > 0
491
517
  array_type_name = if type_schema
492
518
  "#{type_schema}.#{type_name}"
493
519
  else
494
520
  type_name
495
521
  end
496
- PGArray.register(array_type_name, :oid=>array_oid, :converter=>parser, :type_procs=>@conversion_procs, :scalar_typecast=>schema_type_symbol)
522
+ register_array_type(array_type_name, :oid=>array_oid, :converter=>parser, :scalar_typecast=>schema_type_symbol)
497
523
  end
498
524
 
499
525
  @row_types[literal(db_type)] = opts.merge(:parser=>parser, :type=>db_type)
@@ -507,12 +533,11 @@ module Sequel
507
533
  private meth
508
534
  end
509
535
 
510
- conversion_procs_updated
536
+ conversion_procs_updated # SEQUEL5: Remove
511
537
  nil
512
538
  end
513
539
 
514
- # When reseting conversion procs, reregister all the row types so that
515
- # the system tables are introspected again, picking up database changes.
540
+ # SEQUEL5: Remove
516
541
  def reset_conversion_procs
517
542
  procs = super
518
543
 
@@ -558,10 +583,10 @@ module Sequel
558
583
  def bound_variable_array(arg)
559
584
  case arg
560
585
  when ArrayRow
561
- "\"(#{arg.map{|v| bound_variable_array(v) if v}.join(COMMA).gsub(ESCAPE_RE, ESCAPE_REPLACEMENT)})\""
586
+ "\"(#{arg.map{|v| bound_variable_array(v) if v}.join(',').gsub(/("|\\)/, '\\\\\1')})\""
562
587
  when HashRow
563
588
  arg.check_columns!
564
- "\"(#{arg.values_at(*arg.columns).map{|v| bound_variable_array(v) if v}.join(COMMA).gsub(ESCAPE_RE, ESCAPE_REPLACEMENT)})\""
589
+ "\"(#{arg.values_at(*arg.columns).map{|v| bound_variable_array(v) if v}.join(',').gsub(/("|\\)/, '\\\\\1')})\""
565
590
  else
566
591
  super
567
592
  end
@@ -578,10 +603,14 @@ module Sequel
578
603
  end
579
604
  end
580
605
 
581
- # Register the default anonymous record type
582
- PG_TYPES[2249] = PGRow::Parser.new(:converter=>PGRow::ArrayRow)
606
+ # SEQUEL5: Remove
607
+ parser = PGRow::Parser.new(:converter=>PGRow::ArrayRow)
608
+ PG__TYPES[2249] = lambda do |s|
609
+ Sequel::Deprecation.deprecate("Conversion proc for record added globally by pg_row extension", "Load the pg_row extension into the Database instance")
610
+ parser.call(s)
611
+ end
583
612
  if defined?(PGArray) && PGArray.respond_to?(:register)
584
- PGArray.register('record', :oid=>2287, :scalar_oid=>2249)
613
+ PGArray.register('record', :oid=>2287, :scalar_oid=>2249, :skip_deprecation_warning=>true)
585
614
  end
586
615
  end
587
616
 
@@ -70,7 +70,7 @@
70
70
  #
71
71
  # By casting the expression, you can get a composite type returned:
72
72
  #
73
- # DB[:a].select(a.splat).first # SELECT (a.*)::a FROM a
73
+ # DB[:a].select(a.splat(:a)).first # SELECT (a.*)::a FROM a
74
74
  # # => {:a=>"(1,2)"} # or {:a=>{:a=>1, :b=>2}} if the "a" type has been registered
75
75
  # # with the pg_row extension
76
76
  #
@@ -89,14 +89,20 @@ module Sequel
89
89
  # This class represents a composite type expression reference.
90
90
  class PGRowOp < SQL::PlaceholderLiteralString
91
91
  OPEN = '('.freeze
92
+ Sequel::Deprecation.deprecate_constant(self, :OPEN)
92
93
  CLOSE_DOT = ').'.freeze
94
+ Sequel::Deprecation.deprecate_constant(self, :CLOSE_DOT)
93
95
  CLOSE_STAR = '.*)'.freeze
96
+ Sequel::Deprecation.deprecate_constant(self, :CLOSE_STAR)
94
97
  CLOSE_STAR_CAST = '.*)::'.freeze
98
+ Sequel::Deprecation.deprecate_constant(self, :CLOSE_STAR_CAST)
95
99
  EMPTY = "".freeze
96
- ROW = [OPEN, CLOSE_STAR].freeze
97
- ROW_CAST = [OPEN, CLOSE_STAR_CAST].freeze
98
- QUALIFY = [OPEN, CLOSE_DOT].freeze
99
- WRAP = [EMPTY].freeze
100
+ Sequel::Deprecation.deprecate_constant(self, :EMPTY)
101
+
102
+ ROW = ['(', '.*)'].freeze.each(&:freeze)
103
+ ROW_CAST = ['(', '.*)::'].freeze.each(&:freeze)
104
+ QUALIFY = ['(', ').'].freeze.each(&:freeze)
105
+ WRAP = [""].freeze.each(&:freeze)
100
106
 
101
107
  # Wrap the expression in a PGRowOp, without changing the
102
108
  # SQL it would use.
@@ -35,6 +35,8 @@
35
35
  #
36
36
  # Related module: Sequel::QueryLiterals
37
37
 
38
+ Sequel::Deprecation.deprecate("The query_literals extension", "Please consider maintaining it yourself as an external gem if you want to continue using it")
39
+
38
40
  #
39
41
  module Sequel
40
42
  # The QueryLiterals module can be used to make select, group, and
@@ -22,3 +22,5 @@ class Symbol
22
22
  Sequel::SQL::Function.new(self, *args)
23
23
  end
24
24
  end
25
+
26
+ # SEQUEL5: Remove extension
@@ -27,7 +27,7 @@
27
27
  #
28
28
  # or just into Object if you want it available everywhere:
29
29
  #
30
- # Object.send(:include, Sequel::SQL)
30
+ # Object.send(:include, Sequel::S)
31
31
  #
32
32
  # If you are using Ruby 2+, and you would like to use refinements, you
33
33
  # can use Sequel::S as a refinement, in which case the private #S method
@@ -20,8 +20,12 @@ module Sequel
20
20
  # be :type. The other options added should modify that type (e.g. :size). If a
21
21
  # database type is not recognized, return it as a String type.
22
22
  def column_schema_to_ruby_type(schema)
23
- case schema[:db_type].downcase
24
- when /\A(medium|small)?int(?:eger)?(?:\((\d+)\))?( unsigned)?\z/o
23
+ type = schema[:db_type].downcase
24
+ if database_type == :oracle
25
+ type = type.sub(/ not null\z/, '')
26
+ end
27
+ case type
28
+ when /\A(medium|small)?int(?:eger)?(?:\((\d+)\))?( unsigned)?\z/
25
29
  if !$1 && $2 && $2.to_i >= 10 && $3
26
30
  # Unsigned integer type with 10 digits can potentially contain values which
27
31
  # don't fit signed integer type, so use bigint type in target database.
@@ -29,36 +33,36 @@ module Sequel
29
33
  else
30
34
  {:type=>Integer}
31
35
  end
32
- when /\Atinyint(?:\((\d+)\))?(?: unsigned)?\z/o
36
+ when /\Atinyint(?:\((\d+)\))?(?: unsigned)?\z/
33
37
  {:type =>schema[:type] == :boolean ? TrueClass : Integer}
34
- when /\Abigint(?:\((?:\d+)\))?(?: unsigned)?\z/o
38
+ when /\Abigint(?:\((?:\d+)\))?(?: unsigned)?\z/
35
39
  {:type=>:Bignum}
36
- when /\A(?:real|float|double(?: precision)?|double\(\d+,\d+\)(?: unsigned)?)\z/o
40
+ when /\A(?:real|float|double(?: precision)?|double\(\d+,\d+\)(?: unsigned)?)\z/
37
41
  {:type=>Float}
38
42
  when 'boolean', 'bit', 'bool'
39
43
  {:type=>TrueClass}
40
- when /\A(?:(?:tiny|medium|long|n)?text|clob)\z/o
44
+ when /\A(?:(?:tiny|medium|long|n)?text|clob)\z/
41
45
  {:type=>String, :text=>true}
42
46
  when 'date'
43
47
  {:type=>Date}
44
- when /\A(?:small)?datetime\z/o
48
+ when /\A(?:small)?datetime\z/
45
49
  {:type=>DateTime}
46
- when /\Atimestamp(?:\((\d+)\))?(?: with(?:out)? time zone)?\z/o
50
+ when /\Atimestamp(?:\((\d+)\))?(?: with(?:out)? time zone)?\z/
47
51
  {:type=>DateTime, :size=>($1.to_i if $1)}
48
- when /\Atime(?: with(?:out)? time zone)?\z/o
52
+ when /\Atime(?: with(?:out)? time zone)?\z/
49
53
  {:type=>Time, :only_time=>true}
50
- when /\An?char(?:acter)?(?:\((\d+)\))?\z/o
54
+ when /\An?char(?:acter)?(?:\((\d+)\))?\z/
51
55
  {:type=>String, :size=>($1.to_i if $1), :fixed=>true}
52
- when /\A(?:n?varchar|character varying|bpchar|string)(?:\((\d+)\))?\z/o
56
+ when /\A(?:n?varchar2?|character varying|bpchar|string)(?:\((\d+)\))?\z/
53
57
  {:type=>String, :size=>($1.to_i if $1)}
54
- when /\A(?:small)?money\z/o
58
+ when /\A(?:small)?money\z/
55
59
  {:type=>BigDecimal, :size=>[19,2]}
56
- when /\A(?:decimal|numeric|number)(?:\((\d+)(?:,\s*(\d+))?\))?\z/o
60
+ when /\A(?:decimal|numeric|number)(?:\((\d+)(?:,\s*(\d+))?\))?\z/
57
61
  s = [($1.to_i if $1), ($2.to_i if $2)].compact
58
62
  {:type=>BigDecimal, :size=>(s.empty? ? nil : s)}
59
- when /\A(?:bytea|(?:tiny|medium|long)?blob|(?:var)?binary)(?:\((\d+)\))?\z/o
63
+ when /\A(?:bytea|(?:tiny|medium|long)?blob|(?:var)?binary)(?:\((\d+)\))?\z/
60
64
  {:type=>File, :size=>($1.to_i if $1)}
61
- when /\A(?:year|(?:int )?identity)\z/o
65
+ when /\A(?:year|(?:int )?identity)\z/
62
66
  {:type=>Integer}
63
67
  else
64
68
  {:type=>String}
@@ -77,7 +81,7 @@ module Sequel
77
81
  <<END_MIG
78
82
  Sequel.migration do
79
83
  change do
80
- #{ts.sort_by(&:to_s).map{|t| dump_table_foreign_keys(t)}.reject{|x| x == ''}.join("\n\n").gsub(/^/o, ' ')}
84
+ #{ts.sort_by(&:to_s).map{|t| dump_table_foreign_keys(t)}.reject{|x| x == ''}.join("\n\n").gsub(/^/, ' ')}
81
85
  end
82
86
  end
83
87
  END_MIG
@@ -95,7 +99,7 @@ END_MIG
95
99
  <<END_MIG
96
100
  Sequel.migration do
97
101
  change do
98
- #{ts.sort_by(&:to_s).map{|t| dump_table_indexes(t, :add_index, options)}.reject{|x| x == ''}.join("\n\n").gsub(/^/o, ' ')}
102
+ #{ts.sort_by(&:to_s).map{|t| dump_table_indexes(t, :add_index, options)}.reject{|x| x == ''}.join("\n\n").gsub(/^/, ' ')}
99
103
  end
100
104
  end
101
105
  END_MIG
@@ -129,13 +133,13 @@ END_MIG
129
133
  # alter_table/add_foreign_key. Note that skipped foreign keys
130
134
  # probably result in a broken down migration.
131
135
  sfka = sfk.sort_by{|table, fks| table.to_s}.map{|table, fks| dump_add_fk_constraints(table, fks.values)}
132
- sfka.join("\n\n").gsub(/^/o, ' ') unless sfka.empty?
136
+ sfka.join("\n\n").gsub(/^/, ' ') unless sfka.empty?
133
137
  end
134
138
 
135
139
  <<END_MIG
136
140
  Sequel.migration do
137
141
  change do
138
- #{ts.map{|t| dump_table_schema(t, options)}.join("\n\n").gsub(/^/o, ' ')}#{"\n \n" if skipped_fks}#{skipped_fks}
142
+ #{ts.map{|t| dump_table_schema(t, options)}.join("\n\n").gsub(/^/, ' ')}#{"\n \n" if skipped_fks}#{skipped_fks}
139
143
  end
140
144
  end
141
145
  END_MIG
@@ -146,7 +150,7 @@ END_MIG
146
150
  def dump_table_schema(table, options=OPTS)
147
151
  gen = dump_table_generator(table, options)
148
152
  commands = [gen.dump_columns, gen.dump_constraints, gen.dump_indexes].reject{|x| x == ''}.join("\n\n")
149
- "create_table(#{table.inspect}#{', :ignore_index_errors=>true' if !options[:same_db] && options[:indexes] != false && !gen.indexes.empty?}) do\n#{commands.gsub(/^/o, ' ')}\nend"
153
+ "create_table(#{table.inspect}#{', :ignore_index_errors=>true' if !options[:same_db] && options[:indexes] != false && !gen.indexes.empty?}) do\n#{commands.gsub(/^/, ' ')}\nend"
150
154
  end
151
155
 
152
156
  private
@@ -454,11 +458,11 @@ END_MIG
454
458
 
455
459
  # Dump this generator's indexes to a string that could be evaled inside
456
460
  # another instance to represent the same indexes. Options:
457
- # * :add_index - Use add_index instead of index, so the methods
458
- # can be called outside of a generator but inside a migration.
459
- # The value of this option should be the table name to use.
460
- # * :drop_index - Same as add_index, but create drop_index statements.
461
- # * :ignore_errors - Add the ignore_errors option to the outputted indexes
461
+ # :add_index :: Use add_index instead of index, so the methods
462
+ # can be called outside of a generator but inside a migration.
463
+ # The value of this option should be the table name to use.
464
+ # :drop_index :: Same as add_index, but create drop_index statements.
465
+ # :ignore_errors :: Add the ignore_errors option to the outputted indexes
462
466
  def dump_indexes(options=OPTS)
463
467
  is = indexes.map do |c|
464
468
  c = c.dup
@@ -23,6 +23,8 @@
23
23
  #
24
24
  # Related module: Sequel::Sequel3DatasetMethods
25
25
 
26
+ Sequel::Deprecation.deprecate("The sequel_3_dataset_methods extension", "Please consider maintaining it yourself as an external gem if you want to continue using it")
27
+
26
28
  #
27
29
  module Sequel
28
30
  module Sequel3DatasetMethods
@@ -122,7 +124,7 @@ module Sequel
122
124
  cols = n.columns
123
125
  csv = String.new
124
126
  csv << "#{cols.join(', ')}\r\n" if include_column_titles
125
- n.each{|r| csv << "#{cols.collect{|c| r[c]}.join(', ')}\r\n"}
127
+ n.each{|r| csv << "#{cols.map{|c| r[c]}.join(', ')}\r\n"}
126
128
  csv
127
129
  end
128
130
  end
@@ -0,0 +1,83 @@
1
+ # frozen-string-literal: true
2
+ #
3
+ # This adds the following dataset methods:
4
+ #
5
+ # and :: alias for where
6
+ # exclude_where :: alias for exclude
7
+ # interval :: Returns max - min, using a single query
8
+ # range :: Returns min..max, using a single query
9
+ #
10
+ # It is only recommended to use this for backwards compatibility.
11
+ #
12
+ # You can load this extension into specific datasets:
13
+ #
14
+ # ds = DB[:table]
15
+ # ds = ds.extension(:sequel_4_dataset_methods)
16
+ #
17
+ # Or you can load it into all of a database's datasets, which
18
+ # is probably the desired behavior if you are using this extension:
19
+ #
20
+ # DB.extension(:sequel_4_dataset_methods)
21
+ #
22
+ # Related module: Sequel::Sequel4DatasetMethods
23
+
24
+ #
25
+ module Sequel
26
+ module Sequel4DatasetMethods
27
+ # Alias for where.
28
+ def and(*cond, &block)
29
+ where(*cond, &block)
30
+ end
31
+
32
+ # Alias for exclude.
33
+ def exclude_where(*cond, &block)
34
+ exclude(*cond, &block)
35
+ end
36
+
37
+ # Returns the interval between minimum and maximum values for the given
38
+ # column/expression. Uses a virtual row block if no argument is given.
39
+ #
40
+ # DB[:table].interval(:id) # SELECT (max(id) - min(id)) FROM table LIMIT 1
41
+ # # => 6
42
+ # DB[:table].interval{function(column)} # SELECT (max(function(column)) - min(function(column))) FROM table LIMIT 1
43
+ # # => 7
44
+ def interval(column=Sequel.virtual_row(&Proc.new))
45
+ if loader = cached_placeholder_literalizer(:_interval_loader) do |pl|
46
+ arg = pl.arg
47
+ aggregate_dataset.limit(1).select((SQL::Function.new(:max, arg) - SQL::Function.new(:min, arg)).as(:interval))
48
+ end
49
+
50
+ loader.get(column)
51
+ else
52
+ aggregate_dataset.get{(max(column) - min(column)).as(:interval)}
53
+ end
54
+ end
55
+
56
+ # Returns a +Range+ instance made from the minimum and maximum values for the
57
+ # given column/expression. Uses a virtual row block if no argument is given.
58
+ #
59
+ # DB[:table].range(:id) # SELECT max(id) AS v1, min(id) AS v2 FROM table LIMIT 1
60
+ # # => 1..10
61
+ # DB[:table].interval{function(column)} # SELECT max(function(column)) AS v1, min(function(column)) AS v2 FROM table LIMIT 1
62
+ # # => 0..7
63
+ def range(column=Sequel.virtual_row(&Proc.new))
64
+ r = if loader = cached_placeholder_literalizer(:_range_loader) do |pl|
65
+ arg = pl.arg
66
+ aggregate_dataset.limit(1).select(SQL::Function.new(:min, arg).as(:v1), SQL::Function.new(:max, arg).as(:v2))
67
+ end
68
+
69
+ loader.first(column)
70
+ else
71
+ aggregate_dataset.select{[min(column).as(v1), max(column).as(v2)]}.first
72
+ end
73
+
74
+ if r
75
+ (r[:v1]..r[:v2])
76
+ end
77
+ end
78
+
79
+ end
80
+
81
+ Dataset.register_extension(:sequel_4_dataset_methods, Sequel4DatasetMethods)
82
+ end
83
+
@@ -16,7 +16,7 @@
16
16
  # end
17
17
  # DB[:a].all # Uses default
18
18
  #
19
- # You can even nest calls to with_server:
19
+ # You can nest calls to with_server:
20
20
  #
21
21
  # DB.with_server(:shard1) do
22
22
  # DB[:a].all # Uses shard1
@@ -39,6 +39,19 @@
39
39
  # DB[:a].server(:read_only).all # Uses shard1
40
40
  # end
41
41
  #
42
+ # If you pass two separate shards to with_server, the second shard will
43
+ # be used instead of the :read_only shard, and the first shard will be
44
+ # used instead of the :default shard:
45
+ #
46
+ # DB.with_server(:shard1, :shard2) do
47
+ # DB[:a].all # Uses shard2
48
+ # DB[:a].delete # Uses shard1
49
+ # DB[:a].server(:shard3).all # Uses shard3
50
+ # DB[:a].server(:shard3).delete # Uses shard3
51
+ # DB[:a].server(:default).all # Uses shard1
52
+ # DB[:a].server(:read_only).delete # Uses shard2
53
+ # end
54
+ #
42
55
  # Related modules: Sequel::ServerBlock, Sequel::UnthreadedServerBlock,
43
56
  # Sequel::ThreadedServerBlock
44
57
 
@@ -60,17 +73,17 @@ module Sequel
60
73
  end
61
74
 
62
75
  # Delegate to the connection pool
63
- def with_server(server, &block)
64
- pool.with_server(server, &block)
76
+ def with_server(default_server, read_only_server=default_server, &block)
77
+ pool.with_server(default_server, read_only_server, &block)
65
78
  end
66
79
  end
67
80
 
68
81
  # Adds with_server support for the sharded single connection pool.
69
82
  module UnthreadedServerBlock
70
83
  # Set a default server/shard to use inside the block.
71
- def with_server(server)
84
+ def with_server(default_server, read_only_server=default_server)
72
85
  begin
73
- set_default_server(server)
86
+ set_default_server(default_server, read_only_server)
74
87
  yield
75
88
  ensure
76
89
  clear_default_server
@@ -80,8 +93,8 @@ module Sequel
80
93
  private
81
94
 
82
95
  # Make the given server the new default server.
83
- def set_default_server(server)
84
- @default_servers << server
96
+ def set_default_server(default_server, read_only_server=default_server)
97
+ @default_servers << [default_server, read_only_server]
85
98
  end
86
99
 
87
100
  # Remove the current default server, restoring the
@@ -96,8 +109,10 @@ module Sequel
96
109
  super
97
110
  else
98
111
  case server
99
- when :default, nil, :read_only
100
- @default_servers.last
112
+ when :default, nil
113
+ @default_servers[-1][0]
114
+ when :read_only
115
+ @default_servers[-1][1]
101
116
  else
102
117
  super
103
118
  end
@@ -109,9 +124,9 @@ module Sequel
109
124
  module ThreadedServerBlock
110
125
  # Set a default server/shard to use inside the block for the current
111
126
  # thread.
112
- def with_server(server)
127
+ def with_server(default_server, read_only_server=default_server)
113
128
  begin
114
- set_default_server(server)
129
+ set_default_server(default_server, read_only_server)
115
130
  yield
116
131
  ensure
117
132
  clear_default_server
@@ -121,8 +136,8 @@ module Sequel
121
136
  private
122
137
 
123
138
  # Make the given server the new default server for the current thread.
124
- def set_default_server(server)
125
- sync{(@default_servers[Thread.current] ||= [])} << server
139
+ def set_default_server(default_server, read_only_server=default_server)
140
+ sync{(@default_servers[Thread.current] ||= [])} << [default_server, read_only_server]
126
141
  end
127
142
 
128
143
  # Remove the current default server for the current thread, restoring the
@@ -141,8 +156,10 @@ module Sequel
141
156
  super
142
157
  else
143
158
  case server
144
- when :default, nil, :read_only
145
- a.last
159
+ when :default, nil
160
+ a[-1][0]
161
+ when :read_only
162
+ a[-1][1]
146
163
  else
147
164
  super
148
165
  end
@@ -73,8 +73,8 @@ module Sequel
73
73
  end
74
74
 
75
75
  # Dataset options that do not affect the generated SQL.
76
- def non_sql_options
77
- super + [:defaults, :overrides]
76
+ def non_sql_option?(key)
77
+ super || key == :defaults || key == :overrides
78
78
  end
79
79
  end
80
80