sequel 3.42.0 → 3.43.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 (80) hide show
  1. data/CHANGELOG +40 -0
  2. data/MIT-LICENSE +1 -1
  3. data/Rakefile +1 -1
  4. data/doc/opening_databases.rdoc +2 -2
  5. data/doc/prepared_statements.rdoc +7 -0
  6. data/doc/release_notes/3.43.0.txt +105 -0
  7. data/doc/schema_modification.rdoc +19 -0
  8. data/lib/sequel/adapters/do/mysql.rb +1 -1
  9. data/lib/sequel/adapters/jdbc.rb +13 -8
  10. data/lib/sequel/adapters/jdbc/hsqldb.rb +5 -0
  11. data/lib/sequel/adapters/jdbc/mysql.rb +1 -1
  12. data/lib/sequel/adapters/jdbc/oracle.rb +6 -0
  13. data/lib/sequel/adapters/jdbc/postgresql.rb +9 -3
  14. data/lib/sequel/adapters/mysql.rb +1 -1
  15. data/lib/sequel/adapters/mysql2.rb +1 -1
  16. data/lib/sequel/adapters/oracle.rb +1 -1
  17. data/lib/sequel/adapters/postgres.rb +4 -2
  18. data/lib/sequel/adapters/shared/db2.rb +12 -0
  19. data/lib/sequel/adapters/shared/mssql.rb +9 -5
  20. data/lib/sequel/adapters/shared/postgres.rb +2 -0
  21. data/lib/sequel/adapters/swift/mysql.rb +1 -1
  22. data/lib/sequel/core.rb +2 -2
  23. data/lib/sequel/database.rb +0 -2
  24. data/lib/sequel/database/query.rb +20 -5
  25. data/lib/sequel/database/schema_generator.rb +5 -0
  26. data/lib/sequel/database/schema_methods.rb +5 -0
  27. data/lib/sequel/dataset.rb +0 -2
  28. data/lib/sequel/dataset/actions.rb +25 -2
  29. data/lib/sequel/dataset/misc.rb +1 -1
  30. data/lib/sequel/dataset/sql.rb +28 -6
  31. data/lib/sequel/extensions/core_refinements.rb +221 -0
  32. data/lib/sequel/extensions/date_arithmetic.rb +194 -0
  33. data/lib/sequel/extensions/meta_def.rb +30 -0
  34. data/lib/sequel/extensions/migration.rb +5 -0
  35. data/lib/sequel/extensions/null_dataset.rb +2 -0
  36. data/lib/sequel/extensions/pagination.rb +2 -0
  37. data/lib/sequel/extensions/pg_array.rb +12 -1
  38. data/lib/sequel/extensions/pg_array_ops.rb +10 -1
  39. data/lib/sequel/extensions/pg_hstore.rb +12 -1
  40. data/lib/sequel/extensions/pg_hstore_ops.rb +10 -1
  41. data/lib/sequel/extensions/pg_json.rb +18 -1
  42. data/lib/sequel/extensions/pg_range.rb +12 -1
  43. data/lib/sequel/extensions/pg_range_ops.rb +10 -1
  44. data/lib/sequel/extensions/pg_row.rb +18 -2
  45. data/lib/sequel/extensions/pg_row_ops.rb +10 -1
  46. data/lib/sequel/extensions/query.rb +2 -0
  47. data/lib/sequel/model/associations.rb +5 -13
  48. data/lib/sequel/model/base.rb +4 -6
  49. data/lib/sequel/plugins/boolean_readers.rb +4 -2
  50. data/lib/sequel/plugins/many_through_many.rb +23 -0
  51. data/lib/sequel/plugins/string_stripper.rb +53 -3
  52. data/lib/sequel/plugins/validation_class_methods.rb +5 -0
  53. data/lib/sequel/sql.rb +3 -3
  54. data/lib/sequel/version.rb +1 -1
  55. data/spec/adapters/db2_spec.rb +19 -8
  56. data/spec/adapters/mssql_spec.rb +1 -2
  57. data/spec/adapters/mysql_spec.rb +2 -2
  58. data/spec/adapters/postgres_spec.rb +29 -3
  59. data/spec/core/dataset_spec.rb +107 -0
  60. data/spec/core/expression_filters_spec.rb +5 -0
  61. data/spec/core/schema_spec.rb +14 -3
  62. data/spec/core/spec_helper.rb +2 -0
  63. data/spec/extensions/core_refinements_spec.rb +551 -0
  64. data/spec/extensions/date_arithmetic_spec.rb +150 -0
  65. data/spec/extensions/force_encoding_spec.rb +1 -1
  66. data/spec/extensions/meta_def_spec.rb +21 -0
  67. data/spec/extensions/spec_helper.rb +5 -0
  68. data/spec/extensions/string_stripper_spec.rb +44 -2
  69. data/spec/integration/associations_test.rb +2 -2
  70. data/spec/integration/plugin_test.rb +90 -0
  71. data/spec/integration/schema_test.rb +1 -1
  72. data/spec/model/association_reflection_spec.rb +4 -4
  73. data/spec/model/associations_spec.rb +2 -2
  74. data/spec/model/base_spec.rb +2 -2
  75. data/spec/model/eager_loading_spec.rb +5 -5
  76. data/spec/model/hooks_spec.rb +4 -4
  77. data/spec/model/model_spec.rb +9 -9
  78. data/spec/model/record_spec.rb +15 -18
  79. metadata +12 -5
  80. data/lib/sequel/metaprogramming.rb +0 -13
