sequel 4.21.0 → 4.22.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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +32 -0
  3. data/README.rdoc +3 -4
  4. data/doc/opening_databases.rdoc +10 -75
  5. data/doc/release_notes/4.22.0.txt +72 -0
  6. data/lib/sequel/adapters/ado/access.rb +1 -1
  7. data/lib/sequel/adapters/cubrid.rb +3 -3
  8. data/lib/sequel/adapters/db2.rb +1 -0
  9. data/lib/sequel/adapters/dbi.rb +1 -0
  10. data/lib/sequel/adapters/fdbsql.rb +3 -2
  11. data/lib/sequel/adapters/firebird.rb +1 -0
  12. data/lib/sequel/adapters/ibmdb.rb +1 -21
  13. data/lib/sequel/adapters/informix.rb +1 -0
  14. data/lib/sequel/adapters/jdbc.rb +37 -49
  15. data/lib/sequel/adapters/jdbc/fdbsql.rb +1 -0
  16. data/lib/sequel/adapters/mysql.rb +5 -3
  17. data/lib/sequel/adapters/mysql2.rb +5 -2
  18. data/lib/sequel/adapters/odbc.rb +8 -4
  19. data/lib/sequel/adapters/openbase.rb +1 -0
  20. data/lib/sequel/adapters/oracle.rb +3 -46
  21. data/lib/sequel/adapters/postgres.rb +3 -36
  22. data/lib/sequel/adapters/shared/access.rb +1 -1
  23. data/lib/sequel/adapters/shared/fdbsql.rb +3 -3
  24. data/lib/sequel/adapters/shared/mssql.rb +1 -1
  25. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +12 -44
  26. data/lib/sequel/adapters/shared/oracle.rb +6 -2
  27. data/lib/sequel/adapters/shared/postgres.rb +6 -6
  28. data/lib/sequel/adapters/shared/sqlite.rb +1 -1
  29. data/lib/sequel/adapters/sqlite.rb +3 -46
  30. data/lib/sequel/adapters/tinytds.rb +12 -28
  31. data/lib/sequel/adapters/utils/pg_types.rb +1 -1
  32. data/lib/sequel/connection_pool/sharded_threaded.rb +63 -16
  33. data/lib/sequel/connection_pool/threaded.rb +72 -18
  34. data/lib/sequel/core.rb +1 -1
  35. data/lib/sequel/database/connecting.rb +2 -2
  36. data/lib/sequel/database/misc.rb +5 -5
  37. data/lib/sequel/database/query.rb +3 -2
  38. data/lib/sequel/database/schema_generator.rb +19 -19
  39. data/lib/sequel/database/schema_methods.rb +2 -2
  40. data/lib/sequel/database/transactions.rb +3 -3
  41. data/lib/sequel/dataset/actions.rb +18 -8
  42. data/lib/sequel/dataset/graph.rb +2 -2
  43. data/lib/sequel/dataset/prepared_statements.rb +28 -1
  44. data/lib/sequel/dataset/query.rb +7 -7
  45. data/lib/sequel/exceptions.rb +27 -24
  46. data/lib/sequel/extensions/_pretty_table.rb +1 -1
  47. data/lib/sequel/extensions/constraint_validations.rb +2 -2
  48. data/lib/sequel/extensions/date_arithmetic.rb +2 -2
  49. data/lib/sequel/extensions/pg_array.rb +10 -1
  50. data/lib/sequel/extensions/pg_row.rb +1 -1
  51. data/lib/sequel/extensions/pg_static_cache_updater.rb +1 -1
  52. data/lib/sequel/extensions/schema_dumper.rb +8 -8
  53. data/lib/sequel/extensions/split_array_nil.rb +1 -1
  54. data/lib/sequel/model.rb +1 -1
  55. data/lib/sequel/model/associations.rb +18 -11
  56. data/lib/sequel/model/base.rb +15 -15
  57. data/lib/sequel/model/exceptions.rb +11 -2
  58. data/lib/sequel/plugins/accessed_columns.rb +1 -1
  59. data/lib/sequel/plugins/auto_validations.rb +1 -1
  60. data/lib/sequel/plugins/boolean_readers.rb +1 -1
  61. data/lib/sequel/plugins/class_table_inheritance.rb +4 -7
  62. data/lib/sequel/plugins/composition.rb +1 -1
  63. data/lib/sequel/plugins/constraint_validations.rb +2 -2
  64. data/lib/sequel/plugins/csv_serializer.rb +171 -0
  65. data/lib/sequel/plugins/dirty.rb +2 -2
  66. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  67. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  68. data/lib/sequel/plugins/many_through_many.rb +1 -1
  69. data/lib/sequel/plugins/nested_attributes.rb +5 -5
  70. data/lib/sequel/plugins/pg_array_associations.rb +4 -4
  71. data/lib/sequel/plugins/prepared_statements.rb +2 -2
  72. data/lib/sequel/plugins/prepared_statements_safe.rb +1 -1
  73. data/lib/sequel/plugins/serialization.rb +6 -6
  74. data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
  75. data/lib/sequel/plugins/sharding.rb +3 -1
  76. data/lib/sequel/plugins/single_table_inheritance.rb +5 -13
  77. data/lib/sequel/plugins/static_cache.rb +2 -2
  78. data/lib/sequel/plugins/tactical_eager_loading.rb +1 -1
  79. data/lib/sequel/plugins/tree.rb +1 -1
  80. data/lib/sequel/plugins/validation_class_methods.rb +2 -2
  81. data/lib/sequel/plugins/validation_helpers.rb +4 -4
  82. data/lib/sequel/plugins/xml_serializer.rb +3 -3
  83. data/lib/sequel/sql.rb +1 -1
  84. data/lib/sequel/version.rb +1 -1
  85. data/spec/adapters/postgres_spec.rb +17 -0
  86. data/spec/core/connection_pool_spec.rb +1 -1
  87. data/spec/core/dataset_spec.rb +22 -0
  88. data/spec/extensions/auto_validations_spec.rb +1 -1
  89. data/spec/extensions/blacklist_security_spec.rb +2 -2
  90. data/spec/extensions/csv_serializer_spec.rb +173 -0
  91. data/spec/extensions/json_serializer_spec.rb +2 -2
  92. data/spec/extensions/nested_attributes_spec.rb +9 -9
  93. data/spec/extensions/pg_array_spec.rb +5 -0
  94. data/spec/extensions/single_table_inheritance_spec.rb +21 -0
  95. data/spec/extensions/touch_spec.rb +1 -1
  96. data/spec/extensions/tree_spec.rb +4 -0
  97. data/spec/extensions/xml_serializer_spec.rb +3 -3
  98. data/spec/integration/prepared_statement_test.rb +1 -1
  99. data/spec/integration/schema_test.rb +7 -0
  100. data/spec/integration/type_test.rb +2 -2
  101. data/spec/model/associations_spec.rb +108 -14
  102. data/spec/model/base_spec.rb +8 -8
  103. data/spec/model/record_spec.rb +7 -7
  104. metadata +6 -2
