sequel 2.9.0 → 2.10.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 (78) hide show
  1. data/CHANGELOG +56 -0
  2. data/{README → README.rdoc} +85 -57
  3. data/Rakefile +10 -5
  4. data/bin/sequel +7 -16
  5. data/doc/advanced_associations.rdoc +5 -17
  6. data/doc/cheat_sheet.rdoc +18 -20
  7. data/doc/dataset_filtering.rdoc +8 -32
  8. data/doc/schema.rdoc +20 -0
  9. data/lib/sequel_core.rb +35 -1
  10. data/lib/sequel_core/adapters/ado.rb +1 -1
  11. data/lib/sequel_core/adapters/db2.rb +2 -2
  12. data/lib/sequel_core/adapters/dbi.rb +2 -11
  13. data/lib/sequel_core/adapters/do.rb +205 -0
  14. data/lib/sequel_core/adapters/do/mysql.rb +38 -0
  15. data/lib/sequel_core/adapters/do/postgres.rb +92 -0
  16. data/lib/sequel_core/adapters/do/sqlite.rb +31 -0
  17. data/lib/sequel_core/adapters/firebird.rb +298 -0
  18. data/lib/sequel_core/adapters/informix.rb +10 -1
  19. data/lib/sequel_core/adapters/jdbc.rb +78 -19
  20. data/lib/sequel_core/adapters/jdbc/h2.rb +69 -0
  21. data/lib/sequel_core/adapters/jdbc/mysql.rb +10 -0
  22. data/lib/sequel_core/adapters/jdbc/postgresql.rb +7 -3
  23. data/lib/sequel_core/adapters/mysql.rb +53 -77
  24. data/lib/sequel_core/adapters/odbc.rb +1 -1
  25. data/lib/sequel_core/adapters/openbase.rb +1 -1
  26. data/lib/sequel_core/adapters/oracle.rb +2 -2
  27. data/lib/sequel_core/adapters/postgres.rb +16 -14
  28. data/lib/sequel_core/adapters/shared/mysql.rb +44 -9
  29. data/lib/sequel_core/adapters/shared/oracle.rb +4 -5
  30. data/lib/sequel_core/adapters/shared/postgres.rb +86 -82
  31. data/lib/sequel_core/adapters/shared/sqlite.rb +39 -24
  32. data/lib/sequel_core/adapters/sqlite.rb +11 -1
  33. data/lib/sequel_core/connection_pool.rb +10 -2
  34. data/lib/sequel_core/core_sql.rb +13 -3
  35. data/lib/sequel_core/database.rb +131 -30
  36. data/lib/sequel_core/database/schema.rb +5 -5
  37. data/lib/sequel_core/dataset.rb +31 -6
  38. data/lib/sequel_core/dataset/convenience.rb +11 -11
  39. data/lib/sequel_core/dataset/query.rb +2 -2
  40. data/lib/sequel_core/dataset/sql.rb +6 -6
  41. data/lib/sequel_core/exceptions.rb +4 -0
  42. data/lib/sequel_core/migration.rb +4 -4
  43. data/lib/sequel_core/schema/generator.rb +19 -3
  44. data/lib/sequel_core/schema/sql.rb +24 -20
  45. data/lib/sequel_core/sql.rb +13 -16
  46. data/lib/sequel_core/version.rb +11 -0
  47. data/lib/sequel_model.rb +2 -0
  48. data/lib/sequel_model/base.rb +2 -2
  49. data/lib/sequel_model/hooks.rb +46 -7
  50. data/lib/sequel_model/record.rb +11 -9
  51. data/lib/sequel_model/schema.rb +1 -1
  52. data/lib/sequel_model/validations.rb +72 -61
  53. data/spec/adapters/firebird_spec.rb +371 -0
  54. data/spec/adapters/mysql_spec.rb +118 -62
  55. data/spec/adapters/oracle_spec.rb +5 -5
  56. data/spec/adapters/postgres_spec.rb +33 -18
  57. data/spec/adapters/sqlite_spec.rb +2 -2
  58. data/spec/integration/dataset_test.rb +3 -3
  59. data/spec/integration/schema_test.rb +55 -5
  60. data/spec/integration/spec_helper.rb +11 -0
  61. data/spec/integration/type_test.rb +59 -16
  62. data/spec/sequel_core/connection_pool_spec.rb +14 -0
  63. data/spec/sequel_core/core_sql_spec.rb +24 -14
  64. data/spec/sequel_core/database_spec.rb +96 -11
  65. data/spec/sequel_core/dataset_spec.rb +97 -37
  66. data/spec/sequel_core/expression_filters_spec.rb +51 -40
  67. data/spec/sequel_core/object_graph_spec.rb +2 -2
  68. data/spec/sequel_core/schema_generator_spec.rb +31 -6
  69. data/spec/sequel_core/schema_spec.rb +25 -9
  70. data/spec/sequel_core/spec_helper.rb +4 -1
  71. data/spec/sequel_core/version_spec.rb +7 -0
  72. data/spec/sequel_model/associations_spec.rb +1 -1
  73. data/spec/sequel_model/hooks_spec.rb +68 -13
  74. data/spec/sequel_model/model_spec.rb +4 -4
  75. data/spec/sequel_model/record_spec.rb +22 -0
  76. data/spec/sequel_model/spec_helper.rb +2 -1
  77. data/spec/sequel_model/validations_spec.rb +107 -7
  78. metadata +15 -5
@@ -55,15 +55,15 @@ module Sequel
55
55
  # end
56
56
  #
57
57
  # See Schema::Generator.
58
- def create_table(name, generator=nil, &block)
59
- generator ||= Schema::Generator.new(self, &block)
60
- create_table_sql_list(name, *generator.create_info).flatten.each {|sql| execute_ddl(sql)}
58
+ def create_table(name, options={}, &block)
59
+ options = {:generator=>options} if options.is_a?(Schema::Generator)
60
+ create_table_sql_list(name, *((options[:generator] || Schema::Generator.new(self, &block)).create_info << options)).flatten.each {|sql| execute_ddl(sql)}
61
61
  end
62
62
 
63
63
  # Forcibly creates a table. If the table already exists it is dropped.
64
- def create_table!(name, generator=nil, &block)
64
+ def create_table!(name, options={}, &block)
65
65
  drop_table(name) rescue nil
66
- create_table(name, generator, &block)
66
+ create_table(name, options, &block)
67
67
  end
68
68
 
69
69
  # Creates a view, replacing it if it already exists:
@@ -71,6 +71,12 @@ module Sequel
71
71
 
72
72
  # The database that corresponds to this dataset
73
73
  attr_accessor :db
74
+
75
+ # Set the method to call on identifiers going into the database for this dataset
76
+ attr_accessor :identifier_input_method
77
+
78
+ # Set the method to call on identifiers coming the database for this dataset
79
+ attr_accessor :identifier_output_method
74
80
 
75
81
  # The hash of options for this dataset, keys are symbols.
76
82
  attr_accessor :opts
@@ -83,9 +89,6 @@ module Sequel
83
89
  # fetch_rows to return.
84
90
  attr_accessor :row_proc
85
91
 
86
- # Whether to upcase identifiers for this dataset
87
- attr_writer :upcase_identifiers
88
-
89
92
  # Constructs a new instance of a dataset with an associated database and
90
93
  # options. Datasets are usually constructed by invoking Database methods:
91
94
  #
@@ -100,7 +103,8 @@ module Sequel
100
103
  def initialize(db, opts = nil)
101
104
  @db = db
102
105
  @quote_identifiers = db.quote_identifiers? if db.respond_to?(:quote_identifiers?)
103
- @upcase_identifiers = db.upcase_identifiers? if db.respond_to?(:upcase_identifiers?)
106
+ @identifier_input_method = db.identifier_input_method if db.respond_to?(:identifier_input_method)
107
+ @identifier_output_method = db.identifier_output_method if db.respond_to?(:identifier_output_method)
104
108
  @opts = opts || {}
