diff --git a/src/base/tests/test_util.py b/src/base/tests/test_util.py index ecd2c6fb6..e1ed0c777 100644 --- a/src/base/tests/test_util.py +++ b/src/base/tests/test_util.py @@ -718,11 +718,31 @@ def test_iter_browse_call_twice(self): class TestPG(UnitTestCase): + @parametrize( + [ + ("res_country", "name", "jsonb" if util.version_gte("16.0") else "varchar"), # translated field + ("res_country", "code", "varchar(2)"), + ("res_currency", "active", "bool"), + ("res_country", "create_date", "timestamp"), + ("res_currency", "create_uid", "int4"), + ("res_country", "name_position", "varchar"), + ("res_country", "address_format", "text"), + ("res_partner", "does_not_exists", None), + ] + ) + def test_column_type(self, table, column, expected): + value = util.column_type(self.env.cr, table, column) + if expected is None: + self.assertIsNone(value) + else: + self.assertEqual(value, expected) + def test_alter_column_type(self): cr = self.env.cr cr.execute( """ ALTER TABLE res_partner_bank ADD COLUMN x bool; + ALTER TABLE res_partner_bank ADD COLUMN y varchar(4); UPDATE res_partner_bank SET x = CASE id % 3 @@ -742,6 +762,12 @@ def test_alter_column_type(self): "Some values where not casted correctly via USING", ) + self.assertEqual(util.column_type(cr, "res_partner_bank", "y"), "varchar(4)") + util.alter_column_type(cr, "res_partner_bank", "y", "varchar") + self.assertEqual(util.column_type(cr, "res_partner_bank", "y"), "varchar") + util.alter_column_type(cr, "res_partner_bank", "y", "varchar(12)") + self.assertEqual(util.column_type(cr, "res_partner_bank", "y"), "varchar(12)") + @parametrize( [ ("test", "
test
"), diff --git a/src/util/pg.py b/src/util/pg.py index 469086448..4ab4fb0bf 100644 --- a/src/util/pg.py +++ b/src/util/pg.py @@ -497,9 +497,14 @@ def get_value_or_en_translation(cr, table, column): def _column_info(cr, table, column): _validate_table(table) + # NOTE: usage of both `CONCAT` and `||` in the query below is done on purpose to take advantage of their NULL handling. + # NULLS propagate with `||` and are ignored by `CONCAT`. cr.execute( """ - SELECT COALESCE(bt.typname, t.typname) AS udt_name, + SELECT CONCAT( + COALESCE(bt.typname, t.typname), + '(' || information_schema._pg_char_max_length(information_schema._pg_truetypid(a.*, t.*), information_schema._pg_truetypmod(a.*, t.*)) || ')' + ) AS udt_name, NOT (a.attnotnull OR t.typtype = 'd' AND t.typnotnull) AS is_nullable, ( c.relkind IN ('r','p','v','f') AND pg_column_is_updatable(c.oid::regclass, a.attnum, false)