* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.370 2007/03/13 00:33:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.371 2007/03/17 00:11:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
Const *newnode = makeNode(Const);
COPY_SCALAR_FIELD(consttype);
+ COPY_SCALAR_FIELD(consttypmod);
COPY_SCALAR_FIELD(constlen);
if (from->constbyval || from->constisnull)
{
ArrayRef *newnode = makeNode(ArrayRef);
- COPY_SCALAR_FIELD(refrestype);
COPY_SCALAR_FIELD(refarraytype);
COPY_SCALAR_FIELD(refelemtype);
+ COPY_SCALAR_FIELD(reftypmod);
COPY_NODE_FIELD(refupperindexpr);
COPY_NODE_FIELD(reflowerindexpr);
COPY_NODE_FIELD(refexpr);
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.301 2007/03/13 00:33:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.302 2007/03/17 00:11:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
_equalConst(Const *a, Const *b)
{
COMPARE_SCALAR_FIELD(consttype);
+ COMPARE_SCALAR_FIELD(consttypmod);
COMPARE_SCALAR_FIELD(constlen);
COMPARE_SCALAR_FIELD(constisnull);
COMPARE_SCALAR_FIELD(constbyval);
static bool
_equalArrayRef(ArrayRef *a, ArrayRef *b)
{
- COMPARE_SCALAR_FIELD(refrestype);
COMPARE_SCALAR_FIELD(refarraytype);
COMPARE_SCALAR_FIELD(refelemtype);
+ COMPARE_SCALAR_FIELD(reftypmod);
COMPARE_NODE_FIELD(refupperindexpr);
COMPARE_NODE_FIELD(reflowerindexpr);
COMPARE_NODE_FIELD(refexpr);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/makefuncs.c,v 1.54 2007/01/05 22:19:30 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/makefuncs.c,v 1.55 2007/03/17 00:11:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
Const *
makeConst(Oid consttype,
+ int32 consttypmod,
int constlen,
Datum constvalue,
bool constisnull,
Const *cnst = makeNode(Const);
cnst->consttype = consttype;
+ cnst->consttypmod = consttypmod;
cnst->constlen = constlen;
cnst->constvalue = constvalue;
cnst->constisnull = constisnull;
/*
* makeNullConst -
* creates a Const node representing a NULL of the specified type
+ *
+ * Note: for all current uses, OK to set typmod of the Const to -1.
*/
Const *
makeNullConst(Oid consttype)
get_typlenbyval(consttype, &typLen, &typByVal);
return makeConst(consttype,
+ -1,
(int) typLen,
(Datum) 0,
true,
makeBoolConst(bool value, bool isnull)
{
/* note that pg_type.h hardwires size of bool as 1 ... duplicate it */
- return (Node *) makeConst(BOOLOID, 1, BoolGetDatum(value), isnull, true);
+ return (Node *) makeConst(BOOLOID, -1, 1,
+ BoolGetDatum(value), isnull, true);
}
/*
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.303 2007/03/13 00:33:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.304 2007/03/17 00:11:03 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
WRITE_NODE_TYPE("CONST");
WRITE_OID_FIELD(consttype);
+ WRITE_INT_FIELD(consttypmod);
WRITE_INT_FIELD(constlen);
WRITE_BOOL_FIELD(constbyval);
WRITE_BOOL_FIELD(constisnull);
{
WRITE_NODE_TYPE("ARRAYREF");
- WRITE_OID_FIELD(refrestype);
WRITE_OID_FIELD(refarraytype);
WRITE_OID_FIELD(refelemtype);
+ WRITE_INT_FIELD(reftypmod);
WRITE_NODE_FIELD(refupperindexpr);
WRITE_NODE_FIELD(reflowerindexpr);
WRITE_NODE_FIELD(refexpr);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.203 2007/02/20 17:32:15 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.204 2007/03/17 00:11:04 tgl Exp $
*
* NOTES
* Path and Plan nodes do not have any readfuncs support, because we
READ_LOCALS(Const);
READ_OID_FIELD(consttype);
+ READ_INT_FIELD(consttypmod);
READ_INT_FIELD(constlen);
READ_BOOL_FIELD(constbyval);
READ_BOOL_FIELD(constisnull);
{
READ_LOCALS(ArrayRef);
- READ_OID_FIELD(refrestype);
READ_OID_FIELD(refarraytype);
READ_OID_FIELD(refelemtype);
+ READ_INT_FIELD(reftypmod);
READ_NODE_FIELD(refupperindexpr);
READ_NODE_FIELD(reflowerindexpr);
READ_NODE_FIELD(refexpr);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.216 2007/01/20 20:45:39 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.217 2007/03/17 00:11:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
expr = make_opclause(opr1oid, BOOLOID, false,
(Expr *) leftop,
- (Expr *) makeConst(datatype, -1, opr1right,
+ (Expr *) makeConst(datatype, -1, -1, opr1right,
false, false));
result = list_make1(make_restrictinfo(expr, true, false, false, NULL));
expr = make_opclause(opr2oid, BOOLOID, false,
(Expr *) leftop,
- (Expr *) makeConst(datatype, -1, opr2right,
+ (Expr *) makeConst(datatype, -1, -1, opr2right,
false, false));
result = lappend(result,
make_restrictinfo(expr, true, false, false, NULL));
{
Datum conval = string_to_datum(str, datatype);
- return makeConst(datatype, ((datatype == NAMEOID) ? NAMEDATALEN : -1),
+ return makeConst(datatype, -1,
+ ((datatype == NAMEOID) ? NAMEDATALEN : -1),
conval, false, false);
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.29 2007/02/22 22:00:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.30 2007/03/17 00:11:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* set up LIMIT 1 */
subparse->limitOffset = NULL;
- subparse->limitCount = (Node *) makeConst(INT8OID, sizeof(int64),
+ subparse->limitCount = (Node *) makeConst(INT8OID, -1, sizeof(int64),
Int64GetDatum(1),
false, false /* not by val */ );
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.86 2007/02/19 07:03:30 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.87 2007/03/17 00:11:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
if (!att_tup->attisdropped)
{
new_expr = (Node *) makeConst(atttype,
+ -1,
att_tup->attlen,
(Datum) 0,
true, /* isnull */
{
/* Insert NULL for dropped column */
new_expr = (Node *) makeConst(INT4OID,
+ -1,
sizeof(int32),
(Datum) 0,
true, /* isnull */
{
/* Insert NULL for dropped column */
new_expr = (Node *) makeConst(INT4OID,
+ -1,
sizeof(int32),
(Datum) 0,
true, /* isnull */
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.139 2007/02/22 22:00:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.140 2007/03/17 00:11:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* Add a resjunk flag column */
/* flag value is the given constant */
expr = (Node *) makeConst(INT4OID,
+ -1,
sizeof(int4),
Int32GetDatum(flag),
false,
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.238 2007/03/13 00:33:41 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.239 2007/03/17 00:11:04 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
eval_const_expressions_context *context,
bool *haveNull, bool *forceFalse);
static Expr *simplify_boolean_equality(List *args);
-static Expr *simplify_function(Oid funcid, Oid result_type, List *args,
+static Expr *simplify_function(Oid funcid,
+ Oid result_type, int32 result_typmod, List *args,
bool allow_inline,
eval_const_expressions_context *context);
-static Expr *evaluate_function(Oid funcid, Oid result_type, List *args,
+static Expr *evaluate_function(Oid funcid,
+ Oid result_type, int32 result_typmod, List *args,
HeapTuple func_tuple,
eval_const_expressions_context *context);
static Expr *inline_function(Oid funcid, Oid result_type, List *args,
static Node *substitute_actual_parameters_mutator(Node *node,
substitute_actual_parameters_context *context);
static void sql_inline_error_callback(void *arg);
-static Expr *evaluate_expr(Expr *expr, Oid result_type);
+static Expr *evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod);
/*****************************************************************************
return true;
if (IsA(node, CaseExpr))
return true;
- if (IsA(node, CaseWhen))
- return true;
if (IsA(node, ArrayExpr))
return true;
if (IsA(node, RowExpr))
else
pval = datumCopy(prm->value, typByVal, typLen);
return (Node *) makeConst(param->paramtype,
+ param->paramtypmod,
(int) typLen,
pval,
prm->isnull,
/*
* Code for op/func reduction is pretty bulky, so split it out as a
- * separate function.
+ * separate function. Note: exprTypmod normally returns -1 for a
+ * FuncExpr, but not when the node is recognizably a length coercion;
+ * we want to preserve the typmod in the eventual Const if so.
*/
- simple = simplify_function(expr->funcid, expr->funcresulttype, args,
+ simple = simplify_function(expr->funcid,
+ expr->funcresulttype, exprTypmod(node),
+ args,
true, context);
if (simple) /* successfully simplified it */
return (Node *) simple;
* Code for op/func reduction is pretty bulky, so split it out as a
* separate function.
*/
- simple = simplify_function(expr->opfuncid, expr->opresulttype, args,
+ simple = simplify_function(expr->opfuncid,
+ expr->opresulttype, -1,
+ args,
true, context);
if (simple) /* successfully simplified it */
return (Node *) simple;
* Code for op/func reduction is pretty bulky, so split it out as
* a separate function.
*/
- simple = simplify_function(expr->opfuncid, expr->opresulttype,
- args, false, context);
+ simple = simplify_function(expr->opfuncid,
+ expr->opresulttype, -1,
+ args,
+ false, context);
if (simple) /* successfully simplified it */
{
/*
Const *con = (Const *) arg;
con->consttype = relabel->resulttype;
-
- /*
- * relabel's resulttypmod is discarded, which is OK for now; if
- * the type actually needs a runtime length coercion then there
- * should be a function call to do it just above this node.
- */
+ con->consttypmod = relabel->resulttypmod;
return (Node *) con;
}
else
if (all_const)
return (Node *) evaluate_expr((Expr *) newarray,
- newarray->array_typeid);
+ newarray->array_typeid,
+ exprTypmod(node));
return (Node *) newarray;
}
* (which might originally have been an operator; we don't care)
*
* Inputs are the function OID, actual result type OID (which is needed for
- * polymorphic functions), and the pre-simplified argument list;
+ * polymorphic functions) and typmod, and the pre-simplified argument list;
* also the context data for eval_const_expressions.
*
* Returns a simplified expression if successful, or NULL if cannot
* simplify the function call.
*/
static Expr *
-simplify_function(Oid funcid, Oid result_type, List *args,
+simplify_function(Oid funcid, Oid result_type, int32 result_typmod,
+ List *args,
bool allow_inline,
eval_const_expressions_context *context)
{
if (!HeapTupleIsValid(func_tuple))
elog(ERROR, "cache lookup failed for function %u", funcid);
- newexpr = evaluate_function(funcid, result_type, args,
+ newexpr = evaluate_function(funcid, result_type, result_typmod, args,
func_tuple, context);
if (!newexpr && allow_inline)
* simplify the function.
*/
static Expr *
-evaluate_function(Oid funcid, Oid result_type, List *args,
+evaluate_function(Oid funcid, Oid result_type, int32 result_typmod, List *args,
HeapTuple func_tuple,
eval_const_expressions_context *context)
{
newexpr->funcformat = COERCE_DONTCARE; /* doesn't matter */
newexpr->args = args;
- return evaluate_expr((Expr *) newexpr, result_type);
+ return evaluate_expr((Expr *) newexpr, result_type, result_typmod);
}
/*
* code and ensure we get the same result as the executor would get.
*/
static Expr *
-evaluate_expr(Expr *expr, Oid result_type)
+evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod)
{
EState *estate;
ExprState *exprstate;
/*
* Make the constant result node.
*/
- return (Expr *) makeConst(result_type, resultTypLen,
+ return (Expr *) makeConst(result_type, result_typmod, resultTypLen,
const_val, const_is_null,
resultTypByVal);
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.13 2007/01/05 22:19:33 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.14 2007/03/17 00:11:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* Set up a dummy Const node to hold the per-element values */
state->constexpr.xpr.type = T_Const;
state->constexpr.consttype = ARR_ELEMTYPE(arrayval);
+ state->constexpr.consttypmod = -1;
state->constexpr.constlen = elmlen;
state->constexpr.constbyval = elmbyval;
lsecond(state->opexpr.args) = &state->constexpr;
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.150 2007/01/05 22:19:34 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.151 2007/03/17 00:11:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
targetType = typeidType(baseTypeId);
newcon->consttype = baseTypeId;
+ newcon->consttypmod = -1;
newcon->constlen = typeLen(targetType);
newcon->constbyval = typeByVal(targetType);
newcon->constisnull = con->constisnull;
{
/* Pass target typmod as an int4 constant */
cons = makeConst(INT4OID,
+ -1,
sizeof(int32),
Int32GetDatum(targetTypMod),
false,
{
/* Pass it a boolean isExplicit parameter, too */
cons = makeConst(BOOLOID,
+ -1,
sizeof(bool),
BoolGetDatum(isExplicit),
false,
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.212 2007/02/22 22:00:25 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.213 2007/03/17 00:11:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
result,
exprType(result),
InvalidOid,
- -1,
+ exprTypmod(result),
subscripts,
NULL);
subscripts = NIL;
result,
exprType(result),
InvalidOid,
- -1,
+ exprTypmod(result),
subscripts,
NULL);
type = ((Aggref *) expr)->aggtype;
break;
case T_ArrayRef:
- type = ((ArrayRef *) expr)->refrestype;
+ {
+ ArrayRef *arrayref = (ArrayRef *) expr;
+
+ /* slice and/or store operations yield the array type */
+ if (arrayref->reflowerindexpr || arrayref->refassgnexpr)
+ type = arrayref->refarraytype;
+ else
+ type = arrayref->refelemtype;
+ }
break;
case T_FuncExpr:
type = ((FuncExpr *) expr)->funcresulttype;
case T_CaseExpr:
type = ((CaseExpr *) expr)->casetype;
break;
- case T_CaseWhen:
- type = exprType((Node *) ((CaseWhen *) expr)->result);
- break;
case T_CaseTestExpr:
type = ((CaseTestExpr *) expr)->typeId;
break;
{
case T_Var:
return ((Var *) expr)->vartypmod;
+ case T_Const:
+ return ((Const *) expr)->consttypmod;
case T_Param:
return ((Param *) expr)->paramtypmod;
+ case T_ArrayRef:
+ /* typmod is the same for array or element */
+ return ((ArrayRef *) expr)->reftypmod;
case T_FuncExpr:
{
int32 coercedTypmod;
return coercedTypmod;
}
break;
+ case T_SubLink:
+ {
+ SubLink *sublink = (SubLink *) expr;
+
+ if (sublink->subLinkType == EXPR_SUBLINK ||
+ sublink->subLinkType == ARRAY_SUBLINK)
+ {
+ /* get the typmod of the subselect's first target column */
+ Query *qtree = (Query *) sublink->subselect;
+ TargetEntry *tent;
+
+ if (!qtree || !IsA(qtree, Query))
+ elog(ERROR, "cannot get type for untransformed sublink");
+ tent = (TargetEntry *) linitial(qtree->targetList);
+ Assert(IsA(tent, TargetEntry));
+ Assert(!tent->resjunk);
+ return exprTypmod((Node *) tent->expr);
+ /* note we don't need to care if it's an array */
+ }
+ }
+ break;
case T_FieldSelect:
return ((FieldSelect *) expr)->resulttypmod;
case T_RelabelType:
break;
case T_CaseTestExpr:
return ((CaseTestExpr *) expr)->typeMod;
+ case T_ArrayExpr:
+ {
+ /*
+ * If all the elements agree on type/typmod, return that
+ * typmod, else use -1
+ */
+ ArrayExpr *arrayexpr = (ArrayExpr *) expr;
+ Oid arraytype = arrayexpr->array_typeid;
+ int32 typmod;
+ ListCell *elem;
+
+ if (arrayexpr->elements == NIL)
+ return -1;
+ typmod = exprTypmod((Node *) linitial(arrayexpr->elements));
+ if (typmod < 0)
+ return -1; /* no point in trying harder */
+ foreach(elem, arrayexpr->elements)
+ {
+ Node *e = (Node *) lfirst(elem);
+
+ if (exprType(e) != arraytype)
+ return -1;
+ if (exprTypmod(e) != typmod)
+ return -1;
+ }
+ return typmod;
+ }
+ break;
case T_CoalesceExpr:
{
/*
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_node.c,v 1.96 2007/01/05 22:19:34 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_node.c,v 1.97 2007/03/17 00:11:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* arrayType OID of array's datatype (should match type of arrayBase)
* elementType OID of array's element type (fetch with transformArrayType,
* or pass InvalidOid to do it here)
- * elementTypMod typmod to be applied to array elements (if storing)
+ * elementTypMod typmod to be applied to array elements (if storing) or of
+ * the source array (if fetching)
* indirection Untransformed list of subscripts (must not be NIL)
* assignFrom NULL for array fetch, else transformed expression for source.
*/
List *indirection,
Node *assignFrom)
{
- Oid resultType;
bool isSlice = false;
List *upperIndexpr = NIL;
List *lowerIndexpr = NIL;
}
}
- /*
- * The type represented by the subscript expression is the element type if
- * we are fetching a single element, but it is the same as the array type
- * if we are fetching a slice or storing.
- */
- if (isSlice || assignFrom != NULL)
- resultType = arrayType;
- else
- resultType = elementType;
-
/*
* Transform the subscript expressions.
*/
{
/* Make a constant 1 */
subexpr = (Node *) makeConst(INT4OID,
+ -1,
sizeof(int32),
Int32GetDatum(1),
false,
* Ready to build the ArrayRef node.
*/
aref = makeNode(ArrayRef);
- aref->refrestype = resultType;
aref->refarraytype = arrayType;
aref->refelemtype = elementType;
+ aref->reftypmod = elementTypMod;
aref->refupperindexpr = upperIndexpr;
aref->reflowerindexpr = lowerIndexpr;
aref->refexpr = (Expr *) arrayBase;
case T_Null:
/* return a null const */
con = makeConst(UNKNOWNOID,
+ -1,
-2,
(Datum) 0,
true,
}
con = makeConst(typeid,
+ -1, /* typmod -1 is OK for all cases */
typelen,
val,
false,
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.171 2007/03/01 18:50:28 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.172 2007/03/17 00:11:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
else
{
new_expr = (Node *) makeConst(att_tup->atttypid,
+ -1,
att_tup->attlen,
(Datum) 0,
true, /* isnull */
if (!new_expr)
{
new_expr = (Node *) makeConst(att_tup->atttypid,
+ -1,
att_tup->attlen,
(Datum) 0,
true, /* isnull */
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.253 2007/03/15 23:12:06 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.254 2007/03/17 00:11:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
static void get_func_expr(FuncExpr *expr, deparse_context *context,
bool showimplicit);
static void get_agg_expr(Aggref *aggref, deparse_context *context);
-static void get_const_expr(Const *constval, deparse_context *context);
+static void get_coercion_expr(Node *arg, deparse_context *context,
+ Oid resulttype, int32 resulttypmod,
+ Node *parentNode);
+static void get_const_expr(Const *constval, deparse_context *context,
+ bool showtype);
static void get_sublink_expr(SubLink *sublink, deparse_context *context);
static void get_from_clause(Query *query, const char *prefix,
deparse_context *context);
break;
case T_Const:
- get_const_expr((Const *) node, context);
+ get_const_expr((Const *) node, context, true);
break;
case T_Param:
}
else
{
- if (!PRETTY_PAREN(context))
- appendStringInfoChar(buf, '(');
- get_rule_expr_paren(arg, context, false, node);
- if (!PRETTY_PAREN(context))
- appendStringInfoChar(buf, ')');
- appendStringInfo(buf, "::%s",
- format_type_with_typemod(relabel->resulttype,
- relabel->resulttypmod));
+ get_coercion_expr(arg, context,
+ relabel->resulttype,
+ relabel->resulttypmod,
+ node);
}
}
break;
}
else
{
- if (!PRETTY_PAREN(context))
- appendStringInfoChar(buf, '(');
- get_rule_expr_paren(arg, context, false, node);
- if (!PRETTY_PAREN(context))
- appendStringInfoChar(buf, ')');
- appendStringInfo(buf, "::%s",
- format_type_with_typemod(convert->resulttype, -1));
+ get_coercion_expr(arg, context,
+ convert->resulttype, -1,
+ node);
}
}
break;
}
else
{
- if (!PRETTY_PAREN(context))
- appendStringInfoChar(buf, '(');
- get_rule_expr_paren(arg, context, false, node);
- if (!PRETTY_PAREN(context))
- appendStringInfoChar(buf, ')');
- appendStringInfo(buf, "::%s",
- format_type_with_typemod(ctest->resulttype,
- ctest->resulttypmod));
+ get_coercion_expr(arg, context,
+ ctest->resulttype,
+ ctest->resulttypmod,
+ node);
}
}
break;
/* Get the typmod if this is a length-coercion function */
(void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
- if (!PRETTY_PAREN(context))
- appendStringInfoChar(buf, '(');
- get_rule_expr_paren(arg, context, false, (Node *) expr);
- if (!PRETTY_PAREN(context))
- appendStringInfoChar(buf, ')');
- appendStringInfo(buf, "::%s",
- format_type_with_typemod(rettype, coercedTypmod));
+ get_coercion_expr(arg, context,
+ rettype, coercedTypmod,
+ (Node *) expr);
return;
}
appendStringInfoChar(buf, ')');
}
+/* ----------
+ * get_coercion_expr
+ *
+ * Make a string representation of a value coerced to a specific type
+ * ----------
+ */
+static void
+get_coercion_expr(Node *arg, deparse_context *context,
+ Oid resulttype, int32 resulttypmod,
+ Node *parentNode)
+{
+ StringInfo buf = context->buf;
+
+ /*
+ * Since parse_coerce.c doesn't immediately collapse application of
+ * length-coercion functions to constants, what we'll typically see
+ * in such cases is a Const with typmod -1 and a length-coercion
+ * function right above it. Avoid generating redundant output.
+ * However, beware of suppressing casts when the user actually wrote
+ * something like 'foo'::text::char(3).
+ */
+ if (arg && IsA(arg, Const) &&
+ ((Const *) arg)->consttype == resulttype &&
+ ((Const *) arg)->consttypmod == -1)
+ {
+ /* Show the constant without normal ::typename decoration */
+ get_const_expr((Const *) arg, context, false);
+ }
+ else
+ {
+ if (!PRETTY_PAREN(context))
+ appendStringInfoChar(buf, '(');
+ get_rule_expr_paren(arg, context, false, parentNode);
+ if (!PRETTY_PAREN(context))
+ appendStringInfoChar(buf, ')');
+ }
+ appendStringInfo(buf, "::%s",
+ format_type_with_typemod(resulttype, resulttypmod));
+}
/* ----------
* get_const_expr
*
* Make a string representation of a Const
+ *
+ * Note: if showtype is false, the Const is the direct argument of a coercion
+ * operation with the same target type, and so we should suppress "::typename"
+ * to avoid redundant output.
* ----------
*/
static void
-get_const_expr(Const *constval, deparse_context *context)
+get_const_expr(Const *constval, deparse_context *context, bool showtype)
{
StringInfo buf = context->buf;
Oid typoutput;
* Always label the type of a NULL constant to prevent misdecisions
* about type when reparsing.
*/
- appendStringInfo(buf, "NULL::%s",
- format_type_with_typemod(constval->consttype, -1));
+ appendStringInfo(buf, "NULL");
+ if (showtype)
+ appendStringInfo(buf, "::%s",
+ format_type_with_typemod(constval->consttype,
+ constval->consttypmod));
return;
}
pfree(extval);
+ if (!showtype)
+ return;
+
/*
* Append ::typename unless the constant will be implicitly typed as the
* right type when it is read in. XXX this code has to be kept in sync
}
if (needlabel)
appendStringInfo(buf, "::%s",
- format_type_with_typemod(constval->consttype, -1));
+ format_type_with_typemod(constval->consttype,
+ constval->consttypmod));
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.228 2007/02/27 23:48:09 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.229 2007/03/17 00:11:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
args = list_make2(leftop,
makeConst(nominal_element_type,
+ -1,
elmlen,
elem_values[i],
elem_nulls[i],
{
Datum conval = string_to_datum(str, datatype);
- return makeConst(datatype, ((datatype == NAMEOID) ? NAMEDATALEN : -1),
+ return makeConst(datatype, -1,
+ ((datatype == NAMEOID) ? NAMEDATALEN : -1),
conval, false, false);
}
SET_VARSIZE(bstr, VARHDRSZ + str_len);
conval = PointerGetDatum(bstr);
- return makeConst(BYTEAOID, -1, conval, false, false);
+ return makeConst(BYTEAOID, -1, -1, conval, false, false);
}
/*-------------------------------------------------------------------------
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.148 2007/02/14 01:58:57 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.149 2007/03/17 00:11:05 tgl Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
getTypeIOParam(typeTuple), -1);
/* Build a Const node containing the value */
expr = (Node *) makeConst(typid,
+ -1,
type->typlen,
datum,
false,
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.390 2007/03/16 17:57:36 mha Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.391 2007/03/17 00:11:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200703161
+#define CATALOG_VERSION_NO 200703162
#endif
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/makefuncs.h,v 1.57 2007/01/05 22:19:55 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/makefuncs.h,v 1.58 2007/03/17 00:11:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern TargetEntry *flatCopyTargetEntry(TargetEntry *src_tle);
extern Const *makeConst(Oid consttype,
+ int32 consttypmod,
int constlen,
Datum constvalue,
bool constisnull,
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.127 2007/02/22 22:00:25 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.128 2007/03/17 00:11:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
typedef struct Const
{
Expr xpr;
- Oid consttype; /* PG_TYPE OID of the constant's datatype */
+ Oid consttype; /* pg_type OID of the constant's datatype */
+ int32 consttypmod; /* typmod value, if any */
int constlen; /* typlen of the constant's datatype */
Datum constvalue; /* the constant's value */
bool constisnull; /* whether the constant is null (if true,
* reflowerindexpr must be the same length as refupperindexpr when it
* is not NIL.
*
- * Note: refrestype is NOT the element type, but the array type,
- * when doing subarray fetch or either type of store.
+ * Note: the result datatype is the element type when fetching a single
+ * element; but it is the array type when doing subarray fetch or either
+ * type of store.
* ----------------
*/
typedef struct ArrayRef
{
Expr xpr;
- Oid refrestype; /* type of the result of the ArrayRef
- * operation */
Oid refarraytype; /* type of the array proper */
Oid refelemtype; /* type of the array elements */
+ int32 reftypmod; /* typmod of the array (and elements too) */
List *refupperindexpr;/* expressions that evaluate to upper array
* indexes */
List *reflowerindexpr;/* expressions that evaluate to lower array