Re: dblink: add polymorphic functions.
От | Tom Lane |
---|---|
Тема | Re: dblink: add polymorphic functions. |
Дата | |
Msg-id | 27045.1438275067@sss.pgh.pa.us обсуждение исходный текст |
Ответ на | Re: dblink: add polymorphic functions. (Joe Conway <mail@joeconway.com>) |
Ответы |
Re: dblink: add polymorphic functions.
(Alvaro Herrera <alvherre@2ndquadrant.com>)
Re: dblink: add polymorphic functions. (Joe Conway <mail@joeconway.com>) |
Список | pgsql-hackers |
Joe Conway <mail@joeconway.com> writes: > What about just TYPE then? > SELECT x::TYPE(some_expression) FROM ... > SELECT CAST (x AS TYPE(some_expression)) FROM ... Yeah, that would work. Quick-hack proof-of-concept patch attached. Some usage examples in the regression database: regression=# select pg_typeof(43::type(q1)) from int8_tbl; pg_typeof ----------- bigint bigint bigint bigint bigint (5 rows) regression=# select pg_typeof(43::type(q1/0.0)) from int8_tbl; pg_typeof ----------- numeric numeric numeric numeric numeric (5 rows) regression=# select pg_typeof(43::type(f1)) from point_tbl; ERROR: cannot cast type integer to point LINE 1: select pg_typeof(43::type(f1)) from point_tbl; ^ The main limitation of this patch is that it won't work for call sites that pass pstate == NULL to LookupTypeName. There are a fair number of them, some of which wouldn't care because they could never invoke this notation anyway, but for others we'd need to do some work to cons up a suitable pstate. regards, tom lane diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c index 6616639..d5d0f73 100644 *** a/src/backend/parser/parse_type.c --- b/src/backend/parser/parse_type.c *************** *** 19,25 **** --- 19,27 ---- #include "catalog/pg_type.h" #include "lib/stringinfo.h" #include "nodes/makefuncs.h" + #include "nodes/nodeFuncs.h" #include "parser/parser.h" + #include "parser/parse_expr.h" #include "parser/parse_type.h" #include "utils/array.h" #include "utils/builtins.h" *************** static int32 typenameTypeMod(ParseState *** 52,58 **** * found but is a shell, and there is typmod decoration, an error will be * thrown --- this is intentional. * ! * pstate is only used for error location info, and may be NULL. */ Type LookupTypeName(ParseState *pstate, const TypeName *typeName, --- 54,61 ---- * found but is a shell, and there is typmod decoration, an error will be * thrown --- this is intentional. * ! * In most cases pstate is only used for error location info, and may be NULL. ! * However, the TYPE(expression) syntax is not accepted when pstate is NULL. */ Type LookupTypeName(ParseState *pstate, const TypeName *typeName, *************** LookupTypeName(ParseState *pstate, const *** 143,148 **** --- 146,188 ---- format_type_be(typoid)))); } } + else if (pstate != NULL && + list_length(typeName->typmods) == 1 && + list_length(typeName->names) == 1 && + strcmp(strVal(linitial(typeName->names)), "type") == 0) + { + /* TYPE(expression) notation */ + Node *typexpr = (Node *) linitial(typeName->typmods); + + /* XXX should invent a new EXPR_KIND for this, likely */ + typexpr = transformExpr(pstate, typexpr, EXPR_KIND_SELECT_TARGET); + + /* We needn't bother assigning collations to the expr */ + + /* We use the expression's type/typmod and then throw the expr away */ + typoid = exprType(typexpr); + + /* If an array reference, return the array type instead */ + if (typeName->arrayBounds != NIL) + typoid = get_array_type(typoid); + + if (!OidIsValid(typoid)) + { + if (typmod_p) + *typmod_p = -1; + return NULL; + } + + if (typmod_p) + *typmod_p = exprTypmod(typexpr); + + /* Duplicative, but I'm too lazy to refactor this function right now */ + tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typoid)); + if (!HeapTupleIsValid(tup)) /* should not happen */ + elog(ERROR, "cache lookup failed for type %u", typoid); + + return (Type) tup; + } else { /* Normal reference to a type name */
В списке pgsql-hackers по дате отправления:
Предыдущее
От: Joe ConwayДата:
Сообщение: Re: [COMMITTERS] pgsql: Row-Level Security Policies (RLS)