如何区分C中的Cypher子句与SQL子句?

huangapple go评论54阅读模式
英文:

How to differentiate a Cypher clause from an SQL clause in C?

问题

/* 处理 cypher 匹配命令 */
        if (pg_strncasecmp(query_buf->data, "MATCH", 5) == 0 ||
                pg_strncasecmp(query_buf->data, "OPTIONAL", 8) == 0 ||
                pg_strncasecmp(query_buf->data, "EXPLAIN", 7) == 0 ||
                pg_strncasecmp(query_buf->data, "CREATE", 6) == 0)
        {
            cypherCmdStatus = HandleCypherCmds(scan_state,
                                cond_stack,
                                query_buf,
                                previous_buf);

            success = cypherCmdStatus != PSQL_CMD_ERROR;

            if (cypherCmdStatus == PSQL_CMD_SEND)
            {
                success = SendQuery(convert_to_psql_command(query_buf->data));
            }
        }
        else
            success = SendQuery(query_buf->data);

这种方法的问题在于,例如,CREATE 可能是一个 SQL 子句或一个 Cypher 子句。此外,如果用户在子句中插入了拼写错误,比如将 "MATH" 插入为 "MATCH",那么该子句将无法到达解析器。为了解决这个问题,我正在考虑一种更好的方法来区分 Cypher 子句和 SQL 子句。在 C 语言中是否有实现这一点的方法?

英文:

I am working on adding support for Cypher clauses on Postgres psql. So far, we have added if clauses with string comparison to separate Cypher clauses from SQL clauses, with one parser for each. The HandleCypherCmds() function calls the Cypher parser, and the SendQuery() function calls the SQL parser.

/* handle cypher match command */
        if (pg_strncasecmp(query_buf->data, "MATCH", 5) == 0 ||
                pg_strncasecmp(query_buf->data, "OPTIONAL", 8) == 0 ||
                pg_strncasecmp(query_buf->data, "EXPLAIN", 7) == 0 ||
                pg_strncasecmp(query_buf->data, "CREATE", 6) == 0)
        {
            cypherCmdStatus = HandleCypherCmds(scan_state,
                                cond_stack,
                                query_buf,
                                previous_buf);

            success = cypherCmdStatus != PSQL_CMD_ERROR;

            if (cypherCmdStatus == PSQL_CMD_SEND)
            {
                success = SendQuery(convert_to_psql_command(query_buf->data));
            }
        }
        else
            success = SendQuery(query_buf->data);

The problem with this approach is that, for example, CREATE could be a SQL clause or a Cypher clause. Also, if the user inserts a typo in the clause, like "MATH" instead of "MATCH," the clause will not reach the parser. To solve this problem, I am thinking of a better way to differentiate a Cypher clause from a SQL one. Is there a way to do this in C?

答案1

得分: 1

我们已经解决了这个问题,如果有人感兴趣的话。不是在C文件中进行字符串比较,而是使用变量检查,这是从解析器文件中进行的。

无论用户输入是Cypher还是SQL查询,都将被传递到Cypher解析器中,只有在解析器返回成功的情况下才将输入作为Cypher命令发送到服务器。为了使解析器返回成功,我们已经为每个Cypher子句分配了一个布尔变量,只有当特定命令的语法规则满足时,这些变量才会被设置为true。如果没有匹配发生,这些变量将保持为false,然后解析器将返回不成功。

为了澄清,这是解析器的一部分示例:

%{
/* 包含语句 */
...
bool match = false;
bool set = false;
bool set_path = false;
bool create = false;
bool drop = false;
bool alter = false;
bool load = false;
...
%}

...

%%

statement:
    query
    | statement query
    | statement SEMICOLON { YYACCEPT; }
    ;

query:
    match_clause
    | create_clause { create = true; }
    | drop_clause { drop = true; }
    | alter_clause { alter = true; }
    | load_clause { load = true; }
    | set_clause { set = true; }
    ...
    ;

...
%%

...

bool
psql_scan_cypher_command(char* data)
{
    ...

    YY_BUFFER_STATE buf = yy_scan_string(data);
    yypush_buffer_state(buf);
    yyparse();

    if (match || optional || explain || create || drop || alter || load ||
        set || set_path || merge || rtn || unwind || prepare || execute)
        return true;

    return false;
}

...

请参考cypher.ymainloop.c文件以获取完整的参考资料。

英文:

We have solved this if anyone is interested. Instead of doing the string comparison in the C file, we have used variable checking which is done from the parser file instead.

