Module: Sequel::Schema::SQL
- Included in:
- Database
- Defined in:
- lib/sequel_core/schema/sql.rb,
lib/sequel_core/adapters/shared/mysql.rb
Constant Summary collapse
- AUTOINCREMENT =
'AUTOINCREMENT'.freeze
- CASCADE =
'CASCADE'.freeze
- COMMA_SEPARATOR =
', '.freeze
- NO_ACTION =
'NO ACTION'.freeze
- NOT_NULL =
' NOT NULL'.freeze
- NULL =
' NULL'.freeze
- PRIMARY_KEY =
' PRIMARY KEY'.freeze
- RESTRICT =
'RESTRICT'.freeze
- SET_DEFAULT =
'SET DEFAULT'.freeze
- SET_NULL =
'SET NULL'.freeze
- TYPES =
Hash.new {|h, k| k}
- UNDERSCORE =
'_'.freeze
- UNIQUE =
' UNIQUE'.freeze
- UNSIGNED =
' UNSIGNED'.freeze
Instance Method Summary collapse
-
#alter_table_sql(table, op) ⇒ Object
The SQL to execute to modify the DDL for the given table name.
-
#alter_table_sql_list(table, operations) ⇒ Object
Array of SQL DDL modification statements for the given table, corresponding to the DDL changes specified by the operations.
-
#auto_increment_sql ⇒ Object
The SQL string specify the autoincrement property, generally used by primary keys.
-
#column_definition_sql(column) ⇒ Object
SQL DDL fragment containing the column creation SQL for the given column.
-
#column_list_sql(columns) ⇒ Object
SQL DDL fragment containing the column creation SQL for all given columns, used instead a CREATE TABLE block.
-
#column_references_sql(column) ⇒ Object
(also: #default_column_references_sql)
SQL DDL fragment for column foreign key references.
-
#constraint_definition_sql(constraint) ⇒ Object
SQL DDL fragment specifying a constraint on a table.
-
#create_table_sql_list(name, columns, indexes = nil) ⇒ Object
Array of SQL DDL statements, the first for creating a table with the given name and column specifications, and the others for specifying indexes on the table.
-
#default_index_name(table_name, columns) ⇒ Object
Default index name for the table and columns, may be too long for certain databases.
-
#drop_index_sql(table, op) ⇒ Object
The SQL to drop an index for the table.
-
#drop_table_sql(name) ⇒ Object
SQL DDL statement to drop the table with the given name.
-
#filter_expr(*args, &block) ⇒ Object
Proxy the filter_expr call to the dataset, used for creating constraints.
-
#index_definition_sql(table_name, index) ⇒ Object
SQL DDL statement for creating an index for the table with the given name and index specifications.
-
#index_list_sql_list(table_name, indexes) ⇒ Object
Array of SQL DDL statements, one for each index specification, for the given table.
-
#literal(v) ⇒ Object
Proxy the literal call to the dataset, used for default values.
-
#on_delete_clause(action) ⇒ Object
SQL DDL ON DELETE fragment to use, based on the given action.
-
#quote_identifier(v) ⇒ Object
Proxy the quote_identifier method to the dataset, used for quoting tables and columns.
-
#quote_schema_table(table) ⇒ Object
Proxy the quote_schema_table method to the dataset.
-
#rename_table_sql(name, new_name) ⇒ Object
SQL DDL statement for renaming a table.
-
#schema(table = nil, opts = {}) ⇒ Object
Parse the schema from the database.
-
#schema_utility_dataset ⇒ Object
The dataset to use for proxying certain schema methods.
Instance Method Details
#alter_table_sql(table, op) ⇒ Object
The SQL to execute to modify the DDL for the given table name. op should be one of the operations returned by the AlterTableGenerator.
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/sequel_core/schema/sql.rb', line 22 def alter_table_sql(table, op) quoted_name = quote_identifier(op[:name]) if op[:name] alter_table_op = case op[:op] when :add_column "ADD COLUMN #{column_definition_sql(op)}" when :drop_column "DROP COLUMN #{quoted_name}" when :rename_column "RENAME COLUMN #{quoted_name} TO #{quote_identifier(op[:new_name])}" when :set_column_type "ALTER COLUMN #{quoted_name} TYPE #{type_literal(op)}" when :set_column_default "ALTER COLUMN #{quoted_name} SET DEFAULT #{literal(op[:default])}" when :set_column_null "ALTER COLUMN #{quoted_name} #{op[:null] ? 'DROP' : 'SET'} NOT NULL" when :add_index return index_definition_sql(table, op) when :drop_index return drop_index_sql(table, op) when :add_constraint "ADD #{constraint_definition_sql(op)}" when :drop_constraint "DROP CONSTRAINT #{quoted_name}" else raise Error, "Unsupported ALTER TABLE operation" end "ALTER TABLE #{quote_schema_table(table)} #{alter_table_op}" end |
#alter_table_sql_list(table, operations) ⇒ Object
Array of SQL DDL modification statements for the given table, corresponding to the DDL changes specified by the operations.
53 54 55 |
# File 'lib/sequel_core/schema/sql.rb', line 53 def alter_table_sql_list(table, operations) operations.map{|op| alter_table_sql(table, op)} end |
#auto_increment_sql ⇒ Object
The SQL string specify the autoincrement property, generally used by primary keys.
59 60 61 |
# File 'lib/sequel_core/schema/sql.rb', line 59 def auto_increment_sql AUTOINCREMENT end |
#column_definition_sql(column) ⇒ Object
SQL DDL fragment containing the column creation SQL for the given column.
64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/sequel_core/schema/sql.rb', line 64 def column_definition_sql(column) return constraint_definition_sql(column) if column[:type] == :check sql = "#{quote_identifier(column[:name])} #{type_literal(column)}" sql << UNIQUE if column[:unique] sql << NOT_NULL if column[:null] == false sql << NULL if column[:null] == true sql << " DEFAULT #{literal(column[:default])}" if column.include?(:default) sql << PRIMARY_KEY if column[:primary_key] sql << " #{auto_increment_sql}" if column[:auto_increment] sql << column_references_sql(column) if column[:table] sql end |
#column_list_sql(columns) ⇒ Object
SQL DDL fragment containing the column creation SQL for all given columns, used instead a CREATE TABLE block.
79 80 81 |
# File 'lib/sequel_core/schema/sql.rb', line 79 def column_list_sql(columns) columns.map{|c| column_definition_sql(c)}.join(COMMA_SEPARATOR) end |
#column_references_sql(column) ⇒ Object Also known as: default_column_references_sql
SQL DDL fragment for column foreign key references
84 85 86 87 88 89 90 |
# File 'lib/sequel_core/schema/sql.rb', line 84 def column_references_sql(column) sql = " REFERENCES #{quote_schema_table(column[:table])}" sql << "(#{Array(column[:key]).map{|x| quote_identifier(x)}.join(COMMA_SEPARATOR)})" if column[:key] sql << " ON DELETE #{on_delete_clause(column[:on_delete])}" if column[:on_delete] sql << " ON UPDATE #{on_delete_clause(column[:on_update])}" if column[:on_update] sql end |
#constraint_definition_sql(constraint) ⇒ Object
SQL DDL fragment specifying a constraint on a table.
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/sequel_core/schema/sql.rb', line 93 def constraint_definition_sql(constraint) sql = constraint[:name] ? "CONSTRAINT #{quote_identifier(constraint[:name])} " : "" case constraint[:constraint_type] when :primary_key sql << "PRIMARY KEY #{literal(constraint[:columns])}" when :foreign_key sql << "FOREIGN KEY #{literal(constraint[:columns])}" sql << column_references_sql(constraint) when :unique sql << "UNIQUE #{literal(constraint[:columns])}" else check = constraint[:check] sql << "CHECK #{filter_expr((check.is_a?(Array) && check.length == 1) ? check.first : check)}" end sql end |
#create_table_sql_list(name, columns, indexes = nil) ⇒ Object
Array of SQL DDL statements, the first for creating a table with the given name and column specifications, and the others for specifying indexes on the table.
113 114 115 116 117 |
# File 'lib/sequel_core/schema/sql.rb', line 113 def create_table_sql_list(name, columns, indexes = nil) sql = ["CREATE TABLE #{quote_schema_table(name)} (#{column_list_sql(columns)})"] sql.concat(index_list_sql_list(name, indexes)) if indexes && !indexes.empty? sql end |
#default_index_name(table_name, columns) ⇒ Object
Default index name for the table and columns, may be too long for certain databases.
121 122 123 124 |
# File 'lib/sequel_core/schema/sql.rb', line 121 def default_index_name(table_name, columns) schema, table = schema_and_table(table_name) "#{"#{schema}_" if schema and schema != default_schema}#{table}_#{columns.join(UNDERSCORE)}_index" end |
#drop_index_sql(table, op) ⇒ Object
The SQL to drop an index for the table.
127 128 129 |
# File 'lib/sequel_core/schema/sql.rb', line 127 def drop_index_sql(table, op) "DROP INDEX #{quote_identifier(op[:name] || default_index_name(table, op[:columns]))}" end |
#drop_table_sql(name) ⇒ Object
SQL DDL statement to drop the table with the given name.
132 133 134 |
# File 'lib/sequel_core/schema/sql.rb', line 132 def drop_table_sql(name) "DROP TABLE #{quote_schema_table(name)}" end |
#filter_expr(*args, &block) ⇒ Object
Proxy the filter_expr call to the dataset, used for creating constraints.
137 138 139 |
# File 'lib/sequel_core/schema/sql.rb', line 137 def filter_expr(*args, &block) schema_utility_dataset.literal(schema_utility_dataset.send(:filter_expr, *args, &block)) end |
#index_definition_sql(table_name, index) ⇒ Object
SQL DDL statement for creating an index for the table with the given name and index specifications.
143 144 145 146 147 148 149 150 151 152 |
# File 'lib/sequel_core/schema/sql.rb', line 143 def index_definition_sql(table_name, index) index_name = index[:name] || default_index_name(table_name, index[:columns]) if index[:type] raise Error, "Index types are not supported for this database" elsif index[:where] raise Error, "Partial indexes are not supported for this database" else "CREATE #{'UNIQUE ' if index[:unique]}INDEX #{quote_identifier(index_name)} ON #{quote_identifier(table_name)} #{literal(index[:columns])}" end end |
#index_list_sql_list(table_name, indexes) ⇒ Object
Array of SQL DDL statements, one for each index specification, for the given table.
156 157 158 |
# File 'lib/sequel_core/schema/sql.rb', line 156 def index_list_sql_list(table_name, indexes) indexes.map{|i| index_definition_sql(table_name, i)} end |
#literal(v) ⇒ Object
Proxy the literal call to the dataset, used for default values.
161 162 163 |
# File 'lib/sequel_core/schema/sql.rb', line 161 def literal(v) schema_utility_dataset.literal(v) end |
#on_delete_clause(action) ⇒ Object
SQL DDL ON DELETE fragment to use, based on the given action. The following actions are recognized:
-
:cascade - Delete rows referencing this row.
-
:no_action (default) - Raise an error if other rows reference this row, allow deferring of the integrity check.
-
:restrict - Raise an error if other rows reference this row, but do not allow deferring the integrity check.
-
:set_default - Set columns referencing this row to their default value.
-
:set_null - Set columns referencing this row to NULL.
175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/sequel_core/schema/sql.rb', line 175 def on_delete_clause(action) case action when :restrict RESTRICT when :cascade CASCADE when :set_null SET_NULL when :set_default SET_DEFAULT else NO_ACTION end end |
#quote_identifier(v) ⇒ Object
Proxy the quote_identifier method to the dataset, used for quoting tables and columns.
196 197 198 |
# File 'lib/sequel_core/schema/sql.rb', line 196 def quote_identifier(v) schema_utility_dataset.quote_identifier(v) end |
#quote_schema_table(table) ⇒ Object
Proxy the quote_schema_table method to the dataset
191 192 193 |
# File 'lib/sequel_core/schema/sql.rb', line 191 def quote_schema_table(table) schema_utility_dataset.quote_schema_table(table) end |
#rename_table_sql(name, new_name) ⇒ Object
SQL DDL statement for renaming a table.
201 202 203 |
# File 'lib/sequel_core/schema/sql.rb', line 201 def rename_table_sql(name, new_name) "ALTER TABLE #{quote_schema_table(name)} RENAME TO #{quote_schema_table(new_name)}" end |
#schema(table = nil, opts = {}) ⇒ Object
Parse the schema from the database. If the table_name is not given, returns the schema for all tables as a hash. If the table_name is given, returns the schema for a single table as an array with all members being arrays of length 2. Available options are:
-
:reload - Get fresh information from the database, instead of using cached information. If table_name is blank, :reload should be used unless you are sure that schema has not been called before with a table_name, otherwise you may only getting the schemas for tables that have been requested explicitly.
-
:schema - An explicit schema to use. It may also be implicitly provided via the table name.
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/sequel_core/schema/sql.rb', line 217 def schema(table = nil, opts={}) if table sch, table_name = schema_and_table(table) quoted_name = quote_schema_table(table) end opts = opts.merge(:schema=>sch) if sch && !opts.include?(:schema) if opts[:reload] && @schemas if table_name @schemas.delete(quoted_name) else @schemas = nil end end if @schemas if table_name return @schemas[quoted_name] if @schemas[quoted_name] else return @schemas end end @schemas ||= Hash.new do |h,k| quote_name = quote_schema_table(k) h[quote_name] if h.include?(quote_name) end if table_name if respond_to?(:schema_parse_table, true) cols = schema_parse_table(table_name, opts) raise(Error, 'schema parsing returned no columns, table probably doesn\'t exist') if cols.blank? @schemas[quoted_name] = cols else raise Error, 'schema parsing is not implemented on this database' end else if respond_to?(:schema_parse_tables, true) @schemas.merge!(schema_parse_tables(opts)) elsif respond_to?(:schema_parse_table, true) and respond_to?(:tables, true) tables.each{|t| @schemas[quote_identifier(t)] = schema_parse_table(t.to_s, opts)} @schemas else @schemas = nil raise Error, 'schema parsing is not implemented on this database' end end end |
#schema_utility_dataset ⇒ Object
The dataset to use for proxying certain schema methods.
266 267 268 |
# File 'lib/sequel_core/schema/sql.rb', line 266 def schema_utility_dataset @schema_utility_dataset ||= dataset end |