From 759317a0b640c505dce0d46c67532a36ccd75d48 Mon Sep 17 00:00:00 2001 From: sagu-odoo Date: Sat, 29 Nov 2025 10:27:44 +0530 Subject: [PATCH] [FIX] util/pg: get common column name with type or typcategory 1. This commit Add param ``type_check`` get the common columns info with same typcategory or same data type and skipp the column with different datatype and different type 2. all column name should be returned ``` Traceback (most recent call last): File "/home/odoo/src/odoo/19.0/odoo/service/server.py", line 1514, in preload_registries registry = Registry.new(dbname, update_module=update_module, install_modules=config['init'], upgrade_modules=config['update'], reinit_modules=config['reinit']) File "/home/odoo/src/odoo/19.0/odoo/tools/func.py", line 88, in locked return func(inst, *args, **kwargs) File "/home/odoo/src/odoo/19.0/odoo/orm/registry.py", line 186, in new load_modules( File "/home/odoo/src/odoo/19.0/odoo/modules/loading.py", line 493, in load_modules migrations.migrate_module(package, 'end') File "/home/odoo/src/odoo/19.0/odoo/modules/migration.py", line 220, in migrate_module exec_script(self.cr, installed_version, pyfile, pkg.name, stage, stageformat[stage] % version) File "/home/odoo/src/odoo/19.0/odoo/modules/migration.py", line 257, in exec_script mod.migrate(cr, installed_version) File "/tmp/tmp7yriz79e/migrations/hr/saas~18.4.1.1/end-migrate.py", line 87, in migrate cr.execute(query, [e[1] for e in required_default_values]) File "/home/odoo/src/odoo/19.0/odoo/sql_db.py", line 426, in execute self._obj.execute(query, params) psycopg2.errors.DatatypeMismatch: column "fondo_ahorro" is of type boolean but expression is of type double precision LINE 16: ..."."distance_home_work_unit", "e"."employee_type", "e"."fondo... ^ HINT: You will need to rewrite or cast the expression. ``` ``` select id,name,model,ttype,store from ir_model_fields where name='fondo_ahorro'; id | name | model | ttype | store -------+--------------+-----------------------+---------+------- 28361 | fondo_ahorro | hr.employee | float | t 28687 | fondo_ahorro | calculo.liquidaciones | float | t 28379 | fondo_ahorro | hr.version | boolean | t (3 rows) ``` upg-3444635 opw-5260147 --- src/util/pg.py | 55 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/src/util/pg.py b/src/util/pg.py index 0ab92a9c2..5cd26f238 100644 --- a/src/util/pg.py +++ b/src/util/pg.py @@ -1251,14 +1251,15 @@ def get_columns(cr, table, ignore=("id",)): return ColumnList(*cr.fetchone()) -def get_common_columns(cr, table1, table2, ignore=("id",)): +def get_common_columns(cr, table1, table2, ignore=("id",), type_check=True): """ Return a list of columns present in both tables. :param str table1: first table name whose columns are retrieved :param str table2: second table name whose columns are retrieved :param list(str) ignore: list of column names to ignore in the returning list - :return: a list of column names present in both tables + :param bool type_check: only returns common columns with compatible data type + :return: a list of column names present in both table :rtype: :class:`~odoo.upgrade.util.pg.ColumnList` """ _validate_table(table1) @@ -1266,22 +1267,46 @@ def get_common_columns(cr, table1, table2, ignore=("id",)): cr.execute( """ - WITH _common AS ( - SELECT column_name - FROM information_schema.columns - WHERE table_schema = 'public' - AND table_name IN %s - AND column_name != ALL(%s) - GROUP BY column_name - HAVING count(table_name) = 2 - ) - SELECT coalesce(array_agg(column_name::varchar ORDER BY column_name), ARRAY[]::varchar[]), - coalesce(array_agg(quote_ident(column_name) ORDER BY column_name), ARRAY[]::varchar[]) - FROM _common + SELECT c.column_name, + quote_ident(c.column_name), + count(DISTINCT t.oid) = 1 AS same_type, + count(DISTINCT t.typcategory) = 1 AS compatible + FROM information_schema.columns c + JOIN pg_type t + ON c.udt_name = t.typname + WHERE c.table_schema = 'public' + AND c.table_name IN %s + AND c.column_name != ALL(%s) + GROUP BY c.column_name + HAVING count(c.table_name) = 2 + ORDER BY c.column_name """, [(table1, table2), list(ignore)], ) - return ColumnList(*cr.fetchone()) + cols_info = cr.fetchall() + + if type_check: + incompatible_cols = [qname for _, qname, _, compatible in cols_info if not compatible] + if incompatible_cols: + _logger.warning( + "Common columns with incompatible types between %s and %s: %s", + table1, + table2, + ", ".join(incompatible_cols), + ) + compatible_cols = [qname for _, qname, same_type, compatible in cols_info if not same_type and compatible] + if compatible_cols: + _logger.warning( + "Common columns with types that can be implicitly converted between %s and %s: %s", + table1, + table2, + ", ".join(compatible_cols), + ) + + common_columns, quoted_common_columns = zip( + *((name, qname) for name, qname, _, compatible in cols_info if not type_check or compatible) + ) + return ColumnList(common_columns, quoted_common_columns) def rename_table(cr, old_table, new_table, remove_constraints=True):