如何使用PostgreSQL C源函数更改表以继承其他表?

lx0bsm1f  于 2023-04-29  发布在  PostgreSQL
关注(0)|答案(1)|浏览(85)

在Apache AGE源代码中,我们可以看到顶点和边可以继承多个标签。为此,它使用了create_labelcreate_table_for_label以及create_vlabelcreate_elabel(取决于它是顶点还是边)。所有这些功能都可以在here中找到。
create_vlabel有三个参数:首先是图形名称,然后是标签名称,最后是父标签数组。然后将这些父标签添加到列表中,并将名为is_inheriting的变量设置为1。
create_vlabel函数结束时,它将调用create_label函数,该函数将调用create_table_for_label。在这个例子中,它将检查父列表是否不同于零,以及is_inheriting是否等于0。如果没有进行最后一个比较(is_inheriting比较),当标签继承自多个标签时,它会抛出一个错误,指出要创建的标签表必须包含一个不同于父标签表的默认值,或者父标签表必须具有一个等于子标签表的默认值。

static void create_table_for_label(char *graph_name, char *label_name,
                                   char *schema_name, char *rel_name,
                                   char *seq_name, char label_type,
                                   List *parents, int is_inheriting)
{
    CreateStmt *create_stmt;
    PlannedStmt *wrapper;

    create_stmt = makeNode(CreateStmt);

    // relpersistence is set to RELPERSISTENCE_PERMANENT by makeRangeVar()
    create_stmt->relation = makeRangeVar(schema_name, rel_name, -1);
    
    /*
     * When a new table has parents, do not create a column definition list.
     * Use the parents' column definition list instead, via Postgres'
     * inheritance system.
     */
    if (list_length(parents) != 0 && is_inheriting == 0)
        create_stmt->tableElts = NIL;
    else if (label_type == LABEL_TYPE_EDGE)
        create_stmt->tableElts = create_edge_table_elements(
            graph_name, label_name, schema_name, rel_name, seq_name);
    else if (label_type == LABEL_TYPE_VERTEX)
        create_stmt->tableElts = create_vertex_table_elements(
            graph_name, label_name, schema_name, rel_name, seq_name);
    else
        ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR),
                        errmsg("undefined label type \'%c\'", label_type)));

    create_stmt->inhRelations = parents;
    create_stmt->partbound = NULL;
    create_stmt->ofTypename = NULL;
    create_stmt->constraints = NIL;
    create_stmt->options = NIL;
    create_stmt->oncommit = ONCOMMIT_NOOP;
    create_stmt->tablespacename = NULL;
    create_stmt->if_not_exists = false;

    wrapper = makeNode(PlannedStmt);
    wrapper->commandType = CMD_UTILITY;
    wrapper->canSetTag = false;
    wrapper->utilityStmt = (Node *)create_stmt;
    wrapper->stmt_location = -1;
    wrapper->stmt_len = 0;

    ProcessUtility(wrapper, "(generated CREATE TABLE command)",
                   PROCESS_UTILITY_SUBCOMMAND, NULL, NULL, None_Receiver,
                   NULL);
    // CommandCounterIncrement() is called in ProcessUtility()
}

继承工作正常,但输出看起来很奇怪,多次显示消息“* 合并列的多个继承定义。.. *”

SELECT create_vlabel('cypher_create', 'child_vlabel_three', ARRAY['parent_vlabel', 'child_vlabel_one', 'child_vlabel_two']);
NOTICE:  VLabel child_vlabel_three will inherit from parent_vlabel
NOTICE:  VLabel child_vlabel_three will inherit from child_vlabel_one
NOTICE:  VLabel child_vlabel_three will inherit from child_vlabel_two
NOTICE:  merging multiple inherited definitions of column "id"
NOTICE:  merging multiple inherited definitions of column "properties"
NOTICE:  merging multiple inherited definitions of column "id"
NOTICE:  merging multiple inherited definitions of column "properties"
NOTICE:  merging column "id" with inherited definition
NOTICE:  merging column "properties" with inherited definition
NOTICE:  VLabel "child_vlabel_three" has been created
 create_vlabel 
