mirror of
https://github.com/postgres/postgres.git
synced 2025-11-24 00:23:06 +03:00
Fix up the remaining places where the expression node structure would lose
available information about the typmod of an expression; namely, Const, ArrayRef, ArrayExpr, and EXPR and ARRAY SubLinks. In the ArrayExpr and SubLink cases it wasn't really the data structure's fault, but exprTypmod() being lazy. This seems like a good idea in view of the expected increase in typmod usage from Teodor's work to allow user-defined types to have typmods. In particular this responds to the concerns we had about eliminating the special-purpose hack that exprTypmod() used to have for BPCHAR Consts. We can now tell whether or not such a Const has been cast to a specific length, and report or display properly if so. initdb forced due to changes in stored rules.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -186,6 +186,7 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
targetType = typeidType(baseTypeId);
|
||||
|
||||
newcon->consttype = baseTypeId;
|
||||
newcon->consttypmod = -1;
|
||||
newcon->constlen = typeLen(targetType);
|
||||
newcon->constbyval = typeByVal(targetType);
|
||||
newcon->constisnull = con->constisnull;
|
||||
@@ -661,6 +662,7 @@ build_coercion_expression(Node *node, Oid funcId,
|
||||
{
|
||||
/* Pass target typmod as an int4 constant */
|
||||
cons = makeConst(INT4OID,
|
||||
-1,
|
||||
sizeof(int32),
|
||||
Int32GetDatum(targetTypMod),
|
||||
false,
|
||||
@@ -673,6 +675,7 @@ build_coercion_expression(Node *node, Oid funcId,
|
||||
{
|
||||
/* Pass it a boolean isExplicit parameter, too */
|
||||
cons = makeConst(BOOLOID,
|
||||
-1,
|
||||
sizeof(bool),
|
||||
BoolGetDatum(isExplicit),
|
||||
false,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -312,7 +312,7 @@ transformIndirection(ParseState *pstate, Node *basenode, List *indirection)
|
||||
result,
|
||||
exprType(result),
|
||||
InvalidOid,
|
||||
-1,
|
||||
exprTypmod(result),
|
||||
subscripts,
|
||||
NULL);
|
||||
subscripts = NIL;
|
||||
@@ -330,7 +330,7 @@ transformIndirection(ParseState *pstate, Node *basenode, List *indirection)
|
||||
result,
|
||||
exprType(result),
|
||||
InvalidOid,
|
||||
-1,
|
||||
exprTypmod(result),
|
||||
subscripts,
|
||||
NULL);
|
||||
|
||||
@@ -1705,7 +1705,15 @@ exprType(Node *expr)
|
||||
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;
|
||||
@@ -1802,9 +1810,6 @@ exprType(Node *expr)
|
||||
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;
|
||||
@@ -1872,8 +1877,13 @@ exprTypmod(Node *expr)
|
||||
{
|
||||
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;
|
||||
@@ -1883,6 +1893,27 @@ exprTypmod(Node *expr)
|
||||
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:
|
||||
@@ -1920,6 +1951,34 @@ exprTypmod(Node *expr)
|
||||
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:
|
||||
{
|
||||
/*
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -153,7 +153,8 @@ transformArrayType(Oid arrayType)
|
||||
* 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.
|
||||
*/
|
||||
@@ -166,7 +167,6 @@ transformArraySubscripts(ParseState *pstate,
|
||||
List *indirection,
|
||||
Node *assignFrom)
|
||||
{
|
||||
Oid resultType;
|
||||
bool isSlice = false;
|
||||
List *upperIndexpr = NIL;
|
||||
List *lowerIndexpr = NIL;
|
||||
@@ -196,16 +196,6 @@ transformArraySubscripts(ParseState *pstate,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
@@ -235,6 +225,7 @@ transformArraySubscripts(ParseState *pstate,
|
||||
{
|
||||
/* Make a constant 1 */
|
||||
subexpr = (Node *) makeConst(INT4OID,
|
||||
-1,
|
||||
sizeof(int32),
|
||||
Int32GetDatum(1),
|
||||
false,
|
||||
@@ -284,9 +275,9 @@ transformArraySubscripts(ParseState *pstate,
|
||||
* 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;
|
||||
@@ -399,6 +390,7 @@ make_const(Value *value)
|
||||
case T_Null:
|
||||
/* return a null const */
|
||||
con = makeConst(UNKNOWNOID,
|
||||
-1,
|
||||
-2,
|
||||
(Datum) 0,
|
||||
true,
|
||||
@@ -411,6 +403,7 @@ make_const(Value *value)
|
||||
}
|
||||
|
||||
con = makeConst(typeid,
|
||||
-1, /* typmod -1 is OK for all cases */
|
||||
typelen,
|
||||
val,
|
||||
false,
|
||||
|
||||
Reference in New Issue
Block a user