sequel 3.35.0 → 3.36.0

Sign up to get free protection for your applications and to get access to all the features.
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