diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2020-11-19 17:39:39 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2020-11-19 17:39:39 -0500 |
commit | 926fa801ac9eb54c5275472271ec63a059904698 (patch) | |
tree | 95a76e3721417c364b28fb4e0a715a3425461b59 /src/backend | |
parent | 97390fe8a6e96a153e59b0180f4303acaeb75b84 (diff) | |
download | postgresql-926fa801ac9eb54c5275472271ec63a059904698.tar.gz postgresql-926fa801ac9eb54c5275472271ec63a059904698.zip |
Remove undocumented IS [NOT] OF syntax.
This feature was added a long time ago, in 7c1e67bd5 and eb121ba2c,
but never documented in any user-facing way. (Documentation added
in 6126d3e70 was commented out almost immediately, in 8272fc3f7.)
That's because, while this syntax is defined by SQL:99, our
implementation is only vaguely related to the standard's semantics.
The standard appears to intend a run-time not parse-time test, and
it definitely intends that the test should understand subtype
relationships.
No one has stepped up to fix that in the intervening years, but
people keep coming across the code and asking why it's not documented.
Let's just get rid of it: if anyone ever wants to make it work per
spec, they can easily recover whatever parts of this code are still
of value from our git history.
If there's anyone out there who's actually using this despite its
undocumented status, they can switch to using pg_typeof() instead,
eg. "pg_typeof(something) = 'mytype'::regtype". That gives
essentially the same semantics as what our IS OF code did.
(We didn't have that function last time this was discussed, or
we would have ripped out IS OF then.)
Discussion: https://postgr.es/m/CAKFQuwZ2pTc-DSkOiTfjauqLYkNREeNZvWmeg12Q-_69D+sYZA@mail.gmail.com
Discussion: https://postgr.es/m/BAY20-F23E9F2B4DAB3E4E88D3623F99B0@phx.gbl
Discussion: https://postgr.es/m/3E7CF81D.1000203@joeconway.com
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/catalog/sql_features.txt | 2 | ||||
-rw-r--r-- | src/backend/nodes/outfuncs.c | 4 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 16 | ||||
-rw-r--r-- | src/backend/parser/parse_expr.c | 54 |
4 files changed, 1 insertions, 75 deletions
diff --git a/src/backend/catalog/sql_features.txt b/src/backend/catalog/sql_features.txt index b6e58e84939..caa971c4356 100644 --- a/src/backend/catalog/sql_features.txt +++ b/src/backend/catalog/sql_features.txt @@ -373,7 +373,7 @@ S096 Optional array bounds YES S097 Array element assignment NO S098 ARRAY_AGG YES S111 ONLY in query expressions YES -S151 Type predicate NO +S151 Type predicate NO see pg_typeof() S161 Subtype treatment NO S162 Subtype treatment for references NO S201 SQL-invoked routines on arrays YES diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 4504b1503b9..f26498cea2d 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -3213,10 +3213,6 @@ _outAExpr(StringInfo str, const A_Expr *node) appendStringInfoString(str, " NULLIF "); WRITE_NODE_FIELD(name); break; - case AEXPR_OF: - appendStringInfoString(str, " OF "); - WRITE_NODE_FIELD(name); - break; case AEXPR_IN: appendStringInfoString(str, " IN "); WRITE_NODE_FIELD(name); diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 2cb377d0342..efc9c997541 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -13238,14 +13238,6 @@ a_expr: c_expr { $$ = $1; } { $$ = (Node *) makeSimpleA_Expr(AEXPR_NOT_DISTINCT, "=", $1, $6, @2); } - | a_expr IS OF '(' type_list ')' %prec IS - { - $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "=", $1, (Node *) $5, @2); - } - | a_expr IS NOT OF '(' type_list ')' %prec IS - { - $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "<>", $1, (Node *) $6, @2); - } | a_expr BETWEEN opt_asymmetric b_expr AND a_expr %prec BETWEEN { $$ = (Node *) makeSimpleA_Expr(AEXPR_BETWEEN, @@ -13464,14 +13456,6 @@ b_expr: c_expr { $$ = (Node *) makeSimpleA_Expr(AEXPR_NOT_DISTINCT, "=", $1, $6, @2); } - | b_expr IS OF '(' type_list ')' %prec IS - { - $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "=", $1, (Node *) $5, @2); - } - | b_expr IS NOT OF '(' type_list ')' %prec IS - { - $$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "<>", $1, (Node *) $6, @2); - } | b_expr IS DOCUMENT_P %prec IS { $$ = makeXmlExpr(IS_DOCUMENT, NULL, NIL, diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index f5165863d77..36002f059d1 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -94,7 +94,6 @@ static Node *transformAExprOpAny(ParseState *pstate, A_Expr *a); static Node *transformAExprOpAll(ParseState *pstate, A_Expr *a); static Node *transformAExprDistinct(ParseState *pstate, A_Expr *a); static Node *transformAExprNullIf(ParseState *pstate, A_Expr *a); -static Node *transformAExprOf(ParseState *pstate, A_Expr *a); static Node *transformAExprIn(ParseState *pstate, A_Expr *a); static Node *transformAExprBetween(ParseState *pstate, A_Expr *a); static Node *transformBoolExpr(ParseState *pstate, BoolExpr *a); @@ -228,9 +227,6 @@ transformExprRecurse(ParseState *pstate, Node *expr) case AEXPR_NULLIF: result = transformAExprNullIf(pstate, a); break; - case AEXPR_OF: - result = transformAExprOf(pstate, a); - break; case AEXPR_IN: result = transformAExprIn(pstate, a); break; @@ -1168,51 +1164,6 @@ transformAExprNullIf(ParseState *pstate, A_Expr *a) return (Node *) result; } -/* - * Checking an expression for match to a list of type names. Will result - * in a boolean constant node. - */ -static Node * -transformAExprOf(ParseState *pstate, A_Expr *a) -{ - Node *lexpr = a->lexpr; - Const *result; - ListCell *telem; - Oid ltype, - rtype; - bool matched = false; - - if (operator_precedence_warning) - emit_precedence_warnings(pstate, PREC_GROUP_POSTFIX_IS, "IS", - lexpr, NULL, - a->location); - - lexpr = transformExprRecurse(pstate, lexpr); - - ltype = exprType(lexpr); - foreach(telem, (List *) a->rexpr) - { - rtype = typenameTypeId(pstate, lfirst(telem)); - matched = (rtype == ltype); - if (matched) - break; - } - - /* - * We have two forms: equals or not equals. Flip the sense of the result - * for not equals. - */ - if (strcmp(strVal(linitial(a->name)), "<>") == 0) - matched = (!matched); - - result = (Const *) makeBoolConst(matched, false); - - /* Make the result have the original input's parse location */ - result->location = exprLocation((Node *) a); - - return (Node *) result; -} - static Node * transformAExprIn(ParseState *pstate, A_Expr *a) { @@ -3257,11 +3208,6 @@ operator_precedence_group(Node *node, const char **nodename) *nodename = "IS"; group = PREC_GROUP_INFIX_IS; } - else if (aexpr->kind == AEXPR_OF) - { - *nodename = "IS"; - group = PREC_GROUP_POSTFIX_IS; - } else if (aexpr->kind == AEXPR_IN) { *nodename = "IN"; |