先说 heap_insert 函数:

/*
* heap_insert - insert tuple into a heap
*
* The new tuple is stamped with current transaction ID and the specified
* command ID.
*
* If the HEAP_INSERT_SKIP_WAL option is specified, the new tuple is not
* logged in WAL, even for a non-temp relation. Safe usage of this behavior
* requires that we arrange that all new tuples go into new pages not
* containing any tuples from other transactions, and that the relation gets
* fsync'd before commit. (See also heap_sync() comments)
*
* The HEAP_INSERT_SKIP_FSM option is passed directly to
* RelationGetBufferForTuple, which see for more info.
*
* Note that these options will be applied when inserting into the heap's
* TOAST table, too, if the tuple requires any out-of-line data.
*
* The BulkInsertState object (if any; bistate can be NULL for default
* behavior) is also just passed through to RelationGetBufferForTuple.
*
* The return value is the OID assigned to the tuple (either here or by the
* caller), or InvalidOid if no OID. The header fields of *tup are updated
* to match the stored tuple; in particular tup->t_self receives the actual
* TID where the tuple was stored. But note that any toasting of fields
* within the tuple data is NOT reflected into *tup.
*/
Oid
heap_insert(Relation relation, HeapTuple tup, CommandId cid,
int options, BulkInsertState bistate)
{
/**
Form_pg_class tmprel = relation->rd_rel;
NameData tmprelname = tmprel->relname;
fprintf(stderr,"Insert into: %s\n", tmprelname.data);
fprintf(stderr,"In heap_insert,going to insert into table:%d \n\n",relation->rd_node.relNode );
   */
TransactionId xid = GetCurrentTransactionId(); HeapTuple heaptup;
Buffer buffer;
bool all_visible_cleared = false; if (relation->rd_rel->relhasoids)
{
#ifdef NOT_USED
/* this is redundant with an Assert in HeapTupleSetOid */
Assert(tup->t_data->t_infomask & HEAP_HASOID);
#endif /*
* If the object id of this tuple has already been assigned, trust the
* caller. There are a couple of ways this can happen. At initial db
* creation, the backend program sets oids for tuples. When we define
* an index, we set the oid. Finally, in the future, we may allow
* users to set their own object ids in order to support a persistent
* object store (objects need to contain pointers to one another).
*/
if (!OidIsValid(HeapTupleGetOid(tup)))
HeapTupleSetOid(tup, GetNewOid(relation));
}
else
{
/* check there is not space for an OID */
Assert(!(tup->t_data->t_infomask & HEAP_HASOID));
} tup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
tup->t_data->t_infomask2 &= ~(HEAP2_XACT_MASK);
tup->t_data->t_infomask |= HEAP_XMAX_INVALID;
HeapTupleHeaderSetXmin(tup->t_data, xid);
HeapTupleHeaderSetCmin(tup->t_data, cid); HeapTupleHeaderSetXmax(tup->t_data, ); /* for cleanliness */
tup->t_tableOid = RelationGetRelid(relation); /*
* If the new tuple is too big for storage or contains already toasted
* out-of-line attributes from some other relation, invoke the toaster.
*
* Note: below this point, heaptup is the data we actually intend to store
* into the relation; tup is the caller's original untoasted data.
*/
if (relation->rd_rel->relkind != RELKIND_RELATION)
{
/* toast table entries should never be recursively toasted */
Assert(!HeapTupleHasExternal(tup));
heaptup = tup;
}
else if (HeapTupleHasExternal(tup) || tup->t_len > TOAST_TUPLE_THRESHOLD)
heaptup = toast_insert_or_update(relation, tup, NULL, options);
else
heaptup = tup; /*
* We're about to do the actual insert -- but check for conflict first,
* to avoid possibly having to roll back work we've just done.
*
* For a heap insert, we only need to check for table-level SSI locks.
* Our new tuple can't possibly conflict with existing tuple locks, and
* heap page locks are only consolidated versions of tuple locks; they do
* not lock "gaps" as index page locks do. So we don't need to identify
* a buffer before making the call.
*/
CheckForSerializableConflictIn(relation, NULL, InvalidBuffer); /* Find buffer to insert this tuple into */
buffer = RelationGetBufferForTuple(relation, heaptup->t_len,
InvalidBuffer, options, bistate); /* NO EREPORT(ERROR) from here till changes are logged */
START_CRIT_SECTION(); RelationPutHeapTuple(relation, buffer, heaptup); if (PageIsAllVisible(BufferGetPage(buffer)))
{
all_visible_cleared = true;
PageClearAllVisible(BufferGetPage(buffer));
} /*
* XXX Should we set PageSetPrunable on this page ?
*
* The inserting transaction may eventually abort thus making this tuple
* DEAD and hence available for pruning. Though we don't want to optimize
* for aborts, if no other tuple in this page is UPDATEd/DELETEd, the
* aborted tuple will never be pruned until next vacuum is triggered.
*
* If you do add PageSetPrunable here, add it in heap_xlog_insert too.
*/ MarkBufferDirty(buffer); /* XLOG stuff */
if (!(options & HEAP_INSERT_SKIP_WAL) && RelationNeedsWAL(relation))
{
xl_heap_insert xlrec;
xl_heap_header xlhdr;
XLogRecPtr recptr;
XLogRecData rdata[];
Page page = BufferGetPage(buffer);
uint8 info = XLOG_HEAP_INSERT; xlrec.all_visible_cleared = all_visible_cleared;
xlrec.target.node = relation->rd_node;
xlrec.target.tid = heaptup->t_self;
rdata[].data = (char *) &xlrec;
rdata[].len = SizeOfHeapInsert;
rdata[].buffer = InvalidBuffer;
rdata[].next = &(rdata[]); xlhdr.t_infomask2 = heaptup->t_data->t_infomask2;
xlhdr.t_infomask = heaptup->t_data->t_infomask;
xlhdr.t_hoff = heaptup->t_data->t_hoff; /*
* note we mark rdata[1] as belonging to buffer; if XLogInsert decides
* to write the whole page to the xlog, we don't need to store
* xl_heap_header in the xlog.
*/
rdata[].data = (char *) &xlhdr;
rdata[].len = SizeOfHeapHeader;
rdata[].buffer = buffer;
rdata[].buffer_std = true;
rdata[].next = &(rdata[]); /* PG73FORMAT: write bitmap [+ padding] [+ oid] + data */
rdata[].data = (char *) heaptup->t_data + offsetof(HeapTupleHeaderData, t_bits);
rdata[].len = heaptup->t_len - offsetof(HeapTupleHeaderData, t_bits);
rdata[].buffer = buffer;
rdata[].buffer_std = true;
rdata[].next = NULL; /*
* If this is the single and first tuple on page, we can reinit the
* page instead of restoring the whole thing. Set flag, and hide
* buffer references from XLogInsert.
*/
if (ItemPointerGetOffsetNumber(&(heaptup->t_self)) == FirstOffsetNumber &&
PageGetMaxOffsetNumber(page) == FirstOffsetNumber)
{
info |= XLOG_HEAP_INIT_PAGE;
rdata[].buffer = rdata[].buffer = InvalidBuffer;
} recptr = XLogInsert(RM_HEAP_ID, info, rdata); PageSetLSN(page, recptr);
PageSetTLI(page, ThisTimeLineID);
} END_CRIT_SECTION(); UnlockReleaseBuffer(buffer); /* Clear the bit in the visibility map if necessary */
if (all_visible_cleared)
visibilitymap_clear(relation,
ItemPointerGetBlockNumber(&(heaptup->t_self))); /*
* If tuple is cachable, mark it for invalidation from the caches in case
* we abort. Note it is OK to do this after releasing the buffer, because
* the heaptup data structure is all in local memory, not in the shared
* buffer.
*/
CacheInvalidateHeapTuple(relation, heaptup); pgstat_count_heap_insert(relation); /*
* If heaptup is a private copy, release it. Don't forget to copy t_self
* back to the caller's image, too.
*/
if (heaptup != tup)
{
tup->t_self = heaptup->t_self;
heap_freetuple(heaptup);
}
return HeapTupleGetOid(tup);
}

