我正在做一个项目,在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解析器才能工作,导致了同样的错误。
我一直找不到解决这个问题的办法。有人可以帮助我实现这个功能吗?
1条答案
按热度按时间i5desfxk1#
想到的一种方法是预处理查询。您可以尝试执行一个预处理步骤,这样就可以尝试使用正则表达式或一些自定义函数来分离SQL部分和Cypher部分,而不是将整个查询发送到cypher解析器。