sequel 5.8.0 → 5.9.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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +30 -0
  3. data/doc/release_notes/5.9.0.txt +99 -0
  4. data/doc/testing.rdoc +10 -10
  5. data/lib/sequel/adapters/ado.rb +1 -1
  6. data/lib/sequel/adapters/amalgalite.rb +1 -1
  7. data/lib/sequel/adapters/jdbc.rb +19 -7
  8. data/lib/sequel/adapters/jdbc/oracle.rb +1 -1
  9. data/lib/sequel/adapters/jdbc/postgresql.rb +0 -5
  10. data/lib/sequel/adapters/postgres.rb +3 -3
  11. data/lib/sequel/adapters/shared/access.rb +5 -6
  12. data/lib/sequel/adapters/shared/mysql.rb +28 -2
  13. data/lib/sequel/adapters/shared/postgres.rb +16 -6
  14. data/lib/sequel/adapters/shared/sqlite.rb +1 -1
  15. data/lib/sequel/adapters/sqlanywhere.rb +1 -1
  16. data/lib/sequel/adapters/sqlite.rb +2 -2
  17. data/lib/sequel/connection_pool.rb +2 -1
  18. data/lib/sequel/connection_pool/sharded_threaded.rb +12 -4
  19. data/lib/sequel/connection_pool/threaded.rb +19 -7
  20. data/lib/sequel/core.rb +1 -1
  21. data/lib/sequel/database/connecting.rb +6 -6
  22. data/lib/sequel/database/misc.rb +3 -3
  23. data/lib/sequel/database/query.rb +2 -2
  24. data/lib/sequel/database/schema_generator.rb +9 -3
  25. data/lib/sequel/database/schema_methods.rb +12 -5
  26. data/lib/sequel/dataset/features.rb +5 -0
  27. data/lib/sequel/dataset/misc.rb +1 -1
  28. data/lib/sequel/dataset/prepared_statements.rb +4 -4
  29. data/lib/sequel/dataset/query.rb +5 -0
  30. data/lib/sequel/dataset/sql.rb +8 -6
  31. data/lib/sequel/extensions/escaped_like.rb +100 -0
  32. data/lib/sequel/extensions/eval_inspect.rb +3 -1
  33. data/lib/sequel/extensions/looser_typecasting.rb +3 -3
  34. data/lib/sequel/extensions/pg_extended_date_support.rb +23 -10
  35. data/lib/sequel/model/associations.rb +18 -4
  36. data/lib/sequel/model/base.rb +9 -2
  37. data/lib/sequel/plugins/defaults_setter.rb +1 -1
  38. data/lib/sequel/plugins/many_through_many.rb +1 -1
  39. data/lib/sequel/plugins/nested_attributes.rb +2 -2
  40. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +2 -2
  41. data/lib/sequel/plugins/rcte_tree.rb +5 -7
  42. data/lib/sequel/plugins/sharding.rb +2 -2
  43. data/lib/sequel/plugins/tactical_eager_loading.rb +1 -1
  44. data/lib/sequel/plugins/tree.rb +2 -2
  45. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  46. data/lib/sequel/sql.rb +2 -2
  47. data/lib/sequel/version.rb +4 -1
  48. data/spec/adapters/mysql_spec.rb +24 -0
  49. data/spec/adapters/postgres_spec.rb +9 -9
  50. data/spec/adapters/sqlite_spec.rb +10 -10
  51. data/spec/core/connection_pool_spec.rb +22 -0
  52. data/spec/core/database_spec.rb +6 -6
  53. data/spec/core/dataset_spec.rb +16 -5
  54. data/spec/core/expression_filters_spec.rb +1 -1
  55. data/spec/core/schema_spec.rb +1 -1
  56. data/spec/core/version_spec.rb +7 -0
  57. data/spec/extensions/connection_expiration_spec.rb +20 -2
  58. data/spec/extensions/connection_validator_spec.rb +20 -3
  59. data/spec/extensions/escaped_like_spec.rb +40 -0
  60. data/spec/extensions/eval_inspect_spec.rb +1 -1
  61. data/spec/extensions/nested_attributes_spec.rb +6 -0
  62. data/spec/extensions/pg_array_spec.rb +13 -13
  63. data/spec/extensions/pg_auto_constraint_validations_spec.rb +0 -1
  64. data/spec/extensions/pg_range_spec.rb +1 -1
  65. data/spec/extensions/schema_dumper_spec.rb +2 -2
  66. data/spec/extensions/sql_expr_spec.rb +1 -1
  67. data/spec/extensions/string_agg_spec.rb +1 -1
  68. data/spec/extensions/timestamps_spec.rb +2 -2
  69. data/spec/extensions/validation_helpers_spec.rb +1 -1
  70. data/spec/integration/associations_test.rb +12 -0
  71. data/spec/integration/dataset_test.rb +21 -0
  72. data/spec/integration/type_test.rb +4 -4
  73. data/spec/model/base_spec.rb +9 -0
  74. data/spec/model/eager_loading_spec.rb +25 -0
  75. data/spec/model/record_spec.rb +1 -1
  76. metadata +6 -2
