diff --git a/regress/expected/expr.out b/regress/expected/expr.out index 30d66793c..476a0d841 100644 --- a/regress/expected/expr.out +++ b/regress/expected/expr.out @@ -7304,6 +7304,152 @@ SELECT results, pg_typeof(user) FROM cypher('issue_1124', $$ MATCH (u) RETURN u {"id": 281474976710657, "label": "", "properties": {}}::vertex | name (1 row) +-- +-- issue 1303: segmentation fault on queries like SELECT * FROM agtype(null); +-- +-- Test Const and CoerceViaIO expression node types +SELECT * FROM agtype(null); + agtype +-------- + +(1 row) + +SELECT * FROM agtype('1'); + agtype +-------- + 1 +(1 row) + +SELECT * FROM agtype('[1, 2, 3]'); + agtype +----------- + [1, 2, 3] +(1 row) + +SELECT * FROM agtype('{"a": 1}'); + agtype +---------- + {"a": 1} +(1 row) + +SELECT * FROM agtype('{"id": 844424930131971, "label": "v", "properties": {"i": 1}}::vertex'); + agtype +----------------------------------------------------------------------- + {"id": 844424930131971, "label": "v", "properties": {"i": 1}}::vertex +(1 row) + +SELECT * FROM agtype('{"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge'); + agtype +--------------------------------------------------------------------------------------------------------------------------- + {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge +(1 row) + +SELECT * FROM agtype('[{"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex, {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge, {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex, {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge, {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex]::path'); + agtype +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + [{"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex, {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge, {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex, {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge, {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex]::path +(1 row) + +SELECT * FROM text(1); + text +------ + 1 +(1 row) + +SELECT * FROM text('1'); + text +------ + 1 +(1 row) + +SELECT * FROM int4(1); + int4 +------ + 1 +(1 row) + +SELECT * FROM json('1'); + json +------ + 1 +(1 row) + +SELECT * FROM jsonb('1'); + jsonb +------- + 1 +(1 row) + +SELECT * FROM bytea('1'); + bytea +------- + \x31 +(1 row) + +-- Test Var expression node types +SELECT create_graph('issue_1303'); +NOTICE: graph "issue_1303" has been created + create_graph +-------------- + +(1 row) + +SELECT result, agtype('[1, 2, 3]') FROM cypher('issue_1303', $$ CREATE (u) RETURN u $$) AS (result agtype); + result | agtype +----------------------------------------------------------------+----------- + {"id": 281474976710657, "label": "", "properties": {}}::vertex | [1, 2, 3] +(1 row) + +SELECT result, result2, pg_typeof(result2) FROM cypher('issue_1303', $$ MATCH (u) RETURN u $$) AS (result agtype), agtype('[1, 2, 3]') AS result2; + result | result2 | pg_typeof +----------------------------------------------------------------+-----------+----------- + {"id": 281474976710657, "label": "", "properties": {}}::vertex | [1, 2, 3] | agtype +(1 row) + +SELECT result, result2, pg_typeof(result2) FROM cypher('issue_1303', $$ MATCH (u) RETURN u $$) AS (result agtype), text(1) AS result2; + result | result2 | pg_typeof +----------------------------------------------------------------+---------+----------- + {"id": 281474976710657, "label": "", "properties": {}}::vertex | 1 | text +(1 row) + +SELECT result, result2, pg_typeof(result2), result3, pg_typeof(result3) FROM cypher('issue_1303', $$ MATCH (u) RETURN u $$) AS (result agtype), text(1) AS result2, agtype(result) AS result3; + result | result2 | pg_typeof | result3 | pg_typeof +----------------------------------------------------------------+---------+-----------+----------------------------------------------------------------+----------- + {"id": 281474976710657, "label": "", "properties": {}}::vertex | 1 | text | {"id": 281474976710657, "label": "", "properties": {}}::vertex | agtype +(1 row) + +SELECT result, result2, pg_typeof(result2), result3, pg_typeof(result3) FROM cypher('issue_1303', $$ MATCH (u) RETURN u $$) AS (result agtype), text(1) AS result2, agtype(result2) AS result3; + result | result2 | pg_typeof | result3 | pg_typeof +----------------------------------------------------------------+---------+-----------+---------+----------- + {"id": 281474976710657, "label": "", "properties": {}}::vertex | 1 | text | 1 | agtype +(1 row) + +-- Text OpExpr expression node types +SELECT * FROM agtype('[1, 2, 3]'::agtype || '[5, 6, 7]'); + agtype +-------------------- + [1, 2, 3, 5, 6, 7] +(1 row) + +SELECT * FROM agtype('[1, 2, 3]'::agtype -> 2); + agtype +-------- + 3 +(1 row) + +SELECT * FROM agtype('{"a": 1, "b": 2}'::agtype -> 'a'::text); + agtype +-------- + 1 +(1 row) + +-- Text BoolExpr expression node types +SELECT * FROM bool(true AND false); + bool +------ + f +(1 row) + -- -- Cleanup -- @@ -7317,6 +7463,16 @@ NOTICE: graph "issue_1124" has been dropped (1 row) +SELECT * FROM drop_graph('issue_1303', true); +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to table issue_1303._ag_label_vertex +drop cascades to table issue_1303._ag_label_edge +NOTICE: graph "issue_1303" has been dropped + drop_graph +------------ + +(1 row) + SELECT * FROM drop_graph('graph_395', true); NOTICE: drop cascades to 7 other objects DETAIL: drop cascades to table graph_395._ag_label_vertex diff --git a/regress/sql/expr.sql b/regress/sql/expr.sql index 13d1ca3c3..bf9ffc948 100644 --- a/regress/sql/expr.sql +++ b/regress/sql/expr.sql @@ -2986,10 +2986,47 @@ SELECT * FROM create_graph('issue_1124'); SELECT results, pg_typeof(user) FROM cypher('issue_1124', $$ CREATE (u) RETURN u $$) AS (results agtype), user; SELECT results, pg_typeof(user) FROM cypher('issue_1124', $$ MATCH (u) RETURN u $$) AS (results agtype), user; +-- +-- issue 1303: segmentation fault on queries like SELECT * FROM agtype(null); +-- + +-- Test Const and CoerceViaIO expression node types +SELECT * FROM agtype(null); +SELECT * FROM agtype('1'); +SELECT * FROM agtype('[1, 2, 3]'); +SELECT * FROM agtype('{"a": 1}'); +SELECT * FROM agtype('{"id": 844424930131971, "label": "v", "properties": {"i": 1}}::vertex'); +SELECT * FROM agtype('{"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge'); +SELECT * FROM agtype('[{"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex, {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge, {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex, {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge, {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex]::path'); + +SELECT * FROM text(1); +SELECT * FROM text('1'); +SELECT * FROM int4(1); +SELECT * FROM json('1'); +SELECT * FROM jsonb('1'); +SELECT * FROM bytea('1'); + +-- Test Var expression node types +SELECT create_graph('issue_1303'); +SELECT result, agtype('[1, 2, 3]') FROM cypher('issue_1303', $$ CREATE (u) RETURN u $$) AS (result agtype); +SELECT result, result2, pg_typeof(result2) FROM cypher('issue_1303', $$ MATCH (u) RETURN u $$) AS (result agtype), agtype('[1, 2, 3]') AS result2; +SELECT result, result2, pg_typeof(result2) FROM cypher('issue_1303', $$ MATCH (u) RETURN u $$) AS (result agtype), text(1) AS result2; +SELECT result, result2, pg_typeof(result2), result3, pg_typeof(result3) FROM cypher('issue_1303', $$ MATCH (u) RETURN u $$) AS (result agtype), text(1) AS result2, agtype(result) AS result3; +SELECT result, result2, pg_typeof(result2), result3, pg_typeof(result3) FROM cypher('issue_1303', $$ MATCH (u) RETURN u $$) AS (result agtype), text(1) AS result2, agtype(result2) AS result3; + +-- Text OpExpr expression node types +SELECT * FROM agtype('[1, 2, 3]'::agtype || '[5, 6, 7]'); +SELECT * FROM agtype('[1, 2, 3]'::agtype -> 2); +SELECT * FROM agtype('{"a": 1, "b": 2}'::agtype -> 'a'::text); + +-- Text BoolExpr expression node types +SELECT * FROM bool(true AND false); + -- -- Cleanup -- SELECT * FROM drop_graph('issue_1124', true); +SELECT * FROM drop_graph('issue_1303', true); SELECT * FROM drop_graph('graph_395', true); SELECT * FROM drop_graph('chained', true); SELECT * FROM drop_graph('VLE', true); diff --git a/src/backend/parser/cypher_analyze.c b/src/backend/parser/cypher_analyze.c index a481b3158..64725a23f 100644 --- a/src/backend/parser/cypher_analyze.c +++ b/src/backend/parser/cypher_analyze.c @@ -171,13 +171,20 @@ static bool convert_cypher_walker(Node *node, ParseState *pstate) * From PG - * SQLValueFunction - parameterless functions with special grammar * productions. + * CoerceViaIO - represents a type coercion between two types whose textual + * representations are compatible + * Var - expression node representing a variable (ie, a table column) + * OpExpr - expression node for an operator invocation + * Const - constant value or expression node + * BoolExpr - expression node for the basic Boolean operators AND, OR, NOT * * These are a special case that needs to be ignored. * - * TODO: This likely needs to be done with XmlExpr types, and maybe - * a few others too. */ - if (IsA(funcexpr, SQLValueFunction)) + if (IsA(funcexpr, SQLValueFunction) + || IsA(funcexpr, CoerceViaIO) + || IsA(funcexpr, Var) || IsA(funcexpr, OpExpr) + || IsA(funcexpr, Const) || IsA(funcexpr, BoolExpr)) { return false; } @@ -315,13 +322,20 @@ static bool is_func_cypher(FuncExpr *funcexpr) * From PG - * SQLValueFunction - parameterless functions with special grammar * productions. + * CoerceViaIO - represents a type coercion between two types whose textual + * representations are compatible + * Var - expression node representing a variable (ie, a table column) + * OpExpr - expression node for an operator invocation + * Const - constant value or expression node + * BoolExpr - expression node for the basic Boolean operators AND, OR, NOT * * These are a special case that needs to be ignored. * - * TODO: This likely needs to be done with XmlExpr types, and maybe - * a few others too. */ - if (IsA(funcexpr, SQLValueFunction)) + if (IsA(funcexpr, SQLValueFunction) + || IsA(funcexpr, CoerceViaIO) + || IsA(funcexpr, Var) || IsA(funcexpr, OpExpr) + || IsA(funcexpr, Const) || IsA(funcexpr, BoolExpr)) { return false; }