@@ -1,5 +1,6 @@
1
1
  Sequel::JDBC.load_driver('com.foundationdb.sql.jdbc.Driver')
2
2
  Sequel.require 'adapters/shared/fdbsql'
3
+ Sequel::Deprecation.deprecate 'The jdbc/fdbsql adapter is deprecated and will be removed in a future version of Sequel.'
3
4
 
4
5
  module Sequel
5
6
  Fdbsql::CONVERTED_EXCEPTIONS << NativeException
@@ -303,7 +303,7 @@ module Sequel
303
303
  type_proc = f.type == 1 && cast_tinyint_integer?(f) ? cps[2] : cps[f.type]
304
304
  [output_identifier(f.name), type_proc, i+=1]
305
305
  end
306
- @columns = cols.map{|c| c.first}
306
+ @columns = cols.map(&:first)
307
307
  if opts[:split_multiple_result_sets]
308
308
  s = []
309
309
  yield_rows(r, cols){|h| s << h}
@@ -347,8 +347,10 @@ module Sequel
347
347
  end
348
348
 
349
349
  # Set the :type option to :select if it hasn't been set.
350
- def execute(sql, opts=OPTS, &block)
351
- super(sql, {:type=>:select}.merge(opts), &block)
350
+ def execute(sql, opts=OPTS)
351
+ opts = Hash[opts]
352
+ opts[:type] = :select
353
+ super
352
354
  end
353
355
 
354
356
  # Handle correct quoting of strings using ::MySQL.quote.
@@ -188,8 +188,11 @@ module Sequel
188
188
  end
189
189
 
190
190
  # Set the :type option to :select if it hasn't been set.
191
- def execute(sql, opts=OPTS, &block)
192
- super(sql, {:type=>:select, :stream=>@opts[:stream]}.merge(opts), &block)
191
+ def execute(sql, opts=OPTS)
192
+ opts = Hash[opts]
193
+ opts[:type] = :select
194
+ opts[:stream] = @opts[:stream]
195
+ super
193
196
  end
194
197
 
195
198
  # Handle correct quoting of strings using ::Mysql2::Client#escape.
@@ -94,13 +94,13 @@ module Sequel
94
94
  def fetch_rows(sql)
95
95
  execute(sql) do |s|
96
96
  i = -1
97
- cols = s.columns(true).map{|c| [output_identifier(c.name), i+=1]}
97
+ cols = s.columns(true).map{|c| [output_identifier(c.name), c.type, i+=1]}
98
98
  columns = cols.map{|c| c.at(0)}
99
99
  @columns = columns
100
100
  if rows = s.fetch_all
101
101
  rows.each do |row|
102
102
  hash = {}
103
- cols.each{|n,j| hash[n] = convert_odbc_value(row[j])}
103
+ cols.each{|n,t,j| hash[n] = convert_odbc_value(row[j], t)}
104
104
  yield hash
105
105
  end
106
106
  end
@@ -110,7 +110,7 @@ module Sequel
110
110
 
111
111
  private
112
112
 
113
- def convert_odbc_value(v)
113
+ def convert_odbc_value(v, t)
114
114
  # When fetching a result set, the Ruby ODBC driver converts all ODBC
115
115
  # SQL types to an equivalent Ruby type; with the exception of
116
116
  # SQL_TYPE_DATE, SQL_TYPE_TIME and SQL_TYPE_TIMESTAMP.
@@ -125,7 +125,11 @@ module Sequel
125
125
  when ::ODBC::Date
126
126
  Date.new(v.year, v.month, v.day)
127
127
  else
128
- v
128
+ if t == ::ODBC::SQL_BIT
129
+ v == 1
130
+ else
131
+ v
132
+ end
129
133
  end
130
134
  end
131
135
 
@@ -1,4 +1,5 @@
1
1
  require 'openbase'
2
+ Sequel::Deprecation.deprecate 'The openbase adapter is deprecated and will be removed in a future version of Sequel.'
2
3
 
3
4
  module Sequel
4
5
  module OpenBase
@@ -15,7 +15,7 @@ module Sequel
15
15
 
16
16
  ORACLE_TYPES = {
17
17
  :blob=>lambda{|b| Sequel::SQL::Blob.new(b.read)},
18
- :clob=>lambda{|b| b.read}
18
+ :clob=>lambda(&:read)
19
19
  }
20
20
 
21
21
  # Hash of conversion procs for this database.
@@ -348,52 +348,9 @@ module Sequel
348
348
  end
349
349
  end
350
350
 
351
- # Oracle prepared statement uses a new prepared statement each time
352
- # it is called, but it does use the bind arguments.
353
- module BindArgumentMethods
354
- include ArgumentMapper
351
+ BindArgumentMethods = prepared_statements_module(:bind, ArgumentMapper)
352
+ PreparedStatementMethods = prepared_statements_module(:prepare, BindArgumentMethods)
355
353
 
