sequel 3.35.0 → 3.36.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 (81) hide show
  1. data/CHANGELOG +78 -0
  2. data/Rakefile +3 -3
  3. data/bin/sequel +3 -1
  4. data/doc/advanced_associations.rdoc +154 -11
  5. data/doc/migration.rdoc +18 -0
  6. data/doc/object_model.rdoc +541 -0
  7. data/doc/opening_databases.rdoc +4 -1
  8. data/doc/release_notes/3.36.0.txt +245 -0
  9. data/doc/schema_modification.rdoc +0 -6
  10. data/lib/sequel/adapters/do/mysql.rb +7 -0
  11. data/lib/sequel/adapters/jdbc.rb +11 -3
  12. data/lib/sequel/adapters/jdbc/mysql.rb +3 -5
  13. data/lib/sequel/adapters/jdbc/postgresql.rb +10 -8
  14. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  15. data/lib/sequel/adapters/mock.rb +2 -6
  16. data/lib/sequel/adapters/mysql.rb +3 -9
  17. data/lib/sequel/adapters/mysql2.rb +12 -11
  18. data/lib/sequel/adapters/postgres.rb +32 -40
  19. data/lib/sequel/adapters/shared/mssql.rb +15 -11
  20. data/lib/sequel/adapters/shared/mysql.rb +28 -3
  21. data/lib/sequel/adapters/shared/oracle.rb +5 -0
  22. data/lib/sequel/adapters/shared/postgres.rb +59 -5
  23. data/lib/sequel/adapters/shared/sqlite.rb +3 -13
  24. data/lib/sequel/adapters/sqlite.rb +0 -7
  25. data/lib/sequel/adapters/swift/mysql.rb +2 -5
  26. data/lib/sequel/adapters/tinytds.rb +1 -2
  27. data/lib/sequel/connection_pool/sharded_threaded.rb +5 -1
  28. data/lib/sequel/connection_pool/threaded.rb +9 -1
  29. data/lib/sequel/database/dataset_defaults.rb +3 -1
  30. data/lib/sequel/database/misc.rb +7 -1
  31. data/lib/sequel/database/query.rb +11 -3
  32. data/lib/sequel/database/schema_generator.rb +40 -9
  33. data/lib/sequel/database/schema_methods.rb +6 -1
  34. data/lib/sequel/dataset/actions.rb +5 -5
  35. data/lib/sequel/dataset/prepared_statements.rb +3 -1
  36. data/lib/sequel/dataset/query.rb +1 -1
  37. data/lib/sequel/extensions/migration.rb +28 -0
  38. data/lib/sequel/extensions/pg_auto_parameterize.rb +0 -9
  39. data/lib/sequel/extensions/pg_inet.rb +89 -0
  40. data/lib/sequel/extensions/pg_json.rb +178 -0
  41. data/lib/sequel/extensions/schema_dumper.rb +24 -6
  42. data/lib/sequel/model/associations.rb +19 -15
  43. data/lib/sequel/model/base.rb +11 -12
  44. data/lib/sequel/plugins/composition.rb +1 -2
  45. data/lib/sequel/plugins/eager_each.rb +59 -0
  46. data/lib/sequel/plugins/json_serializer.rb +41 -4
  47. data/lib/sequel/plugins/nested_attributes.rb +72 -52
  48. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  49. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  50. data/lib/sequel/version.rb +1 -1
  51. data/spec/adapters/postgres_spec.rb +271 -1
  52. data/spec/adapters/sqlite_spec.rb +11 -0
  53. data/spec/core/connection_pool_spec.rb +26 -1
  54. data/spec/core/database_spec.rb +19 -0
  55. data/spec/core/dataset_spec.rb +45 -5
  56. data/spec/core/expression_filters_spec.rb +31 -67
  57. data/spec/core/mock_adapter_spec.rb +4 -0
  58. data/spec/extensions/core_extensions_spec.rb +83 -0
  59. data/spec/extensions/eager_each_spec.rb +34 -0
  60. data/spec/extensions/inflector_spec.rb +0 -4
  61. data/spec/extensions/json_serializer_spec.rb +32 -1
  62. data/spec/extensions/migration_spec.rb +28 -0
  63. data/spec/extensions/nested_attributes_spec.rb +134 -1
  64. data/spec/extensions/optimistic_locking_spec.rb +15 -1
  65. data/spec/extensions/pg_hstore_spec.rb +1 -1
  66. data/spec/extensions/pg_inet_spec.rb +44 -0
  67. data/spec/extensions/pg_json_spec.rb +101 -0
  68. data/spec/extensions/prepared_statements_spec.rb +30 -0
  69. data/spec/extensions/rcte_tree_spec.rb +9 -0
  70. data/spec/extensions/schema_dumper_spec.rb +195 -7
  71. data/spec/extensions/serialization_spec.rb +4 -0
  72. data/spec/extensions/spec_helper.rb +9 -1
  73. data/spec/extensions/tactical_eager_loading_spec.rb +8 -0
  74. data/spec/integration/database_test.rb +5 -1
  75. data/spec/integration/prepared_statement_test.rb +20 -2
  76. data/spec/model/associations_spec.rb +27 -0
  77. data/spec/model/base_spec.rb +54 -0
  78. data/spec/model/model_spec.rb +6 -0
  79. data/spec/model/record_spec.rb +18 -0
  80. data/spec/rcov.opts +2 -0
  81. metadata +14 -3