105
109
  @row_proc = nil
106
110
  @transform = nil
@@ -221,7 +225,7 @@ module Sequel
221
225
  # Inserts values into the associated table. The returned value is generally
222
226
  # the value of the primary key for the inserted row, but that is adapter dependent.
223
227
  def insert(*values)
224
- execute_dui(insert_sql(*values))
228
+ execute_insert(insert_sql(*values))
225
229
  end
226
230
 
227
231
  # Returns a string representation of the dataset including the class name
@@ -419,9 +423,13 @@ module Sequel
419
423
  end
420
424
  end
421
425
 
426
+ def upcase_identifiers=(v)
427
+ @identifier_input_method = v ? :upcase : nil
428
+ end
429
+
422
430
  # Whether this dataset upcases identifiers.
423
431
  def upcase_identifiers?
424
- @upcase_identifiers
432
+ @identifier_input_method == :upcase
425
433
  end
426
434
 
427
435
  # Updates values for the dataset. The returned value is generally the
@@ -468,6 +476,17 @@ module Sequel
468
476
  def execute_dui(sql, opts={}, &block)
469
477
  @db.execute_dui(sql, {:server=>@opts[:server] || :default}.merge(opts), &block)
470
478
  end
479
+
480
+ # Execute the given SQL on the database using execute_insert.
481
+ def execute_insert(sql, opts={}, &block)
482
+ @db.execute_insert(sql, {:server=>@opts[:server] || :default}.merge(opts), &block)
483
+ end
484
+
485
+ # Modify the identifier returned from the database based on the
486
+ # identifier_output_method.
487
+ def input_identifier(v)
488
+ (i = identifier_input_method) ? v.to_s.send(i) : v.to_s
489
+ end
471
490
 
472
491
  # Modify the receiver with the results of sending the meth, args, and block
473
492
  # to the receiver and merging the options of the resulting dataset into
@@ -477,5 +496,11 @@ module Sequel
477
496
  @opts.merge!(copy.opts)
478
497
  self
479
498
  end
499
+
500
+ # Modify the identifier returned from the database based on the
501
+ # identifier_output_method.
502
+ def output_identifier(v)
503
+ (i = identifier_output_method) ? v.to_s.send(i).to_sym : v.to_sym
504
+ end
480
505
  end
481
506
  end
@@ -1,7 +1,7 @@
1
1
  module Sequel
2
2
  class Dataset
3
3
  COMMA_SEPARATOR = ', '.freeze
4
- COUNT_OF_ALL_AS_COUNT = :count['*'.lit].as(:count)
4
+ COUNT_OF_ALL_AS_COUNT = SQL::Function.new(:count, '*'.lit).as(:count)
5
5
 
6
6
  # Returns the first record matching the conditions.
7
7
  def [](*conditions)
@@ -16,7 +16,7 @@ module Sequel
16
16
 
17
17
  # Returns the average value for the given column.
18
18
  def avg(column)
19
- get(:avg[column])
19
+ get(SQL::Function.new(:avg, column))
20
20
  end
21
21
 
22
22
  # Returns true if no records exists in the dataset
@@ -40,11 +40,11 @@ module Sequel
40
40
  # ds.first(:id=>2) => {:id=>2}
41
41
  # ds.first("id = 3") => {:id=>3}
42
42
  # ds.first("id = ?", 4) => {:id=>4}
43
- # ds.first{:id > 2} => {:id=>5}
44
- # ds.order(:id).first{:id > 2} => {:id=>3}
45
- # ds.first{:id > 2} => {:id=>5}
46
- # ds.first("id > ?", 4){:id < 6) => {:id=>5}
47
- # ds.order(:id).first(2){:id < 2} => [{:id=>1}]
43
+ # ds.first{|o| o.id > 2} => {:id=>5}
44
+ # ds.order(:id).first{|o| o.id > 2} => {:id=>3}
45
+ # ds.first{|o| o.id > 2} => {:id=>5}
46
+ # ds.first("id > ?", 4){|o| o.id < 6} => {:id=>5}
47
+ # ds.order(:id).first(2){|o| o.id < 2} => [{:id=>1}]
48
48
  def first(*args, &block)
