sequel 3.13.0 → 3.14.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 +36 -0
- data/doc/release_notes/3.14.0.txt +118 -0
- data/lib/sequel/adapters/oracle.rb +7 -2
- data/lib/sequel/adapters/shared/mssql.rb +9 -3
- data/lib/sequel/connection_pool/sharded_threaded.rb +1 -1
- data/lib/sequel/connection_pool/threaded.rb +3 -3
- data/lib/sequel/database/connecting.rb +47 -11
- data/lib/sequel/database/dataset.rb +17 -6
- data/lib/sequel/database/dataset_defaults.rb +15 -3
- data/lib/sequel/database/logging.rb +4 -3
- data/lib/sequel/database/misc.rb +33 -21
- data/lib/sequel/database/query.rb +61 -22
- data/lib/sequel/database/schema_generator.rb +108 -45
- data/lib/sequel/database/schema_methods.rb +8 -5
- data/lib/sequel/dataset/actions.rb +194 -45
- data/lib/sequel/dataset/features.rb +1 -1
- data/lib/sequel/dataset/graph.rb +51 -43
- data/lib/sequel/dataset/misc.rb +29 -5
- data/lib/sequel/dataset/mutation.rb +0 -1
- data/lib/sequel/dataset/prepared_statements.rb +14 -2
- data/lib/sequel/dataset/query.rb +268 -125
- data/lib/sequel/dataset/sql.rb +33 -44
- data/lib/sequel/extensions/migration.rb +3 -2
- data/lib/sequel/extensions/pagination.rb +1 -1
- data/lib/sequel/model/associations.rb +89 -87
- data/lib/sequel/model/base.rb +386 -109
- data/lib/sequel/model/errors.rb +15 -1
- data/lib/sequel/model/exceptions.rb +3 -3
- data/lib/sequel/model/inflections.rb +2 -2
- data/lib/sequel/model/plugins.rb +9 -5
- data/lib/sequel/plugins/rcte_tree.rb +43 -15
- data/lib/sequel/plugins/schema.rb +6 -5
- data/lib/sequel/plugins/serialization.rb +1 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/tree.rb +33 -1
- data/lib/sequel/timezones.rb +16 -10
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +36 -2
- data/spec/adapters/mysql_spec.rb +4 -4
- data/spec/adapters/postgres_spec.rb +1 -1
- data/spec/adapters/spec_helper.rb +2 -2
- data/spec/core/database_spec.rb +8 -1
- data/spec/core/dataset_spec.rb +36 -1
- data/spec/extensions/pagination_spec.rb +1 -1
- data/spec/extensions/rcte_tree_spec.rb +40 -8
- data/spec/extensions/schema_spec.rb +5 -0
- data/spec/extensions/serialization_spec.rb +4 -4
- data/spec/extensions/single_table_inheritance_spec.rb +7 -0
- data/spec/extensions/tree_spec.rb +36 -0
- data/spec/integration/dataset_test.rb +19 -0
- data/spec/integration/prepared_statement_test.rb +2 -2
- data/spec/integration/schema_test.rb +1 -1
- data/spec/integration/spec_helper.rb +4 -4
- data/spec/integration/timezone_test.rb +27 -21
- data/spec/model/associations_spec.rb +5 -5
- data/spec/model/dataset_methods_spec.rb +13 -0
- data/spec/model/hooks_spec.rb +31 -0
- data/spec/model/record_spec.rb +24 -7
- data/spec/model/validations_spec.rb +9 -4
- metadata +6 -4
@@ -58,7 +58,11 @@ module Sequel
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
# Set the method to call on identifiers going into the database
|
61
|
+
# Set the method to call on identifiers going into the database:
|
62
|
+
#
|
63
|
+
# DB[:items] # SELECT * FROM items
|
64
|
+
# DB.identifier_input_method = :upcase
|
65
|
+
# DB[:items] # SELECT * FROM ITEMS
|
62
66
|
def identifier_input_method=(v)
|
63
67
|
reset_schema_utility_dataset
|
64
68
|
@identifier_input_method = v || ""
|
@@ -77,13 +81,21 @@ module Sequel
|
|
77
81
|
end
|
78
82
|
end
|
79
83
|
|
80
|
-
# Set the method to call on identifiers coming from the database
|
84
|
+
# Set the method to call on identifiers coming from the database:
|
85
|
+
#
|
86
|
+
# DB[:items].first # {:id=>1, :name=>'foo'}
|
87
|
+
# DB.identifier_output_method = :upcase
|
88
|
+
# DB[:items].first # {:ID=>1, :NAME=>'foo'}
|
81
89
|
def identifier_output_method=(v)
|
82
90
|
reset_schema_utility_dataset
|
83
91
|
@identifier_output_method = v || ""
|
84
92
|
end
|
85
93
|
|
86
|
-
#
|
94
|
+
# Set whether to quote identifiers (columns and tables) for this database:
|
95
|
+
#
|
96
|
+
# DB[:items] # SELECT * FROM items
|
97
|
+
# DB.quote_identifiers = true
|
98
|
+
# DB[:items] # SELECT * FROM "items"
|
87
99
|
def quote_identifiers=(v)
|
88
100
|
reset_schema_utility_dataset
|
89
101
|
@quote_identifiers = v
|
@@ -9,7 +9,7 @@ module Sequel
|
|
9
9
|
# level instead of info level.
|
10
10
|
attr_accessor :log_warn_duration
|
11
11
|
|
12
|
-
# Array of SQL loggers to use for this database
|
12
|
+
# Array of SQL loggers to use for this database.
|
13
13
|
attr_accessor :loggers
|
14
14
|
|
15
15
|
# Log a message at level info to all loggers.
|
@@ -33,7 +33,9 @@ module Sequel
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
# Remove any existing loggers and just use the given logger
|
36
|
+
# Remove any existing loggers and just use the given logger:
|
37
|
+
#
|
38
|
+
# DB.logger = Logger.new($stdout)
|
37
39
|
def logger=(logger)
|
38
40
|
@loggers = Array(logger)
|
39
41
|
end
|
@@ -57,6 +59,5 @@ module Sequel
|
|
57
59
|
def log_each(level, message)
|
58
60
|
@loggers.each{|logger| logger.send(level, message)}
|
59
61
|
end
|
60
|
-
|
61
62
|
end
|
62
63
|
end
|
data/lib/sequel/database/misc.rb
CHANGED
@@ -16,24 +16,24 @@ module Sequel
|
|
16
16
|
end
|
17
17
|
private_class_method :uri_to_options
|
18
18
|
|
19
|
-
# The options for this database
|
19
|
+
# The options hash for this database
|
20
20
|
attr_reader :opts
|
21
21
|
|
22
22
|
# Constructs a new instance of a database connection with the specified
|
23
23
|
# options hash.
|
24
24
|
#
|
25
|
-
#
|
25
|
+
# Accepts the following options:
|
26
|
+
# :default_schema :: The default schema to use, should generally be nil
|
27
|
+
# :disconnection_proc :: A proc used to disconnect the connection
|
28
|
+
# :identifier_input_method :: A string method symbol to call on identifiers going into the database
|
29
|
+
# :identifier_output_method :: A string method symbol to call on identifiers coming from the database
|
30
|
+
# :logger :: A specific logger to use
|
31
|
+
# :loggers :: An array of loggers to use
|
32
|
+
# :quote_identifiers :: Whether to quote identifiers
|
33
|
+
# :servers :: A hash specifying a server/shard specific options, keyed by shard symbol
|
34
|
+
# :single_threaded :: Whether to use a single-threaded connection pool
|
26
35
|
#
|
27
|
-
#
|
28
|
-
# * :default_schema : The default schema to use, should generally be nil
|
29
|
-
# * :disconnection_proc: A proc used to disconnect the connection.
|
30
|
-
# * :identifier_input_method: A string method symbol to call on identifiers going into the database
|
31
|
-
# * :identifier_output_method: A string method symbol to call on identifiers coming from the database
|
32
|
-
# * :loggers : An array of loggers to use.
|
33
|
-
# * :quote_identifiers : Whether to quote identifiers
|
34
|
-
# * :single_threaded : Whether to use a single-threaded connection pool
|
35
|
-
#
|
36
|
-
# All options given are also passed to the ConnectionPool. If a block
|
36
|
+
# All options given are also passed to the connection pool. If a block
|
37
37
|
# is given, it is used as the connection_proc for the ConnectionPool.
|
38
38
|
def initialize(opts = {}, &block)
|
39
39
|
@opts ||= opts
|
@@ -58,6 +58,9 @@ module Sequel
|
|
58
58
|
end
|
59
59
|
|
60
60
|
# Cast the given type to a literal type
|
61
|
+
#
|
62
|
+
# DB.cast_type_literal(Float) # double precision
|
63
|
+
# DB.cast_type_literal(:foo) # foo
|
61
64
|
def cast_type_literal(type)
|
62
65
|
type_literal(:type=>type)
|
63
66
|
end
|
@@ -69,28 +72,33 @@ module Sequel
|
|
69
72
|
"#<#{self.class}: #{(uri rescue opts).inspect}>"
|
70
73
|
end
|
71
74
|
|
72
|
-
# Proxy the literal call to the dataset
|
75
|
+
# Proxy the literal call to the dataset.
|
76
|
+
#
|
77
|
+
# DB.literal(1) # 1
|
78
|
+
# DB.literal(:a) # a
|
79
|
+
# DB.literal('a') # 'a'
|
73
80
|
def literal(v)
|
74
81
|
schema_utility_dataset.literal(v)
|
75
82
|
end
|
76
83
|
|
77
|
-
# Default serial primary key options
|
84
|
+
# Default serial primary key options, used by the table creation
|
85
|
+
# code.
|
78
86
|
def serial_primary_key_options
|
79
87
|
{:primary_key => true, :type => Integer, :auto_increment => true}
|
80
88
|
end
|
81
89
|
|
82
90
|
# Whether the database and adapter support prepared transactions
|
83
|
-
# (two-phase commit), false by default
|
91
|
+
# (two-phase commit), false by default.
|
84
92
|
def supports_prepared_transactions?
|
85
93
|
false
|
86
94
|
end
|
87
95
|
|
88
|
-
# Whether the database and adapter support savepoints, false by default
|
96
|
+
# Whether the database and adapter support savepoints, false by default.
|
89
97
|
def supports_savepoints?
|
90
98
|
false
|
91
99
|
end
|
92
100
|
|
93
|
-
# Whether the database and adapter support transaction isolation levels, false by default
|
101
|
+
# Whether the database and adapter support transaction isolation levels, false by default.
|
94
102
|
def supports_transaction_isolation_levels?
|
95
103
|
false
|
96
104
|
end
|
@@ -110,12 +118,17 @@ module Sequel
|
|
110
118
|
end
|
111
119
|
end
|
112
120
|
|
113
|
-
# Returns the URI identifying the database
|
121
|
+
# Returns the URI identifying the database, which may not be the
|
122
|
+
# same as the URI used when connecting.
|
114
123
|
# This method can raise an error if the database used options
|
115
|
-
# instead of a connection string
|
124
|
+
# instead of a connection string, and will not include uri
|
125
|
+
# parameters.
|
126
|
+
#
|
127
|
+
# Sequel.connect('postgres://localhost/db?user=billg').url
|
128
|
+
# # => "postgres://billg@localhost/db"
|
116
129
|
def uri
|
117
130
|
uri = URI::Generic.new(
|
118
|
-
|
131
|
+
adapter_scheme.to_s,
|
119
132
|
nil,
|
120
133
|
@opts[:host],
|
121
134
|
@opts[:port],
|
@@ -203,7 +216,6 @@ module Sequel
|
|
203
216
|
|
204
217
|
# Typecast the value to a DateTime or Time depending on Sequel.datetime_class
|
205
218
|
def typecast_value_datetime(value)
|
206
|
-
raise(Sequel::InvalidValue, "invalid value for Datetime: #{value.inspect}") unless [DateTime, Date, Time, String, Hash].any?{|c| value.is_a?(c)}
|
207
219
|
klass = Sequel.datetime_class
|
208
220
|
if value.is_a?(Hash)
|
209
221
|
klass.send(klass == Time ? :mktime : :new, *[:year, :month, :day, :hour, :minute, :second].map{|x| (value[x] || value[x.to_s]).to_i})
|
@@ -26,7 +26,7 @@ module Sequel
|
|
26
26
|
MYSQL_TIMESTAMP_RE = /\ACURRENT_(?:DATE|TIMESTAMP)?\z/
|
27
27
|
STRING_DEFAULT_RE = /\A'(.*)'\z/
|
28
28
|
|
29
|
-
# The prepared statement
|
29
|
+
# The prepared statement object hash for this database, keyed by name symbol
|
30
30
|
attr_reader :prepared_statements
|
31
31
|
|
32
32
|
# The default transaction isolation level for this database,
|
@@ -44,6 +44,9 @@ module Sequel
|
|
44
44
|
|
45
45
|
# Call the prepared statement with the given name with the given hash
|
46
46
|
# of arguments.
|
47
|
+
#
|
48
|
+
# DB[:items].filter(:id=>1).prepare(:first, :sa)
|
49
|
+
# DB.call(:sa) # SELECT * FROM items WHERE id = 1
|
47
50
|
def call(ps_name, hash={})
|
48
51
|
prepared_statements[ps_name].call(hash)
|
49
52
|
end
|
@@ -55,7 +58,7 @@ module Sequel
|
|
55
58
|
end
|
56
59
|
|
57
60
|
# Method that should be used when submitting any DDL (Data Definition
|
58
|
-
# Language) SQL
|
61
|
+
# Language) SQL, such as +create_table+. By default, calls +execute_dui+.
|
59
62
|
# This method should not be called directly by user code.
|
60
63
|
def execute_ddl(sql, opts={}, &block)
|
61
64
|
execute_dui(sql, opts, &block)
|
@@ -77,11 +80,9 @@ module Sequel
|
|
77
80
|
|
78
81
|
# Returns a single value from the database, e.g.:
|
79
82
|
#
|
80
|
-
# # SELECT 1
|
81
|
-
#
|
82
|
-
#
|
83
|
-
# # SELECT version()
|
84
|
-
# DB.get(:version.sql_function) #=> ...
|
83
|
+
# DB.get(1) # SELECT 1
|
84
|
+
# # => 1
|
85
|
+
# DB.get{version{}} # SELECT server_version()
|
85
86
|
def get(*args, &block)
|
86
87
|
dataset.get(*args, &block)
|
87
88
|
end
|
@@ -92,13 +93,18 @@ module Sequel
|
|
92
93
|
# depending on if the index is unique.
|
93
94
|
#
|
94
95
|
# Should not include the primary key index, functional indexes, or partial indexes.
|
96
|
+
#
|
97
|
+
# DB.indexes(:artists)
|
98
|
+
# # => {:artists_name_ukey=>{:columns=>[:name], :unique=>true}}
|
95
99
|
def indexes(table, opts={})
|
96
100
|
raise NotImplemented, "#indexes should be overridden by adapters"
|
97
101
|
end
|
98
102
|
|
99
103
|
# Runs the supplied SQL statement string on the database server. Returns nil.
|
100
104
|
# Options:
|
101
|
-
#
|
105
|
+
# :server :: The server to run the SQL on.
|
106
|
+
#
|
107
|
+
# DB.run("SET some_server_variable = 42")
|
102
108
|
def run(sql, opts={})
|
103
109
|
execute_ddl(sql, opts)
|
104
110
|
nil
|
@@ -109,13 +115,40 @@ module Sequel
|
|
109
115
|
# the first member being the column name, and the second member being a hash of column information.
|
110
116
|
# Available options are:
|
111
117
|
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
118
|
+
# :reload :: Ignore any cached results, and get fresh information from the database.
|
119
|
+
# :schema :: An explicit schema to use. It may also be implicitly provided
|
120
|
+
# via the table name.
|
121
|
+
#
|
122
|
+
# If schema parsing is supported by the database, the column information should at least contain the
|
123
|
+
# following columns:
|
124
|
+
#
|
125
|
+
# :allow_null :: Whether NULL is an allowed value for the column.
|
126
|
+
# :db_type :: The database type for the column, as a database specific string.
|
127
|
+
# :default :: The database default for the column, as a database specific string.
|
128
|
+
# :primary_key :: Whether the columns is a primary key column. If this column is not present,
|
129
|
+
# it means that primary key information is unavailable, not that the column
|
130
|
+
# is not a primary key.
|
131
|
+
# :ruby_default :: The database default for the column, as a ruby object. In many cases, complex
|
132
|
+
# database defaults cannot be parsed into ruby objects.
|
133
|
+
# :type :: A symbol specifying the type, such as :integer or :string.
|
134
|
+
#
|
135
|
+
# Example:
|
136
|
+
#
|
137
|
+
# DB.schema(:artists)
|
138
|
+
# # [[:id,
|
139
|
+
# # {:type=>:integer,
|
140
|
+
# # :primary_key=>true,
|
141
|
+
# # :default=>"nextval('artist_id_seq'::regclass)",
|
142
|
+
# # :ruby_default=>nil,
|
143
|
+
# # :db_type=>"integer",
|
144
|
+
# # :allow_null=>false}],
|
145
|
+
# # [:name,
|
146
|
+
# # {:type=>:string,
|
147
|
+
# # :primary_key=>false,
|
148
|
+
# # :default=>nil,
|
149
|
+
# # :ruby_default=>nil,
|
150
|
+
# # :db_type=>"text",
|
151
|
+
# # :allow_null=>false}]]
|
119
152
|
def schema(table, opts={})
|
120
153
|
raise(Error, 'schema parsing is not implemented on this database') unless respond_to?(:schema_parse_table, true)
|
121
154
|
|
@@ -134,6 +167,8 @@ module Sequel
|
|
134
167
|
|
135
168
|
# Returns true if a table with the given name exists. This requires a query
|
136
169
|
# to the database.
|
170
|
+
#
|
171
|
+
# DB.table_exists?(:foo) # => false
|
137
172
|
def table_exists?(name)
|
138
173
|
begin
|
139
174
|
from(name).first
|
@@ -144,6 +179,8 @@ module Sequel
|
|
144
179
|
end
|
145
180
|
|
146
181
|
# Return all tables in the database as an array of symbols.
|
182
|
+
#
|
183
|
+
# DB.tables # => [:albums, :artists]
|
147
184
|
def tables(opts={})
|
148
185
|
raise NotImplemented, "#tables should be overridden by adapters"
|
149
186
|
end
|
@@ -155,13 +192,15 @@ module Sequel
|
|
155
192
|
# The following options are respected:
|
156
193
|
#
|
157
194
|
# :isolation :: The transaction isolation level to use for this transaction,
|
158
|
-
# should be :uncommitted, :committed, :repeatable, or :serializable
|
195
|
+
# should be :uncommitted, :committed, :repeatable, or :serializable,
|
196
|
+
# used if given and the database/adapter supports customizable
|
197
|
+
# transaction isolation levels.
|
159
198
|
# :prepare :: A string to use as the transaction identifier for a
|
160
199
|
# prepared transaction (two-phase commit), if the database/adapter
|
161
|
-
# supports prepared transactions
|
162
|
-
# :server :: The server to use for the transaction
|
200
|
+
# supports prepared transactions.
|
201
|
+
# :server :: The server to use for the transaction.
|
163
202
|
# :savepoint :: Whether to create a new savepoint for this transaction,
|
164
|
-
# only respected if the database
|
203
|
+
# only respected if the database/adapter supports savepoints. By
|
165
204
|
# default Sequel will reuse an existing transaction, so if you want to
|
166
205
|
# use a savepoint you must use this option.
|
167
206
|
def transaction(opts={}, &block)
|
@@ -175,7 +214,7 @@ module Sequel
|
|
175
214
|
|
176
215
|
# Internal generic transaction method. Any exception raised by the given
|
177
216
|
# block will cause the transaction to be rolled back. If the exception is
|
178
|
-
# not Sequel::Rollback, the error will be reraised. If no exception occurs
|
217
|
+
# not a Sequel::Rollback, the error will be reraised. If no exception occurs
|
179
218
|
# inside the block, the transaction is commited.
|
180
219
|
def _transaction(conn, opts={})
|
181
220
|
begin
|
@@ -379,8 +418,8 @@ module Sequel
|
|
379
418
|
end
|
380
419
|
|
381
420
|
# Match the database's column type to a ruby type via a
|
382
|
-
# regular expression
|
383
|
-
#
|
421
|
+
# regular expression, and return the ruby type as a symbol
|
422
|
+
# such as :integer or :string.
|
384
423
|
def schema_column_type(db_type)
|
385
424
|
case db_type
|
386
425
|
when /\Ainterval\z/io
|
@@ -19,13 +19,13 @@ module Sequel
|
|
19
19
|
GENERIC_TYPES=[String, Integer, Fixnum, Bignum, Float, Numeric, BigDecimal,
|
20
20
|
Date, DateTime, Time, File, TrueClass, FalseClass]
|
21
21
|
|
22
|
-
# Return the
|
22
|
+
# Return the column hashes created by this generator
|
23
23
|
attr_reader :columns
|
24
24
|
|
25
|
-
# Return the
|
25
|
+
# Return the constraint hashes created by this generator
|
26
26
|
attr_reader :constraints
|
27
27
|
|
28
|
-
# Return the
|
28
|
+
# Return the index hashes created by this generator
|
29
29
|
attr_reader :indexes
|
30
30
|
|
31
31
|
# Set the database in which to create the table, and evaluate the block
|
@@ -50,14 +50,26 @@ module Sequel
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
# Add
|
54
|
-
# or args
|
53
|
+
# Add an unnamed constraint to the DDL, specified by the given block
|
54
|
+
# or args:
|
55
|
+
#
|
56
|
+
# check(:num=>1..5) # CHECK num >= 1 AND num <= 5
|
57
|
+
# check{num > 5} # CHECK num > 5
|
55
58
|
def check(*args, &block)
|
56
59
|
constraint(nil, *args, &block)
|
57
60
|
end
|
58
61
|
|
59
62
|
# Add a column with the given name, type, and opts to the DDL.
|
60
63
|
#
|
64
|
+
# column :num, :integer
|
65
|
+
# # num INTEGER
|
66
|
+
#
|
67
|
+
# column :name, String, :null=>false, :default=>'a'
|
68
|
+
# # name varchar(255) NOT NULL DEFAULT 'a'
|
69
|
+
#
|
70
|
+
# inet :ip
|
71
|
+
# # ip inet
|
72
|
+
#
|
61
73
|
# You can also create columns via method missing, so the following are
|
62
74
|
# equivalent:
|
63
75
|
#
|
@@ -66,30 +78,32 @@ module Sequel
|
|
66
78
|
#
|
67
79
|
# The following options are supported:
|
68
80
|
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
#
|
90
|
-
#
|
91
|
-
#
|
92
|
-
#
|
81
|
+
# :default :: The default value for the column.
|
82
|
+
# :deferrable :: This ensure Referential Integrity will work even if
|
83
|
+
# reference table will use for its foreign key a value that does not
|
84
|
+
# exists(yet) on referenced table. Basically it adds
|
85
|
+
# DEFERRABLE INITIALLY DEFERRED on key creation.
|
86
|
+
# :index :: Create an index on this column.
|
87
|
+
# :key :: For foreign key columns, the column in the associated table
|
88
|
+
# that this column references. Unnecessary if this column
|
89
|
+
# references the primary key of the associated table.
|
90
|
+
# :null :: Mark the column as allowing NULL values (if true),
|
91
|
+
# or not allowing NULL values (if false). If unspecified, will default
|
92
|
+
# to whatever the database default is.
|
93
|
+
# :on_delete :: Specify the behavior of this column when being deleted
|
94
|
+
# (:restrict, cascade, :set_null, :set_default, :no_action).
|
95
|
+
# :on_update :: Specify the behavior of this column when being updated
|
96
|
+
# (:restrict, cascade, :set_null, :set_default, :no_action).
|
97
|
+
# :primary_key :: Make the column as a single primary key column. This should only
|
98
|
+
# be used if you have a single, nonautoincrementing primary key column.
|
99
|
+
# :size :: The size of the column, generally used with string
|
100
|
+
# columns to specify the maximum number of characters the column will hold.
|
101
|
+
# An array of two integers can be provided to set the size and the
|
102
|
+
# precision, respectively, of decimal columns.
|
103
|
+
# :unique :: Mark the column as unique, generally has the same effect as
|
104
|
+
# creating a unique index on the column.
|
105
|
+
# :unsigned :: Make the column type unsigned, only useful for integer
|
106
|
+
# columns.
|
93
107
|
def column(name, type, opts = {})
|
94
108
|
columns << {:name => name, :type => type}.merge(opts)
|
95
109
|
index(name) if opts[:index]
|
@@ -97,12 +111,19 @@ module Sequel
|
|
97
111
|
|
98
112
|
# Adds a named constraint (or unnamed if name is nil) to the DDL,
|
99
113
|
# with the given block or args.
|
114
|
+
#
|
115
|
+
# constraint(:blah, :num=>1..5) # CONSTRAINT blah CHECK num >= 1 AND num <= 5
|
116
|
+
# check(:foo){num > 5} # CONSTRAINT foo CHECK num > 5
|
100
117
|
def constraint(name, *args, &block)
|
101
118
|
constraints << {:name => name, :type => :check, :check => block || args}
|
102
119
|
end
|
103
120
|
|
104
121
|
# Add a foreign key in the table that references another table to the DDL. See column
|
105
122
|
# for available options.
|
123
|
+
#
|
124
|
+
# foreign_key(:artist_id) # artist_id INTEGER
|
125
|
+
# foreign_key(:artist_id, :artists) # artist_id INTEGER REFERENCES artists
|
126
|
+
# foreign_key(:artist_id, :artists, :key=>:id) # artist_id INTEGER REFERENCES artists(id)
|
106
127
|
def foreign_key(name, table=nil, opts = {})
|
107
128
|
opts = case table
|
108
129
|
when Hash
|
@@ -131,31 +152,38 @@ module Sequel
|
|
131
152
|
# Add an index on the given column(s) with the given options to the DDL.
|
132
153
|
# The available options are:
|
133
154
|
#
|
134
|
-
#
|
135
|
-
#
|
136
|
-
#
|
155
|
+
# :type :: The type of index to use (only supported by some databases)
|
156
|
+
# :unique :: Make the index unique, so duplicate values are not allowed.
|
157
|
+
# :where :: Create a partial index (only supported by some databases)
|
158
|
+
#
|
159
|
+
# index :name
|
160
|
+
# # CREATE INDEX table_name_index ON table (name)
|
161
|
+
#
|
162
|
+
# index [:artist_id, :name]
|
163
|
+
# # CREATE INDEX table_artist_id_name_index ON table (artist_id, name)
|
137
164
|
def index(columns, opts = {})
|
138
165
|
indexes << {:columns => Array(columns)}.merge(opts)
|
139
166
|
end
|
140
167
|
|
141
|
-
# Add a column with the given type, name, and opts to the DDL. See column for available
|
168
|
+
# Add a column with the given type, name, and opts to the DDL. See +column+ for available
|
142
169
|
# options.
|
143
170
|
def method_missing(type, name = nil, opts = {})
|
144
171
|
name ? column(name, type, opts) : super
|
145
172
|
end
|
146
173
|
|
147
|
-
#
|
148
|
-
#
|
149
|
-
#
|
150
|
-
#
|
151
|
-
#
|
152
|
-
#
|
174
|
+
# Adds an autoincrementing primary key column or a primary key constraint to the DDL.
|
175
|
+
# To create a constraint, the first argument should be an array of column symbols
|
176
|
+
# specifying the primary key columns. To create an autoincrementing primary key
|
177
|
+
# column, a single symbol can be used. In both cases, an options hash can be used
|
178
|
+
# as the second argument.
|
179
|
+
#
|
180
|
+
# If you want to create a primary key column that is not autoincrementing, you
|
181
|
+
# should not use this method. Instead, you should use the regular +column+ method
|
182
|
+
# with a <tt>:primary_key=>true</tt> option.
|
153
183
|
#
|
154
184
|
# Examples:
|
155
185
|
# primary_key(:id)
|
156
|
-
# primary_key(:zip_code, :null => false)
|
157
186
|
# primary_key([:street_number, :house_number])
|
158
|
-
# primary_key(:id, :string, :auto_increment => false)
|
159
187
|
def primary_key(name, *args)
|
160
188
|
return composite_primary_key(name, *args) if name.is_a?(Array)
|
161
189
|
@primary_key = @db.serial_primary_key_options.merge({:name => name})
|
@@ -170,7 +198,7 @@ module Sequel
|
|
170
198
|
@primary_key
|
171
199
|
end
|
172
200
|
|
173
|
-
# The name of the primary key for this
|
201
|
+
# The name of the primary key for this generator, if it has a primary key.
|
174
202
|
def primary_key_name
|
175
203
|
@primary_key[:name] if @primary_key
|
176
204
|
end
|
@@ -181,6 +209,8 @@ module Sequel
|
|
181
209
|
end
|
182
210
|
|
183
211
|
# Add a unique constraint on the given columns to the DDL.
|
212
|
+
#
|
213
|
+
# unique(:name) # UNIQUE (name)
|
184
214
|
def unique(columns, opts = {})
|
185
215
|
constraints << {:type => :unique, :columns => Array(columns)}.merge(opts)
|
186
216
|
end
|
@@ -205,7 +235,7 @@ module Sequel
|
|
205
235
|
# to instantiate directly. Instances are created by Database#alter_table.
|
206
236
|
# It is used to specify table alteration parameters. It takes a Database
|
207
237
|
# object and a block of operations to perform on the table, and
|
208
|
-
# gives the Database
|
238
|
+
# gives the Database an array of table altering operations, which the database uses to
|
209
239
|
# alter a table's description.
|
210
240
|
#
|
211
241
|
# For more information on Sequel's support for schema modification, see
|
@@ -224,17 +254,25 @@ module Sequel
|
|
224
254
|
|
225
255
|
# Add a column with the given name, type, and opts to the DDL for the table.
|
226
256
|
# See Generator#column for the available options.
|
257
|
+
#
|
258
|
+
# add_column(:name, String) # ADD COLUMN name varchar(255)
|
227
259
|
def add_column(name, type, opts = {})
|
228
260
|
@operations << {:op => :add_column, :name => name, :type => type}.merge(opts)
|
229
261
|
end
|
230
262
|
|
231
263
|
# Add a constraint with the given name and args to the DDL for the table.
|
232
264
|
# See Generator#constraint.
|
265
|
+
#
|
266
|
+
# add_constraint(:valid_name, :name.like('A%'))
|
267
|
+
# # ADD CONSTRAINT valid_name CHECK (name LIKE 'A%')
|
233
268
|
def add_constraint(name, *args, &block)
|
234
269
|
@operations << {:op => :add_constraint, :name => name, :type => :check, :check => block || args}
|
235
270
|
end
|
236
271
|
|
237
272
|
# Add a unique constraint to the given column(s)
|
273
|
+
#
|
274
|
+
# add_unique_constraint(:name) # ADD UNIQUE (name)
|
275
|
+
# add_unique_constraint(:name, :name=>:unique_name) # ADD CONSTRAINT unique_name UNIQUE (name)
|
238
276
|
def add_unique_constraint(columns, opts = {})
|
239
277
|
@operations << {:op => :add_constraint, :type => :unique, :columns => Array(columns)}.merge(opts)
|
240
278
|
end
|
@@ -246,8 +284,11 @@ module Sequel
|
|
246
284
|
# keys. In this case, it will assume the columns exists and will only add
|
247
285
|
# the constraint.
|
248
286
|
#
|
249
|
-
# NOTE: If you need to add a foreign key constraint to
|
287
|
+
# NOTE: If you need to add a foreign key constraint to a single existing column
|
250
288
|
# use the composite key syntax even if it is only one column.
|
289
|
+
#
|
290
|
+
# add_foreign_key(:artist_id, :table) # ADD COLUMN artist_id integer REFERENCES table
|
291
|
+
# add_foreign_key([:name], :table) # ADD FOREIGN KEY (name) REFERENCES table
|
251
292
|
def add_foreign_key(name, table, opts = {})
|
252
293
|
return add_composite_foreign_key(name, table, opts) if name.is_a?(Array)
|
253
294
|
add_column(name, Integer, {:table=>table}.merge(opts))
|
@@ -261,12 +302,18 @@ module Sequel
|
|
261
302
|
|
262
303
|
# Add an index on the given columns to the DDL for the table. See
|
263
304
|
# Generator#index for available options.
|
305
|
+
#
|
306
|
+
# add_index(:artist_id) # CREATE INDEX table_artist_id_index ON table (artist_id)
|
264
307
|
def add_index(columns, opts = {})
|
265
308
|
@operations << {:op => :add_index, :columns => Array(columns)}.merge(opts)
|
266
309
|
end
|
267
310
|
|
268
311
|
# Add a primary key to the DDL for the table. See Generator#column
|
269
|
-
# for the available options.
|
312
|
+
# for the available options. Like +add_foreign_key+, if you specify
|
313
|
+
# the column name as an array, it just creates a constraint:
|
314
|
+
#
|
315
|
+
# add_primary_key(:id) # ADD COLUMN id serial PRIMARY KEY
|
316
|
+
# add_primary_key([:artist_id, :name]) # ADD PRIMARY KEY (artist_id, name)
|
270
317
|
def add_primary_key(name, opts = {})
|
271
318
|
return add_composite_primary_key(name, opts) if name.is_a?(Array)
|
272
319
|
opts = @db.serial_primary_key_options.merge(opts)
|
@@ -280,36 +327,52 @@ module Sequel
|
|
280
327
|
end
|
281
328
|
|
282
329
|
# Remove a column from the DDL for the table.
|
330
|
+
#
|
331
|
+
# drop_column(:artist_id) # DROP COLUMN artist_id
|
283
332
|
def drop_column(name)
|
284
333
|
@operations << {:op => :drop_column, :name => name}
|
285
334
|
end
|
286
335
|
|
287
336
|
# Remove a constraint from the DDL for the table.
|
337
|
+
#
|
338
|
+
# drop_constraint(:unique_name) # DROP CONSTRAINT unique_name
|
288
339
|
def drop_constraint(name)
|
289
340
|
@operations << {:op => :drop_constraint, :name => name}
|
290
341
|
end
|
291
342
|
|
292
343
|
# Remove an index from the DDL for the table.
|
344
|
+
#
|
345
|
+
# drop_index(:artist_id) # DROP INDEX table_artist_id_index
|
346
|
+
# drop_index([:a, :b]) # DROP INDEX table_a_b_index
|
347
|
+
# drop_index([:a, :b], :name=>:foo) # DROP INDEX foo
|
293
348
|
def drop_index(columns, options={})
|
294
349
|
@operations << {:op => :drop_index, :columns => Array(columns)}.merge(options)
|
295
350
|
end
|
296
351
|
|
297
352
|
# Modify a column's name in the DDL for the table.
|
353
|
+
#
|
354
|
+
# rename_column(:name, :artist_name) # RENAME COLUMN name TO artist_name
|
298
355
|
def rename_column(name, new_name, opts = {})
|
299
356
|
@operations << {:op => :rename_column, :name => name, :new_name => new_name}.merge(opts)
|
300
357
|
end
|
301
358
|
|
302
359
|
# Modify a column's default value in the DDL for the table.
|
360
|
+
#
|
361
|
+
# set_column_default(:artist_name, 'a') # ALTER COLUMN artist_name SET DEFAULT 'a'
|
303
362
|
def set_column_default(name, default)
|
304
363
|
@operations << {:op => :set_column_default, :name => name, :default => default}
|
305
364
|
end
|
306
365
|
|
307
366
|
# Modify a column's type in the DDL for the table.
|
367
|
+
#
|
368
|
+
# set_column_type(:artist_name, 'char(10)') # ALTER COLUMN artist_name TYPE char(10)
|
308
369
|
def set_column_type(name, type, opts={})
|
309
370
|
@operations << {:op => :set_column_type, :name => name, :type => type}.merge(opts)
|
310
371
|
end
|
311
372
|
|
312
373
|
# Modify a column's NOT NULL constraint.
|
374
|
+
#
|
375
|
+
# set_column_allow_null(:artist_name, false) # ALTER COLUMN artist_name SET NOT NULL
|
313
376
|
def set_column_allow_null(name, allow_null)
|
314
377
|
@operations << {:op => :set_column_null, :name => name, :null => allow_null}
|
315
378
|
end
|