Fix MERGE crashes due to incorrect label type (#957)
diff --git a/src/backend/nodes/cypher_outfuncs.c b/src/backend/nodes/cypher_outfuncs.c
index b73f29f..d7fc791 100644
--- a/src/backend/nodes/cypher_outfuncs.c
+++ b/src/backend/nodes/cypher_outfuncs.c
@@ -204,6 +204,7 @@
WRITE_STRING_FIELD(name);
WRITE_STRING_FIELD(label);
+ WRITE_STRING_FIELD(parsed_label);
WRITE_NODE_FIELD(props);
WRITE_LOCATION_FIELD(location);
}
@@ -215,6 +216,7 @@
WRITE_STRING_FIELD(name);
WRITE_STRING_FIELD(label);
+ WRITE_STRING_FIELD(parsed_label);
WRITE_NODE_FIELD(props);
WRITE_NODE_FIELD(varlen);
WRITE_ENUM_FIELD(dir, cypher_rel_dir);
diff --git a/src/backend/parser/cypher_clause.c b/src/backend/parser/cypher_clause.c
index 18cf3c6..493206c 100644
--- a/src/backend/parser/cypher_clause.c
+++ b/src/backend/parser/cypher_clause.c
@@ -307,7 +307,6 @@
bool p_lateral_ok);
static List *make_target_list_from_join(ParseState *pstate,
RangeTblEntry *rte);
-static Expr *add_volatile_wrapper(Expr *node);
static FuncExpr *make_clause_func_expr(char *function_name,
Node *clause_information);
/* for VLE support */
@@ -5165,6 +5164,9 @@
}
/*
+ * TODO A function called get_<something> should NOT modify the contents of what
+ * it gets. This needs to be fixed.
+ *
* Returns the resno for the TargetEntry with the resname equal to the name
* passed. Returns -1 otherwise.
*/
@@ -5570,6 +5572,12 @@
{
Oid oid;
+ /* if the passed Expr node is NULL it will cause a crash, so notify us */
+ if (node == NULL)
+ {
+ ereport(ERROR, (errmsg_internal("add_volatile_wrapper: NULL expr")));
+ }
+
oid = get_ag_func_oid("agtype_volatile_wrapper", 1, ANYOID);
return (Expr *)makeFuncExpr(oid, AGTYPEOID, list_make1(node), InvalidOid,
@@ -5581,10 +5589,10 @@
* Modified entry point for recursively analyzing a sub-statement in union.
*/
Query *cypher_parse_sub_analyze_union(cypher_clause *clause,
- cypher_parsestate *cpstate,
- CommonTableExpr *parentCTE,
- bool locked_from_parent,
- bool resolve_unknowns)
+ cypher_parsestate *cpstate,
+ CommonTableExpr *parentCTE,
+ bool locked_from_parent,
+ bool resolve_unknowns)
{
cypher_parsestate *state = make_cypher_parsestate(cpstate);
Query *query;
@@ -6079,6 +6087,21 @@
rv = makeRangeVar(cpstate->graph_name, edge->label, -1);
label_relation = parserOpenTable(&cpstate->pstate, rv, RowExclusiveLock);
+ /*
+ * TODO
+ * It is possible for a vertex label to be retrieved, instead of an edge,
+ * due to the above logic. So, we need to check if it is a vertex label.
+ * This whole section needs to be fixed because it could be a relation that
+ * isn't either and has the correct number of columns. However, for now,
+ * we just check the number of columns.
+ */
+ if (label_relation->rd_att->natts == 2) // TODO temporarily hardcoded
+ {
+ ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("Expecting edge label, found existing vertex label"),
+ parser_errposition(&cpstate->pstate, edge->location)));
+ }
+
// Store the relid
rel->relid = RelationGetRelid(label_relation);
@@ -6184,6 +6207,21 @@
rv = makeRangeVar(cpstate->graph_name, node->label, -1);
label_relation = parserOpenTable(&cpstate->pstate, rv, RowExclusiveLock);
+ /*
+ * TODO
+ * It is possible for an edge label to be retrieved, instead of a vertex,
+ * due to the above logic. So, we need to check if it is an edge label.
+ * This whole section needs to be fixed because it could be a relation that
+ * isn't either and has the correct number of columns. However, for now,
+ * we just check the number of columns.
+ */
+ if (label_relation->rd_att->natts == 4) // TODO temporarily hardcoded
+ {
+ ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("Expecting vertex label, found existing edge label"),
+ parser_errposition(&cpstate->pstate, node->location)));
+ }
+
// Store the relid
rel->relid = RelationGetRelid(label_relation);