@@ -0,0 +1,194 @@
1
+ # The date_arithmetic extension adds the ability to perform database-independent
2
+ # addition/substraction of intervals to/from dates and timestamps.
3
+ #
4
+ # First, you need to load the extension into the database:
5
+ #
6
+ # DB.extension :date_arithmetic
7
+ #
8
+ # Then you can use the Sequel.date_add and Sequel.date_sub methods
9
+ # to return Sequel expressions:
10
+ #
11
+ # add = Sequel.date_add(:date_column, :years=>1, :months=>2, :days=>3)
12
+ # sub = Sequel.date_sub(:date_column, :hours=>1, :minutes=>2, :seconds=>3)
13
+ #
14
+ # In addition to specifying the interval as a hash, there is also
15
+ # support for specifying the interval as an ActiveSupport::Duration
16
+ # object:
17
+ #
18
+ # require 'active_support/all'
19
+ # add = Sequel.date_add(:date_column, 1.years + 2.months + 3.days)
20
+ # sub = Sequel.date_sub(:date_column, 1.hours + 2.minutes + 3.seconds)
21
+ #
22
+ # These expressions can be used in your datasets, or anywhere else that
23
+ # Sequel expressions are allowed:
24
+ #
25
+ # DB[:table].select(add.as(:d)).where(sub > Sequel::CURRENT_TIMESTAMP)
26
+
27
+ module Sequel
28
+ module SQL
29
+ module Builders
30
+ # Return a DateAdd expression, adding an interval to the date/timestamp expr.
31
+ def date_add(expr, interval)
32
+ DateAdd.new(expr, interval)
33
+ end
34
+
35
+ # Return a DateAdd expression, adding the negative of the interval to
36
+ # the date/timestamp expr.
37
+ def date_sub(expr, interval)
38
+ interval = if interval.is_a?(Hash)
39
+ h = {}
40
+ interval.each{|k,v| h[k] = -v unless v.nil?}
41
+ h
42
+ else
43
+ -interval
44
+ end
45
+ DateAdd.new(expr, interval)
46
+ end
47
+ end
48
+
49
+ # The DateAdd class represents the addition of an interval to a
50
+ # date/timestamp expression.
51
+ class DateAdd < GenericExpression
52
+ # These methods are added to datasets using the date_arithmetic
53
+ # extension, for the purposes of correctly literalizing DateAdd
54
+ # expressions for the appropriate database type.
55
+ module DatasetMethods
56
+ DURATION_UNITS = [:years, :months, :days, :hours, :minutes, :seconds].freeze
57
+ DEF_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| s.to_s.freeze}).freeze
58
+ MYSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.upcase[0...-1]).freeze}).freeze
59
+ MSSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s[0...-1]).freeze}).freeze
60
+ H2_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| s.to_s[0...-1].freeze}).freeze
61
+ DERBY_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit("SQL_TSI_#{s.to_s.upcase[0...-1]}").freeze}).freeze
62
+ ACCESS_DURATION_UNITS = DURATION_UNITS.zip(%w'yyyy m d h n s'.map{|s| s.freeze}).freeze
63
+ DB2_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s).freeze}).freeze
64
+
65
+ # Return an SQL fragment for the literalized version of the
66
+ # DateAdd expression.
67
+ def date_add_sql(da)
68
+ sql = ''
69
+ date_arith_sql_append(sql, da)
70
+ sql
71
+ end
72
+
73
+ # Append the SQL fragment for the DateAdd expression to the SQL query.
74
+ def date_add_sql_append(sql, da)
75
+ h = da.interval
76
+ expr = da.expr
77
+ cast = case db_type = db.database_type
78
+ when :postgres
79
+ interval = ""
80
+ each_valid_interval_unit(h, DEF_DURATION_UNITS) do |value, sql_unit|
81
+ interval << "#{value} #{sql_unit} "
82
+ end
83
+ if interval.empty?
84
+ return literal_append(sql, Sequel.cast(expr, Time))
85
+ else
86
+ return complex_expression_sql_append(sql, :+, [Sequel.cast(expr, Time), Sequel.cast(interval, :interval)])
87
+ end
88
+ when :sqlite
89
+ args = [expr]
90
+ each_valid_interval_unit(h, DEF_DURATION_UNITS) do |value, sql_unit|
91
+ args << "#{value} #{sql_unit}"
92
+ end
93
+ return _function_sql_append(sql, :datetime, args)
94
+ when :mysql, :hsqldb, :cubrid
95
+ if db_type == :hsqldb
96
+ # HSQLDB requires 2.2.9+ for the DATE_ADD function
97
+ expr = Sequel.cast(expr, Time)
98
+ end
99
+ each_valid_interval_unit(h, MYSQL_DURATION_UNITS) do |value, sql_unit|
100
+ expr = Sequel.function(:DATE_ADD, expr, Sequel.lit(["INTERVAL ", " "], value, sql_unit))
101
+ end
102
+ when :mssql, :h2, :access
103
+ units = case db_type
104
+ when :mssql
105
+ MSSQL_DURATION_UNITS
106
+ when :h2
107
+ H2_DURATION_UNITS
108
+ when :access
109
+ ACCESS_DURATION_UNITS
110
+ end
111
+ each_valid_interval_unit(h, units) do |value, sql_unit|
112
+ expr = Sequel.function(:DATEADD, sql_unit, value, expr)
113
+ end
114
+ when :derby
115
+ if expr.is_a?(Date) && !expr.is_a?(DateTime)
116
+ # Work around for https://issues.apache.org/jira/browse/DERBY-896
117
+ expr = Sequel.cast_string(expr) + ' 00:00:00'
118
+ end
119
+ each_valid_interval_unit(h, DERBY_DURATION_UNITS) do |value, sql_unit|
120
+ expr = Sequel.lit(["{fn timestampadd(#{sql_unit}, ", ", timestamp(", "))}"], value, expr)
121
+ end
122
+ when :oracle
123
+ each_valid_interval_unit(h, MYSQL_DURATION_UNITS) do |value, sql_unit|
124
+ expr = Sequel.+(expr, Sequel.lit(["INTERVAL ", " "], value.to_s, sql_unit))
125
+ end
126
+ when :db2
127
+ expr = Sequel.cast(expr, Time)
128
+ each_valid_interval_unit(h, DB2_DURATION_UNITS) do |value, sql_unit|
129
+ expr = Sequel.+(expr, Sequel.lit(["", " "], value, sql_unit))
130
+ end
131
+ false
132
+ else
133
+ raise NotImplemented, "date arithmetic is not implemented on #{db.database_type}"
134
+ end
135
+
136
+ if cast
137
+ expr = Sequel.cast(expr, Time)
138
+ end
139
+
140
+ literal_append(sql, expr)
141
+ end
142
+
143
+ private
144
+
145
+ # Yield the value in the interval for each of the units
146
+ # present in the interval, along with the SQL fragment
147
+ # representing the unit name. Returns false if any
148
+ # values were yielded, true otherwise
149
+ def each_valid_interval_unit(interval, units)
150
+ cast = true
151
+ units.each do |unit, sql_unit|
152
+ if (value = interval[unit]) && value != 0
153
+ cast = false
154
+ yield value, sql_unit
155
+ end
156
+ end
157
+ cast
158
+ end
159
+ end
160
+
161
+ # The expression that the interval is being added to.
162
+ attr_reader :expr
163
+
164
+ # The interval added to the expression, as a hash with
165
+ # symbol keys.
166
+ attr_reader :interval
167
+
168
+ # Supports two types of intervals:
169
+ # Hash :: Used directly, but values cannot be plain strings.
170
+ # ActiveSupport::Duration :: Converted to a hash using the interval's parts.
171
+ def initialize(expr, interval)
172
+ @expr = expr
173
+ @interval = if interval.is_a?(Hash)
174
+ interval.each_value do |v|
175
+ # Attempt to prevent SQL injection by users who pass untrusted strings
176
+ # as interval values.
177
+ if v.is_a?(String) && !v.is_a?(LiteralString)
178
+ raise Sequel::InvalidValue, "cannot provide String value as interval part: #{v.inspect}"
179
+ end
180
+ end
181
+ interval
182
+ else
183
+ h = Hash.new(0)
184
+ interval.parts.each{|unit, value| h[unit] += value}
185
+ {}.merge(h)
186
+ end
187
+ end
188
+
189
+ to_s_method :date_add_sql
190
+ end
191
+ end
192
+
193
+ Dataset.register_extension(:date_arithmetic, SQL::DateAdd::DatasetMethods)
194
+ end
@@ -0,0 +1,30 @@
1
+ # The meta_def extension is designed for backwards compatibility
2
+ # with older Sequel code that uses the meta_def method on
3
+ # Database, Dataset, and Model classes and/or instances. It is
4
+ # not recommended for usage in new code. To load this extension:
5
+ #
6
+ # Sequel.extension :meta_def
7
+
8
+ module Sequel
9
+ # Contains meta_def method for adding methods to objects via blocks.
10
+ # Only recommended for backwards compatibility with existing code.
11
+ module Metaprogramming
12
+ # Define a method with the given name and block body on the receiver.
13
+ #
14
+ # ds = DB[:items]
15
+ # ds.meta_def(:x){42}
16
+ # ds.x # => 42
17
+ def meta_def(name, &block)
18
+ (class << self; self end).send(:define_method, name, &block)
19
+ end
20
+ end
21
+
22
+ Database.extend Metaprogramming
23
+ Database.send(:include, Metaprogramming)
24
+ Dataset.extend Metaprogramming
25
+ Dataset.send(:include, Metaprogramming)
26
+ if defined?(Model)
27
+ Model.extend Metaprogramming
28
+ Model.send(:include, Metaprogramming)
29
+ end
30
+ end
@@ -61,6 +61,11 @@ module Sequel
61
61
  @db.send(method_sym, *args, &block)
62
62
  end
63
63
 
64
+ # This object responds to all methods the database responds to.
65
+ def respond_to_missing?(meth, include_private)
66
+ @db.respond_to?(meth, include_private)
67
+ end
68
+
64
69
  # The default up action does nothing
65
70
  def up
66
71
  end
@@ -24,6 +24,8 @@
24
24
  # dataset and the dataset doesn't have an already cached
25
25
  # version of the columns, it will create a new dataset with
26
26
  # the same options to get the columns.
27
+ #
28
+ # This extension uses Object#extend at runtime, which can hurt performance.
27
29
 
28
30
  module Sequel
29
31
  class Dataset
@@ -5,6 +5,8 @@
5
5
  # To load the extension:
6
6
  #
7
7
  # Sequel.extension :pagination
8
+ #
9
+ # This extension uses Object#extend at runtime, which can hurt performance.
8
10
 
9
11
  module Sequel
10
12
  class Dataset
@@ -18,7 +18,8 @@
18
18
  # Sequel.pg_array(array)
19
19
  #
20
20
  # If you have loaded the {core_extensions extension}[link:files/doc/core_extensions_rdoc.html]),
21
- # you can also use Array#pg_array:
21
+ # or you have loaded the {core_refinements extension}[link:files/doc/core_refinements_rdoc.html])
22
+ # and have activated refinements for the file, you can also use Array#pg_array:
22
23
  #
23
24
  # array.pg_array
24
25
  #
@@ -537,3 +538,13 @@ if Sequel.core_extensions?
537
538
  end
538
539
  end
539
540
  end
541
+
542
+ if defined?(Sequel::CoreRefinements)
543
+ module Sequel::CoreRefinements
544
+ refine Array do
545
+ def pg_array(type=nil)
546
+ Sequel::Postgres::PGArray.new(self, type)
547
+ end
548
+ end
549
+ end
550
+ end
@@ -20,7 +20,8 @@
20
20
  # ia = Sequel.expr(:int_array_column).pg_array
21
21
  #
22
22
  # If you have loaded the {core_extensions extension}[link:files/doc/core_extensions_rdoc.html]),
23
- # you can also call Symbol#pg_array:
23
+ # or you have loaded the {core_refinements extension}[link:files/doc/core_refinements_rdoc.html])
24
+ # and have activated refinements for the file, you can also use Symbol#pg_array:
24
25
  #
25
26
  # ia = :int_array_column.pg_array
26
27
  #
@@ -261,3 +262,11 @@ if Sequel.core_extensions?
261
262
  include Sequel::Postgres::ArrayOpMethods
262
263
  end
263
264
  end
265
+
266
+ if defined?(Sequel::CoreRefinements)
267
+ module Sequel::CoreRefinements
268
+ refine Symbol do
269
+ include Sequel::Postgres::ArrayOpMethods
270
+ end
271
+ end
272
+ end
@@ -20,7 +20,8 @@
20
20
  # Sequel.hstore(hash)