356
- private
357
-
358
- # Run execute_select on the database with the given SQL and the stored
359
- # bind arguments.
360
- def execute(sql, opts=OPTS, &block)
361
- super(prepared_sql, {:arguments=>bind_arguments}.merge(opts), &block)
362
- end
363
-
364
- # Same as execute, explicit due to intricacies of alias and super.
365
- def execute_dui(sql, opts=OPTS, &block)
366
- super(prepared_sql, {:arguments=>bind_arguments}.merge(opts), &block)
367
- end
368
-
369
- # Same as execute, explicit due to intricacies of alias and super.
370
- def execute_insert(sql, opts=OPTS, &block)
371
- super(prepared_sql, {:arguments=>bind_arguments}.merge(opts), &block)
372
- end
373
- end
374
-
375
- module PreparedStatementMethods
376
- include BindArgumentMethods
377
-
378
- private
379
-
380
- # Execute the stored prepared statement name and the stored bind
381
- # arguments instead of the SQL given.
382
- def execute(sql, opts=OPTS, &block)
383
- super(prepared_statement_name, opts, &block)
384
- end
385
-
386
- # Same as execute, explicit due to intricacies of alias and super.
387
- def execute_dui(sql, opts=OPTS, &block)
388
- super(prepared_statement_name, opts, &block)
389
- end
390
-
391
- # Same as execute, explicit due to intricacies of alias and super.
392
- def execute_insert(sql, opts=OPTS, &block)
393
- super(prepared_statement_name, opts, &block)
394
- end
395
- end
396
-
397
354
  # Execute the given type of statement with the hash of values.
398
355
  def call(type, bind_vars={}, *values, &block)
399
356
  ps = to_prepared_statement(type, values)
@@ -681,7 +681,7 @@ module Sequel
681
681
  # This is untested with the prepared statement/bound variable support,
682
682
  # and unlikely to work with either.
683
683
  def use_cursor(opts=OPTS)
684
- clone(:cursor=>{:rows_per_fetch=>1000}.merge(opts))
684
+ clone(:cursor=>{:rows_per_fetch=>1000}.merge!(opts))
685
685
  end
686
686
 
687
687
  # Replace the WHERE clause with one that uses CURRENT OF with the given
@@ -732,47 +732,14 @@ module Sequel
732
732
  end
733
733
  end
734
734
 
735
- # Allow use of bind arguments for PostgreSQL using the pg driver.
736
- module BindArgumentMethods
737
- include ArgumentMapper
738
- include ::Sequel::Postgres::DatasetMethods::PreparedStatementMethods
739
-
740
- private
741
-
742
- # Execute the given SQL with the stored bind arguments.
743
- def execute(sql, opts=OPTS, &block)
744
- super(sql, {:arguments=>bind_arguments}.merge(opts), &block)
745
- end
746
-
747
- # Same as execute, explicit due to intricacies of alias and super.
748
- def execute_dui(sql, opts=OPTS, &block)
749
- super(sql, {:arguments=>bind_arguments}.merge(opts), &block)
750
- end
751
- end
752
-
753
- # Allow use of server side prepared statements for PostgreSQL using the
754
- # pg driver.
755
- module PreparedStatementMethods
756
- include BindArgumentMethods
735
+ BindArgumentMethods = prepared_statements_module(:bind, [ArgumentMapper, ::Sequel::Postgres::DatasetMethods::PreparedStatementMethods], %w'execute execute_dui')
757
736
 
737
+ PreparedStatementMethods = prepared_statements_module(:prepare, BindArgumentMethods, %w'execute execute_dui') do
758
738
  # Raise a more obvious error if you attempt to call a unnamed prepared statement.
759
739
  def call(*)
760
740
  raise Error, "Cannot call prepared statement without a name" if prepared_statement_name.nil?
761
741
  super
762
742
  end
763
-
764
- private
765
-
766
- # Execute the stored prepared statement name and the stored bind
767
- # arguments instead of the SQL given.
768
- def execute(sql, opts=OPTS, &block)
769
- super(prepared_statement_name, opts, &block)
770
- end
771
-
772
- # Same as execute, explicit due to intricacies of alias and super.
773
- def execute_dui(sql, opts=OPTS, &block)
774
- super(prepared_statement_name, opts, &block)
775
- end
776
743
  end
777
744
 
778
745
  # Execute the given type of statement with the hash of values.
@@ -12,7 +12,7 @@ module Sequel
12
12
 
13
13
  # Doesn't work, due to security restrictions on MSysObjects
14
14
  #def tables
15
- # from(:MSysObjects).filter(:Type=>1, :Flags=>0).select_map(:Name).map{|x| x.to_sym}
15
+ # from(:MSysObjects).filter(:Type=>1, :Flags=>0).select_map(:Name).map(&:to_sym)
16
16
  #end
17
17
 
18
18
  # Access doesn't support renaming tables from an SQL query,
@@ -265,9 +265,9 @@ module Sequel
265
265
  end
266
266
 
267
267
  STALE_STATEMENT_SQLSTATE = '0A50A'.freeze
268
- NOT_NULL_CONSTRAINT_SQLSTATES = %w'23502'.freeze.each{|s| s.freeze}
269
- FOREIGN_KEY_CONSTRAINT_SQLSTATES = %w'23503 23504'.freeze.each{|s| s.freeze}
270
- UNIQUE_CONSTRAINT_SQLSTATES = %w'23501'.freeze.each{|s| s.freeze}
268
+ NOT_NULL_CONSTRAINT_SQLSTATES = %w'23502'.freeze.each(&:freeze)
269
+ FOREIGN_KEY_CONSTRAINT_SQLSTATES = %w'23503 23504'.freeze.each(&:freeze)
270
+ UNIQUE_CONSTRAINT_SQLSTATES = %w'23501'.freeze.each(&:freeze)
271
271
 
272
272
  # Given the SQLState, return the appropriate DatabaseError subclass.
273
273
  def database_specific_error_class_from_sqlstate(sqlstate)
@@ -466,7 +466,7 @@ module Sequel
466
466
  else
467
467
  schema_column_type(row[:db_type])
468
468
  end
469
- row[:max_length] = row[:max_chars] if row[:type] == :string
469
+ row[:max_length] = row[:max_chars] if row[:type] == :string && row[:max_chars] >= 0
470
470
  [m.call(row.delete(:column)), row]
471
471
  end
472
472
  end
@@ -6,7 +6,7 @@ module Sequel
6
6
  # prepared statements and stored procedures.
7
7
  module PreparedStatements
8
8
  module DatabaseMethods
9
- disconnect_errors = <<-END.split("\n").map{|l| l.strip}
9
+ disconnect_errors = <<-END.split("\n").map(&:strip)
10
10
  Commands out of sync; you can't run this command now
11
11
  Can't connect to local MySQL server through socket
12
12
  MySQL server has gone away
@@ -100,51 +100,19 @@ module Sequel
100
100
  end
101
101
  end
102
102
 
103
- # Methods for MySQL prepared statements using the native driver.
104
- module PreparedStatementMethods
105
- include Sequel::Dataset::UnnumberedArgumentMapper
106
-
107
- # Raise a more obvious error if you attempt to call a unnamed prepared statement.
108
- def call(*)
109
- raise Error, "Cannot call prepared statement without a name" if prepared_statement_name.nil?
110
- super
111
- end
112
-
113
- private
114
-
115
- # Execute the prepared statement with the bind arguments instead of
116
- # the given SQL.
117
- def execute(sql, opts=OPTS, &block)
118
- super(prepared_statement_name, {:arguments=>bind_arguments}.merge(opts), &block)
119
- end
120
-
121
- # Same as execute, explicit due to intricacies of alias and super.
122
- def execute_dui(sql, opts=OPTS, &block)
123
- super(prepared_statement_name, {:arguments=>bind_arguments}.merge(opts), &block)
124
- end
125
-
126
- # Same as execute, explicit due to intricacies of alias and super.
127
- def execute_insert(sql, opts=OPTS, &block)
128
- super(prepared_statement_name, {:arguments=>bind_arguments}.merge(opts), &block)
129
- end
103
+ PreparedStatementMethods = Sequel::Dataset.send(:prepared_statements_module,
104
+ :prepare_bind,
105
+ Sequel::Dataset::UnnumberedArgumentMapper) do
106
+ # Raise a more obvious error if you attempt to call a unnamed prepared statement.
107
+ def call(*)
108
+ raise Error, "Cannot call prepared statement without a name" if prepared_statement_name.nil?
109
+ super
110
+ end
130
111
  end
131
112
 
132
- # Methods for MySQL stored procedures using the native driver.
133
- module StoredProcedureMethods
134
- include Sequel::Dataset::StoredProcedureMethods
135
-
136
- private
137
-
138
- # Execute the database stored procedure with the stored arguments.
139
- def execute(sql, opts=OPTS, &block)
140
- super(@sproc_name, {:args=>@sproc_args, :sproc=>true}.merge(opts), &block)
141
- end
142
-
143
- # Same as execute, explicit due to intricacies of alias and super.
144
- def execute_dui(sql, opts=OPTS, &block)
145
- super(@sproc_name, {:args=>@sproc_args, :sproc=>true}.merge(opts), &block)
146
- end
147
- end
113
+ StoredProcedureMethods = Sequel::Dataset.send(:prepared_statements_module,
114
+ "sql = @sproc_name; opts = Hash[opts]; opts[:args] = @sproc_args; opts[:sproc] = true",
115
+ Sequel::Dataset::StoredProcedureMethods, %w'execute execute_dui')
148
116
 
149
117
  # MySQL is different in that it supports prepared statements but not bound
150
118
  # variables outside of prepared statements. The default implementation
@@ -474,8 +474,12 @@ module Sequel
474
474
  # If this dataset is associated with a sequence, return the most recently
475
475
  # inserted sequence value.
476
476
  def execute_insert(sql, opts=OPTS)
477
- f = @opts[:from]
478
- super(sql, {:table=>(f.first if f), :sequence=>@opts[:sequence]}.merge(opts))
477
+ opts = Hash[opts]
478
+ if f = @opts[:from]
479
+ opts[:table] = f.first
480
+ end
481
+ opts[:sequence] = @opts[:sequence]
482
+ super
479
483
  end
480
484
 
481
485
  # Use a colon for the timestamp offset, since Oracle appears to require it.
@@ -64,7 +64,7 @@ module Sequel
64
64
  # :where :: Create a partial exclusion constraint, which only affects
65
65
  # a subset of table rows, value should be a filter expression.
66
66
  def exclude(elements, opts=OPTS)
67
- constraints << {:type => :exclude, :elements => elements}.merge(opts)
67
+ constraints << {:type => :exclude, :elements => elements}.merge!(opts)
68
68
  end
69
69
  end
70
70
 
@@ -72,7 +72,7 @@ module Sequel
72
72
  # Adds an exclusion constraint to an existing table, see
73
73
  # CreateTableGenerator#exclude.
74
74
  def add_exclusion_constraint(elements, opts=OPTS)
75
- @operations << {:op => :add_constraint, :type => :exclude, :elements => elements}.merge(opts)
75
+ @operations << {:op => :add_constraint, :type => :exclude, :elements => elements}.merge!(opts)
76
76
  end
77
77
 
78
78
  # Validate the constraint with the given name, which should have
@@ -667,7 +667,7 @@ module Sequel
667
667
  if search_path = @opts[:search_path]
668
668
  case search_path
669
669
  when String
670
- search_path = search_path.split(",").map{|s| s.strip}
670
+ search_path = search_path.split(",").map(&:strip)
671
671
  when Array
672
672
  # nil
673
673
  else
@@ -706,7 +706,7 @@ module Sequel
706
706
  # Convert the hash of named conversion procs into a hash a oid conversion procs.
707
707
  def convert_named_procs_to_procs(named_procs)
708
708
  h = {}
709
- from(:pg_type).where(:typtype=>'b', :typname=>named_procs.keys.map{|t| t.to_s}).select_map([:oid, :typname]).each do |oid, name|
709
+ from(:pg_type).where(:typtype=>'b', :typname=>named_procs.keys.map(&:to_s)).select_map([:oid, :typname]).each do |oid, name|
710
710
  h[oid.to_i] = named_procs[name.untaint.to_sym]
711
711
  end
712
712
  h
@@ -1197,7 +1197,7 @@ module Sequel
1197
1197
  WINDOW = " WINDOW ".freeze
1198
1198
  SELECT_VALUES = "VALUES ".freeze
1199
1199
  EMPTY_STRING = ''.freeze
1200
- LOCK_MODES = ['ACCESS SHARE', 'ROW SHARE', 'ROW EXCLUSIVE', 'SHARE UPDATE EXCLUSIVE', 'SHARE', 'SHARE ROW EXCLUSIVE', 'EXCLUSIVE', 'ACCESS EXCLUSIVE'].each{|s| s.freeze}
1200
+ LOCK_MODES = ['ACCESS SHARE', 'ROW SHARE', 'ROW EXCLUSIVE', 'SHARE UPDATE EXCLUSIVE', 'SHARE', 'SHARE ROW EXCLUSIVE', 'EXCLUSIVE', 'ACCESS EXCLUSIVE'].each(&:freeze)
1201
1201
 
