写点什么

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

作者:daydayup
  • 2023-07-27
    北京
  • 本文字数:2530 字

    阅读完需:约 8 分钟

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;……
复制代码



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。



:创建表 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
复制代码


用户头像

daydayup

关注

还未添加个人签名 2023-07-18 加入

还未添加个人简介

评论

发布
暂无评论
openGauss内核分析(九):数据库表的创建过程_daydayup_InfoQ写作社区