@@ -60,7 +60,7 @@ module Sequel
60
60
  [17] => tt.method(:bytea),
61
61
  [20, 21, 23, 26] => tt.method(:integer),
62
62
  [700, 701] => tt.method(:float),
63
- [1700] => ::BigDecimal.method(:new),
63
+ [1700] => ::Kernel.method(:BigDecimal),
64
64
  [1083, 1266] => ::Sequel.method(:string_to_time),
65
65
  [1082] => ::Sequel.method(:string_to_date),
66
66
  [1184, 1114] => ::Sequel.method(:database_to_application_timestamp),
@@ -261,7 +261,7 @@ module Sequel
261
261
  raise Error, "convert_serial_to_identity is only supported on PostgreSQL 10.2+" unless server_version >= 100002
262
262
 
263
263
  server = opts[:server]
264
- server_hash = server ? {:server=>server} : {}
264
+ server_hash = server ? {:server=>server} : OPTS
265
265
  ds = dataset
266
266
  ds = ds.server(server) if server
267
267
 
@@ -269,7 +269,7 @@ module Sequel
269
269
 
270
270
  table_oid = regclass_oid(table)
271
271
  im = input_identifier_meth
272
- unless column = im.call(opts[:column] || ((sch = schema(table).find{|col, sch| sch[:primary_key] && sch[:auto_increment]}) && sch[0]))
272
+ unless column = im.call(opts[:column] || ((sch = schema(table).find{|_, sc| sc[:primary_key] && sc[:auto_increment]}) && sch[0]))
273
273
  raise Error, "could not determine column to convert from serial to identity automatically"
274
274
  end
275
275
 
@@ -482,6 +482,10 @@ module Sequel
482
482
  nsp[:nspname].as(:schema)
483
483
  ]}
484
484
 
485
+ if reverse
486
+ ds = ds.order_append(Sequel[:nsp][:nspname], Sequel[:cl2][:relname])
487
+ end
488
+
485
489
  h = {}
486
490
  fklod_map = FOREIGN_KEY_LIST_ON_DELETE_MAP
487
491
 
@@ -1689,8 +1693,8 @@ module Sequel
1689
1693
  end
1690
1694
 
1691
1695
  # Return a clone of the dataset with an addition named window that can be
1692
- # referenced in window functions. See {SQL::Window} for a list of options
1693
- # that can be passed in.
1696
+ # referenced in window functions. See Sequel::SQL::Window for a list of
1697
+ # options that can be passed in.
1694
1698
  def window(name, opts)
1695
1699
  clone(:window=>(@opts[:window]||[]) + [[name, SQL::Window.new(opts)]])
1696
1700
  end
@@ -1718,7 +1722,7 @@ module Sequel
1718
1722
 
1719
1723
  # Format TRUNCATE statement with PostgreSQL specific options.
1720
1724
  def _truncate_sql(table)
1721
- to = @opts[:truncate_opts] || {}
1725
+ to = @opts[:truncate_opts] || OPTS
1722
1726
  "TRUNCATE TABLE#{' ONLY' if to[:only]} #{table}#{' RESTART IDENTITY' if to[:restart]}#{' CASCADE' if to[:cascade]}"
1723
1727
  end
1724
1728
 
@@ -1855,6 +1859,12 @@ module Sequel
1855
1859
  sql << ')'
1856
1860
  end
1857
1861
 
1862
+ # Backslash is supported by default as the escape character on PostgreSQL,
1863
+ # and using ESCAPE can break LIKE ANY() usage.
1864
+ def requires_like_escape?
1865
+ false
1866
+ end
1867
+
1858
1868
  # Support FOR SHARE locking when using the :share lock style.
1859
1869
  # Use SKIP LOCKED if skipping locked rows.
