diff options
Diffstat (limited to 'src/backend/parser/parse_expr.c')
-rw-r--r-- | src/backend/parser/parse_expr.c | 93 |
1 files changed, 60 insertions, 33 deletions
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 9f0a501dc53..45e488e33f5 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.214 2007/03/17 01:15:55 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.215 2007/03/27 23:21:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -265,6 +265,7 @@ transformExpr(ParseState *pstate, Node *expr) case T_FieldSelect: case T_FieldStore: case T_RelabelType: + case T_ArrayCoerceExpr: case T_ConvertRowtypeExpr: case T_CaseTestExpr: case T_CoerceToDomain: @@ -1804,6 +1805,9 @@ exprType(Node *expr) case T_RelabelType: type = ((RelabelType *) expr)->resulttype; break; + case T_ArrayCoerceExpr: + type = ((ArrayCoerceExpr *) expr)->resulttype; + break; case T_ConvertRowtypeExpr: type = ((ConvertRowtypeExpr *) expr)->resulttype; break; @@ -1918,6 +1922,8 @@ exprTypmod(Node *expr) return ((FieldSelect *) expr)->resulttypmod; case T_RelabelType: return ((RelabelType *) expr)->resulttypmod; + case T_ArrayCoerceExpr: + return ((ArrayCoerceExpr *) expr)->resulttypmod; case T_CaseExpr: { /* @@ -2072,47 +2078,68 @@ exprTypmod(Node *expr) bool exprIsLengthCoercion(Node *expr, int32 *coercedTypmod) { - FuncExpr *func; - int nargs; - Const *second_arg; - if (coercedTypmod != NULL) *coercedTypmod = -1; /* default result on failure */ - /* Is it a function-call at all? */ - if (expr == NULL || !IsA(expr, FuncExpr)) - return false; - func = (FuncExpr *) expr; - /* - * If it didn't come from a coercion context, reject. + * Scalar-type length coercions are FuncExprs, array-type length + * coercions are ArrayCoerceExprs */ - if (func->funcformat != COERCE_EXPLICIT_CAST && - func->funcformat != COERCE_IMPLICIT_CAST) - return false; + if (expr && IsA(expr, FuncExpr)) + { + FuncExpr *func = (FuncExpr *) expr; + int nargs; + Const *second_arg; - /* - * If it's not a two-argument or three-argument function with the second - * argument being an int4 constant, it can't have been created from a - * length coercion (it must be a type coercion, instead). - */ - nargs = list_length(func->args); - if (nargs < 2 || nargs > 3) - return false; + /* + * If it didn't come from a coercion context, reject. + */ + if (func->funcformat != COERCE_EXPLICIT_CAST && + func->funcformat != COERCE_IMPLICIT_CAST) + return false; - second_arg = (Const *) lsecond(func->args); - if (!IsA(second_arg, Const) || - second_arg->consttype != INT4OID || - second_arg->constisnull) - return false; + /* + * If it's not a two-argument or three-argument function with the + * second argument being an int4 constant, it can't have been created + * from a length coercion (it must be a type coercion, instead). + */ + nargs = list_length(func->args); + if (nargs < 2 || nargs > 3) + return false; - /* - * OK, it is indeed a length-coercion function. - */ - if (coercedTypmod != NULL) - *coercedTypmod = DatumGetInt32(second_arg->constvalue); + second_arg = (Const *) lsecond(func->args); + if (!IsA(second_arg, Const) || + second_arg->consttype != INT4OID || + second_arg->constisnull) + return false; + + /* + * OK, it is indeed a length-coercion function. + */ + if (coercedTypmod != NULL) + *coercedTypmod = DatumGetInt32(second_arg->constvalue); + + return true; + } + + if (expr && IsA(expr, ArrayCoerceExpr)) + { + ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) expr; + + /* It's not a length coercion unless there's a nondefault typmod */ + if (acoerce->resulttypmod < 0) + return false; + + /* + * OK, it is indeed a length-coercion expression. + */ + if (coercedTypmod != NULL) + *coercedTypmod = acoerce->resulttypmod; + + return true; + } - return true; + return false; } /* |