summaryrefslogtreecommitdiff
path: root/odoo/tools/sql.py
diff options
context:
space:
mode:
authorRaphael Collet <rco@openerp.com>2017-02-07 10:21:15 +0100
committerRaphael Collet <rco@openerp.com>2017-02-22 15:24:08 +0100
commitf8e573db2350b025afec8407eeb5849c7a31afa4 (patch)
tree3f984c432b43add8b636ebb69f1125be41cdfd4e /odoo/tools/sql.py
parentdc82ff59accf0733229f39b57fc030782600530e (diff)
[REF] models: refactoring of foreign keys
Diffstat (limited to 'odoo/tools/sql.py')
-rw-r--r--odoo/tools/sql.py39
1 files changed, 39 insertions, 0 deletions
diff --git a/odoo/tools/sql.py b/odoo/tools/sql.py
index 6bdcbb05303..0b3851df651 100644
--- a/odoo/tools/sql.py
+++ b/odoo/tools/sql.py
@@ -6,6 +6,14 @@ import psycopg2
_schema = logging.getLogger('odoo.schema')
+_CONFDELTYPES = {
+ 'RESTRICT': 'r',
+ 'NO ACTION': 'a',
+ 'CASCADE': 'c',
+ 'SET NULL': 'n',
+ 'SET DEFAULT': 'd',
+}
+
def table_exists(cr, tablename):
""" Return whether the given table exists. """
query = "SELECT 1 FROM pg_class WHERE relkind IN ('r','v') AND relname=%s"
@@ -121,6 +129,37 @@ def drop_constraint(cr, tablename, constraintname):
except Exception:
_schema.warning("Table %r: unable to drop constraint %r!", tablename, constraintname)
+def add_foreign_key(cr, tablename1, columnname1, tablename2, columnname2, ondelete):
+ """ Create the given foreign key, and return ``True``. """
+ query = 'ALTER TABLE "{}" ADD FOREIGN KEY ("{}") REFERENCES "{}"("{}") ON DELETE {}'
+ cr.execute(query.format(tablename1, columnname1, tablename2, columnname2, ondelete))
+ _schema.debug("Table %r: added foreign key %r references %r(%r) ON DELETE %s",
+ tablename1, columnname1, tablename2, columnname2, ondelete)
+ return True
+
+def fix_foreign_key(cr, tablename1, columnname1, tablename2, columnname2, ondelete):
+ """ Update the foreign keys between tables to match the given one, and
+ return ``True`` if the given foreign key has been recreated.
+ """
+ deltype = _CONFDELTYPES.get(ondelete.upper(), 'a')
+ query = """ SELECT con.conname, c2.relname, a2.attnum, con.confdeltype as deltype
+ FROM pg_constraint as con, pg_class as c1, pg_class as c2,
+ pg_attribute as a1, pg_attribute as a2
+ WHERE con.contype='f' AND con.conrelid=c1.oid AND con.confrelid=c2.oid
+ AND array_lower(con.conkey, 1)=1 AND con.conkey[1]=a1.attnum
+ AND array_lower(con.confkey, 1)=1 AND con.confkey[1]=a2.attnum
+ AND a1.attrelid=c1.oid AND a2.attrelid=c2.oid
+ AND c1.relname=%s AND a1.attname=%s """
+ cr.execute(query, (tablename1, columnname1))
+ found = False
+ for fk in cr.fetchall():
+ if not found and fk[1:] == (tablename2, columnname2, deltype):
+ found = True
+ else:
+ drop_constraint(cr, tablename1, fk[0])
+ if not found:
+ return add_foreign_key(cr, tablename1, columnname1, tablename2, columnname2, ondelete)
+
def index_exists(cr, indexname):
""" Return whether the given index exists. """
cr.execute("SELECT 1 FROM pg_indexes WHERE indexname=%s", (indexname,))