@@ -118,19 +118,13 @@ module Sequel
118
118
  Mysql::CLIENT_MULTI_STATEMENTS +
119
119
  (opts[:compress] == false ? 0 : Mysql::CLIENT_COMPRESS)
120
120
  )
121
- sqls = []
121
+ sqls = mysql_connection_setting_sqls
122
+
122
123
  # Set encoding a slightly different way after connecting,
123
124
  # in case the READ_DEFAULT_GROUP overrode the provided encoding.
124
125
  # Doesn't work across implicit reconnects, but Sequel doesn't turn on
125
126
  # that feature.
126
- sqls << "SET NAMES #{literal(encoding.to_s)}" if encoding
127
-
128
- # Increase timeout so mysql server doesn't disconnect us
129
- # Value used by default is maximum allowed value on Windows.
130
- sqls << "SET @@wait_timeout = #{opts[:timeout] || 2147483}"
131
-
132
- # By default, MySQL 'where id is null' selects the last inserted id
133
- sqls << "SET SQL_AUTO_IS_NULL=0" unless opts[:auto_is_null]
127
+ sqls.unshift("SET NAMES #{literal(encoding.to_s)}") if encoding
134
128
 
135
129
  sqls.each{|sql| log_yield(sql){conn.query(sql)}}
136
130
 
@@ -10,7 +10,7 @@ module Sequel
10
10
  include Sequel::MySQL::PreparedStatements::DatabaseMethods
11
11
 
12
12
  # Mysql::Error messages that indicate the current connection should be disconnected
13
- MYSQL_DATABASE_DISCONNECT_ERRORS = /\A(Commands out of sync; you can't run this command now|Can't connect to local MySQL server through socket|MySQL server has gone away|This connection is still waiting for a result, try again once you have the result)/
13
+ MYSQL_DATABASE_DISCONNECT_ERRORS = /\A(Commands out of sync; you can't run this command now|Can't connect to local MySQL server through socket|MySQL server has gone away|This connection is still waiting for a result, try again once you have the result|closed MySQL connection)/
14
14
 
15
15
  set_adapter_scheme :mysql2
16
16
 
@@ -48,22 +48,16 @@ module Sequel
48
48
  opts[:flags] = ::Mysql2::Client::FOUND_ROWS if ::Mysql2::Client.const_defined?(:FOUND_ROWS)
49
49
  conn = ::Mysql2::Client.new(opts)
50
50
 
51
- sqls = []
51
+ sqls = mysql_connection_setting_sqls
52
+
52
53
  # Set encoding a slightly different way after connecting,
53
54
  # in case the READ_DEFAULT_GROUP overrode the provided encoding.
54
55
  # Doesn't work across implicit reconnects, but Sequel doesn't turn on