1860
1870
  def select_lock_sql(sql)
@@ -328,7 +328,7 @@ module Sequel
328
328
 
329
329
  # The array of column schema hashes for the current columns in the table
330
330
  def defined_columns_for(table)
331
- cols = parse_pragma(table, {})
331
+ cols = parse_pragma(table, OPTS)
332
332
  cols.each do |c|
333
333
  c[:default] = LiteralString.new(c[:default]) if c[:default]
334
334
  c[:type] = c[:db_type]
@@ -21,7 +21,7 @@ module Sequel
21
21
  def blob(s) ::Sequel::SQL::Blob.new(s) end
22
22
  def boolean(s) s.to_i != 0 end
23
23
  def date(s) ::Date.strptime(s) end
24
- def decimal(s) ::BigDecimal.new(s) end
24
+ def decimal(s) BigDecimal(s) end
25
25
  def time(s) ::Sequel.string_to_time(s) end
26
26
  end.new
27
27
 
@@ -40,7 +40,7 @@ module Sequel
40
40
 
41
41
  def numeric(s)
42
42
  s = s.to_s unless s.is_a?(String)
43
- ::BigDecimal.new(s) rescue s
43
+ BigDecimal(s) rescue s
44
44
  end
45
45
 
46
46
  def time(s)
@@ -181,7 +181,7 @@ module Sequel
181
181
  return execute_prepared_statement(conn, type, sql, opts, &block) if sql.is_a?(Symbol)
182
182
  log_args = opts[:arguments]
183
183
  args = {}
184
- opts.fetch(:arguments, {}).each{|k, v| args[k] = prepared_statement_argument(v)}
184
+ opts.fetch(:arguments, OPTS).each{|k, v| args[k] = prepared_statement_argument(v)}
185
185
  case type
186
186
  when :select
187
187
  log_connection_yield(sql, conn, log_args){conn.query(sql, args, &block)}
@@ -109,7 +109,8 @@ class Sequel::ConnectionPool
109
109
 
110
110
  private
111
111
 
112
- # Remove the connection from the pool.
112
+ # Remove the connection from the pool. For threaded connections, this should be
113
+ # called without the mutex, because the disconnection may block.
113
114
  def disconnect_connection(conn)
114
115
  db.disconnect_connection(conn)
115
116
  end
@@ -19,6 +19,7 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
19
19
  super
20
20
  @available_connections = {}
21
21
  @connections_to_remove = []
22
+ @connections_to_disconnect = []
22
23
  @servers = opts.fetch(:servers_hash, Hash.new(:default))
23
24
  remove_instance_variable(:@waiter)
24
25
  @waiters = {}
@@ -130,6 +131,9 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
130
131
  raise
131
132
  ensure
132
133
  sync{release(t, conn, server)} if conn
134
+ while dconn = sync{@connections_to_disconnect.shift}
135
+ disconnect_connection(dconn)
136
+ end
133
137
  end
134
138
  end
135
139
 
@@ -201,7 +205,7 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
201
205
 
202
206
  # :nocov:
203
207
  # It's difficult to get to this point, it can only happen if there is a race condition
204
- # where a connection cannot be acquired even after the thread is signalled by the condition
208
+ # where a connection cannot be acquired even after the thread is signalled by the condition variable
205
209
  sync do
206
210
  @waiters[server].wait(@mutex, timeout - elapsed)
207
211
  if conn = next_available(server)
@@ -227,7 +231,11 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
227
231
  end
228
232
 
229
233
  if (n = _size(server)) >= (max = @max_size)
230
- alloc.to_a.each{|t,c| release(t, c, server) unless t.alive?}
234
+ alloc.to_a.each do |t,c|
235
+ unless t.alive?
236
+ remove(t, c, server)
237
+ end
238
+ end
231
239
  n = nil
232
240
  end
233
241
 
@@ -339,7 +347,7 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
339
347
  conn = allocated(server).delete(thread)
340
348
 
341
349
  if @connection_handling == :disconnect
342
- disconnect_connection(conn)
350
+ @connections_to_disconnect << conn
343
351
  else
344
352
  checkin_connection(server, conn)
345
353
  end
@@ -355,6 +363,6 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
355
363
  def remove(thread, conn, server)
356
364
  @connections_to_remove.delete(conn)
357
365
  allocated(server).delete(thread) if @servers.include?(server)
358
- disconnect_connection(conn)
366
+ @connections_to_disconnect << conn
359
367
  end
