From 2a22cf077c98423144f0577b2922c94816b438a4 Mon Sep 17 00:00:00 2001 From: Khushboo Vashi Date: Wed, 10 May 2023 10:32:47 +0530 Subject: [PATCH] Fix circular reference error for the multirange data types in the query tool. #6221 Add support for the multirange data types. --- .../sql/default/get_types_where_condition.sql | 2 +- web/pgadmin/utils/driver/psycopg3/typecast.py | 15 ++++-- .../feature_tests/datatype_test.json | 46 +++++++++++++++++++ .../pg_datatype_validation_test.py | 6 ++- .../feature_utils/base_feature_test.py | 7 +-- 5 files changed, 67 insertions(+), 9 deletions(-) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/default/get_types_where_condition.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/default/get_types_where_condition.sql index aa6aca84c..2104d9c3c 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/default/get_types_where_condition.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/default/get_types_where_condition.sql @@ -1,5 +1,5 @@ {### Additional where condition for get_types route for column node ###} -typisdefined AND typtype IN ('b', 'c', 'd', 'e', 'r') +typisdefined AND typtype IN ('b', 'c', 'd', 'e', 'r', 'm') AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_class WHERE relnamespace=typnamespace AND relname = typname AND relkind != 'c') AND (typname NOT LIKE '_%' OR NOT EXISTS (SELECT 1 FROM pg_catalog.pg_class WHERE diff --git a/web/pgadmin/utils/driver/psycopg3/typecast.py b/web/pgadmin/utils/driver/psycopg3/typecast.py index 3adcbe49b..0bfdc479b 100644 --- a/web/pgadmin/utils/driver/psycopg3/typecast.py +++ b/web/pgadmin/utils/driver/psycopg3/typecast.py @@ -110,14 +110,22 @@ PSYCOPG_SUPPORTED_IPADDRESS_ARRAY_TYPES = (1041, 651) # OID reference psycopg/lib/extras.py PSYCOPG_SUPPORTED_IPADDRESS_ARRAY_TYPES = (2951, 2950) -# int4range, int8range, numrange, daterange tsrange, tstzrange[] +# int4range, int8range, numrange, daterange tsrange, tstzrange # OID reference psycopg/lib/_range.py PSYCOPG_SUPPORTED_RANGE_TYPES = (3904, 3926, 3906, 3912, 3908, 3910) +# int4multirange, int8multirange, nummultirange, datemultirange tsmultirange, +# tstzmultirange[] +PSYCOPG_SUPPORTED_MULTIRANGE_TYPES = (4535, 4451, 4536, 4532, 4533, 4534) + # int4range[], int8range[], numrange[], daterange[] tsrange[], tstzrange[] # OID reference psycopg/lib/_range.py PSYCOPG_SUPPORTED_RANGE_ARRAY_TYPES = (3905, 3927, 3907, 3913, 3909, 3911) +# int4multirange[], int8multirange[], nummultirange[], +# datemultirange[] tsmultirange[], tstzmultirange[] +PSYCOPG_SUPPORTED_MULTIRANGE_ARRAY_TYPES = (6155, 6150, 6157, 6151, 6152, 6153) + def register_global_typecasters(): # This registers a unicode type caster for datatype 'RECORD'. @@ -128,7 +136,7 @@ def register_global_typecasters(): 2287, TextLoaderpgAdmin) for typ in TO_STRING_DATATYPES + TO_STRING_NUMERIC_DATATYPES +\ - PSYCOPG_SUPPORTED_RANGE_TYPES: + PSYCOPG_SUPPORTED_RANGE_TYPES + PSYCOPG_SUPPORTED_MULTIRANGE_TYPES: psycopg.adapters.register_loader(typ, TextLoaderpgAdmin) @@ -176,7 +184,8 @@ def register_array_to_string_typecasters(connection=None): type_array = PSYCOPG_SUPPORTED_BUILTIN_ARRAY_DATATYPES +\ PSYCOPG_SUPPORTED_JSON_ARRAY_TYPES +\ PSYCOPG_SUPPORTED_IPADDRESS_ARRAY_TYPES +\ - PSYCOPG_SUPPORTED_RANGE_ARRAY_TYPES +\ + PSYCOPG_SUPPORTED_RANGE_ARRAY_TYPES + \ + PSYCOPG_SUPPORTED_MULTIRANGE_ARRAY_TYPES + \ TO_ARRAY_OF_STRING_DATATYPES for typ in type_array: diff --git a/web/regression/feature_tests/datatype_test.json b/web/regression/feature_tests/datatype_test.json index 77bf7d999..3972b2e59 100644 --- a/web/regression/feature_tests/datatype_test.json +++ b/web/regression/feature_tests/datatype_test.json @@ -22,6 +22,18 @@ "daterange[]": 90200, "tsrange[]": 90200, "tstzrange[]": 90200, + "int4multirange": 140000, + "int8multirange": 140000, + "nummultirange": 140000, + "datemultirange": 140000, + "tsmultirange": 140000, + "tstzmultirange": 140000, + "int4multirange[]": 140000, + "int8multirange[]": 140000, + "nummultirange[]": 140000, + "datemultirange[]": 140000, + "tsmultirange[]": 140000, + "tstzmultirange[]": 140000, "inet": 0, "inet[]": 0, "cidr": 0, @@ -212,6 +224,40 @@ "08:00:2b:01:02:03", "{08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03}" ] + }, { + "datatype": [ + "int4multirange", + "int8multirange", + "nummultirange", + "datemultirange", + "tsmultirange", + "int4multirange[]", + "int8multirange[]", + "nummultirange[]", + "datemultirange[]" + ], + "input": [ + "'{[1,4],[6,10]}'", + "'{(2,2002), (3001,922337203685477580)}'", + "'{(3,92233), (92234,922337203685.922337203685)}'", + "'{(2010-01-01,2010-02-01], (2012-01-01,2015-02-01]}'", + "'{[2010-01-01 14:00, 2010-04-01 15:00)}'", + "'{\"{(1,2147483647)}\", \"{(2,2147483647)}\"}'", + "'{\"{(2,9223372036854775807)}\", \"{(2,9223372036854775807)}\"}'", + "'{\"{(3,922337203685.922337203685]}\", \"{(5,922337203685.922337203685]}\"}'", + "'{\"{(2010-01-01, 2010-02-01]}\", \"{(2010-01-01, 2010-02-01]}\"}'" + ], + "output": [ + "{[1,5),[6,11)}", + "{[3,2002),[3002,922337203685477580)}", + "{(3,92233),(92234,922337203685.922337203685)}", + "{[2010-01-02,2010-02-02),[2012-01-02,2015-02-02)}", + "{[\"2010-01-01 14:00:00\",\"2010-04-01 15:00:00\")}", + "{\"{[2,2147483647)}\",\"{[3,2147483647)}\"}", + "{\"{[3,9223372036854775807)}\",\"{[3,9223372036854775807)}\"}", + "{\"{(3,922337203685.922337203685]}\",\"{(5,922337203685.922337203685]}\"}", + "{\"{[2010-01-02,2010-02-02)}\",\"{[2010-01-02,2010-02-02)}\"}" + ] } ] } diff --git a/web/regression/feature_tests/pg_datatype_validation_test.py b/web/regression/feature_tests/pg_datatype_validation_test.py index af5c0feed..1c1ff008d 100644 --- a/web/regression/feature_tests/pg_datatype_validation_test.py +++ b/web/regression/feature_tests/pg_datatype_validation_test.py @@ -225,7 +225,8 @@ class PGDataypeFeatureTest(BaseFeatureTest): cnt += 1 continue - if datatype in ('tstzrange', 'tstzrange[]'): + if datatype in ('tstzrange', 'tstzrange[]', 'tstzmultirange', + 'tstzmultirange[]'): expected_output = expected_output.format( **dict([('tz', self.timezone_hh_mm)])) try: @@ -256,7 +257,8 @@ class PGDataypeFeatureTest(BaseFeatureTest): else: dataformatter = '{}' - if datatype in ('tstzrange', 'tstzrange[]'): + if datatype in ('tstzrange', 'tstzrange[]', 'tstzmultirange', + 'tstzmultirange[]'): inputdata = inputdata.format( **dict([('tz', self.timezone_hh_mm)])) if first: diff --git a/web/regression/feature_utils/base_feature_test.py b/web/regression/feature_utils/base_feature_test.py index 956c1b16c..f8d56260e 100644 --- a/web/regression/feature_utils/base_feature_test.py +++ b/web/regression/feature_utils/base_feature_test.py @@ -70,9 +70,10 @@ class BaseFeatureTest(BaseTestGenerator): self.after() def any_step_failed(self): - for step in self._outcome.errors: - if step[1] is not None: - return True + if hasattr(self._outcome, 'errors'): + for step in self._outcome.errors: + if step[1] is not None: + return True return False def current_test_failed(self):