49
49
  ds = block ? filter(&block) : self
50
50
 
@@ -97,12 +97,12 @@ module Sequel
97
97
 
98
98
  # Returns the maximum value for the given column.
99
99
  def max(column)
100
- get(:max[column])
100
+ get(SQL::Function.new(:max, column))
101
101
  end
102
102
 
103
103
  # Returns the minimum value for the given column.
104
104
  def min(column)
105
- get(:min[column])
105
+ get(SQL::Function.new(:min, column))
106
106
  end
107
107
 
108
108
  # Inserts multiple records into the associated table. This method can be
@@ -170,7 +170,7 @@ module Sequel
170
170
  # Returns a Range object made from the minimum and maximum values for the
171
171
  # given column.
172
172
  def range(column)
173
- if r = select(:min[column].as(:v1), :max[column].as(:v2)).first
173
+ if r = select(SQL::Function.new(:min, column).as(:v1), SQL::Function.new(:max, column).as(:v2)).first
174
174
  (r[:v1]..r[:v2])
175
175
  end
176
176
  end
@@ -191,7 +191,7 @@ module Sequel
191
191
 
192
192
  # Returns the sum for the given column.
193
193
  def sum(column)
194
- get(:sum[column])
194
+ get(SQL::Function.new(:sum, column))
195
195
  end
196
196
 
197
197
  # Returns true if the table exists. Will raise an error
@@ -5,13 +5,13 @@ module Sequel
5
5
  #
6
6
  # dataset = DB[:items].query do
7
7
  # select :x, :y, :z
8
- # filter((:x > 1) & (:y > 2))
8
+ # filter{|o| (o.x > 1) & (o.y > 2)}
9
9
  # order :z.desc
10
10
  # end
11
11
  #
12
12
  # Which is the same as:
13
13
  #
14
- # dataset = DB[:items].select(:x, :y, :z).filter((:x > 1) & (:y > 2)).order(:z.desc)
14
+ # dataset = DB[:items].select(:x, :y, :z).filter{|o| (o.x > 1) & (o.y > 2)}.order(:z.desc)
15
15
  #
16
16
  # Note that inside a call to query, you cannot call each, insert, update,
17
17
  # or delete (or any method that calls those), or Sequel will raise an
@@ -76,7 +76,7 @@ module Sequel
76
76
 
77
77
  # Formats a DELETE statement using the given options and dataset options.
78
78
  #
79
- # dataset.filter(:price >= 100).delete_sql #=>
79
+ # dataset.filter{|o| o.price >= 100}.delete_sql #=>
80
80
  # "DELETE FROM items WHERE (price >= 100)"
81
81
  def delete_sql(opts = nil)
82
82
  opts = opts ? @opts.merge(opts) : @opts
@@ -163,13 +163,13 @@ module Sequel
163
163
  # "SELECT * FROM items WHERE price < 100"
164
164
  # dataset.filter(:active).sql #=>
165
165
  # "SELECT * FROM items WHERE :active
166
- # dataset.filter(:price < 100).sql #=>
166
+ # dataset.filter{|o| o.price < 100}.sql #=>
167
167
  # "SELECT * FROM items WHERE (price < 100)"
168
168
  #
169
169
  # Multiple filter calls can be chained for scoping:
170
170
  #
171
171
  # software = dataset.filter(:category => 'software')
172
- # software.filter(price < 100).sql #=>
172
+ # software.filter{|o| o.price < 100}.sql #=>
173
173
  # "SELECT * FROM items WHERE ((category = 'software') AND (price < 100))"
174
174
  #
