[IMP] tools: use information_schema instead of pg-specific tables
This commit is contained in:
+6
-6
@@ -831,16 +831,16 @@ class Field(object):
|
||||
# the column does not exist, create it
|
||||
sql.create_column(model._cr, model._table, self.name, self.column_type[1], self.string)
|
||||
return
|
||||
if column['typname'] == self.column_type[0]:
|
||||
if column['udt_name'] == self.column_type[0]:
|
||||
return
|
||||
if column['typname'] in self.column_cast_from:
|
||||
if column['udt_name'] in self.column_cast_from:
|
||||
sql.convert_column(model._cr, model._table, self.name, self.column_type[1])
|
||||
else:
|
||||
newname = (self.name + '_moved{}').format
|
||||
i = 0
|
||||
while sql.column_exists(model._cr, model._table, newname(i)):
|
||||
i += 1
|
||||
if column['attnotnull']:
|
||||
if column['is_nullable'] == 'NO':
|
||||
sql.drop_not_null(model._cr, model._table, self.name)
|
||||
sql.rename_column(model._cr, model._table, self.name, newname(i))
|
||||
sql.create_column(model._cr, model._table, self.name, self.column_type[1], self.string)
|
||||
@@ -851,7 +851,7 @@ class Field(object):
|
||||
:param model: an instance of the field's model
|
||||
:param column: the column's configuration (dict) if it exists, or ``None``
|
||||
"""
|
||||
has_notnull = column and column['attnotnull']
|
||||
has_notnull = column and column['is_nullable'] == 'NO'
|
||||
|
||||
if not column or (self.required and not has_notnull):
|
||||
# the column is new or it becomes required; initialize its values
|
||||
@@ -1377,8 +1377,8 @@ class Char(_String):
|
||||
|
||||
def update_db_column(self, model, column):
|
||||
if (
|
||||
column and column['typname'] == 'varchar' and column['size'] and
|
||||
(self.size is None or column['size'] < self.size)
|
||||
column and column['udt_name'] == 'varchar' and column['character_maximum_length'] and
|
||||
(self.size is None or column['character_maximum_length'] < self.size)
|
||||
):
|
||||
# the column's varchar size does not match self.size; convert it
|
||||
sql.convert_column(model._cr, model._table, self.name, self.column_type[1])
|
||||
|
||||
+20
-21
@@ -6,6 +6,13 @@ import psycopg2
|
||||
|
||||
_schema = logging.getLogger('odoo.schema')
|
||||
|
||||
_TABLE_KIND = {
|
||||
'BASE TABLE': 'r',
|
||||
'VIEW': 'v',
|
||||
'FOREIGN TABLE': 'f',
|
||||
'LOCAL TEMPORARY': 't',
|
||||
}
|
||||
|
||||
_CONFDELTYPES = {
|
||||
'RESTRICT': 'r',
|
||||
'NO ACTION': 'a',
|
||||
@@ -16,14 +23,17 @@ _CONFDELTYPES = {
|
||||
|
||||
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"
|
||||
query = "SELECT 1 FROM information_schema.tables WHERE table_name=%s"
|
||||
cr.execute(query, (tablename,))
|
||||
return cr.rowcount
|
||||
|
||||
def table_kind(cr, tablename):
|
||||
""" Return the kind of a table: 'r' for ordinary tables, 'v' for views. """
|
||||
cr.execute("SELECT relkind FROM pg_class WHERE relname=%s", (tablename,))
|
||||
return cr.fetchone()[0] if cr.rowcount else None
|
||||
""" Return the kind of a table: ``'r'`` (regular table), ``'v'`` (view),
|
||||
``'f'`` (foreign table), ``'t'`` (temporary table), or ``None``.
|
||||
"""
|
||||
query = "SELECT table_type FROM information_schema.tables WHERE table_name=%s"
|
||||
cr.execute(query, (tablename,))
|
||||
return _TABLE_KIND[cr.fetchone()[0]] if cr.rowcount else None
|
||||
|
||||
def create_model_table(cr, tablename, comment=None):
|
||||
""" Create the table for a model. """
|
||||
@@ -34,28 +44,16 @@ def create_model_table(cr, tablename, comment=None):
|
||||
|
||||
def table_columns(cr, tablename):
|
||||
""" Return a dict mapping column names to their configuration. The latter is
|
||||
a dict with the following keys: `relname` (table name), `attname`
|
||||
(column name), `attlen`, `atttypmod`, `attnotnull` (whether it has a NOT
|
||||
NULL constraint), `atthasdef` (whether it has a default value),
|
||||
`typname` (data type name), `size` (varchar size).
|
||||
a dict with the data from the table ``information_schema.columns``.
|
||||
"""
|
||||
# attlen is the number of bytes necessary to represent the type when the
|
||||
# type has a fixed size. If the type has a varying size attlen is -1 and
|
||||
# atttypmod is the size limit + 4, or -1 if there is no limit.
|
||||
query = """ SELECT c.relname, a.attname, a.attlen, a.atttypmod,
|
||||
a.attnotnull, a.atthasdef, t.typname,
|
||||
CASE WHEN a.attlen=-1 THEN (
|
||||
CASE WHEN a.atttypmod=-1 THEN 0 ELSE a.atttypmod-4 END
|
||||
) ELSE a.attlen END as size
|
||||
FROM pg_class c, pg_attribute a, pg_type t
|
||||
WHERE c.relname=%s AND c.oid=a.attrelid AND a.atttypid=t.oid """
|
||||
query = 'SELECT * FROM information_schema.columns WHERE table_name=%s'
|
||||
cr.execute(query, (tablename,))
|
||||
return {row['attname']: row for row in cr.dictfetchall()}
|
||||
return {row['column_name']: row for row in cr.dictfetchall()}
|
||||
|
||||
def column_exists(cr, tablename, columnname):
|
||||
""" Return whether the given column exists. """
|
||||
query = """ SELECT 1 FROM pg_class c, pg_attribute a
|
||||
WHERE c.relname=%s AND a.attname=%s AND c.oid=a.attrelid """
|
||||
query = """ SELECT 1 FROM information_schema.columns
|
||||
WHERE table_name=%s AND column_name=%s """
|
||||
cr.execute(query, (tablename, columnname))
|
||||
return cr.rowcount
|
||||
|
||||
@@ -141,6 +139,7 @@ def fix_foreign_key(cr, tablename1, columnname1, tablename2, columnname2, ondele
|
||||
""" Update the foreign keys between tables to match the given one, and
|
||||
return ``True`` if the given foreign key has been recreated.
|
||||
"""
|
||||
# Do not use 'information_schema' here, as those views are awfully slow!
|
||||
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,
|
||||
|
||||
Reference in New Issue
Block a user