55
56
  # that feature.
56
57
  if encoding = opts[:encoding] || opts[:charset]
57
- sqls << "SET NAMES #{conn.escape(encoding.to_s)}"
58
+ sqls.unshift("SET NAMES #{conn.escape(encoding.to_s)}")
58
59
  end
59
60
 
60
- # Increase timeout so mysql server doesn't disconnect us.
61
- # Value used by default is maximum allowed value on Windows.
62
- sqls << "SET @@wait_timeout = #{opts[:timeout] || 2147483}"
63
-
64
- # By default, MySQL 'where id is null' selects the last inserted id
65
- sqls << "SET SQL_AUTO_IS_NULL=0" unless opts[:auto_is_null]
66
-
67
61
  sqls.each{|sql| log_yield(sql){conn.query(sql)}}
68
62
 
69
63
  add_prepared_statements_cache(conn)
@@ -113,8 +107,15 @@ module Sequel
113
107
  [::Mysql2::Error]
114
108
  end
115
109
 
110
+ # If a connection object is available, try pinging it. Otherwise, if the
111
+ # error is a Mysql2::Error, check the SQL state and exception message for
112
+ # disconnects.
116
113
  def disconnect_error?(e, opts)
117
- super || (e.is_a?(::Mysql2::Error) && MYSQL_DATABASE_DISCONNECT_ERRORS.match(e.message))
114
+ super ||
115
+ ((conn = opts[:conn]) && !conn.ping) ||
116
+ (e.is_a?(::Mysql2::Error) &&
117
+ (e.sql_state =~ /\A08/ ||
118
+ MYSQL_DATABASE_DISCONNECT_ERRORS.match(e.message)))
118
119
  end
119
120
 
120
121
  # The database name when using the native adapter is always stored in
@@ -294,10 +294,7 @@ module Sequel
294
294
 
295
295
  # Execute the given SQL with the given args on an available connection.
296
296
  def execute(sql, opts={}, &block)
297
- check_database_errors do
298
- return execute_prepared_statement(sql, opts, &block) if Symbol === sql
299
- synchronize(opts[:server]){|conn| conn.execute(sql, opts[:arguments], &block)}
300
- end
297
+ synchronize(opts[:server]){|conn| check_database_errors{_execute(conn, sql, opts, &block)}}
301
298
  end
302
299
 
303
300
  if SEQUEL_POSTGRES_USES_PG
@@ -436,6 +433,15 @@ module Sequel
436
433
 
437
434
  private
438
435
 
436
+ # Execute the given SQL string or prepared statement on the connection object.
437
+ def _execute(conn, sql, opts, &block)
438
+ if sql.is_a?(Symbol)
439
+ execute_prepared_statement(conn, sql, opts, &block)
440
+ else
441
+ conn.execute(sql, opts[:arguments], &block)
442
+ end
443
+ end
444
+
439
445
  # Convert exceptions raised from the block into DatabaseErrors.
440
446
  def check_database_errors
441
447
  begin
@@ -466,38 +472,34 @@ module Sequel
466
472
  # has prepared a statement with the same name and different SQL,
467
473
  # deallocate that statement first and then prepare this statement.
468
474
  # If a block is given, yield the result, otherwise, return the number
469
- # of rows changed. If the :insert option is passed, return the value
470
- # of the primary key for the last inserted row.
471
- def execute_prepared_statement(name, opts={})
475
+ # of rows changed.
476
+ def execute_prepared_statement(conn, name, opts={}, &block)
472
477
  ps = prepared_statement(name)
473
478
  sql = ps.prepared_sql
474
479
  ps_name = name.to_s
475
- synchronize(opts[:server]) do |conn|
476
- if args = opts[:arguments]
477
- args = args.map{|arg| bound_variable_arg(arg, conn)}
478
- end
479
480
 