21
21
  #
22
22
  # If you have loaded the {core_extensions extension}[link:files/doc/core_extensions_rdoc.html]),
23
- # you can also use Hash#hstore:
23
+ # or you have loaded the {core_refinements extension}[link:files/doc/core_refinements_rdoc.html])
24
+ # and have activated refinements for the file, you can also use Hash#hstore:
24
25
  #
25
26
  # hash.hstore
26
27
  #
@@ -332,3 +333,13 @@ if Sequel.core_extensions?
332
333
  end
333
334
  end
334
335
  end
336
+
337
+ if defined?(Sequel::CoreRefinements)
338
+ module Sequel::CoreRefinements
339
+ refine Hash do
340
+ def hstore
341
+ Sequel::Postgres::HStore.new(self)
342
+ end
343
+ end
344
+ end
345
+ end
@@ -21,7 +21,8 @@
21
21
  # h = Sequel.expr(:hstore_column).hstore
22
22
  #
23
23
  # If you have loaded the {core_extensions extension}[link:files/doc/core_extensions_rdoc.html]),
24
- # you can also call Symbol#hstore:
24
+ # or you have loaded the {core_refinements extension}[link:files/doc/core_refinements_rdoc.html])
25
+ # and have activated refinements for the file, you can also use Symbol#hstore:
25
26
  #
26
27
  # h = :hstore_column.hstore
27
28
  #
@@ -291,3 +292,11 @@ if Sequel.core_extensions?
291
292
  include Sequel::Postgres::HStoreOpMethods
292
293
  end
293
294
  end
295
+
296
+ if defined?(Sequel::CoreRefinements)
297
+ module Sequel::CoreRefinements
298
+ refine Symbol do
299
+ include Sequel::Postgres::HStoreOpMethods
300
+ end
301
+ end
302
+ end
@@ -24,7 +24,8 @@
24
24
  # Sequel.pg_json(hash)
25
25
  #
26
26
  # If you have loaded the {core_extensions extension}[link:files/doc/core_extensions_rdoc.html]),
27
- # you can also use Array#pg_json and Hash#pg_json:
27
+ # or you have loaded the {core_refinements extension}[link:files/doc/core_refinements_rdoc.html])
28
+ # and have activated refinements for the file, you can also use Array#pg_json and Hash#pg_json:
28
29
  #
29
30
  # array.pg_json
30
31
  # hash.pg_json
@@ -210,3 +211,19 @@ if Sequel.core_extensions?
210
211
  end
