postgresql 尝试防止SQL子句进入密码分析器的冲突

mbyulnm0  于 2023-06-22  发布在  PostgreSQL
关注(0)|答案(1)|浏览(146)

我正在做一个项目,在Apache AGE中添加对psql上的Cypher查询的支持。目前,要使用Apache AGE创建一个图,我们需要在SQL查询中指定一个Cypher查询。例如:

SELECT * FROM cypher('graph_name', $$
MATCH (v)
RETURN v
$$) as (v agtype);

有了新的支持,我们只需要指定MATCH (v) RETURN v;就可以生成相同的结果。为了实现这一点,我们在psql mainloop.c文件中实现了HandleCypherCmds函数,特别是在PSCAN_SEMICOLON条件下。
下面是相关代码:

/*
 * Send command if semicolon found, or if end of line and we're in
 * single-line mode.
 */
if (scan_result == PSCAN_SEMICOLON ||
    (scan_result == PSCAN_EOL && pset.singleline))
{
    /*
     * Save line in history.  We use history_buf to accumulate
     * multi-line queries into a single history entry.  Note that
     * history accumulation works on input lines, so it doesn't
     * matter whether the query will be ignored due to \if.
     */
    if (pset.cur_cmd_interactive && !line_saved_in_history)
    {
        pg_append_history(line, history_buf);
        pg_send_history(history_buf);
        line_saved_in_history = true;
    }

    /* execute query unless we're in an inactive \if branch */
    if (conditional_active(cond_stack))
    {
        /* 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)
            {
                //char *qry = convert_to_psql_command(query_buf->data);
                success = SendQuery(convert_to_psql_command(query_buf->data));
            }
        }
        else
            success = SendQuery(query_buf->data);

        slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR;
        pset.stmt_lineno = 1;

        /* transfer query to previous_buf by pointer-swapping */
        {
            PQExpBuffer swap_buf = previous_buf;

            previous_buf = query_buf;
            query_buf = swap_buf;
        }
        resetPQExpBuffer(query_buf);

        added_nl_pos = -1;
        /* we need not do psql_scan_reset() here */
    }
    else
    {
        /* if interactive, warn about non-executed query */
        if (pset.cur_cmd_interactive)
            pg_log_error("query ignored; use \\endif or Ctrl-C to exit current \\if block");
        /* fake an OK result for purposes of loop checks */
        success = true;
        slashCmdStatus = PSQL_CMD_SEND;
        pset.stmt_lineno = 1;
        /* note that query_buf doesn't change state */
    }
}

目前,代码实现了临时约束以防止SQL子句进入Cypher解析器,因为这样做会产生语法错误。但是,维护这些约束并不实际,因为它们仅在用户正确编写Cypher子句时才起作用。我尝试使用解析器变量,但它需要进入Cypher解析器才能工作,导致了同样的错误。
我一直找不到解决这个问题的办法。有人可以帮助我实现这个功能吗?

i5desfxk

i5desfxk1#

想到的一种方法是预处理查询。您可以尝试执行一个预处理步骤,这样就可以尝试使用正则表达式或一些自定义函数来分离SQL部分和Cypher部分,而不是将整个查询发送到cypher解析器。

相关问题