480
- unless conn.prepared_statements[ps_name] == sql
481
- if conn.prepared_statements.include?(ps_name)
482
- conn.execute("DEALLOCATE #{ps_name}") unless conn.prepared_statements[ps_name] == sql
483
- end
484
- conn.prepared_statements[ps_name] = sql
485
- conn.check_disconnect_errors{log_yield("PREPARE #{ps_name} AS #{sql}"){conn.prepare(ps_name, sql)}}
486
- end
481
+ if args = opts[:arguments]
482
+ args = args.map{|arg| bound_variable_arg(arg, conn)}
483
+ end
487
484
 
488
- log_sql = "EXECUTE #{ps_name}"
489
- if ps.log_sql
490
- log_sql << " ("
491
- log_sql << sql
492
- log_sql << ")"
493
- end
485
+ unless conn.prepared_statements[ps_name] == sql
486
+ conn.execute("DEALLOCATE #{ps_name}") if conn.prepared_statements.include?(ps_name)
487
+ conn.prepared_statements[ps_name] = sql
488
+ conn.check_disconnect_errors{log_yield("PREPARE #{ps_name} AS #{sql}"){conn.prepare(ps_name, sql)}}
489
+ end
494
490
 
495
- q = conn.check_disconnect_errors{log_yield(log_sql, args){conn.exec_prepared(ps_name, args)}}
496
- begin
497
- block_given? ? yield(q) : q.cmd_tuples
498
- ensure
499
- q.clear
500
- end
491
+ log_sql = "EXECUTE #{ps_name}"
492
+ if ps.log_sql
493
+ log_sql << " ("
494
+ log_sql << sql
495
+ log_sql << ")"
496
+ end
497
+
498
+ q = conn.check_disconnect_errors{log_yield(log_sql, args){conn.exec_prepared(ps_name, args)}}
499
+ begin
500
+ block_given? ? yield(q) : q.cmd_tuples
501
+ ensure
502
+ q.clear
501
503
  end
502
504
  end
503
505
 
@@ -640,11 +642,6 @@ module Sequel
640
642
  def execute_dui(sql, opts={}, &block)
641
643
  super(sql, {:arguments=>bind_arguments}.merge(opts), &block)
642
644
  end
643
-
644
- # Same as execute, explicit due to intricacies of alias and super.
645
- def execute_insert(sql, opts={}, &block)
646
- super(sql, {:arguments=>bind_arguments}.merge(opts), &block)
647
- end
648
645
  end
649
646
 
650
647
  # Allow use of server side prepared statements for PostgreSQL using the
@@ -670,11 +667,6 @@ module Sequel
670
667
  def execute_dui(sql, opts={}, &block)
671
668
  super(prepared_statement_name, opts, &block)
672
669
  end
673
-
674
- # Same as execute, explicit due to intricacies of alias and super.
675
- def execute_insert(sql, opts={}, &block)
676
- super(prepared_statement_name, opts, &block)
677
- end
678
670
  end
679
671
 
680
672
  # Execute the given type of statement with the hash of values.
@@ -28,6 +28,11 @@ module Sequel
28
28
  :mssql
29
29
  end
30
30
 
31
+ # Microsoft SQL Server namespaces indexes per table.
32
+ def global_index_namespace?
33
+ false
34
+ end
35
+
31
36
  # Use the system tables to get index information
32
37
  def indexes(table, opts={})
33
38
  m = output_identifier_meth
@@ -187,6 +192,16 @@ module Sequel
187
192
  "DROP INDEX #{quote_identifier(op[:name] || default_index_name(table, op[:columns]))} ON #{quote_schema_table(table)}"
188
193
  end
189
194
 
195
+ # support for clustered index type
196
+ def index_definition_sql(table_name, index)
197
+ index_name = index[:name] || default_index_name(table_name, index[:columns])
198
+ if index[:type] == :full_text
199
+ "CREATE FULLTEXT INDEX ON #{quote_schema_table(table_name)} #{literal(index[:columns])} KEY INDEX #{literal(index[:key_index])}"
200
+ else
201
+ "CREATE #{'UNIQUE ' if index[:unique]}#{'CLUSTERED ' if index[:type] == :clustered}INDEX #{quote_identifier(index_name)} ON #{quote_schema_table(table_name)} #{literal(index[:columns])}#{" INCLUDE #{literal(index[:include])}" if index[:include]}#{" WHERE #{filter_expr(index[:where])}" if index[:where]}"
202
+ end
203
+ end
204
+
190
205
  # Backbone of the tables and views support.
