openGauss内核分析(九):数据库表的创建过程

除了DML之外的所有查询都通过ProcessUtility模块来执行,包括了各类DDL语句、事务相关语句、游标相关语句等。 上层调用函数为exec_simple_query函数,其中PortalStart函数和PortalDrop函数部分较为简单。 核心函数是PortalRun函数下层调用的standard_ProcessUtility函数,该函数通过switch case语句处理了各种类型的查询语句,包括事务相关查询、游标相关查询、schema相关操作、表空间相关操作、表定义相关操作等。

standard_ProcessUtility函数会根据nodeTag(parsetree)的值来确定sql的操作类型,create table一般都是进入T_CreateStmt分支,调用CreateCommand函数。

void standard_ProcessUtility(Node* parse_tree, const char* query_string, ParamListInfo params, bool is_top_level,    DestReceiver* dest,#ifdef PGXC    bool sent_to_remote,#endif /* PGXC */    char* completion_tag,    bool isCTAS){……    errno_t errorno = EOK;switch (nodeTag(parse_tree)) { // 根据nodeTag(parsetree)的值来确定sql的操作类型……        case T_CreateStmt: { // create table#ifdef PGXC            CreateCommand((CreateStmt*)parse_tree, query_string, params, is_top_level, sent_to_remote, isCTAS);#else            CreateCommand((CreateStmt*)parse_tree, query_string, params, is_top_level, isCTAS);#endif        } break;……

d58d0794-1cde-496e-9284-7def3bab285a.png

CreateCommand函数先解析parse_tree获取stmt,如果stmt为空则表明表已经存在。如果stmt不为空对stmts进行遍历,如果是 CreateStmt就调用DefineRelation。AlterTableCreateToastTable判断是否需要创建toast表并创建,AlterCStoreCreateTables判断是否需要创建列存表并创建。

#ifdef PGXCvoid CreateCommand(CreateStmt *parse_tree, const char *query_string, ParamListInfo params,                   bool is_top_level, bool sent_to_remote, bool isCTAS)#elsevoid CreateCommand(CreateStmt *parse_tree, const char *query_string, ParamListInfo params, bool is_top_level,    bool isCTAS)#endif{……    /* Run parse analysis ... */    if (u_sess->attr.attr_sql.enable_parallel_ddl) // 先解析parse_tree获取stmt        stmts = transformCreateStmt((CreateStmt*)parse_tree, query_string, NIL, true, &namespace_id, is_first_node);    else        stmts = transformCreateStmt((CreateStmt*)parse_tree, query_string, NIL, false, &namespace_id);
    /*     * If stmts is NULL, then the table is exists.     * we need record that for searching the group of table.     */    if (stmts == NIL) { // 如果stmt为空则表明表已经存在        table_is_exist = true;……    /* ... and do it */    foreach (l, stmts) { // 遍历stmts Node* stmt = (Node*)lfirst(l);
        if (IsA(stmt, CreateStmt)) {  // 如果是 CreateStmt就调用DefineRelation            Datum toast_options; static const char* const validnsps[] = HEAP_RELOPT_NAMESPACES;                       /* forbid user to set or change inner options */ ForbidOutUsersToSetInnerOptions(((CreateStmt*)stmt)->options);                        /* Create the table itself */            rel_oid = DefineRelation((CreateStmt*)stmt,                                    ((CreateStmt*)stmt)->relkind == RELKIND_MATVIEW ?                                                                    RELKIND_MATVIEW : RELKIND_RELATION,                                                                                                        InvalidOid, isCTAS);……            AlterTableCreateToastTable(rel_oid, toast_options, AccessShareLock);            AlterCStoreCreateTables(rel_oid, toast_options, (CreateStmt*)stmt);            AlterDfsCreateTables(rel_oid, toast_options, (CreateStmt*)stmt);            AlterCreateChainTables(rel_oid, toast_options, (CreateStmt *)stmt);……

DefineRelation函数获取到表名relname、名字空间relnamespace、表空间reltablespace、表类型relkind和relpersistence等信息后调用heap_create_with_catalog创建relation。

(gdb) f 0#0  heap_create_with_catalog (relname=0x7fb4fa872140 "t100", relnamespace=2200, reltablespace=0, relid=0, reltypeid=0,    reloftypeid=0, ownerid=10, tupdesc=0x7fb4ff2e2e50, cooked_constraints=0x0, relkind=114 'r', relpersistence=112 'p',    shared_relation=false, mapped_relation=false, oidislocal=false, oidinhcount=0, oncommit=ONCOMMIT_NOOP,    reloptions=140415352057720, use_user_acl=true, allow_system_table_mods=false, partTableState=0x0, row_compress=1 '\001',    bucketinfo=0x0, record_dependce=true, ceLst=0x0, storage_type=HEAP_DISK, partLockMode=1) at heap.cpp:2521

其中heap_create内部首先调用了RelationBuildLocalRelation创建RelationData,并加入到relCache,RelationData表示一个表的元信息,这些信息都可以由系统表元组中的信息构造得到。然后根据这些信息通过调用RelalionCreateStorage函数创建物理文件。heap_create_with_catalog主要完成表物理文件的创建和表元信息注册到系统表中,涉及系统包包括pg_class,pg_attribute,pg_depend,pg_object,pg_type,pg_index和pg_partition

27a08fd0-b2d5-45fa-af95-3670e6e9efab.png

创建表create table的函数调用栈

#0  RelationCreateStorage#1  heap_create#2  heap_create_with_catalog#3  DefineRelation#4  CreateCommand#5  standard_ProcessUtility#6  gsaudit_ProcessUtility_hook#7  pgaudit_ProcessUtility#8  hypo_utility_hook#9  ProcessUtility#10 PortalRunUtility#11 PortalRunMulti#12 PortalRun#13 exec_simple_query#14 PostgresMain


欢迎访问openGauss官方网站

e8b82395-ff9f-4432-8b02-dfb4c1db11f7.png

openGauss开源社区官方网站:

https://opengauss.org

openGauss组织仓库:

https://gitee.com/opengauss

openGauss镜像仓库:

https://github.com/opengauss-mirror

e03dab8f-2a95-4b7f-bcf0-1a250c6123b1.png

扫码关注我们

微信公众号|openGauss

微信社群小助手|openGauss-bot

本文分享自微信公众号 - openGauss(openGauss)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“ OSC源创计划 ”,欢迎正在阅读的你也加入,一起分享。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

openGauss社区

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值