[code notes] implementation of creating partition table

SQL

CREATE TABLE measurement (
    city_id     int not null,
    logdate     date not null,
    data        text
) PARTITION BY RANGE (logdate);

CREATE TABLE p1 PARTITION OF measurement
    FOR VALUES FROM ('2020-01-01') TO ('2020-02-01');

Semantic Struct

CreateStmt *n = makeNode(CreateStmt);
n->relation = $4; /* `p1` here */
n->inhRelations = list_make1($7); /* `measurement` here */
n->partbound = $9; /* ('2020-01-01') TO ('2020-02-01') */
/* other attributes are not important */

Execution

DDL statements are handled by function ProcessUtilitySlow. For T_CreateStmt:

  • run the parse analysis through transformCreateStmt
  • After transforming, the create table statment could have three types:
    • CreateStmt
    • CreateForeignTableStmt
    • TableLikeClause
      we are focusing on CreateStmt.
  • Create the table itself by function DefineRelation
  • record a ddl_command_end event
  • parse and validate reloptions for the toast table
  • check and create toast table

DefineRelation

  • Look up the namespace in which we are supposed to create the relation, check we have permission to create there, lock it against concurrent drop, and mark stmt->relation as RELPERSISTENCE_TEMP if a temporary namespace is selected.
  • record the list of OIDs of the parents and lock the parents
  • Select tablespace to use
  • Check permissions except when using database's default
  • In all cases disallow placing user relations in pg_global
  • Identify user ID that will own the table
  • Parse and validate reloptions, if any.
  • Look up inheritance ancestors and generate relation schema, including inherited attributes.
  • Create a tuple descriptor from the relation schema.
  • Find columns with default values and prepare for insertion of the defaults.
  • If the statement hasn't specified an access method, but we're defining a type of relation that needs one, use the default.
  • Create the relation by function heap_create_with_catalog.
  • make the newly created relation visible by function CommandCounterIncrement
  • Now add any newly specified column default and generation expressions to the new relation.
  • Make column generation expressions visible for use by partitioning.
  • lock default partition table with AccessExclusiveLock if exists. Here's the reason.
  • Transform the bound values by function transformPartitionBound
  • Check first that the new partition's bound is valid and does not overlap with any of existing partitions of the parent.
  • If the default partition exists, checks if there exists a row in the default partition that would properly belong to the new partition being added. If it finds one, it throws an error.
  • store the partition bound in the pg_class entry
  • Updates the system catalogs with proper inheritance information.
  • If we're creating a partition, create now all the indexes, triggers, FKs defined in the parent.
  • indexes are created by DefineIndex, triggers are cloned by CloneRowTriggersToPartition, foreign keys ared cloned by CloneForeignKeyConstraints
  • Now add any newly specified CHECK constraints to the new relation by AddRelationNewConstraints
  • Finally, merge the not-null constraints that are declared directly with those that come from parent relations

posted on 2024-03-26 00:33  winter-loo  阅读(10)  评论(0编辑  收藏  举报

导航