191
206
  def information_schema_tables(type, opts)
192
207
  m = output_identifier_meth
@@ -290,17 +305,6 @@ module Sequel
290
305
  def type_literal_generic_file(column)
291
306
  :'varbinary(max)'
292
307
  end
293
-
294
- # support for clustered index type
295
- def index_definition_sql(table_name, index)
296
- index_name = index[:name] || default_index_name(table_name, index[:columns])
297
- raise Error, "Partial indexes are not supported for this database" if index[:where]
298
- if index[:type] == :full_text
299
- "CREATE FULLTEXT INDEX ON #{quote_schema_table(table_name)} #{literal(index[:columns])} KEY INDEX #{literal(index[:key_index])}"
300
- else
301
- "CREATE #{'UNIQUE ' if index[:unique]}#{'CLUSTERED ' if index[:type] == :clustered}INDEX #{quote_identifier(index_name)} ON #{quote_schema_table(table_name)} #{literal(index[:columns])}#{" INCLUDE #{literal(index[:include])}" if index[:include]}"
302
- end
303
- end
304
308
  end
305
309
 
306
310
  module DatasetMethods
@@ -76,6 +76,11 @@ module Sequel
76
76
  h.values
77
77
  end
78
78
 
79
+ # MySQL namespaces indexes per table.
80
+ def global_index_namespace?
81
+ false
82
+ end
83
+
79
84
  # Use SHOW INDEX FROM to get the index information for the
80
85
  # table.
81
86
  #
@@ -124,10 +129,10 @@ module Sequel
124
129
  server_version >= 50000
125
130
  end
126
131
 
127
- # MySQL doesn't appear to support savepoints inside prepared transactions in >=5.5.12,
128
- # see http://bugs.mysql.com/bug.php?id=64374
132
+ # MySQL doesn't support savepoints inside prepared transactions in from
133
+ # 5.5.12 to 5.5.23, see http://bugs.mysql.com/bug.php?id=64374
129
134
  def supports_savepoints_in_prepared_transactions?
130
- super && server_version <= 50512
135
+ super && (server_version <= 50512 || server_version >= 50523)
131
136
  end
132
137
 
133
138
  # MySQL supports transaction isolation levels
@@ -208,6 +213,26 @@ module Sequel
208
213
  super(table, op)
209
214
  end
210
215
  end
216
+
217
+ # The SQL queries to execute on initial connection
218
+ def mysql_connection_setting_sqls
219
+ sqls = []
220
+
221
+ # Increase timeout so mysql server doesn't disconnect us
222
+ # Value used by default is maximum allowed value on Windows.
223
+ sqls << "SET @@wait_timeout = #{opts[:timeout] || 2147483}"
224
+
225
+ # By default, MySQL 'where id is null' selects the last inserted id
226
+ sqls << "SET SQL_AUTO_IS_NULL=0" unless opts[:auto_is_null]
227
+
228
+ # If the user has specified one or more sql modes, enable them
229
+ if sql_mode = opts[:sql_mode]
230
+ sql_mode = Array(sql_mode).join(',').upcase
231
+ sqls << "SET sql_mode = '#{sql_mode}'"
232
+ end
233
+
234
+ sqls
235
+ end
211
236
 
212
237
  # Use MySQL specific AUTO_INCREMENT text.
213
238
  def auto_increment_sql
@@ -29,6 +29,11 @@ module Sequel
29
29
  :oracle
30
30
  end
31
31
 
32
+ # Oracle namespaces indexes per table.
33
+ def global_index_namespace?
34
+ false
35
+ end
36
+
32
37
  def tables(opts={})
33
38
  m = output_identifier_meth
34
39
  metadata_dataset.from(:tab).server(opts[:server]).select(:tname).filter(:tabtype => 'TABLE').map{|r| m.call(r[:tname])}
@@ -247,9 +247,9 @@ module Sequel
247
247
  # If a schema is given, we only search in that schema, and the returned :table
