调用DefineRelation的地方
1 create_ctas_internal - Reference to DefineRelation in createas.c (src\backend\commands) at line 115 --create table as
2 DefineSequence - Reference to DefineRelation in sequence.c (src\backend\commands) at line 215 --序列
3 DefineCompositeType - Reference to DefineRelation in typecmds.c (src\backend\commands) at line 2180--创建类型
4 ProcessUtilitySlow - Reference to DefineRelation in utility.c (src\backend\tcop) at line 1000--ddl slow流程
5 DefineVirtualRelation - Reference to DefineRelation in view.c (src\backend\commands) at line 253 --虚表,主要是view
主要步骤:
1、校验schema
namespaceId =
RangeVarGetAndCheckCreationNamespace(stmt->relation, NoLock, NULL);
2、选择tablespace,不指定则选择默认的
if (stmt->tablespacename)
{
tablespaceId = get_tablespace_oid(stmt->tablespacename, false);
}
else
{
tablespaceId = GetDefaultTablespace(stmt->relation->relpersistence);
/* note InvalidOid is OK in this case */
}
非默认,则校验是否有tablespace的权限 aclresult = pg_tablespace_aclcheck(tablespaceId, GetUserId()
3、不允许在pg_global上创建
if (tablespaceId == GLOBALTABLESPACE_OID)
ereport(ERROR,...)
4、/* Identify user ID that will own the table 找到用户id */
if (!OidIsValid(ownerId))
ownerId = GetUserId();
5、解析和校验创建option
reloptions = transformRelOptions((Datum) 0, stmt->options, NULL, validnsps,
true, false);
/*视图和表不一样*/
if (relkind == RELKIND_VIEW)
(void) view_reloptions(reloptions, true);
else
(void) heap_reloptions(relkind, reloptions, true);
/*create type分支*/
if (stmt->ofTypename)
{
AclResult aclresult;
ofTypeId = typenameTypeId(NULL, stmt->ofTypename);
aclresult = pg_type_aclcheck(ofTypeId, GetUserId(), ACL_USAGE);
if (aclresult != ACLCHECK_OK)
aclcheck_error_type(aclresult, ofTypeId);
}
else
ofTypeId = InvalidOid;
有继承的情况处理,调用MergeAttributes,暂不展开。
6、创建元组描述符(主要包括列数量、列数组、tuple oid等)
descriptor = BuildDescForRelation(stmt->tableElts);/*构建了pg_attribute系统表中的相关内容*/
7、循环处理3类列
(1)RawColumnDefault: /* default value (untransformed parse tree) */
(2)CookedConstraint: /* default value (transformed expr tree) */
(3)自增序列id
char identity; /* attidentity setting */
RangeVar *identitySequence; /* to store identity sequence name for
foreach(listptr, stmt->tableElts)
{
if (colDef->raw_default != NULL)
rawDefaults = lappend(rawDefaults, rawEnt);
else if (colDef->cooked_default != NULL)
cookedDefaults = lappend(cookedDefaults, cooked);
if (colDef->identity)
attr->attidentity = colDef->identity;
}
8、创建表的物理文件并在相应的系统表中注册。会放入RelCache
relationId = heap_create_with_catalog(...),
添加的系统表包括:pg_type,pg_class,pg_constraint,pg_attrdef等
这个步骤最关键,后续单独展开下。TODO
9、使之可见 for opening:<并未真正可见,只有commit后才可见> CommandCounterIncrement();
10、Open the new relation and acquire exclusive lock on it.
rel = relation_open(relationId, AccessExclusiveLock);
11、分区表边界处理,暂时不展开。if (stmt->partbound) ...
12、分区表规格处理 (stmt->partbound) ...
13、If we're creating a partition, create now all the indexes, triggers,FKs defined in the parent.
if (stmt->partbound) ...
14、处理表中的默认值和约束
if (rawDefaults || stmt->constraints)
AddRelationNewConstraints(rel, rawDefaults, stmt->constraints,
true, true, false);
本文详细解析了数据库表创建过程中的关键步骤,包括schema校验、tablespace选择、权限检查、用户ID确认、选项解析、元组描述符构建、物理文件创建及系统表注册等。深入探讨了不同类型的表(如视图、分区表)在创建过程中的特殊处理。
2656

被折叠的 条评论
为什么被折叠?



