sequel 2.4.0 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +34 -0
- data/Rakefile +1 -1
- data/lib/sequel_core.rb +16 -7
- data/lib/sequel_core/adapters/ado.rb +6 -2
- data/lib/sequel_core/adapters/db2.rb +1 -1
- data/lib/sequel_core/adapters/jdbc.rb +2 -2
- data/lib/sequel_core/adapters/jdbc/postgresql.rb +22 -10
- data/lib/sequel_core/adapters/mysql.rb +2 -2
- data/lib/sequel_core/adapters/odbc.rb +6 -2
- data/lib/sequel_core/adapters/postgres.rb +25 -14
- data/lib/sequel_core/adapters/shared/mysql.rb +15 -35
- data/lib/sequel_core/adapters/shared/postgres.rb +137 -77
- data/lib/sequel_core/adapters/sqlite.rb +2 -2
- data/lib/sequel_core/core_ext.rb +11 -7
- data/lib/sequel_core/database.rb +18 -1
- data/lib/sequel_core/dataset.rb +23 -7
- data/lib/sequel_core/dataset/convenience.rb +1 -1
- data/lib/sequel_core/dataset/sql.rb +46 -31
- data/lib/sequel_core/exceptions.rb +4 -0
- data/lib/sequel_core/schema/generator.rb +43 -3
- data/lib/sequel_core/schema/sql.rb +52 -26
- data/lib/sequel_model.rb +2 -5
- data/lib/sequel_model/associations.rb +3 -3
- data/lib/sequel_model/base.rb +19 -13
- data/lib/sequel_model/record.rb +19 -11
- data/lib/sequel_model/schema.rb +10 -4
- data/lib/sequel_model/validations.rb +20 -7
- data/spec/adapters/mysql_spec.rb +1 -1
- data/spec/adapters/postgres_spec.rb +64 -9
- data/spec/integration/dataset_test.rb +32 -0
- data/spec/sequel_core/core_sql_spec.rb +38 -0
- data/spec/sequel_core/database_spec.rb +16 -1
- data/spec/sequel_core/dataset_spec.rb +66 -1
- data/spec/sequel_core/schema_generator_spec.rb +23 -3
- data/spec/sequel_core/schema_spec.rb +175 -4
- data/spec/sequel_model/record_spec.rb +47 -0
- data/spec/sequel_model/validations_spec.rb +70 -0
- metadata +2 -2
@@ -78,7 +78,7 @@ module Sequel
|
|
78
78
|
conn.transaction{result = yield(conn)}
|
79
79
|
result
|
80
80
|
rescue ::Exception => e
|
81
|
-
|
81
|
+
transaction_error(e, SQLite3::Exception)
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
@@ -92,7 +92,7 @@ module Sequel
|
|
92
92
|
log_info(sql, opts[:arguments])
|
93
93
|
synchronize(opts[:server]){|conn| yield conn}
|
94
94
|
rescue SQLite3::Exception => e
|
95
|
-
|
95
|
+
raise_error(e)
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
data/lib/sequel_core/core_ext.rb
CHANGED
@@ -160,18 +160,18 @@ class String
|
|
160
160
|
# Converts a string into a Date object.
|
161
161
|
def to_date
|
162
162
|
begin
|
163
|
-
Date.parse(self)
|
163
|
+
Date.parse(self, Sequel.convert_two_digit_years)
|
164
164
|
rescue => e
|
165
|
-
raise Sequel::Error::InvalidValue, "Invalid
|
165
|
+
raise Sequel::Error::InvalidValue, "Invalid Date value '#{self}' (#{e.message})"
|
166
166
|
end
|
167
167
|
end
|
168
168
|
|
169
169
|
# Converts a string into a DateTime object.
|
170
170
|
def to_datetime
|
171
171
|
begin
|
172
|
-
DateTime.parse(self)
|
172
|
+
DateTime.parse(self, Sequel.convert_two_digit_years)
|
173
173
|
rescue => e
|
174
|
-
raise Sequel::Error::InvalidValue, "Invalid
|
174
|
+
raise Sequel::Error::InvalidValue, "Invalid DateTime value '#{self}' (#{e.message})"
|
175
175
|
end
|
176
176
|
end
|
177
177
|
|
@@ -179,9 +179,13 @@ class String
|
|
179
179
|
# value of Sequel.datetime_class
|
180
180
|
def to_sequel_time
|
181
181
|
begin
|
182
|
-
Sequel.datetime_class
|
182
|
+
if Sequel.datetime_class == DateTime
|
183
|
+
DateTime.parse(self, Sequel.convert_two_digit_years)
|
184
|
+
else
|
185
|
+
Sequel.datetime_class.parse(self)
|
186
|
+
end
|
183
187
|
rescue => e
|
184
|
-
raise Sequel::Error::InvalidValue, "Invalid
|
188
|
+
raise Sequel::Error::InvalidValue, "Invalid #{Sequel.datetime_class} value '#{self}' (#{e.message})"
|
185
189
|
end
|
186
190
|
end
|
187
191
|
|
@@ -190,7 +194,7 @@ class String
|
|
190
194
|
begin
|
191
195
|
Time.parse(self)
|
192
196
|
rescue => e
|
193
|
-
raise Sequel::Error::InvalidValue, "Invalid
|
197
|
+
raise Sequel::Error::InvalidValue, "Invalid Time value '#{self}' (#{e.message})"
|
194
198
|
end
|
195
199
|
end
|
196
200
|
end
|
data/lib/sequel_core/database.rb
CHANGED
@@ -371,7 +371,7 @@ module Sequel
|
|
371
371
|
rescue Exception => e
|
372
372
|
log_info(SQL_ROLLBACK)
|
373
373
|
conn.execute(SQL_ROLLBACK)
|
374
|
-
|
374
|
+
transaction_error(e)
|
375
375
|
ensure
|
376
376
|
unless e
|
377
377
|
log_info(SQL_COMMIT)
|
@@ -495,6 +495,23 @@ module Sequel
|
|
495
495
|
def connection_pool_default_options
|
496
496
|
{}
|
497
497
|
end
|
498
|
+
|
499
|
+
# Convert the given exception to a DatabaseError, keeping message
|
500
|
+
# and traceback.
|
501
|
+
def raise_error(exception, opts={})
|
502
|
+
if !opts[:classes] || exception.is_one_of?(*opts[:classes])
|
503
|
+
e = DatabaseError.new("#{exception.class} #{exception.message}")
|
504
|
+
e.set_backtrace(exception.backtrace)
|
505
|
+
raise e
|
506
|
+
else
|
507
|
+
raise exception
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
# Raise a database error unless the exception is an Error::Rollback.
|
512
|
+
def transaction_error(e, *classes)
|
513
|
+
raise_error(e, :classes=>classes) unless Error::Rollback === e
|
514
|
+
end
|
498
515
|
end
|
499
516
|
end
|
500
517
|
|
data/lib/sequel_core/dataset.rb
CHANGED
@@ -52,7 +52,8 @@ module Sequel
|
|
52
52
|
group group_and_count group_by having inner_join intersect invert join
|
53
53
|
left_outer_join limit naked or order order_by order_more paginate query reject
|
54
54
|
reverse reverse_order right_outer_join select select_all select_more
|
55
|
-
set_graph_aliases set_model sort sort_by
|
55
|
+
set_defaults set_graph_aliases set_model set_overrides sort sort_by
|
56
|
+
unfiltered union unordered where'.collect{|x| x.to_sym}
|
56
57
|
|
57
58
|
NOTIMPL_MSG = "This method must be overridden in Sequel adapters".freeze
|
58
59
|
STOCK_TRANSFORMS = {
|
@@ -183,14 +184,15 @@ module Sequel
|
|
183
184
|
end
|
184
185
|
end
|
185
186
|
|
186
|
-
# Deletes the records in the dataset.
|
187
|
+
# Deletes the records in the dataset. The returned value is generally the
|
188
|
+
# number of records deleted, but that is adapter dependent.
|
187
189
|
def delete(*args)
|
188
190
|
execute_dui(delete_sql(*args))
|
189
191
|
end
|
190
192
|
|
191
193
|
# Iterates over the records in the dataset.
|
192
194
|
def each(opts = nil, &block)
|
193
|
-
if graph
|
195
|
+
if @opts[:graph] and !(opts && opts[:graph] == false)
|
194
196
|
graph_each(opts, &block)
|
195
197
|
else
|
196
198
|
row_proc = @row_proc unless opts && opts[:naked]
|
@@ -205,13 +207,14 @@ module Sequel
|
|
205
207
|
end
|
206
208
|
|
207
209
|
# Executes a select query and fetches records, passing each record to the
|
208
|
-
# supplied block.
|
210
|
+
# supplied block. The yielded records are generally hashes with symbol keys,
|
211
|
+
# but that is adapter dependent.
|
209
212
|
def fetch_rows(sql, &block)
|
210
213
|
raise NotImplementedError, NOTIMPL_MSG
|
211
214
|
end
|
212
215
|
|
213
|
-
# Inserts values into the associated table.
|
214
|
-
#
|
216
|
+
# Inserts values into the associated table. The returned value is generally
|
217
|
+
# the value of the primary key for the inserted row, but that is adapter dependent.
|
215
218
|
def insert(*values)
|
216
219
|
execute_dui(insert_sql(*values))
|
217
220
|
end
|
@@ -260,6 +263,12 @@ module Sequel
|
|
260
263
|
update(*args)
|
261
264
|
end
|
262
265
|
|
266
|
+
# Set the default values for insert and update statements. The values passed
|
267
|
+
# to insert or update are merged into this hash.
|
268
|
+
def set_defaults(hash)
|
269
|
+
clone(:defaults=>(@opts[:defaults]||{}).merge(hash))
|
270
|
+
end
|
271
|
+
|
263
272
|
# Associates or disassociates the dataset with a model(s). If
|
264
273
|
# nil is specified, the dataset is turned into a naked dataset and returns
|
265
274
|
# records as hashes. If a model class specified, the dataset is modified
|
@@ -342,6 +351,12 @@ module Sequel
|
|
342
351
|
self
|
343
352
|
end
|
344
353
|
|
354
|
+
# Set values that override hash arguments given to insert and update statements.
|
355
|
+
# This hash is merged into the hash provided to insert or update.
|
356
|
+
def set_overrides(hash)
|
357
|
+
clone(:overrides=>hash.merge(@opts[:overrides]||{}))
|
358
|
+
end
|
359
|
+
|
345
360
|
# Sets a value transform which is used to convert values loaded and saved
|
346
361
|
# to/from the database. The transform should be supplied as a hash. Each
|
347
362
|
# value in the hash should be an array containing two proc objects - one
|
@@ -399,7 +414,8 @@ module Sequel
|
|
399
414
|
end
|
400
415
|
end
|
401
416
|
|
402
|
-
# Updates values for the dataset.
|
417
|
+
# Updates values for the dataset. The returned value is generally the
|
418
|
+
# number of rows updated, but that is adapter dependent.
|
403
419
|
def update(*args)
|
404
420
|
execute_dui(update_sql(*args))
|
405
421
|
end
|
@@ -184,7 +184,7 @@ module Sequel
|
|
184
184
|
# Returns the first value of the first record in the dataset.
|
185
185
|
# Returns nil if dataset is empty.
|
186
186
|
def single_value(opts = nil)
|
187
|
-
if r =
|
187
|
+
if r = single_record((opts||{}).merge(:graph=>false, :naked=>true))
|
188
188
|
r.values.first
|
189
189
|
end
|
190
190
|
end
|
@@ -70,6 +70,10 @@ module Sequel
|
|
70
70
|
def delete_sql(opts = nil)
|
71
71
|
opts = opts ? @opts.merge(opts) : @opts
|
72
72
|
|
73
|
+
if sql = opts[:sql]
|
74
|
+
return sql
|
75
|
+
end
|
76
|
+
|
73
77
|
if opts[:group]
|
74
78
|
raise Error::InvalidOperation, "Grouped datasets cannot be deleted from"
|
75
79
|
elsif opts[:from].is_a?(Array) && opts[:from].size > 1
|
@@ -256,41 +260,46 @@ module Sequel
|
|
256
260
|
# dataset.insert_sql(:a => 1, :b => 2) #=>
|
257
261
|
# 'INSERT INTO items (a, b) VALUES (1, 2)'
|
258
262
|
def insert_sql(*values)
|
259
|
-
if
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
263
|
+
if sql = @opts[:sql]
|
264
|
+
return sql
|
265
|
+
end
|
266
|
+
|
267
|
+
from = source_list(@opts[:from])
|
268
|
+
case values.size
|
269
|
+
when 0
|
270
|
+
values = {}
|
271
|
+
when 1
|
272
|
+
vals = values.at(0)
|
273
|
+
if vals.is_one_of?(Hash, Dataset, Array)
|
274
|
+
values = vals
|
275
|
+
elsif vals.respond_to?(:values)
|
276
|
+
values = vals.values
|
267
277
|
end
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
"INSERT INTO #{from} (#{fl.join(COMMA_SEPARATOR)}) VALUES (#{vl.join(COMMA_SEPARATOR)})"
|
284
|
-
end
|
285
|
-
when Dataset
|
286
|
-
"INSERT INTO #{from} #{literal(values)}"
|
278
|
+
end
|
279
|
+
|
280
|
+
case values
|
281
|
+
when Array
|
282
|
+
if values.empty?
|
283
|
+
insert_default_values_sql
|
284
|
+
else
|
285
|
+
"INSERT INTO #{from} VALUES #{literal(values)}"
|
286
|
+
end
|
287
|
+
when Hash
|
288
|
+
values = @opts[:defaults].merge(values) if @opts[:defaults]
|
289
|
+
values = values.merge(@opts[:overrides]) if @opts[:overrides]
|
290
|
+
values = transform_save(values) if @transform
|
291
|
+
if values.empty?
|
292
|
+
insert_default_values_sql
|
287
293
|
else
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
294
|
+
fl, vl = [], []
|
295
|
+
values.each do |k, v|
|
296
|
+
fl << literal(String === k ? k.to_sym : k)
|
297
|
+
vl << literal(v)
|
292
298
|
end
|
299
|
+
"INSERT INTO #{from} (#{fl.join(COMMA_SEPARATOR)}) VALUES (#{vl.join(COMMA_SEPARATOR)})"
|
293
300
|
end
|
301
|
+
when Dataset
|
302
|
+
"INSERT INTO #{from} #{literal(values)}"
|
294
303
|
end
|
295
304
|
end
|
296
305
|
|
@@ -698,6 +707,10 @@ module Sequel
|
|
698
707
|
def update_sql(values = {}, opts = nil)
|
699
708
|
opts = opts ? @opts.merge(opts) : @opts
|
700
709
|
|
710
|
+
if sql = opts[:sql]
|
711
|
+
return sql
|
712
|
+
end
|
713
|
+
|
701
714
|
if opts[:group]
|
702
715
|
raise Error::InvalidOperation, "A grouped dataset cannot be updated"
|
703
716
|
elsif (opts[:from].size > 1) or opts[:join]
|
@@ -706,6 +719,8 @@ module Sequel
|
|
706
719
|
|
707
720
|
sql = "UPDATE #{source_list(@opts[:from])} SET "
|
708
721
|
set = if values.is_a?(Hash)
|
722
|
+
values = opts[:defaults].merge(values) if opts[:defaults]
|
723
|
+
values = values.merge(opts[:overrides]) if opts[:overrides]
|
709
724
|
# get values from hash
|
710
725
|
values = transform_save(values) if @transform
|
711
726
|
values.map do |k, v|
|
@@ -27,4 +27,8 @@ module Sequel
|
|
27
27
|
# A transaction block will catch this error and won't pass further up the stack.
|
28
28
|
class Rollback < Error ; end
|
29
29
|
end
|
30
|
+
|
31
|
+
# Generic error raised by the database adapters, indicating a
|
32
|
+
# problem originating from the database server.
|
33
|
+
class DatabaseError < Error; end
|
30
34
|
end
|
@@ -48,6 +48,8 @@ module Sequel
|
|
48
48
|
# to whatever the database default is.
|
49
49
|
# * :on_delete - Specify the behavior of this column when being deleted.
|
50
50
|
# See Schema::SQL#on_delete_clause for options.
|
51
|
+
# * :on_update - Specify the behavior of this column when being updated.
|
52
|
+
# See Schema::SQL#on_delete_clause for options.
|
51
53
|
# * :size - The size of the column, generally used with string
|
52
54
|
# columns to specify the maximum number of characters the column will hold.
|
53
55
|
# * :unique - Mark the column is unique, generally has the same effect as
|
@@ -62,7 +64,8 @@ module Sequel
|
|
62
64
|
# Adds a named constraint (or unnamed if name is nil) to the DDL,
|
63
65
|
# with the given block or args.
|
64
66
|
def constraint(name, *args, &block)
|
65
|
-
@columns << {:name => name, :type => :check, :check => block || args
|
67
|
+
@columns << {:name => name, :type => :check, :check => block || args,
|
68
|
+
:constraint_type => :check}
|
66
69
|
end
|
67
70
|
|
68
71
|
# Return the DDL created by the generator as a array of two elements,
|
@@ -85,6 +88,7 @@ module Sequel
|
|
85
88
|
else
|
86
89
|
raise(Error, "The seconds argument to foreign_key should be a Hash, Symbol, or nil")
|
87
90
|
end
|
91
|
+
return composite_foreign_key(name, opts) if name.is_a?(Array)
|
88
92
|
column(name, :integer, opts)
|
89
93
|
end
|
90
94
|
|
@@ -118,6 +122,7 @@ module Sequel
|
|
118
122
|
# can optionally provide a type argument and/or an options hash argument
|
119
123
|
# to change the primary key options. See column for available options.
|
120
124
|
def primary_key(name, *args)
|
125
|
+
return composite_primary_key(name, *args) if name.is_a?(Array)
|
121
126
|
@primary_key = @db.serial_primary_key_options.merge({:name => name})
|
122
127
|
|
123
128
|
if opts = args.pop
|
@@ -129,7 +134,7 @@ module Sequel
|
|
129
134
|
end
|
130
135
|
@primary_key
|
131
136
|
end
|
132
|
-
|
137
|
+
|
133
138
|
# The name of the primary key for this table, if it has a primary key.
|
134
139
|
def primary_key_name
|
135
140
|
@primary_key[:name] if @primary_key
|
@@ -143,6 +148,21 @@ module Sequel
|
|
143
148
|
# Add a unique index on the given columns to the DDL.
|
144
149
|
def unique(columns, opts = {})
|
145
150
|
index(columns, opts.merge(:unique => true))
|
151
|
+
@columns << {:type => :check, :constraint_type => :unique,
|
152
|
+
:name => nil, :columns => Array(columns)}.merge(opts)
|
153
|
+
end
|
154
|
+
|
155
|
+
private
|
156
|
+
|
157
|
+
def composite_primary_key(columns, *args)
|
158
|
+
opts = args.pop || {}
|
159
|
+
@columns << {:type => :check, :constraint_type => :primary_key,
|
160
|
+
:name => nil, :columns => columns}.merge(opts)
|
161
|
+
end
|
162
|
+
|
163
|
+
def composite_foreign_key(columns, opts)
|
164
|
+
@columns << {:type => :check, :constraint_type => :foreign_key,
|
165
|
+
:name => nil, :columns => columns }.merge(opts)
|
146
166
|
end
|
147
167
|
end
|
148
168
|
|
@@ -170,12 +190,18 @@ module Sequel
|
|
170
190
|
# See Generator#constraint.
|
171
191
|
def add_constraint(name, *args, &block)
|
172
192
|
@operations << {:op => :add_constraint, :name => name, :type => :check, \
|
173
|
-
:check => block || args}
|
193
|
+
:constraint_type => :check, :check => block || args}
|
194
|
+
end
|
195
|
+
|
196
|
+
def add_unique_constraint(columns, opts = {})
|
197
|
+
@operations << {:op => :add_constraint, :type => :check,
|
198
|
+
:constraint_type => :unique, :columns => Array(columns)}.merge(opts)
|
174
199
|
end
|
175
200
|
|
176
201
|
# Add a foreign key with the given name and referencing the given table
|
177
202
|
# to the DDL for the table. See Generator#column for the available options.
|
178
203
|
def add_foreign_key(name, table, opts = {})
|
204
|
+
return add_composite_foreign_key(name, table, opts) if name.is_a?(Array)
|
179
205
|
add_column(name, :integer, {:table=>table}.merge(opts))
|
180
206
|
end
|
181
207
|
|
@@ -194,6 +220,7 @@ module Sequel
|
|
194
220
|
# Add a primary key to the DDL for the table. See Generator#column
|
195
221
|
# for the available options.
|
196
222
|
def add_primary_key(name, opts = {})
|
223
|
+
return add_composite_primary_key(name, opts) if name.is_a?(Array)
|
197
224
|
opts = @db.serial_primary_key_options.merge(opts)
|
198
225
|
add_column(name, opts.delete(:type), opts)
|
199
226
|
end
|
@@ -233,6 +260,19 @@ module Sequel
|
|
233
260
|
def set_column_type(name, type)
|
234
261
|
@operations << {:op => :set_column_type, :name => name, :type => type}
|
235
262
|
end
|
263
|
+
|
264
|
+
private
|
265
|
+
|
266
|
+
def add_composite_primary_key(columns, opts)
|
267
|
+
@operations << {:op => :add_constraint, :type => :check,
|
268
|
+
:constraint_type => :primary_key, :columns => columns}.merge(opts)
|
269
|
+
end
|
270
|
+
|
271
|
+
def add_composite_foreign_key(columns, table, opts)
|
272
|
+
@operations << {:op => :add_constraint, :type => :check,
|
273
|
+
:constraint_type => :foreign_key, :columns => columns,
|
274
|
+
:table => table}.merge(opts)
|
275
|
+
end
|
236
276
|
end
|
237
277
|
end
|
238
278
|
end
|
@@ -22,28 +22,29 @@ module Sequel
|
|
22
22
|
def alter_table_sql(table, op)
|
23
23
|
quoted_table = quote_identifier(table)
|
24
24
|
quoted_name = quote_identifier(op[:name]) if op[:name]
|
25
|
-
case op[:op]
|
25
|
+
alter_table_op = case op[:op]
|
26
26
|
when :add_column
|
27
|
-
"
|
27
|
+
"ADD COLUMN #{column_definition_sql(op)}"
|
28
28
|
when :drop_column
|
29
|
-
"
|
29
|
+
"DROP COLUMN #{quoted_name}"
|
30
30
|
when :rename_column
|
31
|
-
"
|
31
|
+
"RENAME COLUMN #{quoted_name} TO #{quote_identifier(op[:new_name])}"
|
32
32
|
when :set_column_type
|
33
|
-
"ALTER
|
33
|
+
"ALTER COLUMN #{quoted_name} TYPE #{op[:type]}"
|
34
34
|
when :set_column_default
|
35
|
-
"ALTER
|
35
|
+
"ALTER COLUMN #{quoted_name} SET DEFAULT #{literal(op[:default])}"
|
36
36
|
when :add_index
|
37
|
-
index_definition_sql(table, op)
|
37
|
+
return index_definition_sql(table, op)
|
38
38
|
when :drop_index
|
39
|
-
|
39
|
+
return drop_index_sql(table, op)
|
40
40
|
when :add_constraint
|
41
|
-
"
|
41
|
+
"ADD #{constraint_definition_sql(op)}"
|
42
42
|
when :drop_constraint
|
43
|
-
"
|
43
|
+
"DROP CONSTRAINT #{quoted_name}"
|
44
44
|
else
|
45
45
|
raise Error, "Unsupported ALTER TABLE operation"
|
46
46
|
end
|
47
|
+
"ALTER TABLE #{quoted_table} #{alter_table_op}"
|
47
48
|
end
|
48
49
|
|
49
50
|
# Array of SQL DDL modification statements for the given table,
|
@@ -61,22 +62,14 @@ module Sequel
|
|
61
62
|
# SQL DDL fragment containing the column creation SQL for the given column.
|
62
63
|
def column_definition_sql(column)
|
63
64
|
return constraint_definition_sql(column) if column[:type] == :check
|
64
|
-
sql = "#{quote_identifier(column[:name])} #{type_literal(
|
65
|
-
column[:size] ||= 255 if column[:type] == :varchar
|
66
|
-
elements = column[:size] || column[:elements]
|
67
|
-
sql << literal(Array(elements)) if elements
|
68
|
-
sql << UNSIGNED if column[:unsigned]
|
65
|
+
sql = "#{quote_identifier(column[:name])} #{type_literal(column)}"
|
69
66
|
sql << UNIQUE if column[:unique]
|
70
67
|
sql << NOT_NULL if column[:null] == false
|
71
68
|
sql << NULL if column[:null] == true
|
72
69
|
sql << " DEFAULT #{literal(column[:default])}" if column.include?(:default)
|
73
70
|
sql << PRIMARY_KEY if column[:primary_key]
|
74
71
|
sql << " #{auto_increment_sql}" if column[:auto_increment]
|
75
|
-
if column[:table]
|
76
|
-
sql << " REFERENCES #{quote_identifier(column[:table])}"
|
77
|
-
sql << "(#{quote_identifier(column[:key])})" if column[:key]
|
78
|
-
sql << " ON DELETE #{on_delete_clause(column[:on_delete])}" if column[:on_delete]
|
79
|
-
end
|
72
|
+
sql << column_references_sql(column) if column[:table]
|
80
73
|
sql
|
81
74
|
end
|
82
75
|
|
@@ -85,11 +78,30 @@ module Sequel
|
|
85
78
|
def column_list_sql(columns)
|
86
79
|
columns.map{|c| column_definition_sql(c)}.join(COMMA_SEPARATOR)
|
87
80
|
end
|
81
|
+
|
82
|
+
# SQL DDL fragment for column foreign key references
|
83
|
+
def column_references_sql(column)
|
84
|
+
sql = " REFERENCES #{quote_identifier(column[:table])}"
|
85
|
+
sql << "(#{Array(column[:key]).map{|x| quote_identifier(x)}.join(COMMA_SEPARATOR)})" if column[:key]
|
86
|
+
sql << " ON DELETE #{on_delete_clause(column[:on_delete])}" if column[:on_delete]
|
87
|
+
sql << " ON UPDATE #{on_delete_clause(column[:on_update])}" if column[:on_update]
|
88
|
+
sql
|
89
|
+
end
|
88
90
|
|
89
91
|
# SQL DDL fragment specifying a constraint on a table.
|
90
92
|
def constraint_definition_sql(constraint)
|
91
93
|
sql = constraint[:name] ? "CONSTRAINT #{quote_identifier(constraint[:name])} " : ""
|
92
|
-
|
94
|
+
case constraint[:constraint_type]
|
95
|
+
when :primary_key
|
96
|
+
sql << "PRIMARY KEY #{literal(constraint[:columns])}"
|
97
|
+
when :foreign_key
|
98
|
+
sql << "FOREIGN KEY #{literal(constraint[:columns])}"
|
99
|
+
sql << column_references_sql(constraint)
|
100
|
+
when :unique
|
101
|
+
sql << "UNIQUE #{literal(constraint[:columns])}"
|
102
|
+
else
|
103
|
+
sql << "CHECK #{filter_expr(constraint[:check])}"
|
104
|
+
end
|
93
105
|
sql
|
94
106
|
end
|
95
107
|
|
@@ -108,6 +120,11 @@ module Sequel
|
|
108
120
|
"#{table_name}_#{columns.join(UNDERSCORE)}_index"
|
109
121
|
end
|
110
122
|
|
123
|
+
# The SQL to drop an index for the table.
|
124
|
+
def drop_index_sql(table, op)
|
125
|
+
"DROP INDEX #{quote_identifier(op[:name] || default_index_name(table, op[:columns]))}"
|
126
|
+
end
|
127
|
+
|
111
128
|
# SQL DDL statement to drop the table with the given name.
|
112
129
|
def drop_table_sql(name)
|
113
130
|
"DROP TABLE #{quote_identifier(name)}"
|
@@ -127,7 +144,7 @@ module Sequel
|
|
127
144
|
elsif index[:where]
|
128
145
|
raise Error, "Partial indexes are not supported for this database"
|
129
146
|
else
|
130
|
-
"CREATE #{'UNIQUE ' if index[:unique]}INDEX #{index_name} ON #{quote_identifier(table_name)} #{literal(index[:columns])}"
|
147
|
+
"CREATE #{'UNIQUE ' if index[:unique]}INDEX #{quote_identifier(index_name)} ON #{quote_identifier(table_name)} #{literal(index[:columns])}"
|
131
148
|
end
|
132
149
|
end
|
133
150
|
|
@@ -215,10 +232,6 @@ module Sequel
|
|
215
232
|
@schema_utility_dataset ||= dataset
|
216
233
|
end
|
217
234
|
|
218
|
-
# SQL fragment specifying the type of a given column.
|
219
|
-
def type_literal(t)
|
220
|
-
t.is_a?(Symbol) ? t.to_s : literal(t)
|
221
|
-
end
|
222
235
|
|
223
236
|
private
|
224
237
|
|
@@ -320,6 +333,19 @@ module Sequel
|
|
320
333
|
end
|
321
334
|
schema
|
322
335
|
end
|
336
|
+
|
337
|
+
# SQL fragment specifying the type of a given column.
|
338
|
+
def type_literal(column)
|
339
|
+
column[:size] ||= 255 if column[:type] == :varchar
|
340
|
+
elements = column[:size] || column[:elements]
|
341
|
+
"#{type_literal_base(column)}#{literal(Array(elements)) if elements}#{UNSIGNED if column[:unsigned]}"
|
342
|
+
end
|
343
|
+
|
344
|
+
# SQL fragment specifying the base type of a given column,
|
345
|
+
# without the size or elements.
|
346
|
+
def type_literal_base(column)
|
347
|
+
TYPES[column[:type]]
|
348
|
+
end
|
323
349
|
end
|
324
350
|
end
|
325
351
|
end
|