sequel 4.47.0 → 4.48.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +134 -0
- data/Rakefile +1 -1
- data/doc/release_notes/4.48.0.txt +293 -0
- data/lib/sequel/adapters/ado/access.rb +2 -1
- data/lib/sequel/adapters/do/postgres.rb +5 -2
- data/lib/sequel/adapters/ibmdb.rb +24 -7
- data/lib/sequel/adapters/jdbc.rb +36 -22
- data/lib/sequel/adapters/jdbc/db2.rb +12 -3
- data/lib/sequel/adapters/jdbc/derby.rb +4 -5
- data/lib/sequel/adapters/jdbc/oracle.rb +16 -2
- data/lib/sequel/adapters/jdbc/postgresql.rb +43 -18
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +9 -7
- data/lib/sequel/adapters/jdbc/sqlserver.rb +11 -4
- data/lib/sequel/adapters/mock.rb +24 -19
- data/lib/sequel/adapters/mysql.rb +17 -16
- data/lib/sequel/adapters/mysql2.rb +4 -5
- data/lib/sequel/adapters/oracle.rb +5 -9
- data/lib/sequel/adapters/postgres.rb +89 -102
- data/lib/sequel/adapters/shared/db2.rb +22 -6
- data/lib/sequel/adapters/shared/mssql.rb +5 -4
- data/lib/sequel/adapters/shared/mysql.rb +75 -24
- data/lib/sequel/adapters/shared/postgres.rb +196 -94
- data/lib/sequel/adapters/shared/sqlanywhere.rb +23 -10
- data/lib/sequel/adapters/shared/sqlite.rb +72 -82
- data/lib/sequel/adapters/sqlanywhere.rb +4 -1
- data/lib/sequel/adapters/sqlite.rb +5 -3
- data/lib/sequel/adapters/swift/postgres.rb +5 -2
- data/lib/sequel/adapters/tinytds.rb +0 -5
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -1
- data/lib/sequel/adapters/utils/pg_types.rb +2 -76
- data/lib/sequel/core.rb +2 -2
- data/lib/sequel/database/connecting.rb +5 -5
- data/lib/sequel/database/dataset.rb +6 -3
- data/lib/sequel/database/misc.rb +1 -1
- data/lib/sequel/database/query.rb +3 -0
- data/lib/sequel/database/schema_methods.rb +1 -1
- data/lib/sequel/dataset/actions.rb +18 -10
- data/lib/sequel/dataset/graph.rb +1 -1
- data/lib/sequel/dataset/misc.rb +1 -0
- data/lib/sequel/dataset/prepared_statements.rb +3 -3
- data/lib/sequel/dataset/query.rb +19 -8
- data/lib/sequel/extensions/core_extensions.rb +4 -1
- data/lib/sequel/extensions/duplicate_columns_handler.rb +1 -1
- data/lib/sequel/extensions/empty_array_ignore_nulls.rb +3 -0
- data/lib/sequel/extensions/filter_having.rb +2 -0
- data/lib/sequel/extensions/freeze_datasets.rb +2 -0
- data/lib/sequel/extensions/from_block.rb +1 -1
- data/lib/sequel/extensions/graph_each.rb +2 -2
- data/lib/sequel/extensions/hash_aliases.rb +2 -0
- data/lib/sequel/extensions/identifier_mangling.rb +0 -7
- data/lib/sequel/extensions/meta_def.rb +2 -0
- data/lib/sequel/extensions/migration.rb +6 -6
- data/lib/sequel/extensions/no_auto_literal_strings.rb +1 -1
- data/lib/sequel/extensions/pagination.rb +1 -1
- data/lib/sequel/extensions/pg_array.rb +207 -130
- data/lib/sequel/extensions/pg_hstore.rb +38 -20
- data/lib/sequel/extensions/pg_inet.rb +18 -6
- data/lib/sequel/extensions/pg_interval.rb +19 -12
- data/lib/sequel/extensions/pg_json.rb +25 -14
- data/lib/sequel/extensions/pg_json_ops.rb +2 -2
- data/lib/sequel/extensions/pg_range.rb +133 -100
- data/lib/sequel/extensions/pg_range_ops.rb +4 -3
- data/lib/sequel/extensions/pg_row.rb +68 -39
- data/lib/sequel/extensions/pg_row_ops.rb +11 -5
- data/lib/sequel/extensions/query_literals.rb +2 -0
- data/lib/sequel/extensions/ruby18_symbol_extensions.rb +2 -0
- data/lib/sequel/extensions/s.rb +1 -1
- data/lib/sequel/extensions/schema_dumper.rb +24 -24
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +3 -1
- data/lib/sequel/extensions/sequel_4_dataset_methods.rb +83 -0
- data/lib/sequel/extensions/set_overrides.rb +2 -2
- data/lib/sequel/extensions/string_agg.rb +0 -1
- data/lib/sequel/extensions/symbol_aref.rb +0 -4
- data/lib/sequel/model.rb +25 -57
- data/lib/sequel/model/associations.rb +14 -5
- data/lib/sequel/model/base.rb +96 -32
- data/lib/sequel/plugins/association_pks.rb +73 -46
- data/lib/sequel/plugins/association_proxies.rb +1 -1
- data/lib/sequel/plugins/auto_validations.rb +6 -2
- data/lib/sequel/plugins/boolean_readers.rb +1 -1
- data/lib/sequel/plugins/caching.rb +19 -13
- data/lib/sequel/plugins/class_table_inheritance.rb +19 -10
- data/lib/sequel/plugins/column_conflicts.rb +7 -2
- data/lib/sequel/plugins/column_select.rb +1 -1
- data/lib/sequel/plugins/csv_serializer.rb +8 -8
- data/lib/sequel/plugins/defaults_setter.rb +10 -0
- data/lib/sequel/plugins/eager_each.rb +1 -1
- data/lib/sequel/plugins/force_encoding.rb +2 -2
- data/lib/sequel/plugins/hook_class_methods.rb +9 -12
- data/lib/sequel/plugins/identifier_columns.rb +2 -0
- data/lib/sequel/plugins/instance_filters.rb +3 -1
- data/lib/sequel/plugins/instance_hooks.rb +17 -9
- data/lib/sequel/plugins/json_serializer.rb +17 -10
- data/lib/sequel/plugins/lazy_attributes.rb +8 -7
- data/lib/sequel/plugins/modification_detection.rb +3 -0
- data/lib/sequel/plugins/nested_attributes.rb +5 -1
- data/lib/sequel/plugins/pg_array_associations.rb +5 -0
- data/lib/sequel/plugins/prepared_statements.rb +1 -0
- data/lib/sequel/plugins/rcte_tree.rb +4 -4
- data/lib/sequel/plugins/serialization.rb +3 -10
- data/lib/sequel/plugins/single_table_inheritance.rb +2 -2
- data/lib/sequel/plugins/split_values.rb +6 -5
- data/lib/sequel/plugins/static_cache.rb +31 -25
- data/lib/sequel/plugins/subset_conditions.rb +3 -1
- data/lib/sequel/plugins/table_select.rb +1 -1
- data/lib/sequel/plugins/touch.rb +2 -1
- data/lib/sequel/plugins/validation_class_methods.rb +5 -6
- data/lib/sequel/plugins/validation_helpers.rb +2 -4
- data/lib/sequel/plugins/xml_serializer.rb +4 -4
- data/lib/sequel/sql.rb +2 -2
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +115 -14
- data/spec/adapters/mysql_spec.rb +78 -28
- data/spec/adapters/oracle_spec.rb +24 -24
- data/spec/adapters/postgres_spec.rb +38 -24
- data/spec/adapters/sqlanywhere_spec.rb +88 -86
- data/spec/adapters/sqlite_spec.rb +29 -24
- data/spec/core/connection_pool_spec.rb +17 -0
- data/spec/core/database_spec.rb +6 -0
- data/spec/core/dataset_spec.rb +46 -36
- data/spec/core/schema_spec.rb +16 -0
- data/spec/core/spec_helper.rb +1 -0
- data/spec/core_extensions_spec.rb +6 -2
- data/spec/extensions/active_model_spec.rb +1 -1
- data/spec/extensions/arbitrary_servers_spec.rb +1 -1
- data/spec/extensions/association_pks_spec.rb +34 -2
- data/spec/extensions/auto_literal_strings_spec.rb +5 -1
- data/spec/extensions/auto_validations_spec.rb +2 -0
- data/spec/extensions/boolean_readers_spec.rb +1 -1
- data/spec/extensions/boolean_subsets_spec.rb +1 -1
- data/spec/extensions/class_table_inheritance_spec.rb +48 -2
- data/spec/extensions/column_conflicts_spec.rb +11 -0
- data/spec/extensions/connection_validator_spec.rb +1 -1
- data/spec/extensions/dataset_associations_spec.rb +8 -8
- data/spec/extensions/defaults_setter_spec.rb +1 -1
- data/spec/extensions/filter_having_spec.rb +5 -3
- data/spec/extensions/hash_aliases_spec.rb +3 -1
- data/spec/extensions/identifier_columns_spec.rb +3 -1
- data/spec/extensions/implicit_subquery_spec.rb +4 -2
- data/spec/extensions/json_serializer_spec.rb +18 -0
- data/spec/extensions/lazy_attributes_spec.rb +3 -3
- data/spec/extensions/meta_def_spec.rb +9 -0
- data/spec/extensions/migration_spec.rb +3 -3
- data/spec/extensions/nested_attributes_spec.rb +14 -3
- data/spec/extensions/no_auto_literal_strings_spec.rb +8 -4
- data/spec/extensions/pg_array_associations_spec.rb +29 -18
- data/spec/extensions/pg_array_spec.rb +44 -25
- data/spec/extensions/pg_hstore_spec.rb +10 -0
- data/spec/extensions/pg_inet_spec.rb +26 -0
- data/spec/extensions/pg_interval_spec.rb +20 -0
- data/spec/extensions/pg_json_spec.rb +24 -0
- data/spec/extensions/pg_range_spec.rb +98 -14
- data/spec/extensions/pg_row_spec.rb +14 -4
- data/spec/extensions/prepared_statements_safe_spec.rb +1 -1
- data/spec/extensions/query_literals_spec.rb +3 -1
- data/spec/extensions/schema_dumper_spec.rb +96 -98
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +10 -6
- data/spec/extensions/sequel_4_dataset_methods_spec.rb +121 -0
- data/spec/extensions/single_table_inheritance_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +7 -1
- data/spec/extensions/static_cache_spec.rb +75 -24
- data/spec/extensions/string_agg_spec.rb +1 -1
- data/spec/extensions/touch_spec.rb +9 -0
- data/spec/extensions/validation_helpers_spec.rb +9 -3
- data/spec/extensions/whitelist_security_spec.rb +26 -0
- data/spec/integration/dataset_test.rb +45 -44
- data/spec/integration/plugin_test.rb +20 -0
- data/spec/integration/prepared_statement_test.rb +3 -0
- data/spec/integration/schema_test.rb +21 -1
- data/spec/integration/transaction_test.rb +40 -40
- data/spec/model/class_dataset_methods_spec.rb +14 -4
- data/spec/model/dataset_methods_spec.rb +12 -3
- data/spec/model/model_spec.rb +8 -0
- metadata +6 -4
- data/spec/adapters/firebird_spec.rb +0 -405
- data/spec/adapters/informix_spec.rb +0 -100
@@ -335,19 +335,19 @@ module Sequel
|
|
335
335
|
#
|
336
336
|
# For example, to migrate the database to the latest version:
|
337
337
|
#
|
338
|
-
# Sequel::Migrator.
|
338
|
+
# Sequel::Migrator.run(DB, '.')
|
339
339
|
#
|
340
340
|
# For example, to migrate the database all the way down:
|
341
341
|
#
|
342
|
-
# Sequel::Migrator.
|
342
|
+
# Sequel::Migrator.run(DB, '.', :target=>0)
|
343
343
|
#
|
344
344
|
# For example, to migrate the database to version 4:
|
345
345
|
#
|
346
|
-
# Sequel::Migrator.
|
346
|
+
# Sequel::Migrator.run(DB, '.', :target=>4)
|
347
347
|
#
|
348
348
|
# To migrate the database from version 1 to version 5:
|
349
349
|
#
|
350
|
-
# Sequel::Migrator.
|
350
|
+
# Sequel::Migrator.run(DB, '.', :target=>5, :current=>1)
|
351
351
|
#
|
352
352
|
# Part of the +migration+ extension.
|
353
353
|
class Migrator
|
@@ -490,7 +490,7 @@ module Sequel
|
|
490
490
|
def remove_migration_classes
|
491
491
|
# Remove class definitions
|
492
492
|
Migration.descendants.each do |c|
|
493
|
-
Object.send(:remove_const, c.
|
493
|
+
Object.send(:remove_const, c.name) if c.is_a?(Class) && !c.name.to_s.empty? && Object.const_defined?(c.name)
|
494
494
|
end
|
495
495
|
Migration.descendants.clear # remove any defined migration classes
|
496
496
|
end
|
@@ -634,7 +634,7 @@ module Sequel
|
|
634
634
|
ds
|
635
635
|
end
|
636
636
|
|
637
|
-
# Sets the current migration
|
637
|
+
# Sets the current migration version stored in the database.
|
638
638
|
def set_migration_version(version)
|
639
639
|
ds.update(column=>version)
|
640
640
|
end
|
@@ -139,7 +139,7 @@ module Sequel
|
|
139
139
|
# SEQUEL5: Remove
|
140
140
|
# :nocov:
|
141
141
|
def set_pagination_info(page_no, page_size, record_count)
|
142
|
-
Sequel::Deprecation.deprecate("Dataset#set_pagination_info", "It should no longer be necessary to call this method
|
142
|
+
Sequel::Deprecation.deprecate("Dataset#set_pagination_info", "It should no longer be necessary to call this method")
|
143
143
|
self.current_page = page_no
|
144
144
|
self.page_size = page_size
|
145
145
|
self.pagination_record_count = record_count
|
@@ -45,12 +45,10 @@
|
|
45
45
|
# all scalar types that the native postgres adapter handles. It
|
46
46
|
# also makes it easy to add support for other array types. In
|
47
47
|
# general, you just need to make sure that the scalar type is
|
48
|
-
# handled and has the appropriate converter installed
|
49
|
-
# Sequel::Postgres::PG_TYPES or the Database instance's
|
50
|
-
# conversion_procs usingthe appropriate type OID. For user defined
|
48
|
+
# handled and has the appropriate converter installed. For user defined
|
51
49
|
# types, you can do this via:
|
52
50
|
#
|
53
|
-
# DB.
|
51
|
+
# DB.add_conversion_proc(scalar_type_oid){|string| }
|
54
52
|
#
|
55
53
|
# Then you can call
|
56
54
|
# Sequel::Postgres::PGArray::DatabaseMethods#register_array_type
|
@@ -60,18 +58,6 @@
|
|
60
58
|
#
|
61
59
|
# DB.register_array_type('foo')
|
62
60
|
#
|
63
|
-
# You can also register array types on a global basis using
|
64
|
-
# Sequel::Postgres::PGArray.register. In this case, you'll have
|
65
|
-
# to specify the type oids:
|
66
|
-
#
|
67
|
-
# Sequel::Postgres::PG_TYPES[1234] = lambda{|string| }
|
68
|
-
# Sequel::Postgres::PGArray.register('foo', :oid=>4321, :scalar_oid=>1234)
|
69
|
-
#
|
70
|
-
# Both Sequel::Postgres::PGArray::DatabaseMethods#register_array_type
|
71
|
-
# and Sequel::Postgres::PGArray.register support many options to
|
72
|
-
# customize the array type handling. See the Sequel::Postgres::PGArray.register
|
73
|
-
# method documentation.
|
74
|
-
#
|
75
61
|
# While this extension can parse PostgreSQL arrays with explicit bounds, it
|
76
62
|
# currently ignores explicit bounds, so such values do not round
|
77
63
|
# trip.
|
@@ -85,7 +71,7 @@
|
|
85
71
|
|
86
72
|
require 'delegate'
|
87
73
|
require 'strscan'
|
88
|
-
Sequel.require 'adapters/
|
74
|
+
Sequel.require 'adapters/shared/postgres'
|
89
75
|
|
90
76
|
module Sequel
|
91
77
|
module Postgres
|
@@ -94,59 +80,42 @@ module Sequel
|
|
94
80
|
include Sequel::SQL::AliasMethods
|
95
81
|
|
96
82
|
ARRAY = "ARRAY".freeze
|
83
|
+
Sequel::Deprecation.deprecate_constant(self, :ARRAY)
|
97
84
|
DOUBLE_COLON = '::'.freeze
|
85
|
+
Sequel::Deprecation.deprecate_constant(self, :DOUBLE_COLON)
|
98
86
|
EMPTY_ARRAY = "'{}'".freeze
|
87
|
+
Sequel::Deprecation.deprecate_constant(self, :EMPTY_ARRAY)
|
99
88
|
EMPTY_BRACKET = '[]'.freeze
|
89
|
+
Sequel::Deprecation.deprecate_constant(self, :EMPTY_BRACKET)
|
100
90
|
OPEN_BRACKET = '['.freeze
|
91
|
+
Sequel::Deprecation.deprecate_constant(self, :OPEN_BRACKET)
|
101
92
|
CLOSE_BRACKET = ']'.freeze
|
93
|
+
Sequel::Deprecation.deprecate_constant(self, :CLOSE_BRACKET)
|
102
94
|
COMMA = ','.freeze
|
95
|
+
Sequel::Deprecation.deprecate_constant(self, :COMMA)
|
103
96
|
BACKSLASH = '\\'.freeze
|
97
|
+
Sequel::Deprecation.deprecate_constant(self, :BACKSLASH)
|
104
98
|
EMPTY_STRING = ''.freeze
|
99
|
+
Sequel::Deprecation.deprecate_constant(self, :EMPTY_STRING)
|
105
100
|
OPEN_BRACE = '{'.freeze
|
101
|
+
Sequel::Deprecation.deprecate_constant(self, :OPEN_BRACE)
|
106
102
|
CLOSE_BRACE = '}'.freeze
|
103
|
+
Sequel::Deprecation.deprecate_constant(self, :CLOSE_BRACE)
|
107
104
|
NULL = 'NULL'.freeze
|
105
|
+
Sequel::Deprecation.deprecate_constant(self, :NULL)
|
108
106
|
QUOTE = '"'.freeze
|
107
|
+
Sequel::Deprecation.deprecate_constant(self, :QUOTE)
|
109
108
|
|
110
|
-
#
|
111
|
-
# used by the schema parsing for array types registered globally.
|
109
|
+
# SEQUEL5: Remove
|
112
110
|
ARRAY_TYPES = {}
|
113
111
|
|
114
|
-
#
|
115
|
-
# has been extended with DatabaseMethods recognize the array type given and set up the
|
116
|
-
# appropriate typecasting. Also sets up automatic typecasting for the native postgres
|
117
|
-
# adapter, so that on retrieval, the values are automatically converted to PGArray instances.
|
118
|
-
# The db_type argument should be the exact database type used (as returned by the PostgreSQL
|
119
|
-
# format_type database function). Accepts the following options:
|
120
|
-
#
|
121
|
-
# :array_type :: The type to automatically cast the array to when literalizing the array.
|
122
|
-
# Usually the same as db_type.
|
123
|
-
# :converter :: A callable object (e.g. Proc), that is called with each element of the array
|
124
|
-
# (usually a string), and should return the appropriate typecasted object.
|
125
|
-
# :oid :: The PostgreSQL OID for the array type. This is used by the Sequel postgres adapter
|
126
|
-
# to set up automatic type conversion on retrieval from the database.
|
127
|
-
# :scalar_oid :: Should be the PostgreSQL OID for the scalar version of this array type. If given,
|
128
|
-
# automatically sets the :converter option by looking for scalar conversion
|
129
|
-
# proc.
|
130
|
-
# :scalar_typecast :: Should be a symbol indicating the typecast method that should be called on
|
131
|
-
# each element of the array, when a plain array is passed into a database
|
132
|
-
# typecast method. For example, for an array of integers, this could be set to
|
133
|
-
# :integer, so that the typecast_value_integer method is called on all of the
|
134
|
-
# array elements. Defaults to :type_symbol option.
|
135
|
-
# :type_procs :: A hash mapping oids to conversion procs, used for looking up the :scalar_oid and
|
136
|
-
# value and setting the :oid value. Defaults to the global Sequel::Postgres::PG_TYPES.
|
137
|
-
# :type_symbol :: The base of the schema type symbol for this type. For example, if you provide
|
138
|
-
# :integer, Sequel will recognize this type as :integer_array during schema parsing.
|
139
|
-
# Defaults to the db_type argument.
|
140
|
-
# :typecast_method_map :: The map in which to place the database type string to type symbol mapping.
|
141
|
-
# Defaults to ARRAY_TYPES.
|
142
|
-
# :typecast_methods_module :: If given, a module object to add the typecasting method to. Defaults
|
143
|
-
# to DatabaseMethods.
|
144
|
-
#
|
145
|
-
# If a block is given, it is treated as the :converter option.
|
112
|
+
# SEQUEL5: Remove
|
146
113
|
def self.register(db_type, opts=OPTS, &block)
|
114
|
+
Sequel::Deprecation.deprecate("Sequel::Postgres::PGArray.register", "Use Database#register_array_type on a Database instance using the pg_array extension") unless opts[:skip_deprecation_warning]
|
115
|
+
|
147
116
|
db_type = db_type.to_s
|
148
117
|
type = (opts[:type_symbol] || db_type).to_sym
|
149
|
-
type_procs = opts[:type_procs] ||
|
118
|
+
type_procs = opts[:type_procs] || PG__TYPES
|
150
119
|
mod = opts[:typecast_methods_module] || DatabaseMethods
|
151
120
|
typecast_method_map = opts[:typecast_method_map] || ARRAY_TYPES
|
152
121
|
|
@@ -169,14 +138,19 @@ module Sequel
|
|
169
138
|
define_array_typecast_method(mod, type, creator, opts.fetch(:scalar_typecast, type))
|
170
139
|
|
171
140
|
if oid = opts[:oid]
|
141
|
+
if opts[:skip_deprecation_warning]
|
142
|
+
def creator.call(s)
|
143
|
+
Sequel::Deprecation.deprecate("Conversion proc for #{type}[] added globally by pg_array or other pg_* extension", "Load the appropriate pg_* extension(s) into the Database instance")
|
144
|
+
super
|
145
|
+
end
|
146
|
+
end
|
172
147
|
type_procs[oid] = creator
|
173
148
|
end
|
174
149
|
|
175
150
|
nil
|
176
151
|
end
|
177
152
|
|
178
|
-
#
|
179
|
-
# the creator argument to do the type conversion.
|
153
|
+
# SEQUEL5: Remove
|
180
154
|
def self.define_array_typecast_method(mod, type, creator, scalar_typecast)
|
181
155
|
mod.class_eval do
|
182
156
|
meth = :"typecast_value_#{type}_array"
|
@@ -189,9 +163,14 @@ module Sequel
|
|
189
163
|
|
190
164
|
module DatabaseMethods
|
191
165
|
APOS = "'".freeze
|
166
|
+
Sequel::Deprecation.deprecate_constant(self, :APOS)
|
192
167
|
DOUBLE_APOS = "''".freeze
|
168
|
+
Sequel::Deprecation.deprecate_constant(self, :DOUBLE_APOS)
|
193
169
|
ESCAPE_RE = /("|\\)/.freeze
|
170
|
+
Sequel::Deprecation.deprecate_constant(self, :ESCAPE_RE)
|
194
171
|
ESCAPE_REPLACEMENT = '\\\\\1'.freeze
|
172
|
+
Sequel::Deprecation.deprecate_constant(self, :ESCAPE_REPLACEMENT)
|
173
|
+
|
195
174
|
BLOB_RANGE = 1...-1
|
196
175
|
|
197
176
|
# Create the local hash of database type strings to schema type symbols,
|
@@ -200,9 +179,41 @@ module Sequel
|
|
200
179
|
db.instance_eval do
|
201
180
|
@pg_array_schema_types ||= {}
|
202
181
|
procs = conversion_procs
|
203
|
-
|
204
|
-
|
205
|
-
|
182
|
+
add_conversion_proc(1115, Creator.new("timestamp without time zone", procs[1114]))
|
183
|
+
add_conversion_proc(1185, Creator.new("timestamp with time zone", procs[1184]))
|
184
|
+
|
185
|
+
register_array_type('text', :oid=>1009, :scalar_oid=>25, :type_symbol=>:string)
|
186
|
+
register_array_type('integer', :oid=>1007, :scalar_oid=>23)
|
187
|
+
register_array_type('bigint', :oid=>1016, :scalar_oid=>20, :scalar_typecast=>:integer)
|
188
|
+
register_array_type('numeric', :oid=>1231, :scalar_oid=>1700, :type_symbol=>:decimal)
|
189
|
+
register_array_type('double precision', :oid=>1022, :scalar_oid=>701, :type_symbol=>:float)
|
190
|
+
|
191
|
+
register_array_type('boolean', :oid=>1000, :scalar_oid=>16)
|
192
|
+
register_array_type('bytea', :oid=>1001, :scalar_oid=>17, :type_symbol=>:blob)
|
193
|
+
register_array_type('date', :oid=>1182, :scalar_oid=>1082)
|
194
|
+
register_array_type('time without time zone', :oid=>1183, :scalar_oid=>1083, :type_symbol=>:time)
|
195
|
+
register_array_type('time with time zone', :oid=>1270, :scalar_oid=>1083, :type_symbol=>:time_timezone, :scalar_typecast=>:time)
|
196
|
+
|
197
|
+
register_array_type('smallint', :oid=>1005, :scalar_oid=>21, :scalar_typecast=>:integer)
|
198
|
+
register_array_type('oid', :oid=>1028, :scalar_oid=>26, :scalar_typecast=>:integer)
|
199
|
+
register_array_type('real', :oid=>1021, :scalar_oid=>700, :scalar_typecast=>:float)
|
200
|
+
register_array_type('character', :oid=>1014, :converter=>nil, :array_type=>:text, :scalar_typecast=>:string)
|
201
|
+
register_array_type('character varying', :oid=>1015, :converter=>nil, :scalar_typecast=>:string, :type_symbol=>:varchar)
|
202
|
+
|
203
|
+
register_array_type('xml', :oid=>143, :scalar_oid=>142)
|
204
|
+
register_array_type('money', :oid=>791, :scalar_oid=>790)
|
205
|
+
register_array_type('bit', :oid=>1561, :scalar_oid=>1560)
|
206
|
+
register_array_type('bit varying', :oid=>1563, :scalar_oid=>1562, :type_symbol=>:varbit)
|
207
|
+
register_array_type('uuid', :oid=>2951, :scalar_oid=>2950)
|
208
|
+
|
209
|
+
register_array_type('xid', :oid=>1011, :scalar_oid=>28)
|
210
|
+
register_array_type('cid', :oid=>1012, :scalar_oid=>29)
|
211
|
+
|
212
|
+
register_array_type('name', :oid=>1003, :scalar_oid=>19)
|
213
|
+
register_array_type('tid', :oid=>1010, :scalar_oid=>27)
|
214
|
+
register_array_type('int2vector', :oid=>1006, :scalar_oid=>22)
|
215
|
+
register_array_type('oidvector', :oid=>1013, :scalar_oid=>30)
|
216
|
+
|
206
217
|
[:string_array, :integer_array, :decimal_array, :float_array, :boolean_array, :blob_array, :date_array, :time_array, :datetime_array].each do |v|
|
207
218
|
@schema_type_classes[v] = PGArray
|
208
219
|
end
|
@@ -227,23 +238,77 @@ module Sequel
|
|
227
238
|
super
|
228
239
|
end
|
229
240
|
|
230
|
-
# Register a database specific array type.
|
231
|
-
#
|
232
|
-
#
|
233
|
-
#
|
241
|
+
# Register a database specific array type. Options:
|
242
|
+
#
|
243
|
+
# :array_type :: The type to automatically cast the array to when literalizing the array.
|
244
|
+
# Usually the same as db_type.
|
245
|
+
# :converter :: A callable object (e.g. Proc), that is called with each element of the array
|
246
|
+
# (usually a string), and should return the appropriate typecasted object.
|
247
|
+
# :oid :: The PostgreSQL OID for the array type. This is used by the Sequel postgres adapter
|
248
|
+
# to set up automatic type conversion on retrieval from the database.
|
249
|
+
# :scalar_oid :: Should be the PostgreSQL OID for the scalar version of this array type. If given,
|
250
|
+
# automatically sets the :converter option by looking for scalar conversion
|
251
|
+
# proc.
|
252
|
+
# :scalar_typecast :: Should be a symbol indicating the typecast method that should be called on
|
253
|
+
# each element of the array, when a plain array is passed into a database
|
254
|
+
# typecast method. For example, for an array of integers, this could be set to
|
255
|
+
# :integer, so that the typecast_value_integer method is called on all of the
|
256
|
+
# array elements. Defaults to :type_symbol option.
|
257
|
+
# :type_symbol :: The base of the schema type symbol for this type. For example, if you provide
|
258
|
+
# :integer, Sequel will recognize this type as :integer_array during schema parsing.
|
259
|
+
# Defaults to the db_type argument.
|
260
|
+
#
|
261
|
+
# If a block is given, it is treated as the :converter option.
|
234
262
|
def register_array_type(db_type, opts=OPTS, &block)
|
235
|
-
|
236
|
-
|
263
|
+
# Only for convert_named_procs_to_procs usage
|
264
|
+
type_procs = opts[:type_procs] || conversion_procs # SEQUEL5: Remove
|
265
|
+
|
266
|
+
oid = opts[:oid]
|
267
|
+
soid = opts[:scalar_oid]
|
268
|
+
|
269
|
+
if has_converter = opts.has_key?(:converter)
|
270
|
+
raise Error, "can't provide both a block and :converter option to register_array_type" if block
|
271
|
+
converter = opts[:converter]
|
272
|
+
else
|
273
|
+
has_converter = true if block
|
274
|
+
converter = block
|
275
|
+
end
|
276
|
+
|
277
|
+
unless (soid || has_converter) && oid
|
237
278
|
array_oid, scalar_oid = from(:pg_type).where(:typname=>db_type.to_s).get([:typarray, :oid])
|
238
|
-
|
239
|
-
|
279
|
+
soid ||= scalar_oid unless has_converter
|
280
|
+
oid ||= array_oid
|
281
|
+
end
|
282
|
+
|
283
|
+
db_type = db_type.to_s
|
284
|
+
type = (opts[:type_symbol] || db_type).to_sym
|
285
|
+
typecast_method_map = @pg_array_schema_types
|
286
|
+
|
287
|
+
if soid
|
288
|
+
raise Error, "can't provide both a converter and :scalar_oid option to register" if has_converter
|
289
|
+
converter = type_procs[soid] # SEQUEL5: conversion_procs[soid]
|
240
290
|
end
|
241
|
-
|
242
|
-
|
243
|
-
|
291
|
+
|
292
|
+
array_type = (opts[:array_type] || db_type).to_s.dup.freeze
|
293
|
+
creator = Creator.new(array_type, converter)
|
294
|
+
type_procs[oid] = creator # SEQUEL5: Remove
|
295
|
+
#add_conversion_proc(oid, creator) # SEQUEL5
|
296
|
+
|
297
|
+
typecast_method_map[db_type] = :"#{type}_array"
|
298
|
+
|
299
|
+
(class << self; self end).class_eval do # singleton_class.class_eval do # SEQUEL5
|
300
|
+
meth = :"typecast_value_#{type}_array"
|
301
|
+
scalar_typecast_method = :"typecast_value_#{opts.fetch(:scalar_typecast, type)}"
|
302
|
+
define_method(meth){|v| typecast_value_pg_array(v, creator, scalar_typecast_method)}
|
303
|
+
private meth
|
304
|
+
end
|
305
|
+
|
306
|
+
@schema_type_classes[:"#{type}_array"] = PGArray
|
307
|
+
conversion_procs_updated # SEQUEL5: Remove
|
308
|
+
nil
|
244
309
|
end
|
245
310
|
|
246
|
-
#
|
311
|
+
# SEQUEL5: Remove
|
247
312
|
def schema_type_class(type)
|
248
313
|
super || (ARRAY_TYPES.each_value{|v| return PGArray if type == v}; nil)
|
249
314
|
end
|
@@ -254,13 +319,13 @@ module Sequel
|
|
254
319
|
def bound_variable_array(a)
|
255
320
|
case a
|
256
321
|
when Array
|
257
|
-
"{#{a.map{|i| bound_variable_array(i)}.join(
|
322
|
+
"{#{a.map{|i| bound_variable_array(i)}.join(',')}}"
|
258
323
|
when Sequel::SQL::Blob
|
259
|
-
"\"#{literal(a)[BLOB_RANGE].gsub(
|
324
|
+
"\"#{literal(a)[BLOB_RANGE].gsub("''", "'").gsub(/("|\\)/, '\\\\\1')}\""
|
260
325
|
when Sequel::LiteralString
|
261
326
|
a
|
262
327
|
when String
|
263
|
-
"\"#{a.gsub(
|
328
|
+
"\"#{a.gsub(/("|\\)/, '\\\\\1')}\""
|
264
329
|
else
|
265
330
|
literal(a)
|
266
331
|
end
|
@@ -277,9 +342,7 @@ module Sequel
|
|
277
342
|
h
|
278
343
|
end
|
279
344
|
|
280
|
-
#
|
281
|
-
# they use the database's timezone instead of the global Sequel
|
282
|
-
# timezone.
|
345
|
+
# SEQUEL5: Remove
|
283
346
|
def get_conversion_procs
|
284
347
|
procs = super
|
285
348
|
|
@@ -293,7 +356,7 @@ module Sequel
|
|
293
356
|
# array schema types to get the type symbol for the given database type
|
294
357
|
# string.
|
295
358
|
def pg_array_schema_type(type)
|
296
|
-
@pg_array_schema_types[type] || ARRAY_TYPES[type]
|
359
|
+
@pg_array_schema_types[type] || ARRAY_TYPES[type] # SEQUEL5: Remove || ARRAY_TYPES[type]
|
297
360
|
end
|
298
361
|
|
299
362
|
# Make the column type detection handle registered array types.
|
@@ -346,9 +409,13 @@ module Sequel
|
|
346
409
|
# accept, and it will not raise an error for all forms of invalid input.
|
347
410
|
class Parser < StringScanner
|
348
411
|
UNQUOTED_RE = /[{}",]|[^{}",]+/
|
412
|
+
Sequel::Deprecation.deprecate_constant(self, :UNQUOTED_RE)
|
349
413
|
QUOTED_RE = /["\\]|[^"\\]+/
|
414
|
+
Sequel::Deprecation.deprecate_constant(self, :QUOTED_RE)
|
350
415
|
NULL_RE = /NULL",/
|
416
|
+
Sequel::Deprecation.deprecate_constant(self, :NULL_RE)
|
351
417
|
OPEN_RE = /((\[\d+:\d+\])+=)?\{/
|
418
|
+
Sequel::Deprecation.deprecate_constant(self, :OPEN_RE)
|
352
419
|
|
353
420
|
# Set the source for the input, and any converter callable
|
354
421
|
# to call with objects to be created. For nested parsers
|
@@ -358,7 +425,8 @@ module Sequel
|
|
358
425
|
super(source)
|
359
426
|
@converter = converter
|
360
427
|
@stack = [[]]
|
361
|
-
@recorded =
|
428
|
+
@recorded = new_entry_buffer
|
429
|
+
#@encoding = string.encoding # SEQUEL5
|
362
430
|
end
|
363
431
|
|
364
432
|
# Take the buffer of recorded characters and add it to the array
|
@@ -366,13 +434,13 @@ module Sequel
|
|
366
434
|
def new_entry(include_empty=false)
|
367
435
|
if !@recorded.empty? || include_empty
|
368
436
|
entry = @recorded
|
369
|
-
if entry == NULL && !include_empty
|
437
|
+
if entry == 'NULL' && !include_empty
|
370
438
|
entry = nil
|
371
439
|
elsif @converter
|
372
440
|
entry = @converter.call(entry)
|
373
441
|
end
|
374
442
|
@stack.last.push(entry)
|
375
|
-
@recorded =
|
443
|
+
@recorded = new_entry_buffer
|
376
444
|
end
|
377
445
|
end
|
378
446
|
|
@@ -380,36 +448,36 @@ module Sequel
|
|
380
448
|
# of parsed (and potentially converted) objects.
|
381
449
|
def parse
|
382
450
|
raise Sequel::Error, "invalid array, empty string" if eos?
|
383
|
-
raise Sequel::Error, "invalid array, doesn't start with {" unless scan(
|
451
|
+
raise Sequel::Error, "invalid array, doesn't start with {" unless scan(/((\[\d+:\d+\])+=)?\{/)
|
384
452
|
|
385
453
|
while !eos?
|
386
|
-
char = scan(
|
387
|
-
if char ==
|
454
|
+
char = scan(/[{}",]|[^{}",]+/)
|
455
|
+
if char == ','
|
388
456
|
# Comma outside quoted string indicates end of current entry
|
389
457
|
new_entry
|
390
|
-
elsif char ==
|
458
|
+
elsif char == '"'
|
391
459
|
raise Sequel::Error, "invalid array, opening quote with existing recorded data" unless @recorded.empty?
|
392
460
|
while true
|
393
|
-
char = scan(
|
394
|
-
if char ==
|
461
|
+
char = scan(/["\\]|[^"\\]+/)
|
462
|
+
if char == '\\'
|
395
463
|
@recorded << getch
|
396
|
-
elsif char ==
|
464
|
+
elsif char == '"'
|
397
465
|
n = peek(1)
|
398
|
-
raise Sequel::Error, "invalid array, closing quote not followed by comma or closing brace" unless n ==
|
466
|
+
raise Sequel::Error, "invalid array, closing quote not followed by comma or closing brace" unless n == ',' || n == '}'
|
399
467
|
break
|
400
468
|
else
|
401
469
|
@recorded << char
|
402
470
|
end
|
403
471
|
end
|
404
472
|
new_entry(true)
|
405
|
-
elsif char ==
|
473
|
+
elsif char == '{'
|
406
474
|
raise Sequel::Error, "invalid array, opening brace with existing recorded data" unless @recorded.empty?
|
407
475
|
|
408
476
|
# Start of new array, add it to the stack
|
409
477
|
new = []
|
410
478
|
@stack.last << new
|
411
479
|
@stack << new
|
412
|
-
elsif char ==
|
480
|
+
elsif char == '}'
|
413
481
|
# End of current array, add current entry to the current array
|
414
482
|
new_entry
|
415
483
|
|
@@ -431,6 +499,21 @@ module Sequel
|
|
431
499
|
|
432
500
|
raise Sequel::Error, "array parsing finished with array unclosed"
|
433
501
|
end
|
502
|
+
|
503
|
+
private
|
504
|
+
|
505
|
+
if RUBY_VERSION < '1.9.0'
|
506
|
+
# :nocov:
|
507
|
+
def new_entry_buffer
|
508
|
+
String.new
|
509
|
+
end
|
510
|
+
# :nocov:
|
511
|
+
else
|
512
|
+
def new_entry_buffer
|
513
|
+
String.new.force_encoding(string.encoding)
|
514
|
+
#String.new.force_encoding(@encoding) # SEQUEL5
|
515
|
+
end
|
516
|
+
end
|
434
517
|
end unless Sequel::Postgres.respond_to?(:parse_pg_array)
|
435
518
|
|
436
519
|
# Callable object that takes the input string and parses it using Parser.
|
@@ -483,13 +566,13 @@ module Sequel
|
|
483
566
|
def sql_literal_append(ds, sql)
|
484
567
|
at = array_type
|
485
568
|
if empty? && at
|
486
|
-
sql <<
|
569
|
+
sql << "'{}'"
|
487
570
|
else
|
488
|
-
sql << ARRAY
|
571
|
+
sql << "ARRAY"
|
489
572
|
_literal_append(sql, ds, to_a)
|
490
573
|
end
|
491
574
|
if at
|
492
|
-
sql <<
|
575
|
+
sql << '::' << at.to_s << '[]'
|
493
576
|
end
|
494
577
|
end
|
495
578
|
|
@@ -499,9 +582,9 @@ module Sequel
|
|
499
582
|
# arrays, surrounding each with [] and interspersing
|
500
583
|
# entries with ,.
|
501
584
|
def _literal_append(sql, ds, array)
|
502
|
-
sql <<
|
585
|
+
sql << '['
|
503
586
|
comma = false
|
504
|
-
commas =
|
587
|
+
commas = ','
|
505
588
|
array.each do |i|
|
506
589
|
sql << commas if comma
|
507
590
|
if i.is_a?(Array)
|
@@ -511,44 +594,38 @@ module Sequel
|
|
511
594
|
end
|
512
595
|
comma = true
|
513
596
|
end
|
514
|
-
sql <<
|
597
|
+
sql << ']'
|
515
598
|
end
|
516
599
|
|
517
|
-
#
|
518
|
-
|
519
|
-
register('
|
520
|
-
register('
|
521
|
-
register('
|
522
|
-
register('
|
523
|
-
register('
|
524
|
-
|
525
|
-
register('
|
526
|
-
register('
|
527
|
-
register('
|
528
|
-
register('time
|
529
|
-
register('timestamp
|
530
|
-
register('
|
531
|
-
register('
|
532
|
-
|
533
|
-
register('
|
534
|
-
register('
|
535
|
-
register('
|
536
|
-
register('
|
537
|
-
register('
|
538
|
-
|
539
|
-
register('
|
540
|
-
register('
|
541
|
-
register('
|
542
|
-
register('
|
543
|
-
register('
|
544
|
-
|
545
|
-
register('
|
546
|
-
register('cid', :oid=>1012, :scalar_oid=>29)
|
547
|
-
|
548
|
-
register('name', :oid=>1003, :scalar_oid=>19)
|
549
|
-
register('tid', :oid=>1010, :scalar_oid=>27)
|
550
|
-
register('int2vector', :oid=>1006, :scalar_oid=>22)
|
551
|
-
register('oidvector', :oid=>1013, :scalar_oid=>30)
|
600
|
+
# SEQUEL5: Remove
|
601
|
+
register('text', :oid=>1009, :scalar_oid=>25, :type_symbol=>:string, :skip_deprecation_warning=>true)
|
602
|
+
register('integer', :oid=>1007, :scalar_oid=>23, :skip_deprecation_warning=>true)
|
603
|
+
register('bigint', :oid=>1016, :scalar_oid=>20, :scalar_typecast=>:integer, :skip_deprecation_warning=>true)
|
604
|
+
register('numeric', :oid=>1231, :scalar_oid=>1700, :type_symbol=>:decimal, :skip_deprecation_warning=>true)
|
605
|
+
register('double precision', :oid=>1022, :scalar_oid=>701, :type_symbol=>:float, :skip_deprecation_warning=>true)
|
606
|
+
register('boolean', :oid=>1000, :scalar_oid=>16, :skip_deprecation_warning=>true)
|
607
|
+
register('bytea', :oid=>1001, :scalar_oid=>17, :type_symbol=>:blob, :skip_deprecation_warning=>true)
|
608
|
+
register('date', :oid=>1182, :scalar_oid=>1082, :skip_deprecation_warning=>true)
|
609
|
+
register('time without time zone', :oid=>1183, :scalar_oid=>1083, :type_symbol=>:time, :skip_deprecation_warning=>true)
|
610
|
+
register('timestamp without time zone', :oid=>1115, :scalar_oid=>1114, :type_symbol=>:datetime, :skip_deprecation_warning=>true)
|
611
|
+
register('time with time zone', :oid=>1270, :scalar_oid=>1083, :type_symbol=>:time_timezone, :scalar_typecast=>:time, :skip_deprecation_warning=>true)
|
612
|
+
register('timestamp with time zone', :oid=>1185, :scalar_oid=>1184, :type_symbol=>:datetime_timezone, :scalar_typecast=>:datetime, :skip_deprecation_warning=>true)
|
613
|
+
register('smallint', :oid=>1005, :scalar_oid=>21, :scalar_typecast=>:integer, :skip_deprecation_warning=>true)
|
614
|
+
register('oid', :oid=>1028, :scalar_oid=>26, :scalar_typecast=>:integer, :skip_deprecation_warning=>true)
|
615
|
+
register('real', :oid=>1021, :scalar_oid=>700, :scalar_typecast=>:float, :skip_deprecation_warning=>true)
|
616
|
+
register('character', :oid=>1014, :array_type=>:text, :scalar_typecast=>:string, :skip_deprecation_warning=>true)
|
617
|
+
register('character varying', :oid=>1015, :scalar_typecast=>:string, :type_symbol=>:varchar, :skip_deprecation_warning=>true)
|
618
|
+
register('xml', :oid=>143, :scalar_oid=>142, :skip_deprecation_warning=>true)
|
619
|
+
register('money', :oid=>791, :scalar_oid=>790, :skip_deprecation_warning=>true)
|
620
|
+
register('bit', :oid=>1561, :scalar_oid=>1560, :skip_deprecation_warning=>true)
|
621
|
+
register('bit varying', :oid=>1563, :scalar_oid=>1562, :type_symbol=>:varbit, :skip_deprecation_warning=>true)
|
622
|
+
register('uuid', :oid=>2951, :scalar_oid=>2950, :skip_deprecation_warning=>true)
|
623
|
+
register('xid', :oid=>1011, :scalar_oid=>28, :skip_deprecation_warning=>true)
|
624
|
+
register('cid', :oid=>1012, :scalar_oid=>29, :skip_deprecation_warning=>true)
|
625
|
+
register('name', :oid=>1003, :scalar_oid=>19, :skip_deprecation_warning=>true)
|
626
|
+
register('tid', :oid=>1010, :scalar_oid=>27, :skip_deprecation_warning=>true)
|
627
|
+
register('int2vector', :oid=>1006, :scalar_oid=>22, :skip_deprecation_warning=>true)
|
628
|
+
register('oidvector', :oid=>1013, :scalar_oid=>30, :skip_deprecation_warning=>true)
|
552
629
|
end
|
553
630
|
end
|
554
631
|
|