diff --git a/parser/sqlfn.py b/parser/sqlfn.py index 5f4c947..428e8ce 100644 --- a/parser/sqlfn.py +++ b/parser/sqlfn.py @@ -1014,20 +1014,25 @@ def state_deployed_sqlfn(idl: dict) -> tuple[dict, int]: ``sqlName: floatset_in``, the name its ``CREATE FUNCTION`` deploys. When every signature of a function carries one name, that name is the function's ``sqlfn`` and the signatures drop the ``sqlName`` that only restated it. A function whose - signatures carry several names keeps the tag, each signature its own name; a - ``sqlfnBackingOnly`` record, as #classify_backing_sqlfn of parser/portable.py marks - it, keeps its backing tag beside its ``publicSqlName``.""" + signatures carry several names keeps the tag when one of them carries it, each + other signature its own name; when none does, as ``floatset_in`` deploys + ``floatset_in`` and ``floatsetFromText`` under a ``Set_in`` tagged ``intset_in()``, + its ``sqlfn`` is the name of its first signature, which #attach_sqlfn_map lists + from the tagged wrapper first. A ``sqlfnBackingOnly`` record, as + #classify_backing_sqlfn of parser/portable.py marks it, keeps its backing tag + beside its ``publicSqlName``.""" n = 0 for f in idl.get("functions", []): sigs = f.get("sqlSignatures") if not sigs or f.get("sqlfnBackingOnly"): continue - names = {s.get("sqlName", f["sqlfn"]) for s in sigs} - if len(names) != 1: + names = [s.get("sqlName", f["sqlfn"]) for s in sigs] + if len(set(names)) != 1 and f["sqlfn"] in names: continue - name = names.pop() + name = names[0] for s in sigs: - s.pop("sqlName", None) + if s.get("sqlName") == name: + s.pop("sqlName") if name != f["sqlfn"]: f["sqlfn"] = name n += 1 diff --git a/tests/test_sqlfn_deployed.py b/tests/test_sqlfn_deployed.py index a9aee34..160fcb8 100644 --- a/tests/test_sqlfn_deployed.py +++ b/tests/test_sqlfn_deployed.py @@ -45,6 +45,20 @@ def test_signatures_carrying_several_names_keep_the_tag(self): self.assertEqual(fns["ea_dwithin_tgeo_geo"]["sqlSignatures"], sigs) self.assertEqual(n, 0) + def test_several_names_none_the_tag_take_the_first(self): + # As #test_the_one_name_the_signatures_carry_is_the_sqlfn, once the family's + # wrappers deploy a second name: the tag names a sibling, never this function. + fns, n = _state({"name": "floatset_in", "sqlfn": "intset_in", + "sqlSignatures": [{"args": ["cstring"], "ret": "floatset", + "sqlName": "floatset_in"}, + {"args": ["text"], "ret": "floatset", + "sqlName": "floatsetFromText"}]}) + self.assertEqual(fns["floatset_in"]["sqlfn"], "floatset_in") + self.assertEqual(fns["floatset_in"]["sqlSignatures"], + [{"args": ["cstring"], "ret": "floatset"}, + {"args": ["text"], "ret": "floatset", "sqlName": "floatsetFromText"}]) + self.assertEqual(n, 1) + def test_a_backing_tag_stays_beside_its_public_name(self): fns, n = _state({"name": "adjacent_tbox_tnumber", "sqlfn": "adjacent_bbox", "sqlfnBackingOnly": True, "publicSqlName": "adjacent", @@ -76,19 +90,18 @@ def test_per_type_functions_carry_their_own_name(self): ("contains_cbuffer_cbuffer", "cbuffer_contains")): self.assertEqual(self.fns[name]["sqlfn"], sqlfn, name) - def test_backing_tags_keep_their_family_name(self): + def test_an_operator_function_carries_its_class_prefixed_name(self): f = self.fns["adjacent_tbox_tnumber"] - self.assertEqual((f["sqlfn"], f["publicSqlName"]), ("adjacent_bbox", "adjacent")) + self.assertEqual(f["sqlfn"], "tboxAdjacent") def test_no_function_names_a_family_member_its_signatures_do_not(self): """The condition #state_deployed_sqlfn of parser/sqlfn.py reads, asked of the - whole catalog: signatures all carrying one name other than sqlfn, a backing + whole catalog: an sqlfn none of the function's signatures carries, a backing tag aside.""" other = [f["name"] for f in self.fns.values() if f.get("sqlSignatures") and not f.get("sqlfnBackingOnly") - and len(names := {s.get("sqlName", f["sqlfn"]) - for s in f["sqlSignatures"]}) == 1 - and names != {f["sqlfn"]}] + and f["sqlfn"] not in {s.get("sqlName", f["sqlfn"]) + for s in f["sqlSignatures"]}] self.assertEqual(other, [])