---------------
 
(1 row)

如果我可以先创建一个表,然后修改它,使它不显示这些重复的消息,我应该怎么做呢?

2nbm6dog

2nbm6dog1#

在函数定义中,需要检查父列是否已包含在列定义列表中。下面是更新后的代码

static void create_table_for_label(char *graph_name, char *label_name,
                                   char *schema_name, char *rel_name,
                                   char *seq_name, char label_type,
                                   List *parents, int is_inheriting)
{
    CreateStmt *create_stmt;
    PlannedStmt *wrapper;

    create_stmt = makeNode(CreateStmt);

    // relpersistence is set to RELPERSISTENCE_PERMANENT by makeRangeVar()
    create_stmt->relation = makeRangeVar(schema_name, rel_name, -1);
    
    /*
     * When a new table has parents, do not create a column definition list.
     * Use the parents' column definition list instead, via Postgres'
     * inheritance system.
     */
    if (list_length(parents) != 0 && is_inheriting == 0)
        create_stmt->tableElts = NIL;
    else if (label_type == LABEL_TYPE_EDGE)
        create_stmt->tableElts = create_edge_table_elements(
            graph_name, label_name, schema_name, rel_name, seq_name);
    else if (label_type == LABEL_TYPE_VERTEX)
        create_stmt->tableElts = create_vertex_table_elements(
            graph_name, label_name, schema_name, rel_name, seq_name);
    else
        ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR),
                        errmsg("undefined label type \'%c\'", label_type)));

    create_stmt->inhRelations = NIL;  // do not inherit from parents at creation
    create_stmt->partbound = NULL;
    create_stmt->ofTypename = NULL;
    create_stmt->constraints = NIL;
    create_stmt->options = NIL;
    create_stmt->oncommit = ONCOMMIT_NOOP;
    create_stmt->tablespacename = NULL;
    create_stmt->if_not_exists = false;

    wrapper = makeNode(PlannedStmt);
    wrapper->commandType = CMD_UTILITY;
    wrapper->canSetTag = false;
    wrapper->utilityStmt = (Node *)create_stmt;
    wrapper->stmt_location = -1;
    wrapper->stmt_len = 0;

    ProcessUtility(wrapper, "(generated CREATE TABLE command)",
                   PROCESS_UTILITY_SUBCOMMAND, NULL, NULL, None_Receiver,
                   NULL);

    // inherit from parent tables using ALTER TABLE command
    if (list_length(parents) != 0) {
        AlterTableStmt *alter_stmt;
        ListCell *lc;

        alter_stmt = makeNode(AlterTableStmt);
        alter_stmt->relation = create_stmt->relation;
        alter_stmt->cmds = NIL;
        foreach(lc, parents) {
            TypeName *parent_name = makeTypeNameFromNameList((List *) lfirst(lc));
            Node *parent = (Node *) parent_name;
            AlterTableCmd *inherit_cmd;

            inherit_cmd = makeNode(AlterTableCmd);
            inherit_cmd->subtype = AT_InheritPartition;
            inherit_cmd->def = (Node *) parent;

            alter_stmt->cmds = lappend(alter_stmt->cmds, inherit_cmd);
        }

        wrapper = makeNode(PlannedStmt);
        wrapper->commandType = CMD_UTILITY;
        wrapper->canSetTag = false;
        wrapper->utilityStmt = (Node *)alter_stmt;
        wrapper->stmt_location = -1;
        wrapper->stmt_len = 0;

        ProcessUtility(wrapper, "(generated ALTER TABLE command)",
                       PROCESS_UTILITY_SUBCOMMAND, NULL, NULL, None_Receiver,
                       NULL);
    }
}

相关问题