diff --git a/parser/codecs.py b/parser/codecs.py index ef9cc4d..b25a15a 100644 --- a/parser/codecs.py +++ b/parser/codecs.py @@ -128,7 +128,8 @@ def keyed(cls, cands, sql_type, side, table): for the class only when it is the encoding's one candidate (``interval_in``). Two functions of one encoding for one SQL type rank by ``table``, whose first match names the encoding (``cbuffer_out`` before ``cbuffer_as_text`` and - ``cbuffer_as_ewkt``), then by how many SQL types each serves, the narrower first, + ``cbuffer_as_ewkt``, ``cbuffer_as_hexwkb`` before ``cbuffer_as_hexewkb``), then by + how many SQL types each serves, the narrower first, as PostgreSQL resolves an overload to its most specific candidate (``cbufferset_out`` before ``spatialset_out`` for a ``cbufferset``). Two that tie on both contradict each other.""" diff --git a/parser/enrich.py b/parser/enrich.py index a518e1c..ff031c7 100644 --- a/parser/enrich.py +++ b/parser/enrich.py @@ -65,7 +65,10 @@ (re.compile(r"_as_e?wkt$"), "text"), (re.compile(r"_as_mfjson$"), "mfjson"), (re.compile(r"_as_geojson$"), "mfjson"), - (re.compile(r"_as_hex_?e?wkb$"), "wkb"), + # The plain hex-WKB writer ranks before the E one, so a class having both keeps the + # plain one as its codec (#keyed of parser/codecs.py ranks by this order). + (re.compile(r"_as_hex_?wkb$"), "wkb"), + (re.compile(r"_as_hex_?ewkb$"), "wkb"), (re.compile(r"_as_e?wkb$"), "wkb"), ] _DECODERS = [ @@ -74,7 +77,8 @@ (re.compile(r"_from_text$"), "text"), (re.compile(r"_from_mfjson$"), "mfjson"), (re.compile(r"_from_geojson$"), "mfjson"), - (re.compile(r"_from_hex_?e?wkb$"), "wkb"), + (re.compile(r"_from_hex_?wkb$"), "wkb"), + (re.compile(r"_from_hex_?ewkb$"), "wkb"), (re.compile(r"_from_e?wkb$"), "wkb"), ] _IO_RE = [rx for rx, _ in _DECODERS + _ENCODERS] diff --git a/tests/test_codecs.py b/tests/test_codecs.py index 6344877..5b8774b 100644 --- a/tests/test_codecs.py +++ b/tests/test_codecs.py @@ -139,6 +139,32 @@ def test_a_hexewkb_reader_per_type_and_one_writer_for_both(self): self.assertEqual(g["encoderAux"]["wkb"], [{"name": "endian", "kind": "string", "default": None}]) + def test_the_plain_hex_writer_and_reader_rank_before_the_e_ones(self): + """A class having both the plain and the E hex-WKB functions keeps the plain ones, + as #test_a_hexewkb_reader_per_type_and_one_writer_for_both keeps the E ones of a + class having no other.""" + cb = "const Cbuffer *" + both = FUNCTIONS + [ + fn("cbuffer_from_hexwkb", "Cbuffer *", [("const char *", "hexwkb")], + [sig("cbufferFromHexWKB", ["text"], "cbuffer")]), + fn("cbuffer_from_hexewkb", "Cbuffer *", [("const char *", "hexwkb")], + [sig("cbufferFromHexEWKB", ["text"], "cbuffer")]), + fn("cbuffer_as_hexwkb", "char *", + [(cb, "cb"), ("uint8_t", "variant"), ("size_t *", "size_out")], + [sig("asHexWKB", ["cbuffer", "text"], "text")], + shape={"outParams": ["size_out"]}), + fn("cbuffer_as_hexewkb", "char *", + [(cb, "cb"), ("uint8_t", "variant"), ("size_t *", "size_out")], + [sig("asHexEWKB", ["cbuffer", "text"], "text")], + shape={"outParams": ["size_out"]})] + idl = _idl(both) + idl["typeEncodings"]["Cbuffer"] = {} + idl, errors = state_type_encodings(idl) + c = idl["typeEncodings"]["Cbuffer"] + self.assertEqual((c["decoders"]["wkb"], c["encoders"]["wkb"]), + ("cbuffer_from_hexwkb", "cbuffer_as_hexwkb")) + self.assertEqual(errors, []) + def test_a_cell_is_a_class_of_its_own(self): h = self.te["H3Index"] self.assertEqual((h["in"], h["out"]), ("h3index_in", "h3index_out")) diff --git a/tests/test_sqlfn_deployed.py b/tests/test_sqlfn_deployed.py index 160fcb8..1f3bc9b 100644 --- a/tests/test_sqlfn_deployed.py +++ b/tests/test_sqlfn_deployed.py @@ -87,7 +87,7 @@ def setUp(self): def test_per_type_functions_carry_their_own_name(self): for name, sqlfn in (("floatset_in", "floatset_in"), ("tfloat_in", "tfloat_in"), ("tfloatinst_make", "tfloat"), ("tfloat_values", "valueSet"), - ("contains_cbuffer_cbuffer", "cbuffer_contains")): + ("contains_cbuffer_cbuffer", "cbufferContains")): self.assertEqual(self.fns[name]["sqlfn"], sqlfn, name) def test_an_operator_function_carries_its_class_prefixed_name(self):