在年龄密码中创建的引擎盖下
#postgres #database #graphdb #apacheage

你好

问候,继续 Apache Age 的一系列,最后一篇文章是 pright>介绍 to < strong> create_graph 是我们要使用的任何 groph 的第一个条目强>在该图内,因此我们需要了解Create
的引擎盖下的内容 在进行此之前,我想推荐以下文章 good 了解

概述

Apache Age是一个通过PostgreSQL启用的扩展的性质在PostgreSQL顶部扩展的一层,其中之一是在PostgreSQL解析阶段后执行的,我们从Parser和Parse Tree中从Parser和Query Tree中进行了查询树。分析仪和重新编写的阶段,因此在查询树级别执行Apache Age,它需要查询树并返回调查的查询树,

那是什么调整?

从年龄的一侧开始解析查询并在查询树上查找每个函数调用一旦找到函数调用,它就会检查它是否是cypher,如果它是Cypher,它将开始将其转换为子查询

我们今天的使命正在通过创建声明,并知道在年龄的转换阶段将其转换为同等的子问题是什么。

让我们开始吧

首先研究转换cypher_clauess的函数,该功能负责


Query *transform_cypher_clause(cypher_parsestate *cpstate,
                               cypher_clause *clause)

将被解析为Cypher节点并在其类型上转换每个节点后,查看了Cypher从句,
我们正在寻找的类型是创建的,因此在我们具有该功能的某个时刻

    else if (is_ag_node(self, cypher_create))
    {
        result = transform_cypher_create(cpstate, clause);
    }

那是我们的目标是学习transform_cypher_create中正在发生的事情

潜入那个


static Query *transform_cypher_create(cypher_parsestate *cpstate,
                                      cypher_clause *clause)
{
    ParseState *pstate = (ParseState *)cpstate;
    cypher_create *self = (cypher_create *)clause->self;
    cypher_create_target_nodes *target_nodes;
    Const *null_const;
    List *transformed_pattern;
    FuncExpr *func_expr;
    Query *query;
    TargetEntry *tle;

    target_nodes = make_ag_node(cypher_create_target_nodes);
    target_nodes->flags = CYPHER_CLAUSE_FLAG_NONE;
    target_nodes->graph_oid = cpstate->graph_oid;

    query = makeNode(Query);
    query->commandType = CMD_SELECT;
    query->targetList = NIL;

    if (clause->prev)
    {
        handle_prev_clause(cpstate, query, clause->prev, true);

        target_nodes->flags |= CYPHER_CLAUSE_FLAG_PREVIOUS_CLAUSE;
    }

    null_const = makeNullConst(AGTYPEOID, -1, InvalidOid);
    tle = makeTargetEntry((Expr *)null_const, pstate->p_next_resno++,
                          AGE_VARNAME_CREATE_NULL_VALUE, false);
    query->targetList = lappend(query->targetList, tle);

    /*
     * Create the Const Node to hold the pattern. skip the parse node,
     * because we would not be able to control how our pointer to the
     * internal type is copied.
     */
    transformed_pattern = transform_cypher_create_pattern(cpstate, query,
                                                          self->pattern);

    target_nodes->paths = transformed_pattern;
    if (!clause->next)
    {
        target_nodes->flags |= CYPHER_CLAUSE_FLAG_TERMINAL;
    }


    func_expr = make_clause_func_expr(CREATE_CLAUSE_FUNCTION_NAME,
                                      (Node *)target_nodes);

    // Create the target entry
    tle = makeTargetEntry((Expr *)func_expr, pstate->p_next_resno++,
                          AGE_VARNAME_CREATE_CLAUSE, false);
    query->targetList = lappend(query->targetList, tle);

    query->rtable = pstate->p_rtable;
    query->rteperminfos = pstate->p_rteperminfos;
    query->jointree = makeFromExpr(pstate->p_joinlist, NULL);

    return query;
}

功能故障

  • 使用DEFINE_NODE_METHODS(cypher_create_target_nodes)通过DEFINE_NODE_METHODS(cypher_create_target_nodes)扩展了postgresql的节点 cypher_create如下:
typedef struct cypher_create_target_nodes
{
    ExtensibleNode extensible;
    List *paths;
    uint32 flags;
    uint32 graph_oid;
} cypher_create_target_nodes;

,我们可以说我们有一个类型的cypher_create节点,将其附加到postgresql节点上,我们可以从该类型中获得一个节点

  • 将目标节点的图形类图形插图分配给射层的图形类图,并将标志nullptr

  • nullptr。
  • 制作CMD类型的查询节点,用于处理先前的子句

    query = makeNode(Query);
    query->commandType = CMD_SELECT;
    query->targetList = NIL;

    if (clause->prev)
    {
        handle_prev_clause(cpstate, query, clause->prev, true);

        target_nodes->flags |= CYPHER_CLAUSE_FLAG_PREVIOUS_CLAUSE;
    }
  • 创建const节点保存模式。跳过解析节点,因为我们将无法控制如何复制到内部类型的指针。 [来自代码注释]
    transformed_pattern = transform_cypher_create_pattern(cpstate, query, self->pattern);

target_nodes->paths = transformed_pattern;
    if (!clause->next)
    {
        target_nodes->flags |= CYPHER_CLAUSE_FLAG_TERMINAL;
    }
  • 创建代表子句的函数表达式。添加代表子句在执行阶段处理子句需要的元数据的可扩展节点。 [来自代码注释],这意味着我们将其转换为最终查询中代表它的中间函数表达式
  func_expr = make_clause_func_expr(CREATE_CLAUSE_FUNCTION_NAME,
                                      (Node *)target_nodes);

    // Create the target entry
    tle = makeTargetEntry((Expr *)func_expr, pstate->p_next_resno++,
                          AGE_VARNAME_CREATE_CLAUSE, false);
    query->targetList = lappend(query->targetList, tle);
  • 完成查询并返回
    query->rtable = pstate->p_rtable;
    query->rteperminfos = pstate->p_rteperminfos;
    query->jointree = makeFromExpr(pstate->p_joinlist, NULL);

    return query;

所有功能都在那里:

参考和资源