diff --git a/CHANGELOG b/CHANGELOG index 291a1e1511..5bfa6130e7 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,5 @@ +* Use JSONB to store Dict field on PostgreSQL backend + Version 6.2.0 - 2021-11-01 * Bug fixes (see mercurial logs for details) * Allow to cast to date with timezone diff --git a/trytond/backend/postgresql/database.py b/trytond/backend/postgresql/database.py index 5c7204ca74..c874a94a48 100644 --- a/trytond/backend/postgresql/database.py +++ b/trytond/backend/postgresql/database.py @@ -198,13 +198,14 @@ class Database(DatabaseInterface): flavor = Flavor(ilike=True) TYPES_MAPPING = { - 'INTEGER': SQLType('INT4', 'INT4'), 'BIGINT': SQLType('INT8', 'INT8'), - 'FLOAT': SQLType('FLOAT8', 'FLOAT8'), 'BLOB': SQLType('BYTEA', 'BYTEA'), 'DATETIME': SQLType('TIMESTAMP', 'TIMESTAMP(0)'), - 'TIMESTAMP': SQLType('TIMESTAMP', 'TIMESTAMP(6)'), + 'FLOAT': SQLType('FLOAT8', 'FLOAT8'), 'FULLTEXT': SQLType('TSVECTOR', 'TSVECTOR'), + 'INTEGER': SQLType('INT4', 'INT4'), + 'JSON': SQLType('JSONB', 'JSONB'), + 'TIMESTAMP': SQLType('TIMESTAMP', 'TIMESTAMP(6)'), } def __new__(cls, name=_default_name): diff --git a/trytond/backend/sqlite/database.py b/trytond/backend/sqlite/database.py index 61fc4a6de4..9b03b24734 100644 --- a/trytond/backend/sqlite/database.py +++ b/trytond/backend/sqlite/database.py @@ -334,10 +334,11 @@ class Database(DatabaseInterface): IN_MAX = 200 TYPES_MAPPING = { - 'DATETIME': SQLType('TIMESTAMP', 'TIMESTAMP'), 'BIGINT': SQLType('INTEGER', 'INTEGER'), 'BOOL': SQLType('BOOLEAN', 'BOOLEAN'), + 'DATETIME': SQLType('TIMESTAMP', 'TIMESTAMP'), 'FULLTEXT': SQLType('TEXT', 'TEXT'), + 'JSON': SQLType('TEXT', 'TEXT'), } def __new__(cls, name=_default_name): diff --git a/trytond/model/fields/dict.py b/trytond/model/fields/dict.py index 758956cd9f..0b1ef0b4bf 100644 --- a/trytond/model/fields/dict.py +++ b/trytond/model/fields/dict.py @@ -21,7 +21,7 @@ dumps = partial( class Dict(Field): 'Define dict field.' _type = 'dict' - _sql_type = 'TEXT' + _sql_type = 'JSON' _py_type = dict def __init__(self, schema_model, string='', help='', required=False, diff --git a/trytond/tests/field_dict.py b/trytond/tests/field_dict.py index 66da122763..f51673cbb7 100644 --- a/trytond/tests/field_dict.py +++ b/trytond/tests/field_dict.py @@ -34,10 +34,11 @@ class DictRequired(ModelSQL): dico = fields.Dict(None, 'Test Dict', required=True) -class DictJSONB(ModelSQL): - 'Dict JSONB' - __name__ = 'test.dict_jsonb' +class DictText(ModelSQL): + 'Dict TEXT' + __name__ = 'test.dict_text' dico = fields.Dict('test.dict.schema', 'Test Dict') + dico._sql_type = 'TEXT' class DictNoSchema(ModelSQL): @@ -69,7 +70,7 @@ def register(module): Dict, DictDefault, DictRequired, - DictJSONB, + DictText, DictNoSchema, DictUnaccentedOn, DictUnaccentedOff, diff --git a/trytond/tests/test_field_dict.py b/trytond/tests/test_field_dict.py index 948947e955..a3eec9996d 100644 --- a/trytond/tests/test_field_dict.py +++ b/trytond/tests/test_field_dict.py @@ -8,7 +8,6 @@ from trytond.model.exceptions import RequiredValidationError from trytond.pool import Pool from trytond.tests.test_tryton import activate_module, with_transaction from trytond.tests.test_tryton import ExtensionTestCase -from trytond.transaction import Transaction class FieldDictTestCase(unittest.TestCase): @@ -48,11 +47,6 @@ class FieldDictTestCase(unittest.TestCase): 'fr: France'), }]) - def set_jsonb(self, table): - cursor = Transaction().connection.cursor() - cursor.execute('ALTER TABLE "%s" ' - 'ALTER COLUMN dico TYPE json USING dico::json' % table) - @with_transaction() def test_create(self): "Test create dict" @@ -167,16 +161,9 @@ class FieldDictTestCase(unittest.TestCase): }]) @with_transaction() - @unittest.skipIf( - backend.name != 'postgresql', 'jsonb only supported by postgresql') - def test_create_jsonb(self): - "Test create dict as jsonb" - connection = Transaction().connection - if backend.Database().get_version(connection) < (9, 2): - return - - Dict = Pool().get('test.dict_jsonb') - self.set_jsonb(Dict._table) + def test_create_text(self): + "Test create dict as text" + Dict = Pool().get('test.dict_text') dict_, = Dict.create([{ 'dico': {'a': 1, 'b': 2}, @@ -214,16 +201,9 @@ class FieldDictTestCase(unittest.TestCase): self.assertDictEqual(dict_.dico, {'y': 1}) @with_transaction() - @unittest.skipIf( - backend.name != 'postgresql', 'jsonb only supported by postgresql') - def test_write_jsonb(self): - "Test write dict as jsonb" - connection = Transaction().connection - if backend.Database().get_version(connection) < (9, 2): - return - - Dict = Pool().get('test.dict_jsonb') - self.set_jsonb(Dict._table) + def test_write_text(self): + "Test write dict as text" + Dict = Pool().get('test.dict_text') dict_, = Dict.create([{ 'dico': {'a': 1, 'b': 2}, }]) @@ -827,17 +807,10 @@ class FieldDictTestCase(unittest.TestCase): self.assertListEqual(dicts_b_b, []) @with_transaction() - @unittest.skipIf( - backend.name != 'postgresql', 'jsonb only supported by postgresql') - def test_search_element_jsonb(self): - "Test search dict element on jsonb" - connection = Transaction().connection - if backend.Database().get_version(connection) < (9, 2): - return - + def test_search_element_text(self): + "Test search dict element on text" pool = Pool() - Dict = pool.get('test.dict_noschema') - self.set_jsonb(Dict._table) + Dict = pool.get('test.dict_text') dict_, = Dict.create([{ 'dico': {'a': 'Foo'}, }])