175
175
  # See doc/dataset_filters.rdoc for more examples and details.
@@ -572,8 +572,8 @@ module Sequel
572
572
  # being quoted, returns name as a string. If identifiers are being quoted
573
573
  # quote the name with quoted_identifier.
574
574
  def quote_identifier(name)
575
- name = name.to_s
576
- name = name.upcase if upcase_identifiers?
575
+ return name if name.is_a?(LiteralString)
576
+ name = input_identifier(name)
577
577
  name = quoted_identifier(name) if quote_identifiers?
578
578
  name
579
579
  end
@@ -590,7 +590,7 @@ module Sequel
590
590
  # should be overridden by subclasses to provide quoting not matching the
591
591
  # SQL standard, such as backtick (used by MySQL and SQLite).
592
592
  def quoted_identifier(name)
593
- "\"#{name}\""
593
+ "\"#{name.to_s.gsub('"', '""')}\""
594
594
  end
595
595
 
596
596
  # Returns a copy of the dataset with the order reversed. If no order is
@@ -31,6 +31,10 @@ module Sequel
31
31
  # Generic error raised by the database adapters, indicating a
32
32
  # problem originating from the database server.
33
33
  class DatabaseError < Error; end
34
+
35
+ # Error raised when the Sequel is unable to connect to the database with the
36
+ # connection parameters it was given.
37
+ class DatabaseConnectionError < DatabaseError; end
34
38
 
35
39
  # Error that should be raised by adapters when they determine that the connection
36
40
  # to the database has been lost. Instructs the connection pool code to
@@ -6,9 +6,9 @@ module Sequel
6
6
  # def up
7
7
  # create_table :sessions do
8
8
  # primary_key :id
9
- # varchar :session_id, :size => 32, :unique => true
10
- # timestamp :created_at
11
- # text :data
9
+ # String :session_id, :size => 32, :unique => true
10
+ # DateTime :created_at
11
+ # text :data
12
12
  # end
13
13
  # end
14
14
  #
@@ -21,7 +21,7 @@ module Sequel
21
21
  # class AlterItems < Sequel::Migration
22
22
  # def up
23
23
  # alter_table :items do
24
- # add_column :category, :text, :default => 'ruby'
24
+ # add_column :category, String, :default => 'ruby'
25
25
  # end
26
26
  # end
27
27
  #
@@ -13,6 +13,10 @@ module Sequel
13
13
  # allowing users to specify column type as a method instead of using
14
14
  # the column method, which makes for a nicer DSL.
15
15
  class Generator
16
+ # Classes specifying generic types that Sequel will convert to database-specific types.
17
+ GENERIC_TYPES=[String, Integer, Fixnum, Bignum, Float, Numeric, BigDecimal,
18
+ Date, DateTime, Time, File, TrueClass, FalseClass]
19
+
16
20
  # Set the database in which to create the table, and evaluate the block
17
21
  # in the context of this object.
18
22
  def initialize(db, &block)
@@ -23,6 +27,16 @@ module Sequel
23
27
  instance_eval(&block) if block
24
28
  end
25
29
 
30
+ # Add a method for each of the given types that creates a column
31
+ # with that type as a constant. Types given should either already
32
+ # be constants/classes or a capitalized string/symbol with the same name
33
+ # as a constant/class.
34
+ def self.add_type_method(*types)
35
+ types.each do |type|
36
+ class_eval "def #{type}(name, opts={}); column(name, #{type}, opts); end"
37
+ end
38
+ end
39
+
26
40
  # Add a unnamed constraint to the DDL, specified by the given block
27
41
  # or args.
28
42
  def check(*args, &block)
@@ -87,10 +101,10 @@ module Sequel
87
101
  when NilClass
88
102
  opts
89
103
  else
90
- raise(Error, "The seconds argument to foreign_key should be a Hash, Symbol, or nil")
104
+ raise(Error, "The second argument to foreign_key should be a Hash, Symbol, or nil")
91
105
  end
