Skip to content

Port two 1.7 bug fixes to 1.8: search_path-qualified graphid_ops, and null node label in age_create_barbell_graph - #4

Merged
gaoxueyu merged 2 commits into
IvorySQL:release/PG18/1.8.0from
NotHimmel:fix/pg18-label-and-barbell
Sep 10, 2026
Merged

Port two 1.7 bug fixes to 1.8: search_path-qualified graphid_ops, and null node label in age_create_barbell_graph#4
gaoxueyu merged 2 commits into
IvorySQL:release/PG18/1.8.0from
NotHimmel:fix/pg18-label-and-barbell

Conversation

@NotHimmel

Copy link
Copy Markdown
Collaborator

Two independent bug fixes, ported to the 1.8 line. Both were reviewed and
merged on 1.7 (#1, #2), and both defects are still
present on release/PG18/1.8.0.

They touch different files and can be reviewed independently.

1. create_graph fails when ag_catalog is not in search_path

create_index_on_column() passed graphid_ops as an unqualified operator
class name, so it resolved against the caller's search_path. Whenever
ag_catalog was not on the search_path, creating a label failed with

ERROR:  operator class "graphid_ops" does not exist for access method "btree"

even for a fully qualified call such as SELECT ag_catalog.create_graph('g').
The message is misleading: the operator class exists, it is just not visible.

This affects create_graph(), create_vlabel(), create_elabel(), the CSV
loader, and label creation from a CREATE or MERGE clause at query time,
since all of them reach create_label().

The unqualified name arrived with the id column indexes in apache#2117, so this is a
regression: before that commit create_label() built no index and resolved no
name through the search_path. Every other object referenced by the DDL that
create_label() generates is already reached either by OID or by an
ag_catalog qualified name, so qualifying this one restores the previous
behaviour.

Verified on this branch:

SET search_path = public;                          -- ag_catalog deliberately absent
SELECT ag_catalog.create_graph('g');               -- previously failed
SELECT ag_catalog.create_vlabel('g', 'V');         -- previously failed

2. Backend crash in age_create_barbell_graph with a null node label

node_label is declared name = NULL in the SQL signature, so omitting it -
or passing NULL explicitly - is a supported call. Both crashed the backend
with SIGSEGV, which makes the postmaster reinitialize and drops every other
session on the instance.

Two separate faults on that path.

First, the default label was copied into a null pointer:

Name node_label_name = NULL;
...
if (PG_ARGISNULL(3))
    namestrcpy(node_label_name, AG_DEFAULT_LABEL_VERTEX);

namestrcpy() writes through the pointer it is given and does not allocate,
so the default now has its own NameData. This also makes the default
actually take effect, which it never did.

Second, the node label was forwarded to create_complete_graph() as
args[3].value. DirectFunctionCall4() marks every argument as not null, so
a null node label arrived there as a non-null NULL pointer and was
dereferenced by the vertex/edge label comparison. The resolved label is
forwarded instead.

Verified on this branch:

SELECT age_create_barbell_graph('bb', 3, 0, NULL, NULL, 'E', NULL);
-- 6 vertices created; previously SIGSEGV

Note on the conflict resolution

The label_commands.c hunk conflicted with an unrelated upstream change on the
adjacent line (index_col->collation moved from InvalidOid to NIL, which is
the correct spelling since IndexElem.collation is a List *). The 1.8 form of
that line is kept and only the opclass qualification is carried over.

Testing

43/43 installcheck on PostgreSQL 18.4, no compiler warnings.
Regression coverage for the barbell fix is included in graph_generation.

create_index_on_column() passed "graphid_ops" as an unqualified operator
class name, so it was resolved against the caller's search_path. Whenever
ag_catalog was not on the search_path, creating a label failed with

  ERROR:  operator class "graphid_ops" does not exist for access method "btree"

even for a fully qualified call such as

  SELECT ag_catalog.create_graph('g');

The error is misleading: the operator class does exist, it is simply not
visible. This affected create_graph(), create_vlabel(), create_elabel(),
the CSV loader, and label creation from a CREATE or MERGE clause at query
time, since all of them reach create_label().

The unqualified name arrived with the id column indexes in apache#2117, so this
is a regression. Before that commit create_label() built no index and
resolved no name through the search_path. Every other object referenced by
the DDL that create_label() generates is already reached either by OID or
by an ag_catalog qualified name, so qualifying this one restores the
previous behaviour.
node_label is declared "name = NULL" in the SQL signature, so leaving it
out - or passing NULL explicitly - is a supported call. Both crashed the
backend with SIGSEGV, which makes the postmaster reinitialize and drops
every other session on the instance.

There were two separate faults on that path.

First, the default label was copied into a null pointer:

    Name node_label_name = NULL;
    ...
    if (PG_ARGISNULL(3))
        namestrcpy(node_label_name, AG_DEFAULT_LABEL_VERTEX);

namestrcpy() writes through the pointer it is given and does not
allocate, so give the default its own NameData. This also makes the
default actually take effect, which it never did.

Second, the node label was forwarded to create_complete_graph() as
args[3].value. DirectFunctionCall4() marks every argument as not null, so
a null node label arrived there as a non-null NULL pointer and was
dereferenced by the vertex/edge label comparison. Forward the resolved
label instead.

create_complete_graph() already handles its own null node label correctly;
follow the same approach here.

Extend the graph_generation test with the previously untested cases. The
existing barbell tests always passed a node label, except for the
all-arguments-null case which errors out on the graph name before ever
reaching this code.
@gaoxueyu
gaoxueyu merged commit ec1f921 into IvorySQL:release/PG18/1.8.0 Sep 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants