module ActiveRecord::ConnectionAdapters::Materialize::SchemaStatements
Public Instance Methods
Unsupported collation
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 114 def collation nil end
Create a new Materialize database. Options include :owner
, :template
, :encoding
(defaults to utf8), :collation
, :ctype
, :tablespace
, and :connection_limit
(note that MySQL uses :charset
while Materialize uses :encoding
).
Example:
create_database config[:database], config create_database 'foo_development', encoding: 'unicode'
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 22 def create_database(name, options = {}) options = {}.merge(options.symbolize_keys) if_exists = "IF NOT EXISTS " unless [false, 'false', '0', 0].include? options[:if_exists] execute "CREATE DATABASE #{if_exists}#{quote_table_name(name)}" end
Creates a schema for the given schema name.
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 136 def create_schema(schema_name) execute "CREATE SCHEMA #{quote_schema_name(schema_name.to_s)}" end
Get ctype
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 119 def ctype query_value("SELECT datctype FROM pg_database WHERE datname = #{quote(current_database)}", "SCHEMA") end
Unsupported current_database
() use default config
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 99 def current_database @config[:database] end
Returns the current schema name.
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 104 def current_schema query_value("SELECT current_schema", "SCHEMA") end
Drops the schema for the given schema name.
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 141 def drop_schema(schema_name, options = {}) execute "DROP SCHEMA#{' IF EXISTS' if options[:if_exists]} #{quote_schema_name(schema_name.to_s)} CASCADE" end
Get encoding of database
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 109 def encoding query_value("SELECT pg_encoding_to_char(encoding) FROM pg_database WHERE datname = #{quote(current_database)}", "SCHEMA") end
Verifies existence of an index with a given name.
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 47 def index_name_exists?(table_name, index_name) available_indexes = execute(<<~SQL, "SCHEMA") SHOW INDEXES FROM #{quote_table_name(table_name)} SQL available_indexes.map { |c| c['key_name'] }.include? index_name.to_s end
Renames an index of a table. Raises error if length of new index name is greater than allowed limit.
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 245 def rename_index(table_name, old_name, new_name) validate_index_length!(table_name, new_name) execute "ALTER INDEX #{quote_column_name(old_name)} RENAME TO #{quote_table_name(new_name)}" end
Renames a table with index references
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 169 def rename_table(table_name, new_name) clear_cache! execute "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}" if index_name_exists?(new_name, "#{table_name}_primary_idx") rename_index(new_name, "#{table_name}_primary_idx", "#{new_name}_primary_idx") end rename_table_indexes(table_name, new_name) end
Returns true if schema exists.
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 42 def schema_exists?(name) schema_names.include? name.to_s end
Returns an array of schema names.
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 124 def schema_names query_values(<<~SQL, "SCHEMA") SELECT s.name FROM mz_schemas s LEFT JOIN mz_databases d ON s.database_id = d.id WHERE d.name = #{quote(current_database)} SQL end
Returns the active schema search path.
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 146 def schema_search_path @schema_search_path ||= query_value("SHOW search_path", "SCHEMA") end
Validates the given constraint.
Validates the constraint named constraint_name
on accounts
.
validate_constraint :accounts, :constraint_name
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 290 def validate_constraint(table_name, constraint_name) return unless supports_validate_constraints? at = create_alter_table table_name at.validate_constraint constraint_name execute schema_creation.accept(at) end
Validates the given foreign key.
Validates the foreign key on accounts.branch_id
.
validate_foreign_key :accounts, :branches
Validates the foreign key on accounts.owner_id
.
validate_foreign_key :accounts, column: :owner_id
Validates the foreign key named special_fk_name
on the accounts
table.
validate_foreign_key :accounts, name: :special_fk_name
The options
hash accepts the same keys as SchemaStatements#add_foreign_key.
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 314 def validate_foreign_key(from_table, to_table = nil, **options) return unless supports_validate_constraints? fk_name_to_validate = foreign_key_for!(from_table, to_table: to_table, **options).name validate_constraint from_table, fk_name_to_validate end
Private Instance Methods
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 386 def add_column_for_alter(table_name, column_name, type, **options) return super unless options.key?(:comment) [super, Proc.new { change_column_comment(table_name, column_name, options[:comment]) }] end
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 418 def add_index_opclass(quoted_columns, **options) opclasses = options_for_index_columns(options[:opclass]) quoted_columns.each do |name, column| column << " #{opclasses[name]}" if opclasses[name].present? end end
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 425 def add_options_for_index_columns(quoted_columns, **options) quoted_columns = add_index_opclass(quoted_columns, **options) super end
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 399 def change_column_default_for_alter(table_name, column_name, default_or_changes) column = column_for(table_name, column_name) return unless column default = extract_new_default_value(default_or_changes) alter_column_query = "ALTER COLUMN #{quote_column_name(column_name)} %s" if default.nil? # <tt>DEFAULT NULL</tt> results in the same behavior as <tt>DROP DEFAULT</tt>. However, Materialize will # cast the default to the columns type, which leaves us with a default like "default NULL::character varying". alter_column_query % "DROP DEFAULT" else alter_column_query % "SET DEFAULT #{quote_default_expression(default, column)}" end end
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 391 def change_column_for_alter(table_name, column_name, type, options = {}) td = create_table_definition(table_name) cd = td.new_column_definition(column_name, type, **options) sqls = [schema_creation.accept(ChangeColumnDefinition.new(cd, column_name))] sqls << Proc.new { change_column_comment(table_name, column_name, options[:comment]) } if options.key?(:comment) sqls end
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 414 def change_column_null_for_alter(table_name, column_name, null, default = nil) "ALTER COLUMN #{quote_column_name(column_name)} #{null ? 'DROP' : 'SET'} NOT NULL" end
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 331 def create_alter_table(name) Materialize::AlterTable.new create_table_definition(name) end
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 327 def create_table_definition(*args, **options) Materialize::TableDefinition.new(self, *args, **options) end
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 430 def data_source_sql(name = nil, type: nil) scope = quoted_scope(name, type: type) scope[:type] ||= "'table','view'" sql = <<~SQL SELECT o.name FROM mz_objects o LEFT JOIN mz_schemas s ON o.schema_id = s.id LEFT JOIN mz_databases d ON s.database_id = d.id LEFT JOIN mz_sources src ON src.id = o.id LEFT JOIN mz_indexes i ON i.on_id = o.id WHERE d.name = #{quote(current_database)} AND s.name = #{scope[:schema]} AND o.type IN (#{scope[:type]}) SQL # Sources sql += " AND src.id is NULL" unless scope[:type].include? 'source' # Find with name sql += " AND o.name = #{scope[:name]}" if scope[:name] sql += " GROUP BY o.id, o.name" if type == "MATERIALIZED" sql += " HAVING COUNT(i.id) > 0" elsif scope[:type].include?('view') sql += " HAVING COUNT(i.id) = 0" end sql end
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 378 def extract_foreign_key_action(specifier) case specifier when "c"; :cascade when "n"; :nullify when "r"; :restrict end end
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 483 def extract_schema_qualified_name(string) name = Utils.extract_schema_qualified_name(string.to_s) [name.schema, name.identifier] end
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 350 def fetch_type_metadata(column_name, sql_type) cast_type = lookup_cast_type(sql_type) simple_type = SqlTypeMetadata.new( sql_type: sql_type, type: cast_type.type, limit: cast_type.limit, precision: cast_type.precision, scale: cast_type.scale, ) Materialize::TypeMetadata.new(simple_type) end
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 335 def new_column_from_field(table_name, field) column_name, type, nullable, default, comment = field type_metadata = fetch_type_metadata(column_name, type) default_value = extract_value_from_default(default) default_function = extract_default_function(default_value, default) Materialize::Column.new( column_name, default_value, type_metadata, nullable, default_function, comment: comment.presence ) end
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 463 def quoted_scope(name = nil, type: nil) schema, name = extract_schema_qualified_name(name) type = \ case type when "BASE TABLE" "'table'" when "MATERIALIZED" "'view'" when "SOURCE" "'source'" when "VIEW" "'view'" end scope = {} scope[:schema] = schema ? quote(schema) : "ANY (current_schemas(false))" scope[:name] = quote(name) if name scope[:type] = type if type scope end
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 323 def schema_creation Materialize::SchemaCreation.new(self) end
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 362 def sequence_name_from_parts(table_name, column_name, suffix) over_length = [table_name, column_name, suffix].sum(&:length) + 2 - max_identifier_length if over_length > 0 column_name_length = [(max_identifier_length - suffix.length - 2) / 2, column_name.length].min over_length -= column_name.length - column_name_length column_name = column_name[0, column_name_length - [over_length, 0].min] end if over_length > 0 table_name = table_name[0, table_name.length - over_length] end "#{table_name}_#{column_name}_#{suffix}" end