On 07/30/2015 09:51 AM, Tom Lane wrote:
> Joe Conway <m...@joeconway.com> writes:
>> What about just TYPE then?
> 
>>     SELECT x::TYPE(some_expression) FROM ...
>>     SELECT CAST (x AS TYPE(some_expression)) FROM ...

> 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.

Sorry it took so long for me to get back to this, but any reason the
attached won't work?

Joe

-- 
Crunchy Data - http://crunchydata.com
PostgreSQL Support for Secure Enterprises
Consulting, Training, & Open Source Development
diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c
index 5b0d568..a1aba26 100644
*** a/src/backend/parser/parse_agg.c
--- b/src/backend/parser/parse_agg.c
*************** check_agglevels_and_constraints(ParseSta
*** 485,490 ****
--- 485,493 ----
  				err = _("grouping operations are not allowed in trigger WHEN conditions");
  
  			break;
+ 		case EXPR_KIND_TYPE:
+ 			/* okay */
+ 			break;
  
  			/*
  			 * There is intentionally no default: case here, so that the
*************** transformWindowFuncCall(ParseState *psta
*** 842,847 ****
--- 845,853 ----
  		case EXPR_KIND_TRIGGER_WHEN:
  			err = _("window functions are not allowed in trigger WHEN conditions");
  			break;
+ 		case EXPR_KIND_TYPE:
+ 			/* okay */
+ 			break;
  
  			/*
  			 * There is intentionally no default: case here, so that the
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index fa77ef1..9f76ee6 100644
*** a/src/backend/parser/parse_expr.c
--- b/src/backend/parser/parse_expr.c
*************** transformSubLink(ParseState *pstate, Sub
*** 1690,1695 ****
--- 1690,1696 ----
  		case EXPR_KIND_OFFSET:
  		case EXPR_KIND_RETURNING:
  		case EXPR_KIND_VALUES:
+ 		case EXPR_KIND_TYPE:
  			/* okay */
  			break;
  		case EXPR_KIND_CHECK_CONSTRAINT:
*************** ParseExprKindName(ParseExprKind exprKind
*** 3225,3230 ****
--- 3226,3233 ----
  			return "EXECUTE";
  		case EXPR_KIND_TRIGGER_WHEN:
  			return "WHEN";
+ 		case EXPR_KIND_TYPE:
+ 			return "TYPE";
  
  			/*
  			 * There is intentionally no default: case here, so that the
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
index 6616639..19a2684 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,60 ----
   * 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.
   */
  Type
  LookupTypeName(ParseState *pstate, const TypeName *typeName,
*************** LookupTypeName(ParseState *pstate, const
*** 60,66 ****
  {
  	Oid			typoid;
  	HeapTuple	tup;
! 	int32		typmod;
  
  	if (typeName->names == NIL)
  	{
--- 62,68 ----
  {
  	Oid			typoid;
  	HeapTuple	tup;
! 	int32		typmod = -2;
  
  	if (typeName->names == NIL)
  	{
*************** LookupTypeName(ParseState *pstate, const
*** 143,148 ****
--- 145,172 ----
  							format_type_be(typoid))));
  		}
  	}
+ 	else if (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);
+ 
+ 		/* If needed, create a dummy ParseState for transformExpr */
+ 		if (pstate == NULL)
+ 			pstate = make_parsestate(NULL);
+ 
+ 		typexpr = transformExpr(pstate, typexpr, EXPR_KIND_TYPE);
+ 
+ 		/* 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);
+ 		typmod = exprTypmod(typexpr);
+ 
+ 		/* If an array reference, return the array type instead */
+ 		if (typeName->arrayBounds != NIL)
+ 			typoid = get_array_type(typoid);
+ 	}
  	else
  	{
  		/* Normal reference to a type name */
*************** LookupTypeName(ParseState *pstate, const
*** 192,198 ****
  	if (!HeapTupleIsValid(tup)) /* should not happen */
  		elog(ERROR, "cache lookup failed for type %u", typoid);
  
! 	typmod = typenameTypeMod(pstate, typeName, (Type) tup);
  
  	if (typmod_p)
  		*typmod_p = typmod;
--- 216,223 ----
  	if (!HeapTupleIsValid(tup)) /* should not happen */
  		elog(ERROR, "cache lookup failed for type %u", typoid);
  
! 	if (typmod == -2)
! 		typmod = typenameTypeMod(pstate, typeName, (Type) tup);
  
  	if (typmod_p)
  		*typmod_p = typmod;
diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h
index 5249945..7e82af8 100644
*** a/src/include/parser/parse_node.h
--- b/src/include/parser/parse_node.h
*************** typedef enum ParseExprKind
*** 64,70 ****
  	EXPR_KIND_ALTER_COL_TRANSFORM,		/* transform expr in ALTER COLUMN TYPE */
  	EXPR_KIND_EXECUTE_PARAMETER,	/* parameter value in EXECUTE */
  	EXPR_KIND_TRIGGER_WHEN,		/* WHEN condition in CREATE TRIGGER */
! 	EXPR_KIND_POLICY			/* USING or WITH CHECK expr in policy */
  } ParseExprKind;
  
  
--- 64,71 ----
  	EXPR_KIND_ALTER_COL_TRANSFORM,		/* transform expr in ALTER COLUMN TYPE */
  	EXPR_KIND_EXECUTE_PARAMETER,	/* parameter value in EXECUTE */
  	EXPR_KIND_TRIGGER_WHEN,		/* WHEN condition in CREATE TRIGGER */
! 	EXPR_KIND_POLICY,			/* USING or WITH CHECK expr in policy */
! 	EXPR_KIND_TYPE				/* expr defining type cast */
  } ParseExprKind;
  
  

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to