除了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?PGXC void?CreateCommand(CreateStmt?*parse_tree,?const?char?*query_string,?ParamListInfo?params, ???????????????????bool?is_top_level,?bool?sent_to_remote,?bool?isCTAS) #else void?CreateCommand(CreateStmt?*parse_tree,?const?char?*query_string,?ParamListInfo?params,?bool?is_top_level, ????bool?isCTAS) #endif { …… ???? ????if?(u_sess->attr.attr_sql.enable_parallel_ddl)? ????????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?==?NIL)?{? ????????table_is_exist?=?true; …… ???? ????foreach?(l,?stmts)?{? Node* stmt = (Node*)lfirst(l);
????????if?(IsA(stmt,?CreateStmt))?{?? ????????????Datum?toast_options; static const char* const validnsps[] = HEAP_RELOPT_NAMESPACES; ??????????? ???????????? ForbidOutUsersToSetInnerOptions(((CreateStmt*)stmt)->options); ???????????? ???????????? ????????????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的函数调用栈
(编辑:武汉站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|