1202
1202
  Dataset.def_sql_method(self, :delete, [['if server_version >= 90100', %w'with delete from using where returning'], ['else', %w'delete from using where returning']])
1203
1203
  Dataset.def_sql_method(self, :insert, [['if server_version >= 90100', %w'with insert into columns values returning'], ['else', %w'insert into columns values returning']])
@@ -1468,7 +1468,7 @@ module Sequel
1468
1468
  def _import(columns, values, opts=OPTS)
1469
1469
  if @opts[:returning]
1470
1470
  statements = multi_insert_sql(columns, values)
1471
- @db.transaction(opts.merge(:server=>@opts[:server])) do
1471
+ @db.transaction(Hash[opts].merge!(:server=>@opts[:server])) do
1472
1472
  statements.map{|st| returning_fetch_rows(st)}
1473
1473
  end.first.map{|v| v.length == 1 ? v.values.first : v}
1474
1474
  elsif opts[:return] == :primary_key
@@ -416,7 +416,7 @@ module Sequel
416
416
  "DROP TABLE #{bt}"
417
417
  ]
418
418
  indexes(table).each do |name, h|
419
- if (h[:columns].map{|x| x.to_s} - new_columns).empty?
419
+ if (h[:columns].map(&:to_s) - new_columns).empty?
420
420
  a << alter_table_sql(table, h.merge(:op=>:add_index, :name=>name))
421
421
  end
422
422
  end
@@ -304,52 +304,9 @@ module Sequel
304
304
  end
305
305
  end
306
306
 
307
- # SQLite prepared statement uses a new prepared statement each time
308
- # it is called, but it does use the bind arguments.
309
- module BindArgumentMethods
310
- include ArgumentMapper
311
-
312
- private
313
-
314
- # Run execute_select on the database with the given SQL and the stored
315
- # bind arguments.
316
- def execute(sql, opts=OPTS, &block)
317
- super(sql, {:arguments=>bind_arguments}.merge(opts), &block)
318
- end
319
-
320
- # Same as execute, explicit due to intricacies of alias and super.
321
- def execute_dui(sql, opts=OPTS, &block)
322
- super(sql, {:arguments=>bind_arguments}.merge(opts), &block)
323
- end
324
-
325
- # Same as execute, explicit due to intricacies of alias and super.
326
- def execute_insert(sql, opts=OPTS, &block)
327
- super(sql, {:arguments=>bind_arguments}.merge(opts), &block)
328
- end
329
- end
307
+ BindArgumentMethods = prepared_statements_module(:bind, ArgumentMapper)
308
+ PreparedStatementMethods = prepared_statements_module(:prepare, BindArgumentMethods)
330
309
 
331
- module PreparedStatementMethods
332
- include BindArgumentMethods
333
-
334
- private
335
-
336
- # Execute the stored prepared statement name and the stored bind
337
- # arguments instead of the SQL given.
338
- def execute(sql, opts=OPTS, &block)
339
- super(prepared_statement_name, opts, &block)
340
- end
341
-
342
- # Same as execute, explicit due to intricacies of alias and super.
343
- def execute_dui(sql, opts=OPTS, &block)
344
- super(prepared_statement_name, opts, &block)
345
- end
346
-
347
- # Same as execute, explicit due to intricacies of alias and super.
348
- def execute_insert(sql, opts=OPTS, &block)
349
- super(prepared_statement_name, opts, &block)
350
- end
351
- end
352
-
353
310
  # Execute the given type of statement with the hash of values.
354
311
  def call(type, bind_vars={}, *values, &block)
355
312
  ps = to_prepared_statement(type, values)
@@ -364,7 +321,7 @@ module Sequel
364
321
  cps = db.conversion_procs
365
322
  type_procs = result.types.map{|t| cps[base_type_name(t)]}
366
323
  cols = result.columns.map{|c| i+=1; [output_identifier(c), i, type_procs[i]]}
367
- @columns = cols.map{|c| c.first}
324
+ @columns = cols.map(&:first)
368
325
  result.each do |values|
369
326
  row = {}
370
327
  cols.each do |name,id,type_proc|