211
212
  end
212
213
  end
214
+
215
+ if defined?(Sequel::CoreRefinements)
216
+ module Sequel::CoreRefinements
217
+ refine Array do
218
+ def pg_json
219
+ Sequel::Postgres::JSONArray.new(self)
220
+ end
221
+ end
222
+
223
+ refine Hash do
224
+ def pg_json
225
+ Sequel::Postgres::JSONHash.new(self)
226
+ end
227
+ end
228
+ end
229
+ end
@@ -25,7 +25,8 @@
25
25
  # Sequel.pg_range(range)
26
26
  #
27
27
  # If you have loaded the {core_extensions extension}[link:files/doc/core_extensions_rdoc.html]),
28
- # you can also use Range#pg_range:
28
+ # or you have loaded the {core_refinements extension}[link:files/doc/core_refinements_rdoc.html])
29
+ # and have activated refinements for the file, you can also use Range#pg_range:
29
30
  #
30
31
  # range.pg_range
31
32
  #
@@ -511,3 +512,13 @@ if Sequel.core_extensions?
511
512
  end
512
513
  end
513
514
  end
515
+
516
+ if defined?(Sequel::CoreRefinements)
517
+ module Sequel::CoreRefinements
518
+ refine Range do
519
+ def pg_range(db_type=nil)
520
+ Sequel::Postgres::PGRange.from_range(self, db_type)
521
+ end
522
+ end
523
+ end
524
+ end
@@ -20,7 +20,8 @@
20
20
  # r = Sequel.expr(:range).pg_range
21
21
  #
22
22
  # If you have loaded the {core_extensions extension}[link:files/doc/core_extensions_rdoc.html]),
23
- # you can also call Symbol#pg_range:
23
+ # or you have loaded the {core_refinements extension}[link:files/doc/core_refinements_rdoc.html])
24
+ # and have activated refinements for the file, you can also use Symbol#pg_range:
24
25
  #
25
26
  # r = :range.pg_range
26
27
  #
@@ -148,3 +149,11 @@ if Sequel.core_extensions?
148
149
  include Sequel::Postgres::RangeOpMethods
149
150
  end
150
151
  end
152
+
153
+ if defined?(Sequel::CoreRefinements)
154
+ module Sequel::CoreRefinements
155
+ refine Symbol do
156
+ include Sequel::Postgres::RangeOpMethods
157
+ end
158
+ end
159
+ end
@@ -28,7 +28,8 @@
28
28
  # Sequel.pg_row(array)
29
29
  #
30
30
  # If you have loaded the {core_extensions extension}[link:files/doc/core_extensions_rdoc.html]),
31
- # you can also use Array#pg_row:
31
+ # or you have loaded the {core_refinements extension}[link:files/doc/core_refinements_rdoc.html])
32
+ # and have activated refinements for the file, you can also use Array#pg_row:
32
33
  #
33
34
  # array.pg_row
34
35
  #
@@ -460,7 +461,12 @@ module Sequel
460
461
  @conversion_procs[parser.oid] = parser
461
462
 
462
463
  if defined?(PGArray) && PGArray.respond_to?(:register) && array_oid && array_oid > 0
463
- PGArray.register(db_type, :oid=>array_oid, :converter=>parser, :type_procs=>@conversion_procs, :scalar_typecast=>schema_type_symbol)
464
+ array_type_name = if type_schema
465
+ "#{type_schema}.#{type_name}"
466
+ else
467
+ type_name
468
+ end
469
+ PGArray.register(array_type_name, :oid=>array_oid, :converter=>parser, :type_procs=>@conversion_procs, :scalar_typecast=>schema_type_symbol)
464
470
  end
465
471
 
466
472
  @row_types[db_type] = opts.merge(:parser=>parser)
@@ -574,3 +580,13 @@ if Sequel.core_extensions?
574
580
  end
575
581
  end
576
582
  end
583
+
584
+ if defined?(Sequel::CoreRefinements)
585
+ module Sequel::CoreRefinements
586
+ refine Array do
587
+ def pg_row
588
+ Sequel::Postgres::PGRow::ArrayRow.new(self)
589
+ end
590
+ end
591
+ end
592
+ end