sequel 3.3.0 → 3.4.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.
- data/CHANGELOG +62 -0
- data/README.rdoc +4 -4
- data/doc/release_notes/3.3.0.txt +1 -1
- data/doc/release_notes/3.4.0.txt +325 -0
- data/doc/sharding.rdoc +3 -3
- data/lib/sequel/adapters/amalgalite.rb +1 -1
- data/lib/sequel/adapters/firebird.rb +4 -9
- data/lib/sequel/adapters/jdbc.rb +21 -7
- data/lib/sequel/adapters/mysql.rb +2 -1
- data/lib/sequel/adapters/odbc.rb +7 -21
- data/lib/sequel/adapters/oracle.rb +1 -1
- data/lib/sequel/adapters/postgres.rb +6 -1
- data/lib/sequel/adapters/shared/mssql.rb +11 -0
- data/lib/sequel/adapters/shared/mysql.rb +8 -12
- data/lib/sequel/adapters/shared/oracle.rb +13 -0
- data/lib/sequel/adapters/shared/postgres.rb +5 -10
- data/lib/sequel/adapters/shared/sqlite.rb +21 -1
- data/lib/sequel/adapters/sqlite.rb +2 -2
- data/lib/sequel/core.rb +147 -11
- data/lib/sequel/database.rb +21 -9
- data/lib/sequel/dataset.rb +31 -6
- data/lib/sequel/dataset/convenience.rb +1 -1
- data/lib/sequel/dataset/sql.rb +76 -18
- data/lib/sequel/extensions/inflector.rb +2 -51
- data/lib/sequel/model.rb +16 -10
- data/lib/sequel/model/associations.rb +4 -1
- data/lib/sequel/model/base.rb +13 -6
- data/lib/sequel/model/default_inflections.rb +46 -0
- data/lib/sequel/model/inflections.rb +1 -51
- data/lib/sequel/plugins/boolean_readers.rb +52 -0
- data/lib/sequel/plugins/instance_hooks.rb +57 -0
- data/lib/sequel/plugins/lazy_attributes.rb +13 -1
- data/lib/sequel/plugins/nested_attributes.rb +171 -0
- data/lib/sequel/plugins/serialization.rb +35 -16
- data/lib/sequel/plugins/timestamps.rb +87 -0
- data/lib/sequel/plugins/validation_helpers.rb +8 -1
- data/lib/sequel/sql.rb +33 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/sqlite_spec.rb +11 -6
- data/spec/core/core_sql_spec.rb +29 -0
- data/spec/core/database_spec.rb +16 -7
- data/spec/core/dataset_spec.rb +264 -20
- data/spec/extensions/boolean_readers_spec.rb +86 -0
- data/spec/extensions/inflector_spec.rb +67 -4
- data/spec/extensions/instance_hooks_spec.rb +133 -0
- data/spec/extensions/lazy_attributes_spec.rb +45 -5
- data/spec/extensions/nested_attributes_spec.rb +272 -0
- data/spec/extensions/serialization_spec.rb +64 -1
- data/spec/extensions/timestamps_spec.rb +150 -0
- data/spec/extensions/validation_helpers_spec.rb +18 -0
- data/spec/integration/dataset_test.rb +79 -2
- data/spec/integration/schema_test.rb +17 -0
- data/spec/integration/timezone_test.rb +55 -0
- data/spec/model/associations_spec.rb +19 -7
- data/spec/model/model_spec.rb +29 -0
- data/spec/model/record_spec.rb +36 -0
- data/spec/spec_config.rb +1 -1
- metadata +14 -2
@@ -202,7 +202,6 @@ module Sequel
|
|
202
202
|
BOOL_FALSE = '0'.freeze
|
203
203
|
NULL = LiteralString.new('NULL').freeze
|
204
204
|
COMMA_SEPARATOR = ', '.freeze
|
205
|
-
FIREBIRD_TIMESTAMP_FORMAT = "TIMESTAMP '%Y-%m-%d %H:%M:%S".freeze
|
206
205
|
SELECT_CLAUSE_ORDER = %w'with distinct limit columns from join where group having compounds order'.freeze
|
207
206
|
|
208
207
|
# Yield all rows returned by executing the given SQL and converting
|
@@ -248,6 +247,10 @@ module Sequel
|
|
248
247
|
def insert_select(*values)
|
249
248
|
naked.clone(default_server_opts(:sql=>insert_returning_sql(nil, *values))).single_record
|
250
249
|
end
|
250
|
+
|
251
|
+
def requires_sql_standard_datetimes?
|
252
|
+
true
|
253
|
+
end
|
251
254
|
|
252
255
|
# The order of clauses in the SELECT SQL statement
|
253
256
|
def select_clause_order
|
@@ -273,18 +276,10 @@ module Sequel
|
|
273
276
|
end
|
274
277
|
end
|
275
278
|
|
276
|
-
def literal_datetime(v)
|
277
|
-
"#{v.strftime(FIREBIRD_TIMESTAMP_FORMAT)}.#{sprintf("%04d",(v.sec_fraction * 864000000))}'"
|
278
|
-
end
|
279
|
-
|
280
279
|
def literal_false
|
281
280
|
BOOL_FALSE
|
282
281
|
end
|
283
282
|
|
284
|
-
def literal_time(v)
|
285
|
-
"#{v.strftime(FIREBIRD_TIMESTAMP_FORMAT)}.#{sprintf("%04d",v.usec / 100)}'"
|
286
|
-
end
|
287
|
-
|
288
283
|
def literal_true
|
289
284
|
BOOL_TRUE
|
290
285
|
end
|
data/lib/sequel/adapters/jdbc.rb
CHANGED
@@ -197,13 +197,18 @@ module Sequel
|
|
197
197
|
# Values are subhashes with two keys, :columns and :unique. The value of :columns
|
198
198
|
# is an array of symbols of column names. The value of :unique is true or false
|
199
199
|
# depending on if the index is unique.
|
200
|
-
def indexes(table)
|
201
|
-
indexes = {}
|
200
|
+
def indexes(table, opts={})
|
202
201
|
m = output_identifier_meth
|
203
|
-
|
202
|
+
im = input_identifier_meth
|
203
|
+
schema, table = schema_and_table(table)
|
204
|
+
schema ||= opts[:schema]
|
205
|
+
schema = im.call(schema) if schema
|
206
|
+
table = im.call(table)
|
207
|
+
indexes = {}
|
208
|
+
metadata(:getIndexInfo, nil, schema, table, false, true) do |r|
|
204
209
|
next unless name = r[:column_name]
|
205
210
|
next if respond_to?(:primary_key_index_re, true) and r[:index_name] =~ primary_key_index_re
|
206
|
-
i = indexes[m.call(r[:index_name])] ||= {:columns=>[], :unique
|
211
|
+
i = indexes[m.call(r[:index_name])] ||= {:columns=>[], :unique=>[false, 0].include?(r[:non_unique])}
|
207
212
|
i[:columns] << m.call(name)
|
208
213
|
end
|
209
214
|
indexes
|
@@ -324,6 +329,8 @@ module Sequel
|
|
324
329
|
case arg
|
325
330
|
when Integer
|
326
331
|
cps.setInt(i, arg)
|
332
|
+
when Sequel::SQL::Blob
|
333
|
+
cps.setBytes(i, arg.to_java_bytes)
|
327
334
|
when String
|
328
335
|
cps.setString(i, arg)
|
329
336
|
when Date, Java::JavaSql::Date
|
@@ -332,8 +339,12 @@ module Sequel
|
|
332
339
|
cps.setTimestamp(i, arg)
|
333
340
|
when Float
|
334
341
|
cps.setDouble(i, arg)
|
342
|
+
when TrueClass, FalseClass
|
343
|
+
cps.setBoolean(i, arg)
|
335
344
|
when nil
|
336
345
|
cps.setNull(i, JavaSQL::Types::NULL)
|
346
|
+
else
|
347
|
+
cps.setObject(i, arg)
|
337
348
|
end
|
338
349
|
end
|
339
350
|
|
@@ -348,12 +359,13 @@ module Sequel
|
|
348
359
|
conn
|
349
360
|
end
|
350
361
|
|
351
|
-
#
|
362
|
+
# Parse the table schema for the given table.
|
352
363
|
def schema_parse_table(table, opts={})
|
353
364
|
m = output_identifier_meth
|
354
365
|
im = input_identifier_meth
|
355
366
|
ds = dataset
|
356
367
|
schema, table = schema_and_table(table)
|
368
|
+
schema ||= opts[:schema]
|
357
369
|
schema = im.call(schema) if schema
|
358
370
|
table = im.call(table)
|
359
371
|
pks, ts = [], []
|
@@ -361,7 +373,7 @@ module Sequel
|
|
361
373
|
pks << h[:column_name]
|
362
374
|
end
|
363
375
|
metadata(:getColumns, nil, schema, table, nil) do |h|
|
364
|
-
ts << [m.call(h[:column_name]), {:type=>schema_column_type(h[:type_name]), :db_type=>h[:type_name], :default=>(h[:column_def] == '' ? nil : h[:column_def]), :allow_null=>(h[:nullable] != 0), :primary_key=>pks.include?(h[:column_name])}]
|
376
|
+
ts << [m.call(h[:column_name]), {:type=>schema_column_type(h[:type_name]), :db_type=>h[:type_name], :default=>(h[:column_def] == '' ? nil : h[:column_def]), :allow_null=>(h[:nullable] != 0), :primary_key=>pks.include?(h[:column_name]), :column_size=>h[:column_size]}]
|
365
377
|
end
|
366
378
|
ts
|
367
379
|
end
|
@@ -459,7 +471,7 @@ module Sequel
|
|
459
471
|
def convert_type(v)
|
460
472
|
case v
|
461
473
|
when Java::JavaSQL::Timestamp, Java::JavaSQL::Time
|
462
|
-
Sequel.
|
474
|
+
Sequel.database_to_application_timestamp(v.to_string)
|
463
475
|
when Java::JavaSQL::Date
|
464
476
|
Sequel.string_to_date(v.to_string)
|
465
477
|
when Java::JavaIo::BufferedReader
|
@@ -468,6 +480,8 @@ module Sequel
|
|
468
480
|
lines.join("\n")
|
469
481
|
when Java::JavaMath::BigDecimal
|
470
482
|
BigDecimal.new(v.to_string)
|
483
|
+
when Java::byte[]
|
484
|
+
Sequel::SQL::Blob.new(String.from_java_bytes(v))
|
471
485
|
else
|
472
486
|
v
|
473
487
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'mysql'
|
2
|
+
raise(LoadError, "require 'mysql' did not define Mysql::CLIENT_MULTI_RESULTS!\n You are probably using the pure ruby mysql.rb driver,\n which Sequel does not support. You need to install\n the C based adapter, and make sure that the mysql.so\n file is loaded instead of the mysql.rb file.\n") unless defined?(Mysql::CLIENT_MULTI_RESULTS)
|
2
3
|
Sequel.require %w'shared/mysql utils/stored_procedures', 'adapters'
|
3
4
|
|
4
5
|
module Sequel
|
@@ -28,7 +29,7 @@ module Sequel
|
|
28
29
|
[2, 3, 8, 9, 13, 247, 248] => lambda{|v| v.to_i}, # integer
|
29
30
|
[4, 5] => lambda{|v| v.to_f}, # float
|
30
31
|
[10, 14] => lambda{|v| convert_date_time(:string_to_date, v)}, # date
|
31
|
-
[7, 12] => lambda{|v| convert_date_time(:
|
32
|
+
[7, 12] => lambda{|v| convert_date_time(:database_to_application_timestamp, v)}, # datetime
|
32
33
|
[11] => lambda{|v| convert_date_time(:string_to_time, v)}, # time
|
33
34
|
[249, 250, 251, 252] => lambda{|v| Sequel::SQL::Blob.new(v)} # blob
|
34
35
|
}
|
data/lib/sequel/adapters/odbc.rb
CHANGED
@@ -89,9 +89,8 @@ module Sequel
|
|
89
89
|
class Dataset < Sequel::Dataset
|
90
90
|
BOOL_TRUE = '1'.freeze
|
91
91
|
BOOL_FALSE = '0'.freeze
|
92
|
-
ODBC_TIMESTAMP_FORMAT = "{ts '%Y-%m-%d %H:%M:%S'}".freeze
|
93
|
-
ODBC_TIMESTAMP_FORMAT_USEC = "{ts '%Y-%m-%d %H:%M:%S.%%i'}".freeze
|
94
92
|
ODBC_DATE_FORMAT = "{d '%Y-%m-%d'}".freeze
|
93
|
+
TIMESTAMP_FORMAT="{ts '%Y-%m-%d %H:%M:%S%N'}".freeze
|
95
94
|
|
96
95
|
def fetch_rows(sql, &block)
|
97
96
|
execute(sql) do |s|
|
@@ -110,14 +109,6 @@ module Sequel
|
|
110
109
|
end
|
111
110
|
|
112
111
|
private
|
113
|
-
|
114
|
-
def _literal_datetime(v, usec)
|
115
|
-
if usec >= 1000
|
116
|
-
v.strftime(ODBC_TIMESTAMP_FORMAT_USEC) % (usec.to_f/1000).round
|
117
|
-
else
|
118
|
-
v.strftime(ODBC_TIMESTAMP_FORMAT)
|
119
|
-
end
|
120
|
-
end
|
121
112
|
|
122
113
|
def convert_odbc_value(v)
|
123
114
|
# When fetching a result set, the Ruby ODBC driver converts all ODBC
|
@@ -128,25 +119,24 @@ module Sequel
|
|
128
119
|
# ODBCColumn#mapSqlTypeToGenericType and Column#klass.
|
129
120
|
case v
|
130
121
|
when ::ODBC::TimeStamp
|
131
|
-
|
122
|
+
Sequel.database_to_application_timestamp([v.year, v.month, v.day, v.hour, v.minute, v.second])
|
132
123
|
when ::ODBC::Time
|
133
|
-
now
|
134
|
-
Time.gm(now.year, now.month, now.day, v.hour, v.minute, v.second)
|
124
|
+
Sequel.database_to_application_timestamp([now.year, now.month, now.day, v.hour, v.minute, v.second])
|
135
125
|
when ::ODBC::Date
|
136
126
|
Date.new(v.year, v.month, v.day)
|
137
127
|
else
|
138
128
|
v
|
139
129
|
end
|
140
130
|
end
|
131
|
+
|
132
|
+
def default_timestamp_format
|
133
|
+
TIMESTAMP_FORMAT
|
134
|
+
end
|
141
135
|
|
142
136
|
def literal_date(v)
|
143
137
|
v.strftime(ODBC_DATE_FORMAT)
|
144
138
|
end
|
145
139
|
|
146
|
-
def literal_datetime(v)
|
147
|
-
_literal_datetime(v, v.sec_fraction * 86400000000)
|
148
|
-
end
|
149
|
-
|
150
140
|
def literal_false
|
151
141
|
BOOL_FALSE
|
152
142
|
end
|
@@ -154,10 +144,6 @@ module Sequel
|
|
154
144
|
def literal_true
|
155
145
|
BOOL_TRUE
|
156
146
|
end
|
157
|
-
|
158
|
-
def literal_time(v)
|
159
|
-
_literal_datetime(v, v.usec)
|
160
|
-
end
|
161
147
|
end
|
162
148
|
end
|
163
149
|
end
|
@@ -65,6 +65,11 @@ rescue LoadError => e
|
|
65
65
|
unless defined?(CONNECTION_OK)
|
66
66
|
CONNECTION_OK = -1
|
67
67
|
end
|
68
|
+
unless method_defined?(:status)
|
69
|
+
def status
|
70
|
+
CONNECTION_OK
|
71
|
+
end
|
72
|
+
end
|
68
73
|
end
|
69
74
|
class PGresult
|
70
75
|
alias_method :nfields, :num_fields unless method_defined?(:nfields)
|
@@ -94,7 +99,7 @@ module Sequel
|
|
94
99
|
[790, 1700] => lambda{|s| BigDecimal.new(s)}, # numeric
|
95
100
|
[1082] => lambda{|s| @use_iso_date_format ? Date.new(*s.split("-").map{|x| x.to_i}) : Sequel.string_to_date(s)}, # date
|
96
101
|
[1083, 1266] => lambda{|s| Sequel.string_to_time(s)}, # time
|
97
|
-
[1114, 1184] => lambda{|s| Sequel.
|
102
|
+
[1114, 1184] => lambda{|s| Sequel.database_to_application_timestamp(s)}, # timestamp
|
98
103
|
}
|
99
104
|
PG_TYPE_PROCS.each do |k,v|
|
100
105
|
k.each{|n| PG_TYPES[n] = v}
|
@@ -148,6 +148,7 @@ module Sequel
|
|
148
148
|
SELECT_CLAUSE_ORDER = %w'with limit distinct columns from table_options join where group order having compounds'.freeze
|
149
149
|
TIMESTAMP_FORMAT = "'%Y-%m-%d %H:%M:%S'".freeze
|
150
150
|
WILDCARD = LiteralString.new('*').freeze
|
151
|
+
CONSTANT_MAP = {:CURRENT_DATE=>'CAST(CURRENT_TIMESTAMP AS DATE)'.freeze, :CURRENT_TIME=>'CAST(CURRENT_TIMESTAMP AS TIME)'.freeze}
|
151
152
|
|
152
153
|
# MSSQL uses + for string concatenation
|
153
154
|
def complex_expression_sql(op, args)
|
@@ -159,6 +160,11 @@ module Sequel
|
|
159
160
|
end
|
160
161
|
end
|
161
162
|
|
163
|
+
# MSSQL doesn't support the SQL standard CURRENT_DATE or CURRENT_TIME
|
164
|
+
def constant_sql(constant)
|
165
|
+
CONSTANT_MAP[constant] || super
|
166
|
+
end
|
167
|
+
|
162
168
|
# When returning all rows, if an offset is used, delete the row_number column
|
163
169
|
# before yielding the row.
|
164
170
|
def each(&block)
|
@@ -222,6 +228,11 @@ module Sequel
|
|
222
228
|
false
|
223
229
|
end
|
224
230
|
|
231
|
+
# MSSQL supports timezones in literal timestamps
|
232
|
+
def supports_timestamp_timezones?
|
233
|
+
true
|
234
|
+
end
|
235
|
+
|
225
236
|
# MSSQL 2005+ supports window functions
|
226
237
|
def supports_window_functions?
|
227
238
|
true
|
@@ -198,7 +198,6 @@ module Sequel
|
|
198
198
|
module DatasetMethods
|
199
199
|
BOOL_TRUE = '1'.freeze
|
200
200
|
BOOL_FALSE = '0'.freeze
|
201
|
-
TIMESTAMP_FORMAT = "'%Y-%m-%d %H:%M:%S'".freeze
|
202
201
|
COMMA_SEPARATOR = ', '.freeze
|
203
202
|
SELECT_CLAUSE_ORDER = %w'distinct columns from join where group having compounds order limit'.freeze
|
204
203
|
|
@@ -360,6 +359,13 @@ module Sequel
|
|
360
359
|
def supports_intersect_except?
|
361
360
|
false
|
362
361
|
end
|
362
|
+
|
363
|
+
# MySQL does support fractional timestamps in literal timestamps, but it
|
364
|
+
# ignores them. Also, using them seems to cause problems on 1.9. Since
|
365
|
+
# they are ignored anyway, not using them is probably best.
|
366
|
+
def supports_timestamp_usecs?
|
367
|
+
false
|
368
|
+
end
|
363
369
|
|
364
370
|
# MySQL supports ORDER and LIMIT clauses in UPDATE statements.
|
365
371
|
def update_sql(values)
|
@@ -385,22 +391,12 @@ module Sequel
|
|
385
391
|
def insert_default_values_sql
|
386
392
|
"#{insert_sql_base}#{source_list(@opts[:from])} () VALUES ()"
|
387
393
|
end
|
388
|
-
|
389
|
-
# Use MySQL Timestamp format
|
390
|
-
def literal_datetime(v)
|
391
|
-
v.strftime(TIMESTAMP_FORMAT)
|
392
|
-
end
|
393
|
-
|
394
|
+
|
394
395
|
# Use 0 for false on MySQL
|
395
396
|
def literal_false
|
396
397
|
BOOL_FALSE
|
397
398
|
end
|
398
399
|
|
399
|
-
# Use MySQL Timestamp format
|
400
|
-
def literal_time(v)
|
401
|
-
v.strftime(TIMESTAMP_FORMAT)
|
402
|
-
end
|
403
|
-
|
404
400
|
# Use 1 for true on MySQL
|
405
401
|
def literal_true
|
406
402
|
BOOL_TRUE
|
@@ -121,6 +121,11 @@ module Sequel
|
|
121
121
|
false
|
122
122
|
end
|
123
123
|
|
124
|
+
# Oracle supports timezones in literal timestamps.
|
125
|
+
def supports_timestamp_timezones?
|
126
|
+
true
|
127
|
+
end
|
128
|
+
|
124
129
|
# Oracle supports window functions
|
125
130
|
def supports_window_functions?
|
126
131
|
true
|
@@ -143,6 +148,14 @@ module Sequel
|
|
143
148
|
SELECT_CLAUSE_ORDER
|
144
149
|
end
|
145
150
|
|
151
|
+
# Modify the SQL to add the list of tables to select FROM
|
152
|
+
# Oracle doesn't support select without FROM clause
|
153
|
+
# so add the dummy DUAL table if the dataset doesn't select
|
154
|
+
# from a table.
|
155
|
+
def select_from_sql(sql)
|
156
|
+
sql << " FROM #{source_list(@opts[:from] || ['DUAL'])}"
|
157
|
+
end
|
158
|
+
|
146
159
|
# Oracle requires a subselect to do limit and offset
|
147
160
|
def select_limit_sql(sql)
|
148
161
|
if limit = @opts[:limit]
|
@@ -693,6 +693,11 @@ module Sequel
|
|
693
693
|
["#{insert_sql_base}#{source_list(@opts[:from])} (#{identifier_list(columns)}) VALUES #{values}"]
|
694
694
|
end
|
695
695
|
|
696
|
+
# PostgreSQL supports timezones in literal timestamps
|
697
|
+
def supports_timestamp_timezones?
|
698
|
+
true
|
699
|
+
end
|
700
|
+
|
696
701
|
# PostgreSQL 8.4+ supports window functions
|
697
702
|
def supports_window_functions?
|
698
703
|
server_version >= 80400
|
@@ -716,11 +721,6 @@ module Sequel
|
|
716
721
|
"'#{v.gsub(/[\000-\037\047\134\177-\377]/){|b| "\\#{("%o" % b[0..1].unpack("C")[0]).rjust(3, '0')}"}}'"
|
717
722
|
end
|
718
723
|
|
719
|
-
# PostgreSQL supports fractional timestamps
|
720
|
-
def literal_datetime(v)
|
721
|
-
"#{v.strftime(PG_TIMESTAMP_FORMAT)}.#{sprintf("%06d", (v.sec_fraction * 86400000000).to_i)}'"
|
722
|
-
end
|
723
|
-
|
724
724
|
# PostgreSQL uses FALSE for false values
|
725
725
|
def literal_false
|
726
726
|
BOOL_FALSE
|
@@ -736,11 +736,6 @@ module Sequel
|
|
736
736
|
BOOL_TRUE
|
737
737
|
end
|
738
738
|
|
739
|
-
# PostgreSQL supports fractional times
|
740
|
-
def literal_time(v)
|
741
|
-
"#{v.strftime(PG_TIMESTAMP_FORMAT)}.#{sprintf("%06d",v.usec)}'"
|
742
|
-
end
|
743
|
-
|
744
739
|
# The order of clauses in the SELECT SQL statement
|
745
740
|
def select_clause_order
|
746
741
|
server_version >= 80400 ? SELECT_CLAUSE_ORDER_84 : SELECT_CLAUSE_ORDER
|
@@ -10,7 +10,9 @@ module Sequel
|
|
10
10
|
# Run all alter_table commands in a transaction. This is technically only
|
11
11
|
# needed for drop column.
|
12
12
|
def alter_table(name, generator=nil, &block)
|
13
|
-
|
13
|
+
remove_cached_schema(name)
|
14
|
+
generator ||= Schema::AlterTableGenerator.new(self, &block)
|
15
|
+
transaction{generator.operations.each{|op| alter_table_sql_list(name, [op]).flatten.each{|sql| execute_ddl(sql)}}}
|
14
16
|
end
|
15
17
|
|
16
18
|
# A symbol signifying the value of the auto_vacuum PRAGMA.
|
@@ -164,6 +166,7 @@ module Sequel
|
|
164
166
|
# from the existing table into the new table, deleting the existing table
|
165
167
|
# and renaming the new table to the existing table's name.
|
166
168
|
def duplicate_table(table, opts={})
|
169
|
+
remove_cached_schema(table)
|
167
170
|
def_columns = defined_columns_for(table)
|
168
171
|
old_columns = def_columns.map{|c| c[:name]}
|
169
172
|
opts[:old_columns_proc].call(old_columns) if opts[:old_columns_proc]
|
@@ -233,6 +236,7 @@ module Sequel
|
|
233
236
|
# Instance methods for datasets that connect to an SQLite database
|
234
237
|
module DatasetMethods
|
235
238
|
SELECT_CLAUSE_ORDER = %w'distinct columns from join where group having compounds order limit'.freeze
|
239
|
+
CONSTANT_MAP = {:CURRENT_DATE=>"date(CURRENT_TIMESTAMP, 'localtime')".freeze, :CURRENT_TIMESTAMP=>"datetime(CURRENT_TIMESTAMP, 'localtime')".freeze, :CURRENT_TIME=>"time(CURRENT_TIMESTAMP, 'localtime')".freeze}
|
236
240
|
|
237
241
|
# SQLite does not support pattern matching via regular expressions.
|
238
242
|
# SQLite is case insensitive (depending on pragma), so use LIKE for
|
@@ -249,6 +253,11 @@ module Sequel
|
|
249
253
|
end
|
250
254
|
end
|
251
255
|
|
256
|
+
# MSSQL doesn't support the SQL standard CURRENT_DATE or CURRENT_TIME
|
257
|
+
def constant_sql(constant)
|
258
|
+
CONSTANT_MAP[constant] || super
|
259
|
+
end
|
260
|
+
|
252
261
|
# SQLite performs a TRUNCATE style DELETE if no filter is specified.
|
253
262
|
# Since we want to always return the count of records, add a condition
|
254
263
|
# that is always true and then delete.
|
@@ -284,6 +293,12 @@ module Sequel
|
|
284
293
|
def supports_is_true?
|
285
294
|
false
|
286
295
|
end
|
296
|
+
|
297
|
+
# SQLite supports timezones in literal timestamps, since it stores them
|
298
|
+
# as text.
|
299
|
+
def supports_timestamp_timezones?
|
300
|
+
true
|
301
|
+
end
|
287
302
|
|
288
303
|
private
|
289
304
|
|
@@ -304,6 +319,11 @@ module Sequel
|
|
304
319
|
def select_clause_order
|
305
320
|
SELECT_CLAUSE_ORDER
|
306
321
|
end
|
322
|
+
|
323
|
+
# SQLite treats a DELETE with no WHERE clause as a TRUNCATE
|
324
|
+
def _truncate_sql(table)
|
325
|
+
"DELETE FROM #{table}"
|
326
|
+
end
|
307
327
|
end
|
308
328
|
end
|
309
329
|
end
|