W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
被一個(gè)操作符表達(dá)式引用的特定操作符由下列過(guò)程決定。注意這個(gè)過(guò)程會(huì)被所涉及的操作符的優(yōu)先級(jí)間接地影響,因?yàn)檫@將決定哪些子表達(dá)式被用作哪個(gè)操作符的輸入。詳見(jiàn)第 4.1.6 節(jié)。
操作符類型決定
從系統(tǒng)目錄pg_operator
中選出要考慮的操作符。如果使用了一個(gè)不帶模式限定的操作符 名(常見(jiàn)的情況),那么操作符被認(rèn)為是那些在當(dāng)前搜索路徑中可見(jiàn)并有匹配的名字和參數(shù)個(gè)數(shù)的操作符(參見(jiàn)第 5.9.3 節(jié))。如果給出一個(gè)被限定的操作符名,那么只考慮指定模式中的操作符。
如果搜索路徑找到了多個(gè)有相同參數(shù)類型的操作符,那么只考慮最早出現(xiàn)在路徑中的那一個(gè)。 但是不同參數(shù)類型的操作符將被平等看待,而不管它們?cè)诼窂街械奈恢萌绾巍?/p>
查找一個(gè)正好接受輸入?yún)?shù)類型的操作符。如果找到一個(gè)(在一組被考慮的操作符中,可能只存在一個(gè)正好匹配的),則使用之。在通過(guò)限定名稱(非典型)調(diào)用在一個(gè)允許不可信用戶創(chuàng)建對(duì)象的方案中找到的任意操作符時(shí),精確匹配的缺失會(huì)導(dǎo)致安全性危害 [8] 。在這樣的情況下,應(yīng)該造型參數(shù)以便強(qiáng)制一次精確匹配。
如果一個(gè)二元操作符調(diào)用中的一個(gè)參數(shù)是unknown
類型,則在本次檢查中假設(shè)它與另一個(gè)參數(shù)類型相同。 對(duì)于涉及兩個(gè)unknown
輸入的調(diào)用或者帶有一個(gè)unknown
輸入的一元操作符,在這一步將永遠(yuǎn)找不到一個(gè)匹配。
如果一個(gè)二元操作符調(diào)用的其中一個(gè)參數(shù)是unknown
類型 而另一個(gè)是一種域類型,下一次檢查會(huì)看看是否有一個(gè)操作符正好在兩邊都 接受該域的基類型,如果有就使用它。
尋找最優(yōu)匹配。
拋棄那些輸入類型不匹配并且也不能被轉(zhuǎn)換成匹配的候選操作符。
unknown
文字被假定為可以為這個(gè)目的被轉(zhuǎn)換為 任何東西。如果只剩下一個(gè)候選操作符,則使用之,否則繼續(xù)下一 步。
如果任何輸入?yún)?shù)是一種域類型,對(duì)所有后續(xù)步驟都把它當(dāng)做是該 域的基類型。這確保在做有歧義的操作符解析時(shí),域的舉止像它們 的基類型。
遍歷所有候選操作符,保留那些在輸入類型上的匹配最準(zhǔn)確的。如果沒(méi)有一個(gè)操作符能準(zhǔn)確匹配,則保留所有候選。如果只剩下一個(gè)候選操作符,則使用之,否則繼續(xù)下一步。
遍歷所有候選操作符,保留那些在最多個(gè)需要類型轉(zhuǎn)換的位置上接受首選類型(屬于輸入數(shù)據(jù)類型的類型分類)的操作符。如果沒(méi)有接受首選類型的操作符,則保留所有候選。如果只剩下一個(gè)候選操作符,則使用之, 否則繼續(xù)下一步。
如果有任何輸入?yún)?shù)是unknown
類型,檢查被剩余候選操作符在那些參數(shù)位置上接受的類型分類。 在每一個(gè)位置,如果任何候選接受該分類,則選擇string
分類(這種對(duì)字符串的偏愛(ài)是合適的, 因?yàn)槲粗愋偷奈谋敬_實(shí)像字符串)。否則,如果所有剩下的候選操作符都接受相同的類型 分類,則選擇該分類;否則拋出一個(gè)錯(cuò)誤(因?yàn)樵跊](méi)有更多線索的條件下無(wú)法作出正確 的推斷)?,F(xiàn)在拋棄不接受選定的類型分類的候選操作符。然后,如果任意候選操作符接受那個(gè)分類中的首選類型,
則拋棄那些在該參數(shù)位置接受非首選類型的候選操作符。如果沒(méi)有候選操作符能通過(guò)這些測(cè)試則保留全部候選者。如果只剩下一個(gè)候選者,則使用之;否則繼續(xù)下一步。
如果既有unknown
參數(shù)也有已知類型的參數(shù),并且所有已知類型參數(shù)具有相同的類型,則假定該unknown
參數(shù)也是那種類型的,并且檢查哪些候選操作符可以在該unknown
參數(shù)的位置上接受那個(gè)類型。如果正好有一個(gè)候選者通過(guò)了這個(gè)測(cè)試,則使用之;否則失敗。
下面是一些例子。
例 10.1. 平方根運(yùn)算符類型解析
在標(biāo)準(zhǔn)目錄中只有一個(gè)被定義的平方根操作符(前綴|/
),它接受一個(gè)類型為double precision
的參數(shù)。在下面這個(gè)查詢表達(dá)式中,掃描器會(huì)為該參數(shù)分配一個(gè)初始類型integer
:
SELECT |/ 40 AS "square root of 40";
square root of 40
-------------------
6.324555320336759
(1 row)
因此,解析器在操作數(shù)上做了一個(gè)類型轉(zhuǎn)換,該查詢等價(jià)于:
SELECT |/ CAST(40 AS double precision) AS "square root of 40";
例 10.2. 字符串連接操作符類型決定
一個(gè)類字符串的語(yǔ)法被用來(lái)處理字符串類型和處理復(fù)雜的擴(kuò)展類型。未指定類型的字符串與可能的候選操作符匹配。
一個(gè)未指定參數(shù)的例子:
SELECT text 'abc' || 'def' AS "text and unknown";
text and unknown
------------------
abcdef
(1 row)
在這種情況下,解析器查看是否有一個(gè)操作符的兩個(gè)參數(shù)都使用text
。既然有,那么它假設(shè)第二個(gè)參數(shù)應(yīng)被解釋為text
類型。
下面是兩個(gè)未指定類型的值的連接:
SELECT 'abc' || 'def' AS "unspecified";
unspecified
-------------
abcdef
(1 row)
在這種情況下,沒(méi)有對(duì)于使用哪種類型的初始提示,因?yàn)樵诓樵冎袥](méi)有指定類型。 因此,解析器查找所有的候選操作符并找到候選者同時(shí)接受字符串分類和位串分類的輸入。 因?yàn)樽址诸愒诳捎脮r(shí)是首選的,該分類會(huì)被選中,并且接下來(lái)字符串的首選類型(text
)會(huì)被用作解決未知類型文字的指定類型。
例 10.3. 絕對(duì)值與否定操作符類型決定
PostgreSQL操作符目錄中有幾個(gè)對(duì)于前綴操作符@
的條目, 這些都現(xiàn)實(shí)了針對(duì)各種數(shù)字?jǐn)?shù)據(jù)類型的絕對(duì)值操作。其中之一用于float8
類型,它是在數(shù)字分類中的首選類型。 因此,PostgreSQL將在遇到一個(gè)unknown
輸入時(shí)使用它:
SELECT @ '-4.5' AS "abs"; abs ----- 4.5 (1 row)
在這里,系統(tǒng)在應(yīng)用所選操作符之前已經(jīng)隱式地解決了將未知類型文字作為float8
類型。 我們可以驗(yàn)證我們使用的是float8
而不是別的類型:
SELECT @ '-4.5e500' AS "abs";
ERROR: "-4.5e500" is out of range for type double precision
另一方面,前綴符~
(按位取反)只為整數(shù)數(shù)據(jù)類型定義,而沒(méi)有為float8
定義。因此,如果我們嘗試一個(gè)與使用~
類似的情況,我們會(huì)得到:
SELECT ~ '20' AS "negation";
ERROR: operator is not unique: ~ "unknown"
HINT: Could not choose a best candidate operator. You might need to add
explicit type casts.
這是因?yàn)橄到y(tǒng)不能決定在幾個(gè)可能的~
符號(hào)中應(yīng)該選擇哪一個(gè)。我們可以用一個(gè)顯式造型來(lái)幫助它:
SELECT ~ CAST('20' AS int8) AS "negation";
negation
----------
-21
(1 row)
例 10.4. 數(shù)組包含操作符類型決定
這里是另一個(gè)決定帶有一個(gè)已知和一個(gè)未知輸入的操作符的例子:
SELECT array[1,2] <@ '{1,2,3}' as "is subset";
is subset
-----------
t
(1 row)
PostgreSQL操作符目錄有一些條目用于中綴操作符<@
,但是僅有的兩個(gè)可以在左手邊接受一個(gè)整數(shù)數(shù)組的是數(shù)組包含(anyarray
<@
anyarray
)和范圍包含(anyelement
<@
anyrange
)。因?yàn)檫@些多態(tài)偽類型(見(jiàn)第 8.21 節(jié))中沒(méi)有一個(gè)被認(rèn)為是首選的,解析器不能以此為基礎(chǔ)來(lái)解決歧義。不過(guò),本文中操作符類型決定中第3點(diǎn)中的 f 告訴它假定位置類型的文字和其他輸入的類型相同,即整數(shù)數(shù)組。現(xiàn)在這兩個(gè)操作符中只有一個(gè)可以匹配,因此數(shù)組包含被選擇(如果選擇范圍包含,我們將得到一個(gè)錯(cuò)誤,因?yàn)樵撟址疀](méi)有成為一個(gè)范圍文字的正確格式)。
例 10.5. 域類型上的自定義操作符
用戶有時(shí)會(huì)嘗試聲明只適用于一種域類型的操作符。這是可能的, 但是遠(yuǎn)非它看起來(lái)那么有用,因?yàn)椴僮鞣馕鲆?guī)則被設(shè)計(jì)為選擇 適用于域的基類型的操作符??紤]這個(gè)例子:
CREATE DOMAIN mytext AS text CHECK(...);
CREATE FUNCTION mytext_eq_text (mytext, text) RETURNS boolean AS ...;
CREATE OPERATOR = (procedure=mytext_eq_text, leftarg=mytext, rightarg=text);
CREATE TABLE mytable (val mytext);
SELECT * FROM mytable WHERE val = 'foo';
這個(gè)查詢將不會(huì)使用自定義操作符。解析器將首先看看是否有一個(gè)
mytext
=
mytext
操作符( 本文中操作符類型決定中第 2點(diǎn)中 a),當(dāng)然這里沒(méi)有; 然后它將會(huì)考慮該域的基類型text
,并且看看是否有一
個(gè)text
=
text
操作符( 本文中操作符類型決定中第2點(diǎn)中.b),這里也沒(méi)有;因 此它會(huì)把unknown
-類型文字解析為text
并使用
text
=
text
操作符。 讓自定義操作符能被使用的唯一方法是顯式地轉(zhuǎn)換改文字:
SELECT * FROM mytable WHERE val = text 'foo';
這樣根據(jù)準(zhǔn)確匹配規(guī)則會(huì)立即找到
mytext
=
text
操作符。如果 到達(dá)最佳匹配規(guī)則,它們會(huì)積極地排斥域類型上的操作符。如果它 們沒(méi)有,這樣一個(gè)操作符將創(chuàng)建太多歧義操作符失敗,因?yàn)檗D(zhuǎn)換規(guī) 則總是認(rèn)為一個(gè)域可以和它的基類型相互轉(zhuǎn)換,并且因此該域操作 符在所有與該基類型上的一個(gè)類似命名的操作符相同的情況中都被 認(rèn)為可用。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: