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.
Files changed (237) hide show
  1. data/CHANGELOG +3134 -0
  2. data/COPYING +19 -0
  3. data/README.rdoc +723 -0
  4. data/Rakefile +193 -0
  5. data/bin/sequel +196 -0
  6. data/doc/advanced_associations.rdoc +644 -0
  7. data/doc/cheat_sheet.rdoc +218 -0
  8. data/doc/dataset_basics.rdoc +106 -0
  9. data/doc/dataset_filtering.rdoc +158 -0
  10. data/doc/opening_databases.rdoc +296 -0
  11. data/doc/prepared_statements.rdoc +104 -0
  12. data/doc/reflection.rdoc +84 -0
  13. data/doc/release_notes/1.0.txt +38 -0
  14. data/doc/release_notes/1.1.txt +143 -0
  15. data/doc/release_notes/1.3.txt +101 -0
  16. data/doc/release_notes/1.4.0.txt +53 -0
  17. data/doc/release_notes/1.5.0.txt +155 -0
  18. data/doc/release_notes/2.0.0.txt +298 -0
  19. data/doc/release_notes/2.1.0.txt +271 -0
  20. data/doc/release_notes/2.10.0.txt +328 -0
  21. data/doc/release_notes/2.11.0.txt +215 -0
  22. data/doc/release_notes/2.12.0.txt +534 -0
  23. data/doc/release_notes/2.2.0.txt +253 -0
  24. data/doc/release_notes/2.3.0.txt +88 -0
  25. data/doc/release_notes/2.4.0.txt +106 -0
  26. data/doc/release_notes/2.5.0.txt +137 -0
  27. data/doc/release_notes/2.6.0.txt +157 -0
  28. data/doc/release_notes/2.7.0.txt +166 -0
  29. data/doc/release_notes/2.8.0.txt +171 -0
  30. data/doc/release_notes/2.9.0.txt +97 -0
  31. data/doc/release_notes/3.0.0.txt +221 -0
  32. data/doc/release_notes/3.1.0.txt +406 -0
  33. data/doc/release_notes/3.10.0.txt +286 -0
  34. data/doc/release_notes/3.2.0.txt +268 -0
  35. data/doc/release_notes/3.3.0.txt +192 -0
  36. data/doc/release_notes/3.4.0.txt +325 -0
  37. data/doc/release_notes/3.5.0.txt +510 -0
  38. data/doc/release_notes/3.6.0.txt +366 -0
  39. data/doc/release_notes/3.7.0.txt +179 -0
  40. data/doc/release_notes/3.8.0.txt +151 -0
  41. data/doc/release_notes/3.9.0.txt +233 -0
  42. data/doc/schema.rdoc +36 -0
  43. data/doc/sharding.rdoc +113 -0
  44. data/doc/virtual_rows.rdoc +205 -0
  45. data/lib/sequel.rb +1 -0
  46. data/lib/sequel/adapters/ado.rb +90 -0
  47. data/lib/sequel/adapters/ado/mssql.rb +30 -0
  48. data/lib/sequel/adapters/amalgalite.rb +176 -0
  49. data/lib/sequel/adapters/db2.rb +139 -0
  50. data/lib/sequel/adapters/dbi.rb +113 -0
  51. data/lib/sequel/adapters/do.rb +188 -0
  52. data/lib/sequel/adapters/do/mysql.rb +49 -0
  53. data/lib/sequel/adapters/do/postgres.rb +91 -0
  54. data/lib/sequel/adapters/do/sqlite.rb +40 -0
  55. data/lib/sequel/adapters/firebird.rb +283 -0
  56. data/lib/sequel/adapters/informix.rb +77 -0
  57. data/lib/sequel/adapters/jdbc.rb +587 -0
  58. data/lib/sequel/adapters/jdbc/as400.rb +58 -0
  59. data/lib/sequel/adapters/jdbc/h2.rb +133 -0
  60. data/lib/sequel/adapters/jdbc/mssql.rb +57 -0
  61. data/lib/sequel/adapters/jdbc/mysql.rb +78 -0
  62. data/lib/sequel/adapters/jdbc/oracle.rb +50 -0
  63. data/lib/sequel/adapters/jdbc/postgresql.rb +108 -0
  64. data/lib/sequel/adapters/jdbc/sqlite.rb +55 -0
  65. data/lib/sequel/adapters/mysql.rb +421 -0
  66. data/lib/sequel/adapters/odbc.rb +143 -0
  67. data/lib/sequel/adapters/odbc/mssql.rb +42 -0
  68. data/lib/sequel/adapters/openbase.rb +64 -0
  69. data/lib/sequel/adapters/oracle.rb +131 -0
  70. data/lib/sequel/adapters/postgres.rb +504 -0
  71. data/lib/sequel/adapters/shared/mssql.rb +490 -0
  72. data/lib/sequel/adapters/shared/mysql.rb +498 -0
  73. data/lib/sequel/adapters/shared/oracle.rb +195 -0
  74. data/lib/sequel/adapters/shared/postgres.rb +830 -0
  75. data/lib/sequel/adapters/shared/progress.rb +44 -0
  76. data/lib/sequel/adapters/shared/sqlite.rb +389 -0
  77. data/lib/sequel/adapters/sqlite.rb +224 -0
  78. data/lib/sequel/adapters/utils/stored_procedures.rb +84 -0
  79. data/lib/sequel/connection_pool.rb +99 -0
  80. data/lib/sequel/connection_pool/sharded_single.rb +84 -0
  81. data/lib/sequel/connection_pool/sharded_threaded.rb +211 -0
  82. data/lib/sequel/connection_pool/single.rb +29 -0
  83. data/lib/sequel/connection_pool/threaded.rb +150 -0
  84. data/lib/sequel/core.rb +293 -0
  85. data/lib/sequel/core_sql.rb +241 -0
  86. data/lib/sequel/database.rb +1079 -0
  87. data/lib/sequel/database/schema_generator.rb +327 -0
  88. data/lib/sequel/database/schema_methods.rb +203 -0
  89. data/lib/sequel/database/schema_sql.rb +320 -0
  90. data/lib/sequel/dataset.rb +32 -0
  91. data/lib/sequel/dataset/actions.rb +441 -0
  92. data/lib/sequel/dataset/features.rb +86 -0
  93. data/lib/sequel/dataset/graph.rb +254 -0
  94. data/lib/sequel/dataset/misc.rb +119 -0
  95. data/lib/sequel/dataset/mutation.rb +64 -0
  96. data/lib/sequel/dataset/prepared_statements.rb +227 -0
  97. data/lib/sequel/dataset/query.rb +709 -0
  98. data/lib/sequel/dataset/sql.rb +996 -0
  99. data/lib/sequel/exceptions.rb +51 -0
  100. data/lib/sequel/extensions/blank.rb +43 -0
  101. data/lib/sequel/extensions/inflector.rb +242 -0
  102. data/lib/sequel/extensions/looser_typecasting.rb +21 -0
  103. data/lib/sequel/extensions/migration.rb +239 -0
  104. data/lib/sequel/extensions/named_timezones.rb +61 -0
  105. data/lib/sequel/extensions/pagination.rb +100 -0
  106. data/lib/sequel/extensions/pretty_table.rb +82 -0
  107. data/lib/sequel/extensions/query.rb +52 -0
  108. data/lib/sequel/extensions/schema_dumper.rb +271 -0
  109. data/lib/sequel/extensions/sql_expr.rb +122 -0
  110. data/lib/sequel/extensions/string_date_time.rb +46 -0
  111. data/lib/sequel/extensions/thread_local_timezones.rb +48 -0
  112. data/lib/sequel/metaprogramming.rb +9 -0
  113. data/lib/sequel/model.rb +120 -0
  114. data/lib/sequel/model/associations.rb +1514 -0
  115. data/lib/sequel/model/base.rb +1069 -0
  116. data/lib/sequel/model/default_inflections.rb +45 -0
  117. data/lib/sequel/model/errors.rb +39 -0
  118. data/lib/sequel/model/exceptions.rb +21 -0
  119. data/lib/sequel/model/inflections.rb +162 -0
  120. data/lib/sequel/model/plugins.rb +70 -0
  121. data/lib/sequel/plugins/active_model.rb +59 -0
  122. data/lib/sequel/plugins/association_dependencies.rb +103 -0
  123. data/lib/sequel/plugins/association_proxies.rb +41 -0
  124. data/lib/sequel/plugins/boolean_readers.rb +53 -0
  125. data/lib/sequel/plugins/caching.rb +141 -0
  126. data/lib/sequel/plugins/class_table_inheritance.rb +214 -0
  127. data/lib/sequel/plugins/composition.rb +138 -0
  128. data/lib/sequel/plugins/force_encoding.rb +72 -0
  129. data/lib/sequel/plugins/hook_class_methods.rb +126 -0
  130. data/lib/sequel/plugins/identity_map.rb +116 -0
  131. data/lib/sequel/plugins/instance_filters.rb +98 -0
  132. data/lib/sequel/plugins/instance_hooks.rb +57 -0
  133. data/lib/sequel/plugins/lazy_attributes.rb +77 -0
  134. data/lib/sequel/plugins/many_through_many.rb +208 -0
  135. data/lib/sequel/plugins/nested_attributes.rb +206 -0
  136. data/lib/sequel/plugins/optimistic_locking.rb +81 -0
  137. data/lib/sequel/plugins/rcte_tree.rb +281 -0
  138. data/lib/sequel/plugins/schema.rb +66 -0
  139. data/lib/sequel/plugins/serialization.rb +166 -0
  140. data/lib/sequel/plugins/single_table_inheritance.rb +74 -0
  141. data/lib/sequel/plugins/subclasses.rb +45 -0
  142. data/lib/sequel/plugins/tactical_eager_loading.rb +61 -0
  143. data/lib/sequel/plugins/timestamps.rb +87 -0
  144. data/lib/sequel/plugins/touch.rb +118 -0
  145. data/lib/sequel/plugins/typecast_on_load.rb +72 -0
  146. data/lib/sequel/plugins/validation_class_methods.rb +405 -0
  147. data/lib/sequel/plugins/validation_helpers.rb +223 -0
  148. data/lib/sequel/sql.rb +1020 -0
  149. data/lib/sequel/timezones.rb +161 -0
  150. data/lib/sequel/version.rb +12 -0
  151. data/lib/sequel_core.rb +1 -0
  152. data/lib/sequel_model.rb +1 -0
  153. data/spec/adapters/firebird_spec.rb +407 -0
  154. data/spec/adapters/informix_spec.rb +97 -0
  155. data/spec/adapters/mssql_spec.rb +403 -0
  156. data/spec/adapters/mysql_spec.rb +1019 -0
  157. data/spec/adapters/oracle_spec.rb +286 -0
  158. data/spec/adapters/postgres_spec.rb +969 -0
  159. data/spec/adapters/spec_helper.rb +51 -0
  160. data/spec/adapters/sqlite_spec.rb +432 -0
  161. data/spec/core/connection_pool_spec.rb +808 -0
  162. data/spec/core/core_sql_spec.rb +417 -0
  163. data/spec/core/database_spec.rb +1662 -0
  164. data/spec/core/dataset_spec.rb +3827 -0
  165. data/spec/core/expression_filters_spec.rb +595 -0
  166. data/spec/core/object_graph_spec.rb +296 -0
  167. data/spec/core/schema_generator_spec.rb +159 -0
  168. data/spec/core/schema_spec.rb +830 -0
  169. data/spec/core/spec_helper.rb +56 -0
  170. data/spec/core/version_spec.rb +7 -0
  171. data/spec/extensions/active_model_spec.rb +76 -0
  172. data/spec/extensions/association_dependencies_spec.rb +127 -0
  173. data/spec/extensions/association_proxies_spec.rb +50 -0
  174. data/spec/extensions/blank_spec.rb +67 -0
  175. data/spec/extensions/boolean_readers_spec.rb +92 -0
  176. data/spec/extensions/caching_spec.rb +250 -0
  177. data/spec/extensions/class_table_inheritance_spec.rb +252 -0
  178. data/spec/extensions/composition_spec.rb +194 -0
  179. data/spec/extensions/force_encoding_spec.rb +117 -0
  180. data/spec/extensions/hook_class_methods_spec.rb +470 -0
  181. data/spec/extensions/identity_map_spec.rb +202 -0
  182. data/spec/extensions/inflector_spec.rb +181 -0
  183. data/spec/extensions/instance_filters_spec.rb +55 -0
  184. data/spec/extensions/instance_hooks_spec.rb +133 -0
  185. data/spec/extensions/lazy_attributes_spec.rb +153 -0
  186. data/spec/extensions/looser_typecasting_spec.rb +39 -0
  187. data/spec/extensions/many_through_many_spec.rb +884 -0
  188. data/spec/extensions/migration_spec.rb +332 -0
  189. data/spec/extensions/named_timezones_spec.rb +72 -0
  190. data/spec/extensions/nested_attributes_spec.rb +396 -0
  191. data/spec/extensions/optimistic_locking_spec.rb +100 -0
  192. data/spec/extensions/pagination_spec.rb +99 -0
  193. data/spec/extensions/pretty_table_spec.rb +91 -0
  194. data/spec/extensions/query_spec.rb +85 -0
  195. data/spec/extensions/rcte_tree_spec.rb +205 -0
  196. data/spec/extensions/schema_dumper_spec.rb +357 -0
  197. data/spec/extensions/schema_spec.rb +127 -0
  198. data/spec/extensions/serialization_spec.rb +209 -0
  199. data/spec/extensions/single_table_inheritance_spec.rb +96 -0
  200. data/spec/extensions/spec_helper.rb +91 -0
  201. data/spec/extensions/sql_expr_spec.rb +89 -0
  202. data/spec/extensions/string_date_time_spec.rb +93 -0
  203. data/spec/extensions/subclasses_spec.rb +52 -0
  204. data/spec/extensions/tactical_eager_loading_spec.rb +65 -0
  205. data/spec/extensions/thread_local_timezones_spec.rb +45 -0
  206. data/spec/extensions/timestamps_spec.rb +150 -0
  207. data/spec/extensions/touch_spec.rb +155 -0
  208. data/spec/extensions/typecast_on_load_spec.rb +69 -0
  209. data/spec/extensions/validation_class_methods_spec.rb +984 -0
  210. data/spec/extensions/validation_helpers_spec.rb +438 -0
  211. data/spec/integration/associations_test.rb +281 -0
  212. data/spec/integration/database_test.rb +26 -0
  213. data/spec/integration/dataset_test.rb +963 -0
  214. data/spec/integration/eager_loader_test.rb +734 -0
  215. data/spec/integration/model_test.rb +130 -0
  216. data/spec/integration/plugin_test.rb +814 -0
  217. data/spec/integration/prepared_statement_test.rb +213 -0
  218. data/spec/integration/schema_test.rb +361 -0
  219. data/spec/integration/spec_helper.rb +73 -0
  220. data/spec/integration/timezone_test.rb +55 -0
  221. data/spec/integration/transaction_test.rb +122 -0
  222. data/spec/integration/type_test.rb +96 -0
  223. data/spec/model/association_reflection_spec.rb +175 -0
  224. data/spec/model/associations_spec.rb +2633 -0
  225. data/spec/model/base_spec.rb +418 -0
  226. data/spec/model/dataset_methods_spec.rb +78 -0
  227. data/spec/model/eager_loading_spec.rb +1391 -0
  228. data/spec/model/hooks_spec.rb +240 -0
  229. data/spec/model/inflector_spec.rb +26 -0
  230. data/spec/model/model_spec.rb +593 -0
  231. data/spec/model/plugins_spec.rb +236 -0
  232. data/spec/model/record_spec.rb +1500 -0
  233. data/spec/model/spec_helper.rb +97 -0
  234. data/spec/model/validations_spec.rb +153 -0
  235. data/spec/rcov.opts +6 -0
  236. data/spec/spec_config.rb.example +10 -0
  237. 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