module ActiveRecord::ConnectionAdapters::Materialize::SchemaStatements

Public Instance Methods

collation() click to toggle source

Unsupported collation

# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 114
def collation
  nil
end
create_database(name, options = {}) click to toggle source

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
create_schema(schema_name) click to toggle source

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
ctype() click to toggle source

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
current_database() click to toggle source

Unsupported current_database() use default config

# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 99
def current_database
  @config[:database]
end
current_schema() click to toggle source

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
drop_schema(schema_name, options = {}) click to toggle source

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
encoding() click to toggle source

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
index_name_exists?(table_name, index_name) click to toggle source

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
rename_index(table_name, old_name, new_name) click to toggle source

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
rename_table(table_name, new_name) click to toggle source

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
schema_exists?(name) click to toggle source

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
schema_names() click to toggle source

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
schema_search_path() click to toggle source

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
validate_constraint(table_name, constraint_name) click to toggle source

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
validate_foreign_key(from_table, to_table = nil, **options) click to toggle source

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

add_column_for_alter(table_name, column_name, type, **options) click to toggle source
Calls superclass method
# 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
add_index_opclass(quoted_columns, **options) click to toggle source
# 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
add_options_for_index_columns(quoted_columns, **options) click to toggle source
Calls superclass method
# 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
change_column_default_for_alter(table_name, column_name, default_or_changes) click to toggle source
# 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
change_column_for_alter(table_name, column_name, type, options = {}) click to toggle source
# 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
change_column_null_for_alter(table_name, column_name, null, default = nil) click to toggle source
# 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
create_alter_table(name) click to toggle source
# 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
create_table_definition(*args, **options) click to toggle source
# 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
data_source_sql(name = nil, type: nil) click to toggle source
# 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
extract_foreign_key_action(specifier) click to toggle source
# 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
extract_schema_qualified_name(string) click to toggle source
# 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
fetch_type_metadata(column_name, sql_type) click to toggle source
# 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
new_column_from_field(table_name, field) click to toggle source
# 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
quoted_scope(name = nil, type: nil) click to toggle source
# 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
schema_creation() click to toggle source
# File lib/active_record/connection_adapters/materialize/schema_statements.rb, line 323
def schema_creation
  Materialize::SchemaCreation.new(self)
end
sequence_name_from_parts(table_name, column_name, suffix) click to toggle source
# 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