viking-sequel 3.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.
- data/CHANGELOG +3134 -0
- data/COPYING +19 -0
- data/README.rdoc +723 -0
- data/Rakefile +193 -0
- data/bin/sequel +196 -0
- data/doc/advanced_associations.rdoc +644 -0
- data/doc/cheat_sheet.rdoc +218 -0
- data/doc/dataset_basics.rdoc +106 -0
- data/doc/dataset_filtering.rdoc +158 -0
- data/doc/opening_databases.rdoc +296 -0
- data/doc/prepared_statements.rdoc +104 -0
- data/doc/reflection.rdoc +84 -0
- data/doc/release_notes/1.0.txt +38 -0
- data/doc/release_notes/1.1.txt +143 -0
- data/doc/release_notes/1.3.txt +101 -0
- data/doc/release_notes/1.4.0.txt +53 -0
- data/doc/release_notes/1.5.0.txt +155 -0
- data/doc/release_notes/2.0.0.txt +298 -0
- data/doc/release_notes/2.1.0.txt +271 -0
- data/doc/release_notes/2.10.0.txt +328 -0
- data/doc/release_notes/2.11.0.txt +215 -0
- data/doc/release_notes/2.12.0.txt +534 -0
- data/doc/release_notes/2.2.0.txt +253 -0
- data/doc/release_notes/2.3.0.txt +88 -0
- data/doc/release_notes/2.4.0.txt +106 -0
- data/doc/release_notes/2.5.0.txt +137 -0
- data/doc/release_notes/2.6.0.txt +157 -0
- data/doc/release_notes/2.7.0.txt +166 -0
- data/doc/release_notes/2.8.0.txt +171 -0
- data/doc/release_notes/2.9.0.txt +97 -0
- data/doc/release_notes/3.0.0.txt +221 -0
- data/doc/release_notes/3.1.0.txt +406 -0
- data/doc/release_notes/3.10.0.txt +286 -0
- data/doc/release_notes/3.2.0.txt +268 -0
- data/doc/release_notes/3.3.0.txt +192 -0
- data/doc/release_notes/3.4.0.txt +325 -0
- data/doc/release_notes/3.5.0.txt +510 -0
- data/doc/release_notes/3.6.0.txt +366 -0
- data/doc/release_notes/3.7.0.txt +179 -0
- data/doc/release_notes/3.8.0.txt +151 -0
- data/doc/release_notes/3.9.0.txt +233 -0
- data/doc/schema.rdoc +36 -0
- data/doc/sharding.rdoc +113 -0
- data/doc/virtual_rows.rdoc +205 -0
- data/lib/sequel.rb +1 -0
- data/lib/sequel/adapters/ado.rb +90 -0
- data/lib/sequel/adapters/ado/mssql.rb +30 -0
- data/lib/sequel/adapters/amalgalite.rb +176 -0
- data/lib/sequel/adapters/db2.rb +139 -0
- data/lib/sequel/adapters/dbi.rb +113 -0
- data/lib/sequel/adapters/do.rb +188 -0
- data/lib/sequel/adapters/do/mysql.rb +49 -0
- data/lib/sequel/adapters/do/postgres.rb +91 -0
- data/lib/sequel/adapters/do/sqlite.rb +40 -0
- data/lib/sequel/adapters/firebird.rb +283 -0
- data/lib/sequel/adapters/informix.rb +77 -0
- data/lib/sequel/adapters/jdbc.rb +587 -0
- data/lib/sequel/adapters/jdbc/as400.rb +58 -0
- data/lib/sequel/adapters/jdbc/h2.rb +133 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +57 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +78 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +50 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +108 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +55 -0
- data/lib/sequel/adapters/mysql.rb +421 -0
- data/lib/sequel/adapters/odbc.rb +143 -0
- data/lib/sequel/adapters/odbc/mssql.rb +42 -0
- data/lib/sequel/adapters/openbase.rb +64 -0
- data/lib/sequel/adapters/oracle.rb +131 -0
- data/lib/sequel/adapters/postgres.rb +504 -0
- data/lib/sequel/adapters/shared/mssql.rb +490 -0
- data/lib/sequel/adapters/shared/mysql.rb +498 -0
- data/lib/sequel/adapters/shared/oracle.rb +195 -0
- data/lib/sequel/adapters/shared/postgres.rb +830 -0
- data/lib/sequel/adapters/shared/progress.rb +44 -0
- data/lib/sequel/adapters/shared/sqlite.rb +389 -0
- data/lib/sequel/adapters/sqlite.rb +224 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +84 -0
- data/lib/sequel/connection_pool.rb +99 -0
- data/lib/sequel/connection_pool/sharded_single.rb +84 -0
- data/lib/sequel/connection_pool/sharded_threaded.rb +211 -0
- data/lib/sequel/connection_pool/single.rb +29 -0
- data/lib/sequel/connection_pool/threaded.rb +150 -0
- data/lib/sequel/core.rb +293 -0
- data/lib/sequel/core_sql.rb +241 -0
- data/lib/sequel/database.rb +1079 -0
- data/lib/sequel/database/schema_generator.rb +327 -0
- data/lib/sequel/database/schema_methods.rb +203 -0
- data/lib/sequel/database/schema_sql.rb +320 -0
- data/lib/sequel/dataset.rb +32 -0
- data/lib/sequel/dataset/actions.rb +441 -0
- data/lib/sequel/dataset/features.rb +86 -0
- data/lib/sequel/dataset/graph.rb +254 -0
- data/lib/sequel/dataset/misc.rb +119 -0
- data/lib/sequel/dataset/mutation.rb +64 -0
- data/lib/sequel/dataset/prepared_statements.rb +227 -0
- data/lib/sequel/dataset/query.rb +709 -0
- data/lib/sequel/dataset/sql.rb +996 -0
- data/lib/sequel/exceptions.rb +51 -0
- data/lib/sequel/extensions/blank.rb +43 -0
- data/lib/sequel/extensions/inflector.rb +242 -0
- data/lib/sequel/extensions/looser_typecasting.rb +21 -0
- data/lib/sequel/extensions/migration.rb +239 -0
- data/lib/sequel/extensions/named_timezones.rb +61 -0
- data/lib/sequel/extensions/pagination.rb +100 -0
- data/lib/sequel/extensions/pretty_table.rb +82 -0
- data/lib/sequel/extensions/query.rb +52 -0
- data/lib/sequel/extensions/schema_dumper.rb +271 -0
- data/lib/sequel/extensions/sql_expr.rb +122 -0
- data/lib/sequel/extensions/string_date_time.rb +46 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +48 -0
- data/lib/sequel/metaprogramming.rb +9 -0
- data/lib/sequel/model.rb +120 -0
- data/lib/sequel/model/associations.rb +1514 -0
- data/lib/sequel/model/base.rb +1069 -0
- data/lib/sequel/model/default_inflections.rb +45 -0
- data/lib/sequel/model/errors.rb +39 -0
- data/lib/sequel/model/exceptions.rb +21 -0
- data/lib/sequel/model/inflections.rb +162 -0
- data/lib/sequel/model/plugins.rb +70 -0
- data/lib/sequel/plugins/active_model.rb +59 -0
- data/lib/sequel/plugins/association_dependencies.rb +103 -0
- data/lib/sequel/plugins/association_proxies.rb +41 -0
- data/lib/sequel/plugins/boolean_readers.rb +53 -0
- data/lib/sequel/plugins/caching.rb +141 -0
- data/lib/sequel/plugins/class_table_inheritance.rb +214 -0
- data/lib/sequel/plugins/composition.rb +138 -0
- data/lib/sequel/plugins/force_encoding.rb +72 -0
- data/lib/sequel/plugins/hook_class_methods.rb +126 -0
- data/lib/sequel/plugins/identity_map.rb +116 -0
- data/lib/sequel/plugins/instance_filters.rb +98 -0
- data/lib/sequel/plugins/instance_hooks.rb +57 -0
- data/lib/sequel/plugins/lazy_attributes.rb +77 -0
- data/lib/sequel/plugins/many_through_many.rb +208 -0
- data/lib/sequel/plugins/nested_attributes.rb +206 -0
- data/lib/sequel/plugins/optimistic_locking.rb +81 -0
- data/lib/sequel/plugins/rcte_tree.rb +281 -0
- data/lib/sequel/plugins/schema.rb +66 -0
- data/lib/sequel/plugins/serialization.rb +166 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +74 -0
- data/lib/sequel/plugins/subclasses.rb +45 -0
- data/lib/sequel/plugins/tactical_eager_loading.rb +61 -0
- data/lib/sequel/plugins/timestamps.rb +87 -0
- data/lib/sequel/plugins/touch.rb +118 -0
- data/lib/sequel/plugins/typecast_on_load.rb +72 -0
- data/lib/sequel/plugins/validation_class_methods.rb +405 -0
- data/lib/sequel/plugins/validation_helpers.rb +223 -0
- data/lib/sequel/sql.rb +1020 -0
- data/lib/sequel/timezones.rb +161 -0
- data/lib/sequel/version.rb +12 -0
- data/lib/sequel_core.rb +1 -0
- data/lib/sequel_model.rb +1 -0
- data/spec/adapters/firebird_spec.rb +407 -0
- data/spec/adapters/informix_spec.rb +97 -0
- data/spec/adapters/mssql_spec.rb +403 -0
- data/spec/adapters/mysql_spec.rb +1019 -0
- data/spec/adapters/oracle_spec.rb +286 -0
- data/spec/adapters/postgres_spec.rb +969 -0
- data/spec/adapters/spec_helper.rb +51 -0
- data/spec/adapters/sqlite_spec.rb +432 -0
- data/spec/core/connection_pool_spec.rb +808 -0
- data/spec/core/core_sql_spec.rb +417 -0
- data/spec/core/database_spec.rb +1662 -0
- data/spec/core/dataset_spec.rb +3827 -0
- data/spec/core/expression_filters_spec.rb +595 -0
- data/spec/core/object_graph_spec.rb +296 -0
- data/spec/core/schema_generator_spec.rb +159 -0
- data/spec/core/schema_spec.rb +830 -0
- data/spec/core/spec_helper.rb +56 -0
- data/spec/core/version_spec.rb +7 -0
- data/spec/extensions/active_model_spec.rb +76 -0
- data/spec/extensions/association_dependencies_spec.rb +127 -0
- data/spec/extensions/association_proxies_spec.rb +50 -0
- data/spec/extensions/blank_spec.rb +67 -0
- data/spec/extensions/boolean_readers_spec.rb +92 -0
- data/spec/extensions/caching_spec.rb +250 -0
- data/spec/extensions/class_table_inheritance_spec.rb +252 -0
- data/spec/extensions/composition_spec.rb +194 -0
- data/spec/extensions/force_encoding_spec.rb +117 -0
- data/spec/extensions/hook_class_methods_spec.rb +470 -0
- data/spec/extensions/identity_map_spec.rb +202 -0
- data/spec/extensions/inflector_spec.rb +181 -0
- data/spec/extensions/instance_filters_spec.rb +55 -0
- data/spec/extensions/instance_hooks_spec.rb +133 -0
- data/spec/extensions/lazy_attributes_spec.rb +153 -0
- data/spec/extensions/looser_typecasting_spec.rb +39 -0
- data/spec/extensions/many_through_many_spec.rb +884 -0
- data/spec/extensions/migration_spec.rb +332 -0
- data/spec/extensions/named_timezones_spec.rb +72 -0
- data/spec/extensions/nested_attributes_spec.rb +396 -0
- data/spec/extensions/optimistic_locking_spec.rb +100 -0
- data/spec/extensions/pagination_spec.rb +99 -0
- data/spec/extensions/pretty_table_spec.rb +91 -0
- data/spec/extensions/query_spec.rb +85 -0
- data/spec/extensions/rcte_tree_spec.rb +205 -0
- data/spec/extensions/schema_dumper_spec.rb +357 -0
- data/spec/extensions/schema_spec.rb +127 -0
- data/spec/extensions/serialization_spec.rb +209 -0
- data/spec/extensions/single_table_inheritance_spec.rb +96 -0
- data/spec/extensions/spec_helper.rb +91 -0
- data/spec/extensions/sql_expr_spec.rb +89 -0
- data/spec/extensions/string_date_time_spec.rb +93 -0
- data/spec/extensions/subclasses_spec.rb +52 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +65 -0
- data/spec/extensions/thread_local_timezones_spec.rb +45 -0
- data/spec/extensions/timestamps_spec.rb +150 -0
- data/spec/extensions/touch_spec.rb +155 -0
- data/spec/extensions/typecast_on_load_spec.rb +69 -0
- data/spec/extensions/validation_class_methods_spec.rb +984 -0
- data/spec/extensions/validation_helpers_spec.rb +438 -0
- data/spec/integration/associations_test.rb +281 -0
- data/spec/integration/database_test.rb +26 -0
- data/spec/integration/dataset_test.rb +963 -0
- data/spec/integration/eager_loader_test.rb +734 -0
- data/spec/integration/model_test.rb +130 -0
- data/spec/integration/plugin_test.rb +814 -0
- data/spec/integration/prepared_statement_test.rb +213 -0
- data/spec/integration/schema_test.rb +361 -0
- data/spec/integration/spec_helper.rb +73 -0
- data/spec/integration/timezone_test.rb +55 -0
- data/spec/integration/transaction_test.rb +122 -0
- data/spec/integration/type_test.rb +96 -0
- data/spec/model/association_reflection_spec.rb +175 -0
- data/spec/model/associations_spec.rb +2633 -0
- data/spec/model/base_spec.rb +418 -0
- data/spec/model/dataset_methods_spec.rb +78 -0
- data/spec/model/eager_loading_spec.rb +1391 -0
- data/spec/model/hooks_spec.rb +240 -0
- data/spec/model/inflector_spec.rb +26 -0
- data/spec/model/model_spec.rb +593 -0
- data/spec/model/plugins_spec.rb +236 -0
- data/spec/model/record_spec.rb +1500 -0
- data/spec/model/spec_helper.rb +97 -0
- data/spec/model/validations_spec.rb +153 -0
- data/spec/rcov.opts +6 -0
- data/spec/spec_config.rb.example +10 -0
- metadata +346 -0
@@ -0,0 +1,327 @@
|
|
1
|
+
module Sequel
|
2
|
+
# The Schema module holds the schema generators.
|
3
|
+
module Schema
|
4
|
+
# Schema::Generator is an internal class that the user is not expected
|
5
|
+
# to instantiate directly. Instances are created by Database#create_table.
|
6
|
+
# It is used to specify table creation parameters. It takes a Database
|
7
|
+
# object and a block of column/index/constraint specifications, and
|
8
|
+
# gives the Database a table description, which the database uses to
|
9
|
+
# create a table.
|
10
|
+
#
|
11
|
+
# Schema::Generator has some methods but also includes method_missing,
|
12
|
+
# allowing users to specify column type as a method instead of using
|
13
|
+
# the column method, which makes for a nicer DSL.
|
14
|
+
#
|
15
|
+
# For more information on Sequel's support for schema modification, see
|
16
|
+
# the {"Schema Modification" guide}[link:files/doc/schema_rdoc.html].
|
17
|
+
class Generator
|
18
|
+
# Classes specifying generic types that Sequel will convert to database-specific types.
|
19
|
+
GENERIC_TYPES=[String, Integer, Fixnum, Bignum, Float, Numeric, BigDecimal,
|
20
|
+
Date, DateTime, Time, File, TrueClass, FalseClass]
|
21
|
+
|
22
|
+
# Return the columns created by this generator
|
23
|
+
attr_reader :columns
|
24
|
+
|
25
|
+
# Return the constraints created by this generator
|
26
|
+
attr_reader :constraints
|
27
|
+
|
28
|
+
# Return the indexes created by this generator
|
29
|
+
attr_reader :indexes
|
30
|
+
|
31
|
+
# Set the database in which to create the table, and evaluate the block
|
32
|
+
# in the context of this object.
|
33
|
+
def initialize(db, &block)
|
34
|
+
@db = db
|
35
|
+
@columns = []
|
36
|
+
@indexes = []
|
37
|
+
@constraints = []
|
38
|
+
@primary_key = nil
|
39
|
+
instance_eval(&block) if block
|
40
|
+
@columns.unshift(@primary_key) if @primary_key && !has_column?(primary_key_name)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Add a method for each of the given types that creates a column
|
44
|
+
# with that type as a constant. Types given should either already
|
45
|
+
# be constants/classes or a capitalized string/symbol with the same name
|
46
|
+
# as a constant/class.
|
47
|
+
def self.add_type_method(*types)
|
48
|
+
types.each do |type|
|
49
|
+
class_eval("def #{type}(name, opts={}); column(name, #{type}, opts); end", __FILE__, __LINE__)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Add a unnamed constraint to the DDL, specified by the given block
|
54
|
+
# or args.
|
55
|
+
def check(*args, &block)
|
56
|
+
constraint(nil, *args, &block)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Add a column with the given name, type, and opts to the DDL.
|
60
|
+
#
|
61
|
+
# You can also create columns via method missing, so the following are
|
62
|
+
# equivalent:
|
63
|
+
#
|
64
|
+
# column :number, :integer
|
65
|
+
# integer :number
|
66
|
+
#
|
67
|
+
# The following options are supported:
|
68
|
+
#
|
69
|
+
# * :default - The default value for the column.
|
70
|
+
# * :index - Create an index on this column.
|
71
|
+
# * :key - For foreign key columns, the column in the associated table
|
72
|
+
# that this column references. Unnecessary if this column
|
73
|
+
# references the primary key of the associated table.
|
74
|
+
# * :null - Mark the column as allowing NULL values (if true),
|
75
|
+
# or not allowing NULL values (if false). If unspecified, will default
|
76
|
+
# to whatever the database default is.
|
77
|
+
# * :on_delete - Specify the behavior of this column when being deleted.
|
78
|
+
# See Dataset#on_delete_clause for options.
|
79
|
+
# * :on_update - Specify the behavior of this column when being updated.
|
80
|
+
# See Schema::SQL#on_delete_clause for options.
|
81
|
+
# * :size - The size of the column, generally used with string
|
82
|
+
# columns to specify the maximum number of characters the column will hold.
|
83
|
+
# An array of two integers can be provided to set the size and the
|
84
|
+
# precision, respectively, of decimal columns.
|
85
|
+
# * :unique - Mark the column as unique, generally has the same effect as
|
86
|
+
# creating a unique index on the column.
|
87
|
+
# * :unsigned - Make the column type unsigned, only useful for integer
|
88
|
+
# columns.
|
89
|
+
def column(name, type, opts = {})
|
90
|
+
columns << {:name => name, :type => type}.merge(opts)
|
91
|
+
index(name) if opts[:index]
|
92
|
+
end
|
93
|
+
|
94
|
+
# Adds a named constraint (or unnamed if name is nil) to the DDL,
|
95
|
+
# with the given block or args.
|
96
|
+
def constraint(name, *args, &block)
|
97
|
+
constraints << {:name => name, :type => :check, :check => block || args}
|
98
|
+
end
|
99
|
+
|
100
|
+
# Add a foreign key in the table that references another table to the DDL. See column
|
101
|
+
# for available options.
|
102
|
+
def foreign_key(name, table=nil, opts = {})
|
103
|
+
opts = case table
|
104
|
+
when Hash
|
105
|
+
table.merge(opts)
|
106
|
+
when Symbol
|
107
|
+
opts.merge(:table=>table)
|
108
|
+
when NilClass
|
109
|
+
opts
|
110
|
+
else
|
111
|
+
raise(Error, "The second argument to foreign_key should be a Hash, Symbol, or nil")
|
112
|
+
end
|
113
|
+
return composite_foreign_key(name, opts) if name.is_a?(Array)
|
114
|
+
column(name, Integer, opts)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Add a full text index on the given columns to the DDL.
|
118
|
+
def full_text_index(columns, opts = {})
|
119
|
+
index(columns, opts.merge(:type => :full_text))
|
120
|
+
end
|
121
|
+
|
122
|
+
# True if the DDL includes the creation of a column with the given name.
|
123
|
+
def has_column?(name)
|
124
|
+
columns.any?{|c| c[:name] == name}
|
125
|
+
end
|
126
|
+
|
127
|
+
# Add an index on the given column(s) with the given options to the DDL.
|
128
|
+
# The available options are:
|
129
|
+
#
|
130
|
+
# * :type - The type of index to use (only supported by some databases)
|
131
|
+
# * :unique - Make the index unique, so duplicate values are not allowed.
|
132
|
+
# * :where - Create a partial index (only supported by some databases)
|
133
|
+
def index(columns, opts = {})
|
134
|
+
indexes << {:columns => Array(columns)}.merge(opts)
|
135
|
+
end
|
136
|
+
|
137
|
+
# Add a column with the given type, name, and opts to the DDL. See column for available
|
138
|
+
# options.
|
139
|
+
def method_missing(type, name = nil, opts = {})
|
140
|
+
name ? column(name, type, opts) : super
|
141
|
+
end
|
142
|
+
|
143
|
+
# Add primary key information to the DDL. Takes between one and three
|
144
|
+
# arguments. The last one is an options hash as for Generator#column.
|
145
|
+
# The first one distinguishes two modes: an array of existing column
|
146
|
+
# names adds a composite primary key constraint. A single symbol adds a
|
147
|
+
# new column of that name and makes it the primary key. In that case the
|
148
|
+
# optional middle argument denotes the type.
|
149
|
+
#
|
150
|
+
# Examples:
|
151
|
+
# primary_key(:id)
|
152
|
+
# primary_key(:zip_code, :null => false)
|
153
|
+
# primary_key([:street_number, :house_number])
|
154
|
+
# primary_key(:id, :string, :auto_increment => false)
|
155
|
+
def primary_key(name, *args)
|
156
|
+
return composite_primary_key(name, *args) if name.is_a?(Array)
|
157
|
+
@primary_key = @db.serial_primary_key_options.merge({:name => name})
|
158
|
+
|
159
|
+
if opts = args.pop
|
160
|
+
opts = {:type => opts} unless opts.is_a?(Hash)
|
161
|
+
if type = args.pop
|
162
|
+
opts.merge!(:type => type)
|
163
|
+
end
|
164
|
+
@primary_key.merge!(opts)
|
165
|
+
end
|
166
|
+
@primary_key
|
167
|
+
end
|
168
|
+
|
169
|
+
# The name of the primary key for this table, if it has a primary key.
|
170
|
+
def primary_key_name
|
171
|
+
@primary_key[:name] if @primary_key
|
172
|
+
end
|
173
|
+
|
174
|
+
# Add a spatial index on the given columns to the DDL.
|
175
|
+
def spatial_index(columns, opts = {})
|
176
|
+
index(columns, opts.merge(:type => :spatial))
|
177
|
+
end
|
178
|
+
|
179
|
+
# Add a unique constraint on the given columns to the DDL.
|
180
|
+
def unique(columns, opts = {})
|
181
|
+
constraints << {:type => :unique, :columns => Array(columns)}.merge(opts)
|
182
|
+
end
|
183
|
+
|
184
|
+
private
|
185
|
+
|
186
|
+
# Add a composite primary key constraint
|
187
|
+
def composite_primary_key(columns, *args)
|
188
|
+
opts = args.pop || {}
|
189
|
+
constraints << {:type => :primary_key, :columns => columns}.merge(opts)
|
190
|
+
end
|
191
|
+
|
192
|
+
# Add a composite foreign key constraint
|
193
|
+
def composite_foreign_key(columns, opts)
|
194
|
+
constraints << {:type => :foreign_key, :columns => columns}.merge(opts)
|
195
|
+
end
|
196
|
+
|
197
|
+
add_type_method(*GENERIC_TYPES)
|
198
|
+
end
|
199
|
+
|
200
|
+
# Schema::AlterTableGenerator is an internal class that the user is not expected
|
201
|
+
# to instantiate directly. Instances are created by Database#alter_table.
|
202
|
+
# It is used to specify table alteration parameters. It takes a Database
|
203
|
+
# object and a block of operations to perform on the table, and
|
204
|
+
# gives the Database a table an array of operations, which the database uses to
|
205
|
+
# alter a table's description.
|
206
|
+
#
|
207
|
+
# For more information on Sequel's support for schema modification, see
|
208
|
+
# the {"Schema Modification" guide}[link:files/doc/schema_rdoc.html].
|
209
|
+
class AlterTableGenerator
|
210
|
+
# An array of DDL operations to perform
|
211
|
+
attr_reader :operations
|
212
|
+
|
213
|
+
# Set the Database object to which to apply the DDL, and evaluate the
|
214
|
+
# block in the context of this object.
|
215
|
+
def initialize(db, &block)
|
216
|
+
@db = db
|
217
|
+
@operations = []
|
218
|
+
instance_eval(&block) if block
|
219
|
+
end
|
220
|
+
|
221
|
+
# Add a column with the given name, type, and opts to the DDL for the table.
|
222
|
+
# See Generator#column for the available options.
|
223
|
+
def add_column(name, type, opts = {})
|
224
|
+
@operations << {:op => :add_column, :name => name, :type => type}.merge(opts)
|
225
|
+
end
|
226
|
+
|
227
|
+
# Add a constraint with the given name and args to the DDL for the table.
|
228
|
+
# See Generator#constraint.
|
229
|
+
def add_constraint(name, *args, &block)
|
230
|
+
@operations << {:op => :add_constraint, :name => name, :type => :check, :check => block || args}
|
231
|
+
end
|
232
|
+
|
233
|
+
# Add a unique constraint to the given column(s)
|
234
|
+
def add_unique_constraint(columns, opts = {})
|
235
|
+
@operations << {:op => :add_constraint, :type => :unique, :columns => Array(columns)}.merge(opts)
|
236
|
+
end
|
237
|
+
|
238
|
+
# Add a foreign key with the given name and referencing the given table
|
239
|
+
# to the DDL for the table. See Generator#column for the available options.
|
240
|
+
#
|
241
|
+
# You can also pass an array of column names for creating composite foreign
|
242
|
+
# keys. In this case, it will assume the columns exists and will only add
|
243
|
+
# the constraint.
|
244
|
+
#
|
245
|
+
# NOTE: If you need to add a foreign key constraint to an existing column
|
246
|
+
# use the composite key syntax even if it is only one column.
|
247
|
+
def add_foreign_key(name, table, opts = {})
|
248
|
+
return add_composite_foreign_key(name, table, opts) if name.is_a?(Array)
|
249
|
+
add_column(name, Integer, {:table=>table}.merge(opts))
|
250
|
+
end
|
251
|
+
|
252
|
+
# Add a full text index on the given columns to the DDL for the table.
|
253
|
+
# See Generator#index for available options.
|
254
|
+
def add_full_text_index(columns, opts = {})
|
255
|
+
add_index(columns, {:type=>:full_text}.merge(opts))
|
256
|
+
end
|
257
|
+
|
258
|
+
# Add an index on the given columns to the DDL for the table. See
|
259
|
+
# Generator#index for available options.
|
260
|
+
def add_index(columns, opts = {})
|
261
|
+
@operations << {:op => :add_index, :columns => Array(columns)}.merge(opts)
|
262
|
+
end
|
263
|
+
|
264
|
+
# Add a primary key to the DDL for the table. See Generator#column
|
265
|
+
# for the available options.
|
266
|
+
def add_primary_key(name, opts = {})
|
267
|
+
return add_composite_primary_key(name, opts) if name.is_a?(Array)
|
268
|
+
opts = @db.serial_primary_key_options.merge(opts)
|
269
|
+
add_column(name, opts.delete(:type), opts)
|
270
|
+
end
|
271
|
+
|
272
|
+
# Add a spatial index on the given columns to the DDL for the table.
|
273
|
+
# See Generator#index for available options.
|
274
|
+
def add_spatial_index(columns, opts = {})
|
275
|
+
add_index(columns, {:type=>:spatial}.merge(opts))
|
276
|
+
end
|
277
|
+
|
278
|
+
# Remove a column from the DDL for the table.
|
279
|
+
def drop_column(name)
|
280
|
+
@operations << {:op => :drop_column, :name => name}
|
281
|
+
end
|
282
|
+
|
283
|
+
# Remove a constraint from the DDL for the table.
|
284
|
+
def drop_constraint(name)
|
285
|
+
@operations << {:op => :drop_constraint, :name => name}
|
286
|
+
end
|
287
|
+
|
288
|
+
# Remove an index from the DDL for the table.
|
289
|
+
def drop_index(columns, options={})
|
290
|
+
@operations << {:op => :drop_index, :columns => Array(columns)}.merge(options)
|
291
|
+
end
|
292
|
+
|
293
|
+
# Modify a column's name in the DDL for the table.
|
294
|
+
def rename_column(name, new_name, opts = {})
|
295
|
+
@operations << {:op => :rename_column, :name => name, :new_name => new_name}.merge(opts)
|
296
|
+
end
|
297
|
+
|
298
|
+
# Modify a column's default value in the DDL for the table.
|
299
|
+
def set_column_default(name, default)
|
300
|
+
@operations << {:op => :set_column_default, :name => name, :default => default}
|
301
|
+
end
|
302
|
+
|
303
|
+
# Modify a column's type in the DDL for the table.
|
304
|
+
def set_column_type(name, type, opts={})
|
305
|
+
@operations << {:op => :set_column_type, :name => name, :type => type}.merge(opts)
|
306
|
+
end
|
307
|
+
|
308
|
+
# Modify a column's NOT NULL constraint.
|
309
|
+
def set_column_allow_null(name, allow_null)
|
310
|
+
@operations << {:op => :set_column_null, :name => name, :null => allow_null}
|
311
|
+
end
|
312
|
+
|
313
|
+
private
|
314
|
+
|
315
|
+
# Add a composite primary key constraint
|
316
|
+
def add_composite_primary_key(columns, opts)
|
317
|
+
@operations << {:op => :add_constraint, :type => :primary_key, :columns => columns}.merge(opts)
|
318
|
+
end
|
319
|
+
|
320
|
+
# Add a composite foreign key constraint
|
321
|
+
def add_composite_foreign_key(columns, table, opts)
|
322
|
+
@operations << {:op => :add_constraint, :type => :foreign_key, :columns => columns, :table => table}.merge(opts)
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
@@ -0,0 +1,203 @@
|
|
1
|
+
module Sequel
|
2
|
+
class Database
|
3
|
+
# Adds a column to the specified table. This method expects a column name,
|
4
|
+
# a datatype and optionally a hash with additional constraints and options:
|
5
|
+
#
|
6
|
+
# DB.add_column :items, :name, :text, :unique => true, :null => false
|
7
|
+
# DB.add_column :items, :category, :text, :default => 'ruby'
|
8
|
+
#
|
9
|
+
# See alter_table.
|
10
|
+
def add_column(table, *args)
|
11
|
+
alter_table(table) {add_column(*args)}
|
12
|
+
end
|
13
|
+
|
14
|
+
# Adds an index to a table for the given columns:
|
15
|
+
#
|
16
|
+
# DB.add_index :posts, :title
|
17
|
+
# DB.add_index :posts, [:author, :title], :unique => true
|
18
|
+
#
|
19
|
+
#
|
20
|
+
# Options:
|
21
|
+
# * :ignore_errors - Ignore any DatabaseErrors that are raised
|
22
|
+
#
|
23
|
+
# See alter_table.
|
24
|
+
def add_index(table, columns, options={})
|
25
|
+
e = options[:ignore_errors]
|
26
|
+
begin
|
27
|
+
alter_table(table){add_index(columns, options)}
|
28
|
+
rescue DatabaseError
|
29
|
+
raise unless e
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Alters the given table with the specified block. Example:
|
34
|
+
#
|
35
|
+
# DB.alter_table :items do
|
36
|
+
# add_column :category, :text, :default => 'ruby'
|
37
|
+
# drop_column :category
|
38
|
+
# rename_column :cntr, :counter
|
39
|
+
# set_column_type :value, :float
|
40
|
+
# set_column_default :value, :float
|
41
|
+
# add_index [:group, :category]
|
42
|
+
# drop_index [:group, :category]
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# Note that #add_column accepts all the options available for column
|
46
|
+
# definitions using create_table, and #add_index accepts all the options
|
47
|
+
# available for index definition.
|
48
|
+
#
|
49
|
+
# See Schema::AlterTableGenerator and the {"Schema Modification" guide}[link:files/doc/schema_rdoc.html].
|
50
|
+
def alter_table(name, generator=nil, &block)
|
51
|
+
remove_cached_schema(name)
|
52
|
+
generator ||= Schema::AlterTableGenerator.new(self, &block)
|
53
|
+
alter_table_sql_list(name, generator.operations).flatten.each {|sql| execute_ddl(sql)}
|
54
|
+
end
|
55
|
+
|
56
|
+
# Creates a table with the columns given in the provided block:
|
57
|
+
#
|
58
|
+
# DB.create_table :posts do
|
59
|
+
# primary_key :id
|
60
|
+
# column :title, :text
|
61
|
+
# String :content
|
62
|
+
# index :title
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# Options:
|
66
|
+
# * :temp - Create the table as a temporary table.
|
67
|
+
# * :ignore_index_errors - Ignore any errors when creating indexes.
|
68
|
+
#
|
69
|
+
# See Schema::Generator and the {"Schema Modification" guide}[link:files/doc/schema_rdoc.html].
|
70
|
+
def create_table(name, options={}, &block)
|
71
|
+
options = {:generator=>options} if options.is_a?(Schema::Generator)
|
72
|
+
generator = options[:generator] || Schema::Generator.new(self, &block)
|
73
|
+
create_table_from_generator(name, generator, options)
|
74
|
+
create_table_indexes_from_generator(name, generator, options)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Forcibly creates a table, attempting to drop it unconditionally (and catching any errors), then creating it.
|
78
|
+
def create_table!(name, options={}, &block)
|
79
|
+
drop_table(name) rescue nil
|
80
|
+
create_table(name, options, &block)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Creates the table unless the table already exists
|
84
|
+
def create_table?(name, options={}, &block)
|
85
|
+
create_table(name, options, &block) unless table_exists?(name)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Creates a view, replacing it if it already exists:
|
89
|
+
#
|
90
|
+
# DB.create_or_replace_view(:cheap_items, "SELECT * FROM items WHERE price < 100")
|
91
|
+
# DB.create_or_replace_view(:ruby_items, DB[:items].filter(:category => 'ruby'))
|
92
|
+
def create_or_replace_view(name, source)
|
93
|
+
remove_cached_schema(name)
|
94
|
+
source = source.sql if source.is_a?(Dataset)
|
95
|
+
execute_ddl("CREATE OR REPLACE VIEW #{quote_schema_table(name)} AS #{source}")
|
96
|
+
end
|
97
|
+
|
98
|
+
# Creates a view based on a dataset or an SQL string:
|
99
|
+
#
|
100
|
+
# DB.create_view(:cheap_items, "SELECT * FROM items WHERE price < 100")
|
101
|
+
# DB.create_view(:ruby_items, DB[:items].filter(:category => 'ruby'))
|
102
|
+
def create_view(name, source)
|
103
|
+
source = source.sql if source.is_a?(Dataset)
|
104
|
+
execute_ddl("CREATE VIEW #{quote_schema_table(name)} AS #{source}")
|
105
|
+
end
|
106
|
+
|
107
|
+
# Removes a column from the specified table:
|
108
|
+
#
|
109
|
+
# DB.drop_column :items, :category
|
110
|
+
#
|
111
|
+
# See alter_table.
|
112
|
+
def drop_column(table, *args)
|
113
|
+
alter_table(table) {drop_column(*args)}
|
114
|
+
end
|
115
|
+
|
116
|
+
# Removes an index for the given table and column/s:
|
117
|
+
#
|
118
|
+
# DB.drop_index :posts, :title
|
119
|
+
# DB.drop_index :posts, [:author, :title]
|
120
|
+
#
|
121
|
+
# See alter_table.
|
122
|
+
def drop_index(table, columns, options={})
|
123
|
+
alter_table(table){drop_index(columns, options)}
|
124
|
+
end
|
125
|
+
|
126
|
+
# Drops one or more tables corresponding to the given names:
|
127
|
+
#
|
128
|
+
# DB.drop_table(:posts, :comments)
|
129
|
+
def drop_table(*names)
|
130
|
+
names.each do |n|
|
131
|
+
remove_cached_schema(n)
|
132
|
+
execute_ddl(drop_table_sql(n))
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# Drops one or more views corresponding to the given names:
|
137
|
+
#
|
138
|
+
# DB.drop_view(:cheap_items)
|
139
|
+
def drop_view(*names)
|
140
|
+
names.each do |n|
|
141
|
+
remove_cached_schema(n)
|
142
|
+
execute_ddl("DROP VIEW #{quote_schema_table(n)}")
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Renames a table:
|
147
|
+
#
|
148
|
+
# DB.tables #=> [:items]
|
149
|
+
# DB.rename_table :items, :old_items
|
150
|
+
# DB.tables #=> [:old_items]
|
151
|
+
def rename_table(name, new_name)
|
152
|
+
remove_cached_schema(name)
|
153
|
+
execute_ddl(rename_table_sql(name, new_name))
|
154
|
+
end
|
155
|
+
|
156
|
+
# Renames a column in the specified table. This method expects the current
|
157
|
+
# column name and the new column name:
|
158
|
+
#
|
159
|
+
# DB.rename_column :items, :cntr, :counter
|
160
|
+
#
|
161
|
+
# See alter_table.
|
162
|
+
def rename_column(table, *args)
|
163
|
+
alter_table(table) {rename_column(*args)}
|
164
|
+
end
|
165
|
+
|
166
|
+
# Sets the default value for the given column in the given table:
|
167
|
+
#
|
168
|
+
# DB.set_column_default :items, :category, 'perl!'
|
169
|
+
#
|
170
|
+
# See alter_table.
|
171
|
+
def set_column_default(table, *args)
|
172
|
+
alter_table(table) {set_column_default(*args)}
|
173
|
+
end
|
174
|
+
|
175
|
+
# Set the data type for the given column in the given table:
|
176
|
+
#
|
177
|
+
# DB.set_column_type :items, :price, :float
|
178
|
+
#
|
179
|
+
# See alter_table.
|
180
|
+
def set_column_type(table, *args)
|
181
|
+
alter_table(table) {set_column_type(*args)}
|
182
|
+
end
|
183
|
+
|
184
|
+
private
|
185
|
+
|
186
|
+
# Execute the create table statements using the generator.
|
187
|
+
def create_table_from_generator(name, generator, options)
|
188
|
+
execute_ddl(create_table_sql(name, generator, options))
|
189
|
+
end
|
190
|
+
|
191
|
+
# Execute the create index statements using the generator.
|
192
|
+
def create_table_indexes_from_generator(name, generator, options)
|
193
|
+
e = options[:ignore_index_errors]
|
194
|
+
index_sql_list(name, generator.indexes).each do |sql|
|
195
|
+
begin
|
196
|
+
execute_ddl(sql)
|
197
|
+
rescue DatabaseError
|
198
|
+
raise unless e
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|