我如果执行一个普通的sql文,则可以加入这样的调试代码,来看看我是否确实向我想要的表中插入数据:

    /**
Form_pg_class tmprel = relation->rd_rel;
NameData tmprelname = tmprel->relname;
fprintf(stderr,"Insert into: %s\n", tmprelname.data);
fprintf(stderr,"In heap_insert,going to insert into table:%d \n\n",relation->rd_node.relNode );
   */

当我执行 create tablespace的时候,我想它是要写入数据字典的。

但是上述代码反应出来的relNode是不正确的,而 relname也是空的值。

然后我从更高测调用层面来观察:

当我执行 create tablespace的时候,调用关系如下:

PostgresMain-->exec_simple_query-->PortalRun-->PortalRunMulti-->PortalRunUtility-->Createtablespace

-->simple_heap_insert-->heap_insert

再看 Createtablespace函数:

/*
* Create a table space
*
* Only superusers can create a tablespace. This seems a reasonable restriction
* since we're determining the system layout and, anyway, we probably have
* root if we're doing this kind of activity
*/
void
CreateTableSpace(CreateTableSpaceStmt *stmt)
{
#ifdef HAVE_SYMLINK
Relation rel;
Datum values[Natts_pg_tablespace];
bool nulls[Natts_pg_tablespace];
HeapTuple tuple;
Oid tablespaceoid;
char *location;
Oid ownerId; /* Must be super user */
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to create tablespace \"%s\"",
stmt->tablespacename),
errhint("Must be superuser to create a tablespace."))); /* However, the eventual owner of the tablespace need not be */
if (stmt->owner)
ownerId = get_role_oid(stmt->owner, false);
else
ownerId = GetUserId(); /* Unix-ify the offered path, and strip any trailing slashes */
location = pstrdup(stmt->location);
canonicalize_path(location); /* disallow quotes, else CREATE DATABASE would be at risk */
if (strchr(location, '\''))
ereport(ERROR,
(errcode(ERRCODE_INVALID_NAME),
errmsg("tablespace location cannot contain single quotes"))); /*
* Allowing relative paths seems risky
*
* this also helps us ensure that location is not empty or whitespace
*/
if (!is_absolute_path(location))
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("tablespace location must be an absolute path"))); /*
* Check that location isn't too long. Remember that we're going to append
* 'PG_XXX/<dboid>/<relid>.<nnn>'. FYI, we never actually reference the
* whole path, but mkdir() uses the first two parts.
*/
if (strlen(location) + + strlen(TABLESPACE_VERSION_DIRECTORY) + +
OIDCHARS + + OIDCHARS + + OIDCHARS > MAXPGPATH)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("tablespace location \"%s\" is too long",
location))); /*
* Disallow creation of tablespaces named "pg_xxx"; we reserve this
* namespace for system purposes.
*/
if (!allowSystemTableMods && IsReservedName(stmt->tablespacename))
ereport(ERROR,
(errcode(ERRCODE_RESERVED_NAME),
errmsg("unacceptable tablespace name \"%s\"",
stmt->tablespacename),
errdetail("The prefix \"pg_\" is reserved for system tablespaces."))); /*
* Check that there is no other tablespace by this name. (The unique
* index would catch this anyway, but might as well give a friendlier
* message.)
*/
if (OidIsValid(get_tablespace_oid(stmt->tablespacename, true)))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("tablespace \"%s\" already exists",
stmt->tablespacename))); /*
* Insert tuple into pg_tablespace. The purpose of doing this first is to
* lock the proposed tablename against other would-be creators. The
* insertion will roll back if we find problems below.
*/
rel = heap_open(TableSpaceRelationId, RowExclusiveLock); MemSet(nulls, false, sizeof(nulls)); values[Anum_pg_tablespace_spcname - ] =
DirectFunctionCall1(namein, CStringGetDatum(stmt->tablespacename));
values[Anum_pg_tablespace_spcowner - ] =
ObjectIdGetDatum(ownerId);
values[Anum_pg_tablespace_spclocation - ] =
CStringGetTextDatum(location);
nulls[Anum_pg_tablespace_spcacl - ] = true;
nulls[Anum_pg_tablespace_spcoptions - ] = true; tuple = heap_form_tuple(rel->rd_att, values, nulls); tablespaceoid = simple_heap_insert(rel, tuple); CatalogUpdateIndexes(rel, tuple); heap_freetuple(tuple); /* Record dependency on owner */
recordDependencyOnOwner(TableSpaceRelationId, tablespaceoid, ownerId); /* Post creation hook for new tablespace */
InvokeObjectAccessHook(OAT_POST_CREATE,
TableSpaceRelationId, tablespaceoid, ); create_tablespace_directories(location, tablespaceoid); /* Record the filesystem change in XLOG */
{
xl_tblspc_create_rec xlrec;
XLogRecData rdata[]; xlrec.ts_id = tablespaceoid;
rdata[].data = (char *) &xlrec;
rdata[].len = offsetof(xl_tblspc_create_rec, ts_path);
rdata[].buffer = InvalidBuffer;
rdata[].next = &(rdata[]); rdata[].data = (char *) location;
rdata[].len = strlen(location) + ;
rdata[].buffer = InvalidBuffer;
rdata[].next = NULL; (void) XLogInsert(RM_TBLSPC_ID, XLOG_TBLSPC_CREATE, rdata);
} /*
* Force synchronous commit, to minimize the window between creating the
* symlink on-disk and marking the transaction committed. It's not great
* that there is any window at all, but definitely we don't want to make
* it larger than necessary.
*/
ForceSyncCommit(); pfree(location); /* We keep the lock on pg_tablespace until commit */
heap_close(rel, NoLock);
#else /* !HAVE_SYMLINK */
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("tablespaces are not supported on this platform")));
#endif /* HAVE_SYMLINK */
}
/*
* simple_heap_insert - insert a tuple
*
* Currently, this routine differs from heap_insert only in supplying
* a default command ID and not allowing access to the speedup options.
*
* This should be used rather than using heap_insert directly in most places
* where we are modifying system catalogs.
*/
Oid
simple_heap_insert(Relation relation, HeapTuple tup)
{
return heap_insert(relation, tup, GetCurrentCommandId(true), , NULL);
}