92
106
  return composite_foreign_key(name, opts) if name.is_a?(Array)
93
- column(name, :integer, opts)
107
+ column(name, Integer, opts)
94
108
  end
95
109
 
96
110
  # Add a full text index on the given columns to the DDL.
@@ -173,6 +187,8 @@ module Sequel
173
187
  @columns << {:type => :check, :constraint_type => :foreign_key,
174
188
  :name => nil, :columns => columns }.merge(opts)
175
189
  end
190
+
191
+ add_type_method(*GENERIC_TYPES)
176
192
  end
177
193
 
178
194
  # Schema::AlterTableGenerator is an internal class that the user is not expected
@@ -222,7 +238,7 @@ module Sequel
222
238
  # use the composite key syntax even if it is only one column.
223
239
  def add_foreign_key(name, table, opts = {})
224
240
  return add_composite_foreign_key(name, table, opts) if name.is_a?(Array)
225
- add_column(name, :integer, {:table=>table}.merge(opts))
241
+ add_column(name, Integer, {:table=>table}.merge(opts))
226
242
  end
227
243
 
228
244
  # Add a full text index on the given columns to the DDL for the table.
@@ -12,7 +12,11 @@ module Sequel
12
12
  SET_DEFAULT = 'SET DEFAULT'.freeze
13
13
  SET_NULL = 'SET NULL'.freeze
14
14
  TYPES = Hash.new {|h, k| k}
15
- TYPES[:double] = 'double precision'
15
+ TYPES.merge!(:double=>'double precision', String=>'varchar',
16
+ Integer=>'integer', Fixnum=>'integer', Bignum=>'bigint',
17
+ Float=>'double precision', BigDecimal=>'numeric', Numeric=>'numeric',
18
+ Date=>'date', DateTime=>'timestamp', Time=>'timestamp', File=>'blob',
19
+ TrueClass=>'boolean', FalseClass=>'boolean')
16
20
  UNDERSCORE = '_'.freeze
17
21
  UNIQUE = ' UNIQUE'.freeze
18
22
  UNSIGNED = ' UNSIGNED'.freeze
@@ -110,7 +114,7 @@ module Sequel
110
114
  # Array of SQL DDL statements, the first for creating a table with the given
111
115
  # name and column specifications, and the others for specifying indexes on
112
116
  # the table.
113
- def create_table_sql_list(name, columns, indexes = nil)
117
+ def create_table_sql_list(name, columns, indexes = nil, options = {})
114
118
  sql = ["CREATE TABLE #{quote_schema_table(name)} (#{column_list_sql(columns)})"]
115
119
  sql.concat(index_list_sql_list(name, indexes)) if indexes && !indexes.empty?
116
120
  sql
@@ -215,6 +219,8 @@ module Sequel
215
219
  # * :schema - An explicit schema to use. It may also be implicitly provided
216
220
  # via the table name.
217
221
  def schema(table = nil, opts={})
222
+ raise(Error, 'schema parsing is not implemented on this database') unless respond_to?(:schema_parse_table, true)
223
+
218
224
  if table
219
225
  sch, table_name = schema_and_table(table)
220
226
  quoted_name = quote_schema_table(table)
@@ -236,29 +242,20 @@ module Sequel
236
242
  end
237
243
  end
238
244
 
245
+ raise(Error, '#tables does not exist, you must provide a specific table to #schema') if table.nil? && !respond_to?(:tables, true)
246
+
239
247
  @schemas ||= Hash.new do |h,k|
240
248
  quote_name = quote_schema_table(k)
241
249
  h[quote_name] if h.include?(quote_name)
242
250
  end
243
251
 
244
252
  if table_name
245
- if respond_to?(:schema_parse_table, true)
246
- cols = schema_parse_table(table_name, opts)
247
- raise(Error, 'schema parsing returned no columns, table probably doesn\'t exist') if cols.blank?
248
- @schemas[quoted_name] = cols
249
- else
250
- raise Error, 'schema parsing is not implemented on this database'
251
- end
253
+ cols = schema_parse_table(table_name, opts)
254
+ raise(Error, 'schema parsing returned no columns, table probably doesn\'t exist') if cols.blank?
255
+ @schemas[quoted_name] = cols
252
256
  else
253
- if respond_to?(:schema_parse_tables, true)
254
- @schemas.merge!(schema_parse_tables(opts))
255
- elsif respond_to?(:schema_parse_table, true) and respond_to?(:tables, true)
256
- tables.each{|t| @schemas[quote_identifier(t)] = schema_parse_table(t.to_s, opts)}
257
- @schemas
258
- else
259
- @schemas = nil
260
- raise Error, 'schema parsing is not implemented on this database'
261
- end
257
+ tables.each{|t| @schemas[quote_schema_table(t)] = schema_parse_table(t.to_s, opts)}
258
+ @schemas
262
259
  end
263
260
  end
264
261
 
@@ -273,6 +270,12 @@ module Sequel
273
270
  def remove_cached_schema(table)
274
271
  @schemas.delete(quote_schema_table(table)) if @schemas
275
272
  end
273
+
274
+ # Remove the cached schema_utility_dataset, because the identifier
275
+ # quoting has changed.
276
+ def reset_schema_utility_dataset
277
+ @schema_utility_dataset = nil
278
+ end
276
279
 
277
280
  # Match the database's column type to a ruby type via a
278
281
  # regular expression. The following ruby types are supported:
@@ -306,9 +309,10 @@ module Sequel
306
309
 
307
310
  # SQL fragment specifying the type of a given column.
308
311
  def type_literal(column)
309
- column[:size] ||= 255 if column[:type] == :varchar
312
+ type = type_literal_base(column)
313
+ column[:size] ||= 255 if type.to_s == 'varchar'
310
314
  elements = column[:size] || column[:elements]
311
- "#{type_literal_base(column)}#{literal(Array(elements)) if elements}#{UNSIGNED if column[:unsigned]}"
315
+ "#{type}#{literal(Array(elements)) if elements}#{UNSIGNED if column[:unsigned]}"
312
316
  end
313
317
 
314
318
  # SQL fragment specifying the base type of a given column,
@@ -334,11 +334,6 @@ module Sequel
334
334
  #
335
335
  # :price.sql_number/10 > 100
336
336
  module ComplexExpressionMethods
337
- include BooleanMethods
338
- include NumericMethods
339
- include StringMethods
340
- include InequalityMethods
341
-
342
337
  # Extract a datetime_part (e.g. year, month) from self:
343
338
  #
344
339
  # :date.extract(:year) # SQL: extract(year FROM date)
@@ -365,23 +360,21 @@ module Sequel
365
360
  end
366
361
  end
367
362
 
368
- module SpecificExpressionMethods
363
+ class ComplexExpression
369
364
  include AliasMethods
370
365
  include CastMethods
371
366
  include OrderMethods
372
367
  end
373
368
 
374
- module GenericExpressionMethods
375
- include SpecificExpressionMethods
376
- include ComplexExpressionMethods
377
- end
378
-
379
- class ComplexExpression
380
- include SpecificExpressionMethods
381
- end
382
-
383
369
  class GenericExpression
384
- include GenericExpressionMethods
370
+ include AliasMethods
371
+ include CastMethods
372
+ include OrderMethods
373
+ include ComplexExpressionMethods
374
+ include BooleanMethods
375
+ include NumericMethods
376
+ include StringMethods
377
+ include InequalityMethods
385
378
  end
386
379
 
387
380
  ### Classes ###
@@ -864,5 +857,9 @@ module Sequel
864
857
  class LiteralString < ::String
865
858
  include SQL::OrderMethods
866
859
  include SQL::ComplexExpressionMethods
860
+ include SQL::BooleanMethods
861
+ include SQL::NumericMethods
862
+ include SQL::StringMethods
863
+ include SQL::InequalityMethods
867
864
  end
868
865
  end