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_path
(src/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_path
:spa
在 RangeVarGetCreationNamespace
、RelnameGetRelid
、TypenameGetTypid
這類位置會調用它,發生在:建立沒有指定schema的對象、按名字查找對象、肯定對象可見性等等行爲時。這些均可以在 src/backend/catalog/namespace.c
中看到,再也不贅述。code
三、從新計算的邏輯對象
首先將 namespace_search_path
按逗號切分紅多個元素。ip
有兩個特殊名字的處理:$user
和 pg_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下建表看成臨時表。