360
368
  end
@@ -101,7 +101,12 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
101
101
  end
102
102
  raise
103
103
  ensure
104
- sync{release(t)} if conn
104
+ if conn
105
+ sync{release(t)}
106
+ if @connection_handling == :disconnect
107
+ disconnect_connection(conn)
108
+ end
109
+ end
105
110
  end
106
111
  end
107
112
 
@@ -150,7 +155,7 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
150
155
 
151
156
  # :nocov:
152
157
  # It's difficult to get to this point, it can only happen if there is a race condition
153
- # where a connection cannot be acquired even after the thread is signalled by the condition
158
+ # where a connection cannot be acquired even after the thread is signalled by the condition variable
154
159
  sync do
155
160
  @waiter.wait(@mutex, timeout - elapsed)
156
161
  if conn = next_available
@@ -167,15 +172,20 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
167
172
  # The caller should NOT have the mutex before calling this.
168
173
  def assign_connection(thread)
169
174
  allocated = @allocated
170
-
171
175
  do_make_new = false
176
+ to_disconnect = nil
177
+
172
178
  sync do
173
179
  if conn = next_available
174
180
  return(allocated[thread] = conn)
175
181
  end
176
182
 
177
183
  if (n = _size) >= (max = @max_size)
178
- allocated.keys.each{|t| release(t) unless t.alive?}
184
+ allocated.keys.each do |t|
185
+ unless t.alive?
186
+ (to_disconnect ||= []) << @allocated.delete(t)
187
+ end
188
+ end
179
189
  n = nil
180
190
  end
181
191
 
@@ -184,6 +194,10 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
184
194
  end
185
195
  end
186
196
 
197
+ if to_disconnect
198
+ to_disconnect.each{|dconn| disconnect_connection(dconn)}
199
+ end
200
+
187
201
  # Connect to the database outside of the connection pool mutex,
188
202
  # as that can take a long time and the connection pool mutex
189
203
  # shouldn't be locked while the connection takes place.
@@ -252,9 +266,7 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
252
266
  def release(thread)
253
267
  conn = @allocated.delete(thread)
254
268
 
255
- if @connection_handling == :disconnect
256
- disconnect_connection(conn)
257
- else
269
+ unless @connection_handling == :disconnect
258
270
  checkin_connection(conn)
259
271
  end
260
272
 
@@ -384,7 +384,7 @@ module Sequel
384
384
  # Helper method that the database adapter class methods that are added to Sequel via
385
385
  # metaprogramming use to parse arguments.
386
386
  def self.adapter_method(adapter, *args, &block)
387
- options = args.last.is_a?(Hash) ? args.pop : {}
387
+ options = args.last.is_a?(Hash) ? args.pop : OPTS
388
388
  opts = {:adapter => adapter.to_sym}
389
389
  opts[:database] = args.shift if args.first.is_a?(String)
390
390
  if args.any?
@@ -248,6 +248,12 @@ module Sequel
248
248
  end
249
249
 
250
250
  if RUBY_ENGINE == 'ruby' && RUBY_VERSION < '2.5'
251
+ # :nocov:
252
+ def synchronize(server=nil)
253
+ @pool.hold(server || :default){|conn| yield conn}
254
+ end
255
+ # :nocov:
256
+ else
251
257
  # Acquires a database connection, yielding it to the passed block. This is
252
258
  # useful if you want to make sure the same connection is used for all
253
259
  # database queries in the block. It is also useful if you want to gain
@@ -260,15 +266,9 @@ module Sequel
260
266
  # DB.synchronize do |conn|
261
267
  # # ...
262
268
  # end
263
- def synchronize(server=nil)
264
- @pool.hold(server || :default){|conn| yield conn}
265
- end
266
- else
267
- # :nocov:
268
269
  def synchronize(server=nil, &block)
269
270
  @pool.hold(server || :default, &block)
270
271
  end
271
- # :nocov:
272
272
  end
273
273
 
274
274
  # Attempts to acquire a database connection. Returns true if successful.
@@ -461,12 +461,12 @@ module Sequel
461
461
  if RUBY_VERSION >= '2.4'
462
462
  # Typecast a string to a BigDecimal
463
463
  def _typecast_value_string_to_decimal(value)
464
- BigDecimal.new(value)
464
+ BigDecimal(value)
465
465
  end
466
466
  else
467
467
  # :nocov:
468
468
  def _typecast_value_string_to_decimal(value)
469
- d = BigDecimal.new(value)
469
+ d = BigDecimal(value)
470
470
  if d.zero?
471
471
  # BigDecimal parsing is loose by default, returning a 0 value for
472
472
  # invalid input. If a zero value is received, use Float to check
@@ -488,7 +488,7 @@ module Sequel
488
488
  when BigDecimal
489
489
  value
490
490
  when Numeric
491
- BigDecimal.new(value.to_s)
491
+ BigDecimal(value.to_s)
492
492
  when String
493
493
  _typecast_value_string_to_decimal(value)
494
494
  else
@@ -32,7 +32,7 @@ module Sequel
32
32
  #
33
33
  # DB[:items].where(id: 1).prepare(:first, :sa)
34
34
  # DB.call(:sa) # SELECT * FROM items WHERE id = 1
35
- def call(ps_name, hash={}, &block)
35
+ def call(ps_name, hash=OPTS, &block)
36
36
  prepared_statement(ps_name).call(hash, &block)
37
37
  end
38
38
 
@@ -240,7 +240,7 @@ module Sequel
240
240
  when :time
241
241
  Sequel.string_to_time(default)
242
242
  when :decimal
243
- BigDecimal.new(default)
243
+ BigDecimal(default)
244
244
  end
245
245
  end
246
246
 
@@ -67,7 +67,7 @@ module Sequel
67
67
  method = type.to_s
68
68
  end
69
69
 
70
- define_method(method){|name, opts={}| column(name, type, opts)}
70
+ define_method(method){|name, opts=OPTS| column(name, type, opts)}
71
71
  end
72
72
  nil
73
73
  end
@@ -130,10 +130,16 @@ module Sequel
130
130
  # :unique :: Mark the column as unique, generally has the same effect as
131
131
  # creating a unique index on the column.
132
132
  # :unique_constraint_name :: The name to give the unique key constraint
133
+ #
134
+ # MySQL specific options:
135
+ # :generated_always_as :: Specify a GENERATED ALWAYS AS column expression,
136
+ # if generated columns are supported.
137
+ # :generated_type :: Set the type of column when using :generated_always_as,
138
+ # should be :virtual or :stored to force a type.
133
139
  def column(name, type, opts = OPTS)
134
140
  columns << {:name => name, :type => type}.merge!(opts)
135
141
  if index_opts = opts[:index]
136
- index(name, index_opts.is_a?(Hash) ? index_opts : {})
142
+ index(name, index_opts.is_a?(Hash) ? index_opts : OPTS)
137
143
  end
138
144
  nil
139
145
  end
@@ -311,7 +317,7 @@ module Sequel
311
317
 
312
318
  # Add a composite primary key constraint
313
319
  def composite_primary_key(columns, *args)
314
- opts = args.pop || {}
320
+ opts = args.pop || OPTS
315
321
  constraints << {:type => :primary_key, :columns => columns}.merge!(opts)
316
322
  nil
317
323
  end
@@ -80,7 +80,7 @@ module Sequel
80
80
  # Create a join table using a hash of foreign keys to referenced
81
81
  # table names. Example:
82
82
  #
83
- # create_join_table:cat_id: :cats, dog_id: :dogs)
83
+ # create_join_table(cat_id: :cats, dog_id: :dogs)
84
84
  # # CREATE TABLE cats_dogs (
85
85
  # # cat_id integer NOT NULL REFERENCES cats,
86
86
  # # dog_id integer NOT NULL REFERENCES dogs,
@@ -93,6 +93,13 @@ module Sequel
93
93
  # key ensures that entries in the table are unique, which is the typical
94
94
  # desire for a join table.
95
95
  #
96
+ # The default table name this will create is the sorted version of the two
97
+ # hash values, joined by an underscore. So the following two method calls
98
+ # create the same table:
99
+ #
100
+ # create_join_table(cat_id: :cats, dog_id: :dogs) # cats_dogs
101
+ # create_join_table(dog_id: :dogs, cat_id: :cats) # cats_dogs
102
+ #
96
103
  # You can provide column options by making the values in the hash
97
104
  # be option hashes, so long as the option hashes have a :table
98
105
  # entry giving the table referenced:
@@ -121,7 +128,7 @@ module Sequel
121
128
  foreign_key(key, v)
122
129
  end
123
130
  primary_key(keys) unless options[:no_primary_key]
124
- index(keys.reverse, options[:index_options] || {}) unless options[:no_index]
131
+ index(keys.reverse, options[:index_options] || OPTS) unless options[:no_index]
125
132
  end
126
133
  nil
127
134
  end
@@ -314,7 +321,7 @@ module Sequel
314
321
  # DB.drop_table(:posts, :comments)
315
322
  # DB.drop_table(:posts, :comments, cascade: true)
316
323
  def drop_table(*names)
317
- options = names.last.is_a?(Hash) ? names.pop : {}
324
+ options = names.last.is_a?(Hash) ? names.pop : OPTS
318
325
  names.each do |n|
319
326
  execute_ddl(drop_table_sql(n, options))
320
327
  remove_cached_schema(n)
@@ -329,7 +336,7 @@ module Sequel
329
336
  # # SELECT NULL FROM a LIMIT 1 -- check existence
330
337
  # # DROP TABLE a -- if it already exists
331
338
  def drop_table?(*names)
332
- options = names.last.is_a?(Hash) ? names.pop : {}
339
+ options = names.last.is_a?(Hash) ? names.pop : OPTS
333
340
  if supports_drop_table_if_exists?
334
341
  options = options.merge(:if_exists=>true)
335
342
  names.each do |name|
@@ -357,7 +364,7 @@ module Sequel
357
364
  # PostgreSQL specific options:
358
365
  # :materialized :: Drop a materialized view.
359
366
  def drop_view(*names)
360
- options = names.last.is_a?(Hash) ? names.pop : {}
367
+ options = names.last.is_a?(Hash) ? names.pop : OPTS
361
368
  names.each do |n|
362
369
  execute_ddl(drop_view_sql(n, options))
363
370
  remove_cached_schema(n)
@@ -197,6 +197,11 @@ module Sequel
197
197
  true
198
198
  end
199
199
 
200
+ # Whether the dataset needs ESCAPE for LIKE for correct behavior.
201
+ def requires_like_escape?
202
+ true
203
+ end
204
+
200
205
  # Whether common table expressions are supported in UNION/INTERSECT/EXCEPT clauses.
201
206
  def supports_cte_in_compounds?
202
207
  supports_cte_in_subqueries?
@@ -226,7 +226,7 @@ module Sequel
226
226
  used_aliases += opts[:join].map{|j| j.table_alias ? alias_alias_symbol(j.table_alias) : alias_symbol(j.table)} if opts[:join]
227
227
  if used_aliases.include?(table_alias)
228
228
  i = 0
229
- loop do
229
+ while true
230
230
  ta = :"#{table_alias}_#{i}"
231
231
  return ta unless used_aliases.include?(ta)
232
232
  i += 1
@@ -52,7 +52,7 @@ module Sequel
52
52
  end
53
53
 
54
54
  # Set the bind arguments based on the hash and call super.
55
- def call(bind_vars={}, &block)
55
+ def call(bind_vars=OPTS, &block)
56
56
  sql = prepared_sql
57
57
  prepared_args.freeze
58
58
  ps = bind(bind_vars)
@@ -106,7 +106,7 @@ module Sequel
106
106
 
107
107
  # Sets the prepared_args to the given hash and runs the
108
108
  # prepared statement.
109
- def call(bind_vars={}, &block)
109
+ def call(bind_vars=OPTS, &block)
110
110
  bind(bind_vars).run(&block)
111
111
  end
112
112
 
@@ -272,7 +272,7 @@ module Sequel
272
272
  # DB[:table].where(id: :$id).bind(id: 1).call(:first)
273
273
  # # SELECT * FROM table WHERE id = ? LIMIT 1 -- (1)
274
274
  # # => {:id=>1}
275
- def bind(bind_vars={})
275
+ def bind(bind_vars=OPTS)
276
276
  bind_vars = if bv = @opts[:bind_vars]
277
277
  Hash[bv].merge!(bind_vars).freeze
278
278
  else
@@ -293,7 +293,7 @@ module Sequel
293
293
  # DB[:table].where(id: :$id).call(:first, id: 1)
294
294
  # # SELECT * FROM table WHERE id = ? LIMIT 1 -- (1)
295
295
  # # => {:id=>1}
296
- def call(type, bind_variables={}, *values, &block)
296
+ def call(type, bind_variables=OPTS, *values, &block)
297
297
  to_prepared_statement(type, values, :extend=>bound_variable_modules).call(bind_variables, &block)
298
298
  end
299
299