From 6d0c041cf2d56b5d7f6dc0b5e3d8fed4a7a01dc1 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Sat, 3 Oct 2026 14:54:06 +0200 Subject: [PATCH] Name every function by a SQL name it deploys state_deployed_sqlfn sets a function's sqlfn to the name of its first signature when its signatures carry several names and none is its tag, and the signature carrying that name drops the sqlName that restates it; the first signature is the tagged wrapper's, as attach_sqlfn_map lists them. A function one of whose signatures carries its tag keeps it, as before. test_sqlfn_deployed.py states the case, its catalog check asks of every function that one of its signatures carries its sqlfn, and its adjacency check reads the class-prefixed name tboxAdjacent MobilityDB gives the operator function. Witness: since MobilityDB deploys the FromText readers beside the type inputs, floatset_in carries the signatures floatset_in and floatsetFromText under Set_in, tagged intset_in(), so its sqlfn read intset_in, a sibling's name, and so did 61 other functions (tfloat_in read tint_in, temporal_tagg_finalfn tCount, tpointseq_from_base_tstzset tint). The pytest workflow failed on master's catalog: test_per_type_functions_carry_their_own_name on floatset_in, and test_backing_tags_keep_their_family_name on adjacent_tbox_tnumber, whose sqlfn MobilityDB 762b3501cc renamed to tboxAdjacent. Why: a binding names a function by its sqlfn, so these 62 were offered under a name that answers another type. Measured: over MobilityDB 985fdb26b7 the catalog changes the sqlfn of those 62 functions and nothing else; pytest tests/ answers 459 passed and 11 skipped with MDB_SRC_ROOT set, where master answers 2 failed. --- parser/sqlfn.py | 19 ++++++++++++------- tests/test_sqlfn_deployed.py | 25 +++++++++++++++++++------ 2 files changed, 31 insertions(+), 13 deletions(-) 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, [])