diff options
Diffstat (limited to 'activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb')
-rw-r--r-- | activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb | 53 |
1 files changed, 30 insertions, 23 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb index 1dc7a6f0fd..b2aeb3a058 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb @@ -1,18 +1,18 @@ module ActiveRecord module ConnectionAdapters - class PostgreSQLAdapter < AbstractAdapter + module PostgreSQL class SchemaCreation < AbstractAdapter::SchemaCreation private def visit_AddColumn(o) - sql_type = type_to_sql(o.type.to_sym, o.limit, o.precision, o.scale) + sql_type = type_to_sql(o.type, o.limit, o.precision, o.scale) sql = "ADD COLUMN #{quote_column_name(o.name)} #{sql_type}" add_column_options!(sql, column_options(o)) end def visit_ColumnDefinition(o) sql = super - if o.primary_key? && o.type == :uuid + if o.primary_key? && o.type != :primary_key sql << " PRIMARY KEY " add_column_options!(sql, column_options(o)) end @@ -33,10 +33,6 @@ module ActiveRecord end end - def schema_creation - SchemaCreation.new self - end - module SchemaStatements # Drops the database specified on the +name+ attribute # and creates it again using the provided +options+. @@ -101,16 +97,16 @@ module ActiveRecord # 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) def table_exists?(name) - schema, table = Utils.extract_schema_and_table(name.to_s) - return false unless table + name = Utils.extract_schema_qualified_name(name.to_s) + return false unless name.identifier 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 ('r','v','m') -- (r)elation/table, (v)iew, (m)aterialized view - AND c.relname = '#{table.gsub(/(^"|"$)/,'')}' - AND n.nspname = #{schema ? "'#{schema}'" : 'ANY (current_schemas(false))'} + AND c.relname = '#{name.identifier}' + AND n.nspname = #{name.schema ? "'#{name.schema}'" : 'ANY (current_schemas(false))'} SQL end @@ -182,13 +178,15 @@ module ActiveRecord 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 = get_oid_type(oid.to_i, fmod.to_i, column_name) - PostgreSQLColumn.new(column_name, default, oid, type, notnull == 'f') + oid = get_oid_type(oid.to_i, fmod.to_i, column_name, type) + default_value = extract_value_from_default(oid, default) + default_function = extract_default_function(default_value, default) + new_column(column_name, default_value, oid, type, notnull == 'f', default_function) end end - def column_for(table_name, column_name) #:nodoc: - columns(table_name).detect { |c| c.name == column_name.to_s } + def new_column(name, default, cast_type, sql_type = nil, null = true, default_function = nil) # :nodoc: + PostgreSQLColumn.new(name, default, cast_type, sql_type, null, default_function) end # Returns the current database name. @@ -275,9 +273,9 @@ module ActiveRecord def default_sequence_name(table_name, pk = nil) #:nodoc: result = serial_sequence(table_name, pk || 'id') return nil unless result - result.split('.').last + Utils.extract_schema_qualified_name(result) rescue ActiveRecord::StatementInvalid - "#{table_name}_#{pk || 'id'}_seq" + PostgreSQL::Name.new(nil, "#{table_name}_#{pk || 'id'}_seq") end def serial_sequence(table, column) @@ -314,17 +312,19 @@ module ActiveRecord # First try looking for a sequence with a dependency on the # given table's primary key. result = query(<<-end_sql, 'SCHEMA')[0] - SELECT attr.attname, seq.relname + SELECT attr.attname, nsp.nspname, seq.relname FROM pg_class seq, pg_attribute attr, pg_depend dep, - pg_constraint cons + pg_constraint cons, + pg_namespace nsp WHERE seq.oid = dep.objid AND seq.relkind = 'S' AND attr.attrelid = dep.refobjid AND attr.attnum = dep.refobjsubid AND attr.attrelid = cons.conrelid AND attr.attnum = cons.conkey[1] + AND seq.relnamespace = nsp.oid AND cons.contype = 'p' AND dep.classid = 'pg_class'::regclass AND dep.refobjid = '#{quote_table_name(table)}'::regclass @@ -332,7 +332,7 @@ module ActiveRecord if result.nil? or result.empty? result = query(<<-end_sql, 'SCHEMA')[0] - SELECT attr.attname, + SELECT attr.attname, nsp.nspname, CASE WHEN pg_get_expr(def.adbin, def.adrelid) !~* 'nextval' THEN NULL WHEN split_part(pg_get_expr(def.adbin, def.adrelid), '''', 2) ~ '.' THEN @@ -344,13 +344,19 @@ module ActiveRecord JOIN pg_attribute attr ON (t.oid = attrelid) JOIN pg_attrdef def ON (adrelid = attrelid AND adnum = attnum) JOIN pg_constraint cons ON (conrelid = adrelid AND adnum = conkey[1]) + JOIN pg_namespace nsp ON (t.relnamespace = nsp.oid) WHERE t.oid = '#{quote_table_name(table)}'::regclass AND cons.contype = 'p' AND pg_get_expr(def.adbin, def.adrelid) ~* 'nextval|uuid_generate' end_sql end - [result.first, result.last] + pk = result.shift + if result.last + [pk, PostgreSQL::Name.new(*result)] + else + [pk, nil] + end rescue nil end @@ -378,7 +384,7 @@ module ActiveRecord 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" + if seq.identifier == "#{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 @@ -409,6 +415,7 @@ module ActiveRecord def change_column_default(table_name, column_name, default) clear_cache! column = column_for(table_name, column_name) + execute "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} SET DEFAULT #{quote_default_value(default, column)}" if column end @@ -490,7 +497,7 @@ module ActiveRecord # Convert Arel node to string s = s.to_sql unless s.is_a?(String) # Remove any ASC/DESC modifiers - s.gsub(/\s+(ASC|DESC)\s*(NULLS\s+(FIRST|LAST)\s*)?/i, '') + s.gsub(/\s+(?:ASC|DESC)?\s*(?:NULLS\s+(?:FIRST|LAST)\s*)?/i, '') }.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" } [super, *order_columns].join(', ') |