age icon indicating copy to clipboard operation
age copied to clipboard

How to handle the param if there're single quotes in it?

Open noahxzhu opened this issue 10 months ago • 22 comments

Describe the bug An error is observed when a property parameter includes a single quote.

How are you accessing AGE (Command line, driver, etc.)?

  • I'm using the apache-age-python package in a python project.

What data setup do we need to do?

def upsert_triplet_test(subj: str, rel: str, obj: str) -> None:
    prepared_statement = f"""
        MERGE (n1:`Entity` {{id: %s}})
        MERGE (n2:`Entity` {{id: %s}})
        MERGE (n1)-[:`{rel.replace(" ", "_").upper()}`]->(n2)
    """

    ag.execCypher(
        prepared_statement,
        params=(
            subj,
            obj,
        ),
    )

    ag.commit()


upsert_triplet_test(
    "I", "Learned", "It's better for technology companies to be run by product people"
)

This is the error

    cursor.execute(stmt)
psycopg2.errors.SyntaxError: syntax error at or near "'s better for technology companies to be run by product people'"

What is the necessary configuration info needed?

  • nothing

What is the command that caused the error?

SELECT * from ag_catalog.cypher('graph_store', $$
     MERGE (n1:`Entity` {id: 'I'})
     MERGE (n2:`Entity` {id: 'It's better for technology companies to be run by product people'})
     MERGE (n1)-[:`Learned`]->(n2)
$$) as (a ag_catalog.agtype);

Not sure how to handle this case

ERROR:  syntax error at or near "s"
LINE 3:      MERGE (n2:`Entity` {id: 'It's better for technology com...

Expected behavior This merge operation should be succeed.

Environment (please complete the following information):

  • Version: package version 0.0.7
  • AGE Version: 1.5.0

Additional context no

noahxzhu avatar Apr 05 '24 12:04 noahxzhu

When I use Neo4j, I can create like this, the edge label can also include single quote CleanShot 2024-04-05 at 21 59 12@2x

MERGE (n1:`TEST`{id: 'a\'bb'})
MERGE (n2:`TEST`{id: 'bb \'s abc'})
MERGE (n1)-[:`ABC_I'S_a`]->(n2)

noahxzhu avatar Apr 05 '24 14:04 noahxzhu

@noahxzhu Did you try using the backslash for the cypher query? Your example above doesn't show it.

psql-16.1-5432-pgsql=# SELECT * from ag_catalog.cypher('test', $$
     MERGE (n1:`Entity` {id: 'I'})
     MERGE (n2:`Entity` {id: 'It\'s better for technology companies to be run by product people'})
     MERGE (n1)-[:`Learned`]->(n2)
$$) as (a ag_catalog.agtype);
 a
---
(0 rows)

psql-16.1-5432-pgsql=# SELECT * FROM cypher('test', $$ MATCH (v) RETURN v $$) AS (v agtype);
                                                                      v

------------------------------------------------------------------------------------------------------------------------------------
----------
 {"id": 844424930131969, "label": "Entity", "properties": {"id": "I"}}::vertex
 {"id": 844424930131970, "label": "Entity", "properties": {"id": "It's better for technology companies to be run by product people"}
}::vertex
(2 rows)

psql-16.1-5432-pgsql=#

jrgemignani avatar Apr 05 '24 15:04 jrgemignani

@noahxzhu Additionally, this sounds more like a question than a bug.

jrgemignani avatar Apr 05 '24 15:04 jrgemignani

Can you put double quotes around the string?

SELECT * from ag_catalog.cypher('graph_store', $$
     MERGE (n1:`Entity` {id: 'I'})
     MERGE (n2:`Entity` {id: "It's better for technology companies to be run by product people"})
     MERGE (n1)-[:`Learned`]->(n2)
$$) as (a ag_catalog.agtype);

This worked for me alright

markgomer avatar Apr 05 '24 15:04 markgomer

Can you put double quotes around the string?

SELECT * from ag_catalog.cypher('graph_store', $$
     MERGE (n1:`Entity` {id: 'I'})
     MERGE (n2:`Entity` {id: "It's better for technology companies to be run by product people"})
     MERGE (n1)-[:`Learned`]->(n2)
$$) as (a ag_catalog.agtype);

This worked for me alright

@markgomer I just copy and paste yours, it seems not work

CleanShot 2024-04-05 at 23 46 19@2x

noahxzhu avatar Apr 05 '24 15:04 noahxzhu

@noahxzhu Did you try using the backslash for the cypher query? Your example above doesn't show it.

psql-16.1-5432-pgsql=# SELECT * from ag_catalog.cypher('test', $$
     MERGE (n1:`Entity` {id: 'I'})
     MERGE (n2:`Entity` {id: 'It\'s better for technology companies to be run by product people'})
     MERGE (n1)-[:`Learned`]->(n2)
$$) as (a ag_catalog.agtype);
 a
---
(0 rows)

psql-16.1-5432-pgsql=# SELECT * FROM cypher('test', $$ MATCH (v) RETURN v $$) AS (v agtype);
                                                                      v

------------------------------------------------------------------------------------------------------------------------------------
----------
 {"id": 844424930131969, "label": "Entity", "properties": {"id": "I"}}::vertex
 {"id": 844424930131970, "label": "Entity", "properties": {"id": "It's better for technology companies to be run by product people"}
}::vertex
(2 rows)

psql-16.1-5432-pgsql=#

@jrgemignani not work on my side, I need to investigate the reason CleanShot 2024-04-05 at 23 51 52@2x

noahxzhu avatar Apr 05 '24 15:04 noahxzhu

Can you put double quotes around the string?

SELECT * from ag_catalog.cypher('graph_store', $$
     MERGE (n1:`Entity` {id: 'I'})
     MERGE (n2:`Entity` {id: "It's better for technology companies to be run by product people"})
     MERGE (n1)-[:`Learned`]->(n2)
$$) as (a ag_catalog.agtype);

This worked for me alright

@markgomer I just copy and paste yours, it seems not work

CleanShot 2024-04-05 at 23 46 19@2x

Try setting the search_path:

SET search_path TO ag_catalog;

I'm not sure why it is not working without this, though.

markgomer avatar Apr 05 '24 16:04 markgomer

Can you put double quotes around the string?

SELECT * from ag_catalog.cypher('graph_store', $$
     MERGE (n1:`Entity` {id: 'I'})
     MERGE (n2:`Entity` {id: "It's better for technology companies to be run by product people"})
     MERGE (n1)-[:`Learned`]->(n2)
$$) as (a ag_catalog.agtype);

This worked for me alright

@markgomer I just copy and paste yours, it seems not work CleanShot 2024-04-05 at 23 46 19@2x

Try setting the search_path:

SET search_path TO ag_catalog;

I'm not sure why it is not working without this, though.

After setting the search_path, now it's working, but why?

noahxzhu avatar Apr 05 '24 16:04 noahxzhu

Another question, should this work as it in Neo4j?

SELECT * from ag_catalog.cypher('graph_store', $$
	MERGE (n1:`TEST`{id: 'a\'bb'})
	MERGE (n2:`TEST`{id: 'bb \'s abc'})
	MERGE (n1)-[:`ABC_I'S_a`]->(n2)
$$) as (a ag_catalog.agtype);

noahxzhu avatar Apr 05 '24 16:04 noahxzhu

I still have the problem with the python driver, how to handle it with a param which contains single quotes, I digged into the python code, it do set the search_path, but not works CleanShot 2024-04-06 at 00 16 39@2x

noahxzhu avatar Apr 05 '24 16:04 noahxzhu

@noahxzhu

After setting the search_path, now it's working, but why?

The search path is needed to see Cypher

jrgemignani avatar Apr 05 '24 16:04 jrgemignani

Another question, should this work as it in Neo4j?

SELECT * from ag_catalog.cypher('graph_store', $$
	MERGE (n1:`TEST`{id: 'a\'bb'})
	MERGE (n2:`TEST`{id: 'bb \'s abc'})
	MERGE (n1)-[:`ABC_I'S_a`]->(n2)
$$) as (a ag_catalog.agtype);

I'm not sure I understand what you are asking. Also, keep in mind that you will likely need to backslash all non wrapping quote characters.

jrgemignani avatar Apr 05 '24 16:04 jrgemignani

Another question, should this work as it in Neo4j?

SELECT * from ag_catalog.cypher('graph_store', $$
	MERGE (n1:`TEST`{id: 'a\'bb'})
	MERGE (n2:`TEST`{id: 'bb \'s abc'})
	MERGE (n1)-[:`ABC_I'S_a`]->(n2)
$$) as (a ag_catalog.agtype);

I'm not sure I understand what you are asking. Also, keep in mind that you will likely need to backslash all non wrapping quote characters.

I mean, that query works in Neo4j, but I tried it in pg, it doesn't work. Can a label include quotes?

SELECT * from cypher('graph_store', $$
	MERGE (n1:`TEST`{id: 'a\'bb'})
	MERGE (n2:`TEST`{id: 'bb \'s abc'})
	MERGE (n1)-[:`ABC_IS\'_a`]->(n2)
$$) as (a agtype);

noahxzhu avatar Apr 05 '24 17:04 noahxzhu

The behavior in the python driver

NOT WORK

    prepared_statement = """
        MERGE (n1:`TEST` {id: 'a\'bb'})
        MERGE (n2:`TEST` {id: 'bb\'s abc'})
        MERGE (n1)-[:`ABC_IS_a`]->(n2)
    """

    ag.execCypher(
        prepared_statement,
    )

WORK

    prepared_statement = """
        MERGE (n1:`TEST` {id: "a'bb"})
        MERGE (n2:`TEST` {id: "bb's abc"})
        MERGE (n1)-[:`ABC_IS_a`]->(n2)
    """

    ag.execCypher(
        prepared_statement,
    )

NOT WORK

    prepared_statement = """
        MERGE (n1:`TEST` {id: 'a"bb'})
        MERGE (n2:`TEST` {id: 'bb"s abc'})
        MERGE (n1)-[:`ABC_IS_a`]->(n2)
    """

    ag.execCypher(
        prepared_statement,
    )

NOT WORK

    prepared_statement = """
        MERGE (n1:`TEST` {id: 'a\"bb'})
        MERGE (n2:`TEST` {id: 'bb\"s abc'})
        MERGE (n1)-[:`ABC_IS_a`]->(n2)
    """

    ag.execCypher(
        prepared_statement,
    )

noahxzhu avatar Apr 05 '24 17:04 noahxzhu

I mean, that query works in Neo4j, but I tried it in pg, it doesn't work. Can a label include quotes?

SELECT * from cypher('graph_store', $$
	MERGE (n1:`TEST`{id: 'a\'bb'})
	MERGE (n2:`TEST`{id: 'bb \'s abc'})
	MERGE (n1)-[:`ABC_IS\'_a`]->(n2)
$$) as (a agtype);

I tested this on AGE-viewer and it seems to be working... what is the error message you're getting?

markgomer avatar Apr 05 '24 18:04 markgomer

I mean, that query works in Neo4j, but I tried it in pg, it doesn't work. Can a label include quotes?

SELECT * from cypher('graph_store', $$
	MERGE (n1:`TEST`{id: 'a\'bb'})
	MERGE (n2:`TEST`{id: 'bb \'s abc'})
	MERGE (n1)-[:`ABC_IS\'_a`]->(n2)
$$) as (a agtype);

I tested this on AGE-viewer and it seems to be working... what is the error message you're getting?

@markgomer Thank you for your reply it shows label name is invalid CleanShot 2024-04-06 at 02 22 14@2x

the same on age-viewer CleanShot 2024-04-06 at 02 38 41@2x

noahxzhu avatar Apr 05 '24 18:04 noahxzhu

I had the same error showing up, but I worked around it by creating labels separately:

SELECT create_vlabel('graph_store', 'TEST');
SELECT create_elabel('graph_store', 'ABC_IS\'a');

Please check if this works for you

markgomer avatar Apr 05 '24 18:04 markgomer

I had the same error showing up, but I worked around it by creating labels separately:

SELECT create_vlabel('graph_store', 'TEST');
SELECT create_elabel('graph_store', 'ABC_IS\'a');

Please check if this works for you

unfortunately, it doesn't work on my side.

CleanShot 2024-04-06 at 13 32 26@2x

noahxzhu avatar Apr 06 '24 05:04 noahxzhu

I did some tests with the python driver, the behavior likes below

Case 1

def test(p: str):
    prepared_statement = """
        MERGE (n1:`TEST` {id: %s})
    """

    ag.execCypher(prepared_statement, params=(p,))
    ag.commit()


test("a's")

GOT

psycopg2.errors.SyntaxError: syntax error at or near "'s'"
LINE 1: SELECT * from cypher(NULL,NULL) as (v agtype);

Case 2

def test(p: str):
    prepared_statement = """
        MERGE (n1:`TEST` {id: %s})
    """

    ag.execCypher(prepared_statement, params=(p,))
    ag.commit()


test('a"s')

GOT

psycopg2.errors.SyntaxError: unexpected character at or near "\"
LINE 1: SELECT * from cypher(NULL,NULL) as (v agtype);

Case 3

I think we shouldn't add quotes for the params in the query template, right?

def test(p: str):
    prepared_statement = """
        MERGE (n1:`TEST` {id: '%s'})
    """

    ag.execCypher(prepared_statement, params=(p,))
    ag.commit()


test('a"s')

GOT

psycopg2.errors.SyntaxError: unexpected character at or near "\"
LINE 1: SELECT * from cypher(NULL,NULL) as (v agtype);

Case 4

def test(p: str):
    prepared_statement = """
        MERGE (n1:`TEST` {id: '%s'})
    """

    ag.execCypher(prepared_statement, params=(p,))
    ag.commit()


test("a's")

GOT

psycopg2.errors.SyntaxError: syntax error at or near "a"
LINE 1: SELECT * from cypher(NULL,NULL) as (v agtype);

Case 5

def test(p: str):
    prepared_statement = """
        MERGE (n1:`TEST` {id: "%s"})
    """

    ag.execCypher(prepared_statement, params=(p,))
    ag.commit()


test("a's")

GOT Succeed but the data like this

{"id": "'a''s'"}

CleanShot 2024-04-06 at 18 11 00@2x

Case 6

def test(p: str):
    prepared_statement = """
        MERGE (n1:`TEST` {id: "%s"})
    """

    ag.execCypher(prepared_statement, params=(p,))
    ag.commit()


test('a"s')

GOT

psycopg2.errors.SyntaxError: syntax error at or near "s"
LINE 1: SELECT * from cypher(NULL,NULL) as (v agtype);

noahxzhu avatar Apr 06 '24 10:04 noahxzhu

It appears that the upsert_triplet_test function's object parameter contains a single quotation, which is causing the error. 'Technology busin be run by product people' is one of the syntactic errors that the warning particularly addresses. This is probably because the Cypher query contains a syntax mistake because the single quote in the string is being read as the end of the string.

To handle this case, you can escape the single quote within the object parameter. In Python, you can escape a single quote by using another single quote. Here's how you can modify your function call to handle the single quote in the object parameter:

upsert_triplet_test(
    "I", "Learned", "It''s better for technology companies to be run by product people"
)

By replacing the single quote with two single quotes (''), you escape the single quote within the string, ensuring that it is interpreted correctly in the Cypher query.

Your modified Cypher query should look like this:

SELECT * FROM ag_catalog.cypher('graph_store', $$
    MERGE (n1:`Entity` {id: 'I'})
    MERGE (n2:`Entity` {id: 'It''s better for technology companies to be run by product people'})
    MERGE (n1)-[:`Learned`]->(n2)
$$) AS (a ag_catalog.agtype);

mannas006 avatar Apr 12 '24 14:04 mannas006

Hi @mannas006 I just tried, it seems this doesn't work for me

<class 'psycopg2.errors.SyntaxError'> syntax error at or near "'s better for technology companies to be run by product people'"
LINE 4:     MERGE (n2:`Entity` {id: 'It''s better for technology com...

noahxzhu avatar Apr 12 '24 14:04 noahxzhu

Hello @noahxzhu Thank you for informing me.

mannas006 avatar Apr 12 '24 14:04 mannas006

This issue is stale because it has been open 60 days with no activity. Remove "Abondoned" label or comment or this will be closed in 14 days.

github-actions[bot] avatar Jun 12 '24 00:06 github-actions[bot]

This issue was closed because it has been stalled for further 14 days with no activity.

github-actions[bot] avatar Jun 26 '24 00:06 github-actions[bot]