@logger.warn"#{table} has primary key #{pk} with no default sequence"
end
ifpk&&sequence
quoted_sequence=quote_table_name(sequence)
select_value<<-end_sql,'Reset sequence'
SELECT setval('#{quoted_sequence}', (SELECT COALESCE(MAX(#{quote_column_namepk})+(SELECT increment_by FROM #{quoted_sequence}), (SELECT min_value FROM #{quoted_sequence})) FROM #{quote_table_name(table)}), false)
end_sql
end
end
# Returns a table's primary key and belonging sequence.
defpk_and_sequence_for(table)#:nodoc:
# First try looking for a sequence with a dependency on the
# given table's primary key.
result=query(<<-end_sql,'PK and serial sequence')[0]
SELECT attr.attname, seq.relname
FROM pg_class seq,
pg_attribute attr,
pg_depend dep,
pg_namespace name,
pg_constraint cons
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 cons.contype = 'p'
AND dep.refobjid = '#{quote_table_name(table)}'::regclass
end_sql
ifresult.nil?orresult.empty?
# If that fails, try parsing the primary key's default value.
# Support the 7.x and 8.0 nextval('foo'::text) as well as
# the 8.1+ nextval('foo'::regclass).
result=query(<<-end_sql,'PK and custom sequence')[0]
SELECT attr.attname,
CASE
WHEN split_part(def.adsrc, '''', 2) ~ '.' THEN
substr(split_part(def.adsrc, '''', 2),
strpos(split_part(def.adsrc, '''', 2), '.')+1)
ELSE split_part(def.adsrc, '''', 2)
END
FROM pg_class t
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])
WHERE t.oid = '#{quote_table_name(table)}'::regclass
AND cons.contype = 'p'
AND def.adsrc ~* 'nextval'
end_sql
end
[result.first,result.last]
rescue
nil
end
# Returns just a table's primary key
defprimary_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 = '#{table}'::regclass
end_sql
row&&row.first
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')
defrename_table(name,new_name)
clear_cache!
execute"ALTER TABLE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}"
pk,seq=pk_and_sequence_for(new_name)
ifseq=="#{name}_#{pk}_seq"
new_seq="#{new_name}_#{pk}_seq"
execute"ALTER TABLE #{quote_table_name(seq)} RENAME TO #{quote_table_name(new_seq)}"
end
end
# Adds a new column to the named table.
# See TableDefinition#column for details of the options you can use.
execute"ALTER TABLE #{quoted_table_name} ALTER COLUMN #{quote_column_name(column_name)} TYPE #{type_to_sql(type,options[:limit],options[:precision],options[:scale])}"
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")