sequel 5.32.0 → 5.37.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +84 -0
- data/README.rdoc +1 -1
- data/doc/association_basics.rdoc +7 -2
- data/doc/dataset_filtering.rdoc +2 -2
- data/doc/model_plugins.rdoc +1 -1
- data/doc/release_notes/5.33.0.txt +24 -0
- data/doc/release_notes/5.34.0.txt +40 -0
- data/doc/release_notes/5.35.0.txt +56 -0
- data/doc/release_notes/5.36.0.txt +60 -0
- data/doc/release_notes/5.37.0.txt +30 -0
- data/doc/transactions.rdoc +0 -8
- data/doc/validations.rdoc +1 -1
- data/lib/sequel/adapters/odbc.rb +4 -6
- data/lib/sequel/adapters/oracle.rb +2 -1
- data/lib/sequel/adapters/shared/mssql.rb +14 -4
- data/lib/sequel/adapters/shared/oracle.rb +12 -6
- data/lib/sequel/adapters/shared/postgres.rb +39 -1
- data/lib/sequel/adapters/shared/sqlite.rb +13 -3
- data/lib/sequel/adapters/tinytds.rb +1 -0
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -0
- data/lib/sequel/connection_pool/sharded_single.rb +4 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +10 -10
- data/lib/sequel/connection_pool/single.rb +1 -1
- data/lib/sequel/connection_pool/threaded.rb +1 -1
- data/lib/sequel/core.rb +5 -6
- data/lib/sequel/database/connecting.rb +1 -1
- data/lib/sequel/database/misc.rb +16 -10
- data/lib/sequel/database/query.rb +2 -0
- data/lib/sequel/database/schema_generator.rb +0 -1
- data/lib/sequel/database/schema_methods.rb +15 -16
- data/lib/sequel/database/transactions.rb +8 -5
- data/lib/sequel/dataset/actions.rb +10 -6
- data/lib/sequel/dataset/placeholder_literalizer.rb +3 -7
- data/lib/sequel/dataset/query.rb +5 -4
- data/lib/sequel/deprecated.rb +3 -1
- data/lib/sequel/exceptions.rb +2 -0
- data/lib/sequel/extensions/_pretty_table.rb +1 -2
- data/lib/sequel/extensions/columns_introspection.rb +1 -2
- data/lib/sequel/extensions/core_refinements.rb +2 -0
- data/lib/sequel/extensions/duplicate_columns_handler.rb +2 -0
- data/lib/sequel/extensions/migration.rb +8 -2
- data/lib/sequel/extensions/pg_array_ops.rb +4 -0
- data/lib/sequel/extensions/pg_enum.rb +2 -0
- data/lib/sequel/extensions/pg_extended_date_support.rb +1 -1
- data/lib/sequel/extensions/pg_hstore_ops.rb +2 -0
- data/lib/sequel/extensions/pg_inet.rb +2 -0
- data/lib/sequel/extensions/pg_json_ops.rb +46 -2
- data/lib/sequel/extensions/pg_range.rb +3 -7
- data/lib/sequel/extensions/pg_range_ops.rb +2 -0
- data/lib/sequel/extensions/pg_row.rb +0 -1
- data/lib/sequel/extensions/pg_row_ops.rb +24 -0
- data/lib/sequel/extensions/query.rb +1 -0
- data/lib/sequel/extensions/run_transaction_hooks.rb +1 -1
- data/lib/sequel/extensions/s.rb +2 -0
- data/lib/sequel/extensions/schema_dumper.rb +3 -3
- data/lib/sequel/extensions/symbol_aref_refinement.rb +2 -0
- data/lib/sequel/extensions/symbol_as_refinement.rb +2 -0
- data/lib/sequel/extensions/to_dot.rb +9 -3
- data/lib/sequel/model.rb +3 -1
- data/lib/sequel/model/associations.rb +54 -25
- data/lib/sequel/model/base.rb +13 -5
- data/lib/sequel/model/plugins.rb +3 -3
- data/lib/sequel/plugins/association_pks.rb +60 -18
- data/lib/sequel/plugins/association_proxies.rb +1 -0
- data/lib/sequel/plugins/blacklist_security.rb +1 -2
- data/lib/sequel/plugins/class_table_inheritance.rb +3 -3
- data/lib/sequel/plugins/csv_serializer.rb +2 -0
- data/lib/sequel/plugins/dirty.rb +45 -0
- data/lib/sequel/plugins/forbid_lazy_load.rb +2 -0
- data/lib/sequel/plugins/instance_specific_default.rb +113 -0
- data/lib/sequel/plugins/lazy_attributes.rb +1 -1
- data/lib/sequel/plugins/pg_array_associations.rb +2 -3
- data/lib/sequel/plugins/prepared_statements.rb +5 -11
- data/lib/sequel/plugins/prepared_statements_safe.rb +1 -3
- data/lib/sequel/plugins/rcte_tree.rb +10 -16
- data/lib/sequel/plugins/string_stripper.rb +1 -1
- data/lib/sequel/plugins/validation_class_methods.rb +5 -1
- data/lib/sequel/version.rb +1 -1
- metadata +13 -2
@@ -103,12 +103,18 @@ module Sequel
|
|
103
103
|
map{|r| m.call(r[:view_name])}
|
104
104
|
end
|
105
105
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
106
|
+
# Whether a view with a given name exists. By default, looks in all schemas other than system
|
107
|
+
# schemas. If the :current_schema option is given, looks in the schema for the current user.
|
108
|
+
def view_exists?(name, opts=OPTS)
|
109
|
+
ds = metadata_dataset.from(:all_views).where(:view_name=>input_identifier_meth.call(name))
|
110
|
+
|
111
|
+
if opts[:current_schema]
|
112
|
+
ds = ds.where(:owner=>Sequel.function(:SYS_CONTEXT, 'userenv', 'current_schema'))
|
113
|
+
else
|
114
|
+
ds = ds.exclude(:owner=>IGNORE_OWNERS)
|
115
|
+
end
|
116
|
+
|
117
|
+
ds.count > 0
|
112
118
|
end
|
113
119
|
|
114
120
|
# The version of the Oracle server, used for determining capability.
|
@@ -950,7 +950,7 @@ module Sequel
|
|
950
950
|
# default value is given.
|
951
951
|
def column_definition_default_sql(sql, column)
|
952
952
|
super
|
953
|
-
if !column[:serial] && !['serial', 'bigserial'].include?(column[:type].to_s) && !column[:default]
|
953
|
+
if !column[:serial] && !['smallserial', 'serial', 'bigserial'].include?(column[:type].to_s) && !column[:default]
|
954
954
|
if (identity = column[:identity])
|
955
955
|
sql << " GENERATED "
|
956
956
|
sql << (identity == :always ? "ALWAYS" : "BY DEFAULT")
|
@@ -1885,6 +1885,13 @@ module Sequel
|
|
1885
1885
|
end
|
1886
1886
|
end
|
1887
1887
|
|
1888
|
+
# Use WITH TIES when limiting the result set to also include additional
|
1889
|
+
# rules that have the same results for the order column as the final row.
|
1890
|
+
# Requires PostgreSQL 13.
|
1891
|
+
def with_ties
|
1892
|
+
clone(:limit_with_ties=>true)
|
1893
|
+
end
|
1894
|
+
|
1888
1895
|
protected
|
1889
1896
|
|
1890
1897
|
# If returned primary keys are requested, use RETURNING unless already set on the
|
@@ -2071,6 +2078,37 @@ module Sequel
|
|
2071
2078
|
false
|
2072
2079
|
end
|
2073
2080
|
|
2081
|
+
# Support FETCH FIRST WITH TIES on PostgreSQL 13+.
|
2082
|
+
def select_limit_sql(sql)
|
2083
|
+
l = @opts[:limit]
|
2084
|
+
o = @opts[:offset]
|
2085
|
+
|
2086
|
+
return unless l || o
|
2087
|
+
|
2088
|
+
if @opts[:limit_with_ties]
|
2089
|
+
if o
|
2090
|
+
sql << " OFFSET "
|
2091
|
+
literal_append(sql, o)
|
2092
|
+
end
|
2093
|
+
|
2094
|
+
if l
|
2095
|
+
sql << " FETCH FIRST "
|
2096
|
+
literal_append(sql, l)
|
2097
|
+
sql << " ROWS WITH TIES"
|
2098
|
+
end
|
2099
|
+
else
|
2100
|
+
if l
|
2101
|
+
sql << " LIMIT "
|
2102
|
+
literal_append(sql, l)
|
2103
|
+
end
|
2104
|
+
|
2105
|
+
if o
|
2106
|
+
sql << " OFFSET "
|
2107
|
+
literal_append(sql, o)
|
2108
|
+
end
|
2109
|
+
end
|
2110
|
+
end
|
2111
|
+
|
2074
2112
|
# Support FOR SHARE locking when using the :share lock style.
|
2075
2113
|
# Use SKIP LOCKED if skipping locked rows.
|
2076
2114
|
def select_lock_sql(sql)
|
@@ -38,6 +38,10 @@ module Sequel
|
|
38
38
|
# booleans be stored as integers, but historically Sequel has used 't'/'f'.
|
39
39
|
attr_accessor :integer_booleans
|
40
40
|
|
41
|
+
# Whether to keep CURRENT_TIMESTAMP and similar expressions in UTC. By
|
42
|
+
# default, the expressions are converted to localtime.
|
43
|
+
attr_accessor :current_timestamp_utc
|
44
|
+
|
41
45
|
# A symbol signifying the value of the default transaction mode
|
42
46
|
attr_reader :transaction_mode
|
43
47
|
|
@@ -265,6 +269,8 @@ module Sequel
|
|
265
269
|
else
|
266
270
|
duplicate_table(table, :no_foreign_keys=>true)
|
267
271
|
end
|
272
|
+
when :unique
|
273
|
+
duplicate_table(table, :no_unique=>true)
|
268
274
|
else
|
269
275
|
duplicate_table(table)
|
270
276
|
end
|
@@ -418,8 +424,12 @@ module Sequel
|
|
418
424
|
skip_indexes = []
|
419
425
|
indexes(table, :only_autocreated=>true).each do |name, h|
|
420
426
|
skip_indexes << name
|
421
|
-
if h[:
|
422
|
-
|
427
|
+
if h[:unique]
|
428
|
+
if h[:columns].length == 1
|
429
|
+
unique_columns.concat(h[:columns])
|
430
|
+
elsif h[:columns].map(&:to_s) != pks && !opts[:no_unique]
|
431
|
+
constraints << {:type=>:unique, :columns=>h[:columns]}
|
432
|
+
end
|
423
433
|
end
|
424
434
|
end
|
425
435
|
unique_columns -= pks
|
@@ -615,7 +625,7 @@ module Sequel
|
|
615
625
|
# SQLite has CURRENT_TIMESTAMP and related constants in UTC instead
|
616
626
|
# of in localtime, so convert those constants to local time.
|
617
627
|
def constant_sql_append(sql, constant)
|
618
|
-
if c = CONSTANT_MAP[constant]
|
628
|
+
if (c = CONSTANT_MAP[constant]) && !db.current_timestamp_utc
|
619
629
|
sql << c
|
620
630
|
else
|
621
631
|
super
|
@@ -18,6 +18,7 @@ module Sequel
|
|
18
18
|
This connection is still waiting for a result, try again once you have the result
|
19
19
|
closed MySQL connection
|
20
20
|
The MySQL server is running with the --read-only option so it cannot execute this statement
|
21
|
+
Connection was killed
|
21
22
|
END
|
22
23
|
# Error messages for mysql and mysql2 that indicate the current connection should be disconnected
|
23
24
|
MYSQL_DATABASE_DISCONNECT_ERRORS = /\A#{Regexp.union(disconnect_errors)}/
|
@@ -41,7 +41,10 @@ class Sequel::ShardedSingleConnectionPool < Sequel::ConnectionPool
|
|
41
41
|
# :server :: Should be a symbol specifing the server to disconnect from,
|
42
42
|
# or an array of symbols to specify multiple servers.
|
43
43
|
def disconnect(opts=OPTS)
|
44
|
-
(opts[:server] ? Array(opts[:server]) : servers).each
|
44
|
+
(opts[:server] ? Array(opts[:server]) : servers).each do |s|
|
45
|
+
raise Sequel::Error, "invalid server: #{s}" unless @servers.has_key?(s)
|
46
|
+
disconnect_server(s)
|
47
|
+
end
|
45
48
|
end
|
46
49
|
|
47
50
|
def freeze
|
@@ -95,9 +95,7 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
|
|
95
95
|
# or an array of symbols to specify multiple servers.
|
96
96
|
def disconnect(opts=OPTS)
|
97
97
|
(opts[:server] ? Array(opts[:server]) : sync{@servers.keys}).each do |s|
|
98
|
-
|
99
|
-
disconnect_connections(conns)
|
100
|
-
end
|
98
|
+
disconnect_connections(sync{disconnect_server_connections(s)})
|
101
99
|
end
|
102
100
|
end
|
103
101
|
|
@@ -203,9 +201,9 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
|
|
203
201
|
|
204
202
|
until conn = assign_connection(thread, server)
|
205
203
|
elapsed = Sequel.elapsed_seconds_since(timer)
|
204
|
+
# :nocov:
|
206
205
|
raise_pool_timeout(elapsed, server) if elapsed > timeout
|
207
206
|
|
208
|
-
# :nocov:
|
209
207
|
# It's difficult to get to this point, it can only happen if there is a race condition
|
210
208
|
# where a connection cannot be acquired even after the thread is signalled by the condition variable
|
211
209
|
sync do
|
@@ -278,13 +276,15 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
|
|
278
276
|
# Mark any allocated connections to be removed when they are checked back in. The calling
|
279
277
|
# code should already have the mutex before calling this.
|
280
278
|
def disconnect_server_connections(server)
|
281
|
-
|
279
|
+
remove_conns = allocated(server)
|
280
|
+
dis_conns = available_connections(server)
|
281
|
+
raise Sequel::Error, "invalid server: #{server}" unless remove_conns && dis_conns
|
282
282
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
283
|
+
@connections_to_remove.concat(remove_conns.values)
|
284
|
+
|
285
|
+
conns = dis_conns.dup
|
286
|
+
dis_conns.clear
|
287
|
+
@waiters[server].signal
|
288
288
|
conns
|
289
289
|
end
|
290
290
|
|
@@ -11,7 +11,7 @@ class Sequel::SingleConnectionPool < Sequel::ConnectionPool
|
|
11
11
|
|
12
12
|
# Yield the connection if one has been made.
|
13
13
|
def all_connections
|
14
|
-
yield @conn.first
|
14
|
+
yield @conn.first unless @conn.empty?
|
15
15
|
end
|
16
16
|
|
17
17
|
# Disconnect the connection from the database.
|
@@ -152,9 +152,9 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
|
|
152
152
|
|
153
153
|
until conn = assign_connection(thread)
|
154
154
|
elapsed = Sequel.elapsed_seconds_since(timer)
|
155
|
+
# :nocov:
|
155
156
|
raise_pool_timeout(elapsed) if elapsed > timeout
|
156
157
|
|
157
|
-
# :nocov:
|
158
158
|
# It's difficult to get to this point, it can only happen if there is a race condition
|
159
159
|
# where a connection cannot be acquired even after the thread is signalled by the condition variable
|
160
160
|
sync do
|
data/lib/sequel/core.rb
CHANGED
@@ -52,13 +52,12 @@ module Sequel
|
|
52
52
|
#
|
53
53
|
# Sequel.datetime_class = DateTime
|
54
54
|
#
|
55
|
-
# Note that +Time+ and +DateTime+ objects
|
56
|
-
#
|
57
|
-
#
|
58
|
-
# days on +DateTime+).
|
55
|
+
# Note that +Time+ and +DateTime+ objects have a different API, and in
|
56
|
+
# cases where they implement the same methods, they often implement them
|
57
|
+
# differently (e.g. + using seconds on +Time+ and days on +DateTime+).
|
59
58
|
attr_accessor :datetime_class
|
60
59
|
|
61
|
-
# Set whether Sequel is being used in single threaded mode.
|
60
|
+
# Set whether Sequel is being used in single threaded mode. By default,
|
62
61
|
# Sequel uses a thread-safe connection pool, which isn't as fast as the
|
63
62
|
# single threaded connection pool, and also has some additional thread
|
64
63
|
# safety checks. If your program will only have one thread,
|
@@ -67,7 +66,7 @@ module Sequel
|
|
67
66
|
# Sequel.single_threaded = true
|
68
67
|
attr_accessor :single_threaded
|
69
68
|
|
70
|
-
# Alias of original require method, as Sequel.require
|
69
|
+
# Alias of original require method, as Sequel.require does a relative
|
71
70
|
# require for backwards compatibility.
|
72
71
|
alias orig_require require
|
73
72
|
private :orig_require
|
@@ -36,7 +36,7 @@ module Sequel
|
|
36
36
|
c = adapter_class(scheme)
|
37
37
|
uri_options = c.send(:uri_to_options, uri)
|
38
38
|
uri.query.split('&').map{|s| s.split('=')}.each{|k,v| uri_options[k.to_sym] = v if k && !k.empty?} unless uri.query.to_s.strip.empty?
|
39
|
-
uri_options.to_a.each{|k,v| uri_options[k] =
|
39
|
+
uri_options.to_a.each{|k,v| uri_options[k] = URI::DEFAULT_PARSER.unescape(v) if v.is_a?(String)}
|
40
40
|
opts = uri_options.merge(opts).merge!(:orig_opts=>opts.dup, :uri=>conn_string, :adapter=>scheme)
|
41
41
|
end
|
42
42
|
when Hash
|
data/lib/sequel/database/misc.rb
CHANGED
@@ -153,19 +153,23 @@ module Sequel
|
|
153
153
|
reset_default_dataset
|
154
154
|
adapter_initialize
|
155
155
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
156
|
+
keep_reference = typecast_value_boolean(@opts[:keep_reference]) != false
|
157
|
+
begin
|
158
|
+
Sequel.synchronize{::Sequel::DATABASES.push(self)} if keep_reference
|
159
|
+
Sequel::Database.run_after_initialize(self)
|
160
160
|
|
161
|
-
|
161
|
+
initialize_load_extensions(:preconnect_extensions)
|
162
162
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
163
|
+
if typecast_value_boolean(@opts[:preconnect]) && @pool.respond_to?(:preconnect, true)
|
164
|
+
concurrent = typecast_value_string(@opts[:preconnect]) == "concurrently"
|
165
|
+
@pool.send(:preconnect, concurrent)
|
166
|
+
end
|
167
167
|
|
168
|
-
|
168
|
+
initialize_load_extensions(:extensions)
|
169
|
+
rescue
|
170
|
+
Sequel.synchronize{::Sequel::DATABASES.delete(self)} if keep_reference
|
171
|
+
raise
|
172
|
+
end
|
169
173
|
end
|
170
174
|
|
171
175
|
# Freeze internal data structures for the Database instance.
|
@@ -185,7 +189,9 @@ module Sequel
|
|
185
189
|
|
186
190
|
# Disallow dup/clone for Database instances
|
187
191
|
undef_method :dup, :clone, :initialize_copy
|
192
|
+
# :nocov:
|
188
193
|
if RUBY_VERSION >= '1.9.3'
|
194
|
+
# :nocov:
|
189
195
|
undef_method :initialize_clone, :initialize_dup
|
190
196
|
end
|
191
197
|
|
@@ -38,7 +38,6 @@ module Sequel
|
|
38
38
|
@constraints = []
|
39
39
|
@primary_key = nil
|
40
40
|
instance_exec(&block) if block
|
41
|
-
@columns.unshift(@primary_key) if @primary_key && !has_column?(primary_key_name)
|
42
41
|
end
|
43
42
|
|
44
43
|
# Use custom Bignum method to use :Bignum instead of Bignum class, to work
|
@@ -494,7 +494,9 @@ module Sequel
|
|
494
494
|
when :drop_index
|
495
495
|
drop_index_sql(table, op)
|
496
496
|
else
|
497
|
-
|
497
|
+
if sql = alter_table_op_sql(table, op)
|
498
|
+
"ALTER TABLE #{quote_schema_table(table)} #{sql}"
|
499
|
+
end
|
498
500
|
end
|
499
501
|
end
|
500
502
|
|
@@ -811,23 +813,20 @@ module Sequel
|
|
811
813
|
# Proxy the filter_expr call to the dataset, used for creating constraints.
|
812
814
|
# Support passing Proc arguments as blocks, as well as treating plain strings
|
813
815
|
# as literal strings, so that previous migrations that used this API do not break.
|
814
|
-
def filter_expr(
|
815
|
-
if
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
elsif arg.length > 1
|
826
|
-
args = [Sequel.&(*arg)]
|
827
|
-
end
|
816
|
+
def filter_expr(arg=nil, &block)
|
817
|
+
if arg.is_a?(Proc) && !block
|
818
|
+
block = arg
|
819
|
+
arg = nil
|
820
|
+
elsif arg.is_a?(String)
|
821
|
+
arg = Sequel.lit(arg)
|
822
|
+
elsif arg.is_a?(Array)
|
823
|
+
if arg.first.is_a?(String)
|
824
|
+
arg = Sequel.lit(*arg)
|
825
|
+
elsif arg.length > 1
|
826
|
+
arg = Sequel.&(*arg)
|
828
827
|
end
|
829
828
|
end
|
830
|
-
schema_utility_dataset.literal(schema_utility_dataset.send(:filter_expr,
|
829
|
+
schema_utility_dataset.literal(schema_utility_dataset.send(:filter_expr, arg, &block))
|
831
830
|
end
|
832
831
|
|
833
832
|
# SQL statement for creating an index for the table with the given name
|
@@ -154,7 +154,7 @@ module Sequel
|
|
154
154
|
# Note that this should not be used unless the entire transaction
|
155
155
|
# block is idempotent, as otherwise it can cause non-idempotent
|
156
156
|
# behavior to execute multiple times.
|
157
|
-
# :rollback :: Can
|
157
|
+
# :rollback :: Can be set to :reraise to reraise any Sequel::Rollback exceptions
|
158
158
|
# raised, or :always to always rollback even if no exceptions occur
|
159
159
|
# (useful for testing).
|
160
160
|
# :server :: The server to use for the transaction. Set to :default, :read_only, or
|
@@ -205,6 +205,10 @@ module Sequel
|
|
205
205
|
end
|
206
206
|
end
|
207
207
|
|
208
|
+
if opts[:savepoint] && !supports_savepoints?
|
209
|
+
raise Sequel::InvalidOperation, "savepoints not supported on #{database_type}"
|
210
|
+
end
|
211
|
+
|
208
212
|
if already_in_transaction?(conn, opts)
|
209
213
|
if opts[:rollback] == :always && !opts.has_key?(:savepoint)
|
210
214
|
if supports_savepoints?
|
@@ -418,11 +422,10 @@ module Sequel
|
|
418
422
|
end
|
419
423
|
|
420
424
|
# Retrieve the savepoint hooks that should be run for the given
|
421
|
-
# connection and commit status.
|
425
|
+
# connection and commit status. This expacts that you are
|
426
|
+
# already inside a savepoint when calling.
|
422
427
|
def savepoint_hooks(conn, committed)
|
423
|
-
|
424
|
-
_trans(conn)[:savepoints].last[committed ? :after_commit : :after_rollback]
|
425
|
-
end
|
428
|
+
_trans(conn)[:savepoints].last[committed ? :after_commit : :after_rollback]
|
426
429
|
end
|
427
430
|
|
428
431
|
# Retrieve the transaction hooks that should be run for the given
|
@@ -607,14 +607,16 @@ module Sequel
|
|
607
607
|
# as_hash, it accepts an optional :hash parameter, into which entries will
|
608
608
|
# be merged.
|
609
609
|
#
|
610
|
-
# DB[:table].select_hash(:id, :name)
|
610
|
+
# DB[:table].select_hash(:id, :name)
|
611
|
+
# # SELECT id, name FROM table
|
611
612
|
# # => {1=>'a', 2=>'b', ...}
|
612
613
|
#
|
613
614
|
# You can also provide an array of column names for either the key_column,
|
614
615
|
# the value column, or both:
|
615
616
|
#
|
616
|
-
# DB[:table].select_hash([:id, :foo], [:name, :bar])
|
617
|
-
# #
|
617
|
+
# DB[:table].select_hash([:id, :foo], [:name, :bar])
|
618
|
+
# # SELECT id, foo, name, bar FROM table
|
619
|
+
# # => {[1, 3]=>['a', 'c'], [2, 4]=>['b', 'd'], ...}
|
618
620
|
#
|
619
621
|
# When using this method, you must be sure that each expression has an alias
|
620
622
|
# that Sequel can determine.
|
@@ -626,14 +628,16 @@ module Sequel
|
|
626
628
|
# Similar to to_hash_groups, but only selects the columns given. Like to_hash_groups,
|
627
629
|
# it accepts an optional :hash parameter, into which entries will be merged.
|
628
630
|
#
|
629
|
-
# DB[:table].select_hash_groups(:name, :id)
|
631
|
+
# DB[:table].select_hash_groups(:name, :id)
|
632
|
+
# # SELECT id, name FROM table
|
630
633
|
# # => {'a'=>[1, 4, ...], 'b'=>[2, ...], ...}
|
631
634
|
#
|
632
635
|
# You can also provide an array of column names for either the key_column,
|
633
636
|
# the value column, or both:
|
634
637
|
#
|
635
|
-
# DB[:table].select_hash_groups([:first, :middle], [:last, :id])
|
636
|
-
# #
|
638
|
+
# DB[:table].select_hash_groups([:first, :middle], [:last, :id])
|
639
|
+
# # SELECT first, middle, last, id FROM table
|
640
|
+
# # => {['a', 'b']=>[['c', 1], ['d', 2], ...], ...}
|
637
641
|
#
|
638
642
|
# When using this method, you must be sure that each expression has an alias
|
639
643
|
# that Sequel can determine.
|