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)
Следующее
От: Heikki Linnakangas
Дата:
Сообщение: Re: multivariate statistics / patch v7