PostgreSQL參數search_path影響及做用

search_path稍微熟悉PG就會用到,用法這裏就沒必要講,本篇主要講它在程序裏怎樣處理。後端

一、GUC參數定義bash

這是個 config_string 參數ide

{
		{"search_path", PGC_USERSET, CLIENT_CONN_STATEMENT,
			gettext_noop("Sets the schema search order for names that are not schema-qualified."),
			NULL,
			GUC_LIST_INPUT | GUC_LIST_QUOTE
		},
		&namespace_search_path,
		"\"$user\", public",
		check_search_path, assign_search_path, NULL
	},

設置了兩個hook,賦值和檢查。assign_search_pathsrc/backend/catalog/namespace.c)只是簡單標記參數失效,下次使用時須要再次計算。函數

void
assign_search_path(const char *newval, void *extra)
{
	/*
	 * We mark the path as needing recomputation, but don't do anything until
	 * it's needed.  This avoids trying to do database access during GUC
	 * initialization, or outside a transaction.
	 */
	baseSearchPathValid = false;
}

二、從新計算的時機oop

函數 recomputeNamespacePath(void) 從新計算GUC定義的 namespace_search_pathspa

RangeVarGetCreationNamespaceRelnameGetRelidTypenameGetTypid 這類位置會調用它,發生在:建立沒有指定schema的對象、按名字查找對象、肯定對象可見性等等行爲時。這些均可以在 src/backend/catalog/namespace.c 中看到,再也不贅述。code

三、從新計算的邏輯對象

首先將 namespace_search_path 按逗號切分紅多個元素。ip

有兩個特殊名字的處理:$userpg_temp,前者若是存在與當前用戶同名的schema則加入到搜索路徑中,不存則沒有任何影響;後者若是當先後端對應的臨時schema已建立,加入搜索路徑,未建立則標記(activeTempCreationPending)下次使用搜索路徑前須要先建立,很少講這個。文檔

其它按名字查找各自的OID,找不到則跳過,最終造成一個搜索鏈表。至此,這裏做爲建立對象使用的第一個schema位置,接下來是搜索路徑的補足。

不少系統定義都是在 pg_catalog 中,因此:

if (!list_member_oid(oidlist, PG_CATALOG_NAMESPACE))
		oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);

若是定義中沒有包含它,加到最前邊。

一樣,臨時schema已經建立且沒有包含,再加到最前邊,也就是說它是在 pg_catalog 前的。

以默認設置:"$user", public 爲例,若是不存在同名schema,結果就是不指定scheme時,對象建立在public下,搜索時則先pg_catalog 後 public。

四、系統模式 pg_catalog

看完上邊的邏輯,試試把 pg_catalog 加到第一位置會怎樣,它會變成默認建立schema:

flying=# set search_path = pg_catalog,public;
SET
flying=# create table t();
ERROR:  permission denied to create "pg_catalog.t"
DETAIL:  System catalog modifications are currently disallowed.
flying=#

在系統模式下建表是不容許的。

五、臨時模式

pg_temp 放在第一位置:

flying=# set search_path = pg_temp,public;
SET
flying=# create table t();
CREATE TABLE
flying=# select relpersistence from pg_class where relname='t';
 relpersistence
----------------
 t
(1 row)

flying=# \d+ t
                                  Table "pg_temp_3.t"
 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
--------+------+-----------+----------+---------+---------+--------------+-------------

建立的是一個臨時表,根據文檔這是對的,在pg_temp下建表看成臨時表。

相關文章
相關標籤/搜索