# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 298 def primary_key(table) row = exec_query(<<-end_sql, 'SCHEMA').rows.first SELECT DISTINCT attr.attname FROM pg_attribute attr INNER JOIN pg_depend dep ON attr.attrelid = dep.refobjid AND attr.attnum = dep.refobjsubid INNER JOIN pg_constraint cons ON attr.attrelid = cons.conrelid AND attr.attnum = cons.conkey[1] WHERE cons.contype = 'p' AND dep.refobjid = '#{quote_table_name(table)}'::regclass end_sql row && row.first end
module ActiveRecord::ConnectionAdapters::RedshiftAdapter::SchemaStatements
Public Instance Methods
Adds a new column to the named table. See TableDefinition#column
for details of the options you can use.
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 331 def add_column(table_name, column_name, type, options = {}) clear_cache! super end
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 368 def add_index(*args) # ignore end
Changes the column of a table.
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 337 def change_column(table_name, column_name, type, options = {}) clear_cache! quoted_table_name = quote_table_name(table_name) execute "ALTER TABLE #{quoted_table_name} ALTER COLUMN #{quote_column_name(column_name)} TYPE #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}" change_column_default(table_name, column_name, options[:default]) if options_include_default?(options) change_column_null(table_name, column_name, options[:null], options[:default]) if options.key?(:null) end
Changes the default value of a table column.
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 348 def change_column_default(table_name, column_name, default) clear_cache! execute "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} SET DEFAULT #{quote(default)}" end
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 353 def change_column_null(table_name, column_name, null, default = nil) clear_cache! unless null || default.nil? execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL") end execute("ALTER TABLE #{quote_table_name(table_name)} ALTER #{quote_column_name(column_name)} #{null ? 'DROP' : 'SET'} NOT NULL") end
Returns the current database collation.
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 164 def collation query(<<-end_sql, 'SCHEMA')[0][0] SELECT pg_database.datcollate FROM pg_database WHERE pg_database.datname LIKE '#{current_database}' end_sql end
Returns the list of all column definitions for a table.
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 135 def columns(table_name) # Limit, precision, and scale are all handled by the superclass. column_definitions(table_name).map do |column_name, type, default, notnull, oid, fmod| oid = OID::TYPE_MAP.fetch(oid.to_i, fmod.to_i) { OID::Identity.new } RedshiftColumn.new(column_name, default, oid, type, notnull == 'f') end end
Create a new PostgreSQL database. Options include :owner
, :template
, :encoding
, :collation
, :ctype
, :tablespace
, and :connection_limit
(note that MySQL uses :charset
while PostgreSQL uses :encoding
).
Example:
create_database config[:database], config create_database 'foo_development', encoding: 'unicode'
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 56 def create_database(name, options = {}) options = { encoding: 'utf8' }.merge!(options.symbolize_keys) option_string = options.sum do |key, value| case key when :owner " OWNER = \"#{value}\"" when :template " TEMPLATE = \"#{value}\"" when :encoding " ENCODING = '#{value}'" when :collation " LC_COLLATE = '#{value}'" when :ctype " LC_CTYPE = '#{value}'" when :tablespace " TABLESPACE = \"#{value}\"" when :connection_limit " CONNECTION LIMIT = #{value}" else "" end end execute "CREATE DATABASE #{quote_table_name(name)}#{option_string}" end
Creates a schema for the given schema name.
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 189 def create_schema schema_name execute "CREATE SCHEMA #{schema_name}" end
Returns the current database ctype.
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 171 def ctype query(<<-end_sql, 'SCHEMA')[0][0] SELECT pg_database.datctype FROM pg_database WHERE pg_database.datname LIKE '#{current_database}' end_sql end
Returns the current database name.
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 146 def current_database query('select current_database()', 'SCHEMA')[0][0] end
Returns the current schema name.
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 151 def current_schema query('SELECT current_schema', 'SCHEMA')[0][0] end
Drops the schema for the given schema name.
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 194 def drop_schema schema_name execute "DROP SCHEMA #{schema_name} CASCADE" end
Returns the current database encoding format.
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 156 def encoding query(<<-end_sql, 'SCHEMA')[0][0] SELECT pg_encoding_to_char(pg_database.encoding) FROM pg_database WHERE pg_database.datname LIKE '#{current_database}' end_sql end
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 380 def index_name_length 63 end
Returns an array of indexes for the given table.
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 130 def indexes(table_name, name = nil) [] end
Returns just a table’s primary key
Renames a column in a table.
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 362 def rename_column(table_name, column_name, new_column_name) clear_cache! execute "ALTER TABLE #{quote_table_name(table_name)} RENAME COLUMN #{quote_column_name(column_name)} TO #{quote_column_name(new_column_name)}" rename_column_indexes(table_name, column_name, new_column_name) end
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 376 def rename_index(table_name, old_name, new_name) # ignore end
Renames a table. Also renames a table’s primary key sequence if the sequence name matches the Active Record default.
Example:
rename_table('octopuses', 'octopi')
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 317 def rename_table(table_name, new_name) clear_cache! execute "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}" pk, seq = pk_and_sequence_for(new_name) if seq == "#{table_name}_#{pk}_seq" new_seq = "#{new_name}_#{pk}_seq" execute "ALTER TABLE #{quote_table_name(seq)} RENAME TO #{quote_table_name(new_seq)}" end rename_table_indexes(table_name, new_name) end
Returns true if schema exists.
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 121 def schema_exists?(name) exec_query(<<-SQL, 'SCHEMA').rows.first[0].to_i > 0 SELECT COUNT(*) FROM pg_namespace WHERE nspname = '#{name}' SQL end
Returns an array of schema names.
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 178 def schema_names query(<<-SQL, 'SCHEMA').flatten SELECT nspname FROM pg_namespace WHERE nspname !~ '^pg_.*' AND nspname NOT IN ('information_schema') ORDER by nspname; SQL end
Returns the active schema search path.
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 211 def schema_search_path @schema_search_path ||= query('SHOW search_path', 'SCHEMA')[0][0] end
Sets the schema search path to a string of comma-separated schema names. Names beginning with $ have to be quoted (e.g. $user => ‘$user’). See: www.postgresql.org/docs/current/static/ddl-schemas.html
This should be not be called manually but set in database.yml.
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 203 def schema_search_path=(schema_csv) if schema_csv execute("SET search_path TO #{schema_csv}", 'SCHEMA') @schema_search_path = schema_csv end end
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 224 def serial_sequence(table, column) result = exec_query(<<-eosql, 'SCHEMA') SELECT pg_get_serial_sequence('#{table}', '#{column}') eosql result.rows.first.first end
Returns true if table exists. If the schema is not specified as part of name
then it will only find tables within the current schema search path (regardless of permissions to access tables in other schemas)
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 103 def table_exists?(name) schema, table = Utils.extract_schema_and_table(name.to_s) return false unless table binds = [[nil, table]] binds << [nil, schema] if schema exec_query(<<-SQL, 'SCHEMA').rows.first[0].to_i > 0 SELECT COUNT(*) FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind in ('v','r') AND c.relname = '#{table.gsub(/(^"|"$)/,'')}' AND n.nspname = #{schema ? "'#{schema}'" : 'ANY (current_schemas(false))'} SQL end
Returns the list of all tables in the schema search path or a specified schema.
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 92 def tables(name = nil) query(<<-SQL, 'SCHEMA').map { |row| "#{row[0]}.#{row[1]}" } SELECT tablename FROM pg_tables WHERE schemaname = ANY (current_schemas(false)) SQL end
Maps logical Rails types to PostgreSQL-specific data types.
# File lib/active_record/connection_adapters/redshift/schema_statements.rb, line 385 def type_to_sql(type, limit = nil, precision = nil, scale = nil) case type.to_s when 'binary' # PostgreSQL doesn't support limits on binary (bytea) columns. # The hard limit is 1Gb, because of a 32-bit size field, and TOAST. case limit when nil, 0..0x3fffffff; super(type) else raise(ActiveRecordError, "No binary type has byte size #{limit}.") end when 'integer' return 'integer' unless limit case limit when 1, 2; 'smallint' when 3, 4; 'integer' when 5..8; 'bigint' else raise(ActiveRecordError, "No integer type has byte size #{limit}. Use a numeric with precision 0 instead.") end when 'datetime' return super unless precision case precision when 0..6; "timestamp(#{precision})" else raise(ActiveRecordError, "No timestamp type has precision of #{precision}. The allowed range of precision is from 0 to 6") end else super end end