sequel 4.46.0 → 4.49.0

Sign up to get free protection for your applications and to get access to all the features.
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