我把它简练化,看看它都干了什么:

/*
* Create a table space
*
* Only superusers can create a tablespace. This seems a reasonable restriction
* since we're determining the system layout and, anyway, we probably have
* root if we're doing this kind of activity
*/
void
CreateTableSpace(CreateTableSpaceStmt *stmt)
{
......
/*
* Insert tuple into pg_tablespace. The purpose of doing this first is to
* lock the proposed tablename against other would-be creators. The
* insertion will roll back if we find problems below.
*/
rel = heap_open(TableSpaceRelationId, RowExclusiveLock);
......
tablespaceoid = simple_heap_insert(rel, tuple);
......
}

而 heap_open(TableSpaceRelationId, RowExclusiveLock) 这一句,
里面的 TableSpaceRelationId其实是宏:

/* ----------------
* pg_tablespace definition. cpp turns this into
* typedef struct FormData_pg_tablespace
* ----------------
*/
#define TableSpaceRelationId 1213

而如果想要看到值,可以运行下面的语句,恰好 1213 对应的就是 pg_tablespace 表。

[pgsql@localhost bin]$ ./psql
psql (9.1.)
Type "help" for help. pgsql=# select ::regclass;
regclass
---------------
pg_tablespace
( row) pgsql=#

但是,实际上,pg_tablespace是数据字典,而数据库的目录中,并不存在一个单独的1213文件与之对应。

