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 PGXCbool 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 PGXCCreateCommand((CreateStmt*)parse_tree, query_string, params, is_top_level, sent_to_remote, isCTAS);#elseCreateCommand((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获取stmtstmts = transformCreateStmt((CreateStmt*)parse_tree, query_string, NIL, true, &namespace_id, is_first_node);elsestmts = 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) { // 遍历stmtsNode* stmt = (Node*)lfirst(l);if (IsA(stmt, CreateStmt)) { // 如果是 CreateStmt就调用DefineRelationDatum 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
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