248
248
  # entry is schema qualified as well.
249
249
  if schema
250
- ds.join!(:pg_namespace___nsp, :oid=>:cl__relnamespace).
251
- where(:nsp___nspname=>im.call(schema))
252
- ref_ds.join!(:pg_namespace___nsp2, :oid=>:cl2__relnamespace).
250
+ ds = ds.join(:pg_namespace___nsp, :oid=>:cl__relnamespace).
251
+ where(:nsp__nspname=>im.call(schema))
252
+ ref_ds = ref_ds.join(:pg_namespace___nsp2, :oid=>:cl2__relnamespace).
253
253
  select_more(:nsp2__nspname___schema)
254
254
  end
255
255
 
@@ -264,7 +264,7 @@ module Sequel
264
264
  end
265
265
  ref_ds.each do |row|
266
266
  r = h[row[:name]]
267
- r[:table] ||= m.call(schema ? SQL::QualifiedIdentifier.new(row[:schema], row[:table]) : row[:table])
267
+ r[:table] ||= schema ? SQL::QualifiedIdentifier.new(m.call(row[:schema]), m.call(row[:table])) : m.call(row[:table])
268
268
  r[:key] ||= []
269
269
  r[:key] << m.call(row[:refcolumn])
270
270
  end
@@ -444,6 +444,41 @@ module Sequel
444
444
 
445
445
  private
446
446
 
447
+ # Handle :using option for set_column_type op.
448
+ def alter_table_sql(table, op)
449
+ case op[:op]
450
+ when :set_column_type
451
+ s = super
452
+ if using = op[:using]
453
+ using = Sequel::LiteralString.new(using) if using.is_a?(String)
454
+ s << ' USING '
455
+ s << literal(using)
456
+ end
457
+ s
458
+ else
459
+ super
460
+ end
461
+ end
462
+
463
+ # If the :synchronous option is given and non-nil, set synchronous_commit
464
+ # appropriately. Valid values for the :synchronous option are true,
465
+ # :on, false, :off, :local, and :remote_write.
466
+ def begin_new_transaction(conn, opts)
467
+ super
468
+ if opts.has_key?(:synchronous)
469
+ case sync = opts[:synchronous]
470
+ when true
471
+ sync = :on
472
+ when false
473
+ sync = :off
474
+ when nil
475
+ return
476
+ end
477
+
478
+ log_connection_execute(conn, "SET LOCAL synchronous_commit = #{sync}")
479
+ end
480
+ end
481
+
447
482
  # If the :prepare option is given and we aren't in a savepoint,
448
483
  # prepare the transaction for a two-phase commit.
449
484
  def commit_transaction(conn, opts={})
@@ -511,6 +546,11 @@ module Sequel
511
546
  def drop_function_sql(name, opts={})
512
547
  "DROP FUNCTION#{' IF EXISTS' if opts[:if_exists]} #{name}#{sql_function_args(opts[:args])}#{' CASCADE' if opts[:cascade]}"
513
548
  end
549
+
550
+ # Support :if_exists, :cascade, and :concurrently options.
551
+ def drop_index_sql(table, op)
552
+ "DROP INDEX#{' CONCURRENTLY' if op[:concurrently]}#{' IF EXISTS' if op[:if_exists]} #{quote_identifier(op[:name] || default_index_name(table, op[:columns]))}#{' CASCADE' if op[:cascade]}"
553
+ end
514
554
 
515
555
  # SQL for dropping a procedural language from the database.
516
556
  def drop_language_sql(name, opts={})
@@ -567,7 +607,7 @@ module Sequel
567
607
  when :spatial
568
608
  index_type = :gist
569
609
  end
570
- "CREATE #{unique}INDEX #{quote_identifier(index_name)} ON #{quote_schema_table(table_name)} #{"USING #{index_type} " if index_type}#{expr}#{filter}"
610
+ "CREATE #{unique}INDEX#{' CONCURRENTLY' if index[:concurrently]} #{quote_identifier(index_name)} ON #{quote_schema_table(table_name)} #{"USING #{index_type} " if index_type}#{expr}#{filter}"
571
611
  end
572
612
 
573
613
  # Backbone of the tables and views support.
@@ -642,6 +682,20 @@ module Sequel
642
682
  end
643
683
  end
644
684
 
685
+ # Set the transaction isolation level on the given connection
686
+ def set_transaction_isolation(conn, opts)
687
+ level = opts.fetch(:isolation, transaction_isolation_level)
688
+ read_only = opts[:read_only]
689
+ deferrable = opts[:deferrable]
690
+ if level || !read_only.nil? || !deferrable.nil?
691
+ sql = "SET TRANSACTION"
692
+ sql << " ISOLATION LEVEL #{Sequel::Database::TRANSACTION_ISOLATION_LEVELS[level]}" if level
693
+ sql << " READ #{read_only ? 'ONLY' : 'WRITE'}" unless read_only.nil?
694
+ sql << " #{'NOT ' unless deferrable}DEFERRABLE" unless deferrable.nil?
695
+ log_connection_execute(conn, sql)
696
+ end
697
+ end
698
+
645
699
  # Turns an array of argument specifiers into an SQL fragment used for function arguments. See create_function_sql.
646
700
  def sql_function_args(args)
647
701
  "(#{Array(args).map{|a| Array(a).reverse.join(' ')}.join(', ')})"
@@ -28,12 +28,6 @@ module Sequel
28
28
  pragma_set(:auto_vacuum, value)
29
29
  end
30
30
 
31
- # Boolean signifying the value of the case_sensitive_likePRAGMA, or nil
32
- # if not using SQLite 3.2.3+.
33
- def case_sensitive_like
34
- pragma_get(:case_sensitive_like).to_i == 1 if sqlite_version >= 30203
35
- end
36
-
37
31
  # Set the case_sensitive_like PRAGMA using the given boolean value, if using
38
32
  # SQLite 3.2.3+. If not using 3.2.3+, no error is raised. See pragma_set.
39
33
  # Consider using the :case_sensitive_like Database option instead.
@@ -252,7 +246,7 @@ module Sequel
252
246
  end
253
247
  end
254
248
 
255
- # The array of column symbols in the table, except for ones given in opts[:except]
249
+ # A name to use for the backup table
256
250
  def backup_table_name(table, opts={})
257
251
  table = table.gsub('`', '')
258
252
  (opts[:times]||1000).times do |i|
@@ -283,17 +277,13 @@ module Sequel
283
277
  ps
284
278
  end
285
279
 
286
- # The array of column schema hashes, except for the ones given in opts[:except]
287
- def defined_columns_for(table, opts={})
280
+ # The array of column schema hashes for the current columns in the table
281
+ def defined_columns_for(table)
288
282
  cols = parse_pragma(table, {})
289
283
  cols.each do |c|
290
284
  c[:default] = LiteralString.new(c[:default]) if c[:default]
291
285
  c[:type] = c[:db_type]
292
286
  end
293
- if opts[:except]
294
- nono= Array(opts[:except]).compact.map{|n| n.to_s}
295
- cols.reject!{|c| nono.include? c[:name] }
296
- end
297
287
  cols
298
288
  end
299
289
 
@@ -144,11 +144,6 @@ module Sequel
144
144
  _execute(:insert, sql, opts)
145
145
  end
146
146
 
147
- # Run the given SQL with the given arguments and return the first value of the first row.
148
- def single_value(sql, opts={})
149
- _execute(:single_value, sql, opts)
150
- end
151
-
152
147
  # Handle Integer and Float arguments, since SQLite can store timestamps as integers and floats.
153
148
  def to_application_timestamp(s)
154
149
  case s
@@ -177,8 +172,6 @@ module Sequel
177
172
  case type
178
173
  when :select
179
174
  log_yield(sql, log_args){conn.query(sql, args, &block)}
180
- when :single_value
181
- log_yield(sql, log_args){conn.get_first_value(sql, args)}
182
175
  when :insert
183
176
  log_yield(sql, log_args){conn.execute(sql, args)}
184
177
  conn.last_insert_row_id