如果我用上述的:

    /**
Form_pg_class tmprel = relation->rd_rel;
NameData tmprelname = tmprel->relname;
fprintf(stderr,"Insert into: %s\n", tmprelname.data);
fprintf(stderr,"In heap_insert,going to insert into table:%d \n\n",relation->rd_node.relNode );
   */

来看,就会知道 relNode是 12587。

我可以在 global目录下,找到这个 12587文件。

1213 对应着 12587文件。这是一个比较怪异的事情。

create tablespace 与 heap_insert 函数的更多相关文章

  1. DB2 create tablespace

    db2手工创建表空间 db2 v10.11.1 创建系统管理使用文件目录的表空间 db2 "create tablespace newtbs01 managed by system usin ...

  2. oracle create tablespace

    ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED; sqlplus shybt/shybt@127.0.0.1:1521/orcl Cr ...

  3. Oracle create tablespace 、create user and so on

    1.创建临时表空间 CREATE TEMPORARY TABLESPACE test_tempTEMPFILE 'C:\oracle\product\10.1.0\oradata\orcl\test_ ...

  4. Oracle create tablespace 创建表空间语法详解

    CREATE [UNDO]  TABLESPACE tablespace_name          [DATAFILE datefile_spec1 [,datefile_spec2] ...... ...

  5. ODA: After Apply ODA 12.2.1.2.0 Patch, Unable to Create TableSpace Due to [ORA-15001: diskgroup "DATA" does not exist or is not mounted | ORA-15040: diskgroup is incomplete] (Doc ID 2375553.1)

    ODA: After Apply ODA 12.2.1.2.0 Patch, Unable to Create TableSpace Due to [ORA-15001: diskgroup &quo ...

  6. [官网]CREATE EXTENSION PostGreSQL 创建函数的方法

    CREATE EXTENSION https://www.postgresql.org/docs/current/sql-createextension.html CREATE EXTENSION — ...

  7. oracle create user &tablespace & imp

    一.表空间 1.创建表空间 CREATE TABLESPACE 空间名称 DATAFILE '文件名1' SIZE 数字M [,'文件名2' SIZE 数字….] EXTENT MANAGEMENT ...

  8. oracle 函数

    1.--dense_rank()分析函数(查找每个部门工资最高前三名员工信息) select * from (select deptno,ename,sal,dense_rank() over(par ...

  9. oracle 之索引,同义词 ,关键词,视图 ,存储过程,函数,触发器

    --创建索引 关键词 index create[unique] index index_name on table_name(column_name [,column_name…]) [tablesp ...

随机推荐

  1. WinCE启动失败的原因与解决办法分析

    本文通过一个真实的嵌入式项目进行说明.文中的嵌入式系统用的是ARM处理器+WinCE平台,项目的目的是要把WinCE平台从旧版本移植到WinCE6.0平台上.但结果是这个WinCE系统在启动的时候经常 ...

  2. function 的声明

    <?php function test() { echo "abc"; } test(); ?> 结论: 一 编译 a.对 函数声明进行词法分析和语法分析:在语法分析中 ...

  3. 关于 tomcat 集群中 session 共享的三种方法

    前两种均需要使用 memcached 或redis 存储 session ,最后一种使用 terracotta 服务器共享. 建议使用 redis,不仅仅因为它可以将缓存的内容持久化,还因为它支持的单 ...

  4. 常用的js代码

    1.输入框输入提示代码 <input name="keyword" type="text" value="请输入关键字" onFocu ...

  5. html语意化标签

    一.布局的理解误区 网络上流行管新型的布局方式叫“DIV+CSS”,其实是一个错误的理解,导致了很多人过度依赖 与滥用DIV标签, HTML提供了我们一共七八十个标签,其中常用的有三十个左右,DIV不 ...

  6. Spring Bean之间的关系

    bean之间的关系:继承和依赖继承bean的配置 Spring允许继承bean的配置,被继承的bean称为父bean,继承这个父bean的bean称为子bean 子bean从父bean中继承配置,包括 ...

  7. memcache redundancy机制分析及思考

    设计和开发可以掌控客户端的分布式服务端程序是件幸事,可以把很多事情交给客户端来做,而且可以做的很优雅.角色决定命运,在互联网架构中,web server必须冲锋在前,注定要在多浏览器版本以及协议兼容性 ...

  8. ollydbg z

    通达信l2密码器方法: 1:使用Ollydbg,点文件,打开,选择通达信的可执行文件(或者把通达信的执行文件直接拖进Ollydbg的窗口),按F9运行程序. 2:正常使用通达信,进入到K线图后,在k线 ...

  9. ubuntu12.04 安装 chrome

    1.下载deb包 2. sudo apt-get remove google-chrome-stable sudo dpkg -i google-chrome-stable_current_amd64 ...

  10. 《GettingThingsDone》--GTD学习笔记(一)-GTD理论

    利用春节假期阅读了<Getting Things Done>一书,下文整理了下阅读过程中做的读书笔记和心得. ==GTD理论== 一. 目的: 1. 收集需要处理的事情把它置于一个脱离大脑 ...