The user input will be passed into the Cypher parser regardless if it is a Cypher or an SQL query, and only sends the input to the server as a Cypher command if the parser returns a success. For the parser to return a success, we have assigned each Cypher clause with a boolean variable which will be set to true only if the grammar rules are satisfied for the specific command entered. If no match has occurred, the variables will stay false which the parser will then return unsuccessful.

For clarification, here is a snippet of the parser:

%{
/* include statements/*
...
bool match = false;
bool set = false;
bool set_path = false;
bool create = false;
bool drop = false;
bool alter = false;
bool load = false;
...
%}

...

%%
statement:
    query
    | statement query
    | statement SEMICOLON { YYACCEPT; }
    ;

query:
    match_clause
    | create_clause { create = true; }
    | drop_clause { drop = true; }
    | alter_clause { alter = true; }
    | load_clause { load = true; }
    | set_clause { set = true; }
    ...
    ;

...
%%

...

bool
psql_scan_cypher_command(char* data)
{
    ...

    YY_BUFFER_STATE buf = yy_scan_string(data);
    yypush_buffer_state(buf);
    yyparse();

    if (match || optional || explain || create || drop || alter || load ||
        set || set_path || merge || rtn || unwind || prepare || execute)
        return true;

    return false;
}

...

Refer to the 'cypher.y' and 'mainloop.c' files for complete reference.

答案2

得分: 0

在查询中如果有任何拼写错误或错误,建议通过错误消息通知用户。这样,用户可以轻松识别并纠正查询中的任何问题。

为了区分SQL子句和Cypher子句,您可以使用一个分隔符,例如,您可以将所有Cypher查询括在名为cypher(query)BEGIN_CYPHEREND的函数中。另一种方法是使用命名约定,例如,在Cypher函数前标记Cypher函数,如下划线:_MATCH

英文:

In case of any typos or errors in the query, it is recommended to inform the user through an error message. This way, the user can easily identify and correct any issues within the query.

To differentiate between SQL clauses and Cypher clauses, you can use a delimiter, for instance, you can enclose all Cypher queries within a function called cypher(query) or BEGIN_CYPHER and END. Another way is a naming convention, such as marking Cypher functions with a prefix, like an underline: _MATCH.

答案3

得分: 0

一个方法可能很有用,如果你可以尝试编写词法分析器和/或解析器规则。

例如,你可以有词法分析器规则来匹配关键字,如 "CREATE" 或 "MATCH"。

同样地,你可以定义解析由词法分析器生成的标记的规则,并根据语法规则构建抽象语法树。

希望这些对你有帮助。

英文:

A method could be useful if you can try writing lexer and/or parser rules.

For instance, you can have lexer rules to match keywords such as "CREATE" or "MATCH".

Similarly, you can define the rules for parsing the token generated by the lexer and build an abstract syntax tree on the basis of the grammar rules.

Hope these help.

答案4

得分: 0

为了区分在您的Postgres psql项目中的Cypher子句和SQL子句,请尝试使用这种方法。<br>不要直接进行字符串比较,而是在解析器内部使用变量检查。将用户输入传递给Cypher解析器,无论类型如何,只有在解析器确认有效的语法规则后才继续作为Cypher进行。为每个Cypher子句分配布尔变量,在成功解析时将它们设置为true,否则保持为false。

英文:

To differentiate Cypher clauses from SQL ones in your Postgres psql project, try using this approach. <br>Instead of direct string comparison, utilize variable checks within the parser. Pass user input to the Cypher parser regardless of type, and only proceed as Cypher if the parser confirms valid grammar rules. Assign boolean variables to each Cypher clause, setting them true upon successful parsing, otherwise, they stay false.

答案5

得分: 0

比起基本的字符串比较,区分Cypher和SQL子句需要更可靠的方法,特别是关键字可能重叠且可能出现错误的情况。

使用词法分析器或标记器来查找输入查询中的关键字和语法组件是一种典型的策略。然后可以检查上下文来确定它是Cypher查询还是SQL查询。

希望这对你有帮助。

英文:

A more reliable approach than a basic string comparison is required to distinguish between Cypher and SQL clauses, especially when the keywords may overlap and there may be mistakes.

Using a lexer or tokenizer to find keywords and syntax components in the input query is a typical strategy. The context can then be examined to identify whether it is a Cypher or a SQL query.

Hope it is helpful.

huangapple
  • 本文由 发表于 2023年6月30日 02:56:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/76583907.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定