aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/parse_coerce.c5
-rw-r--r--src/backend/parser/parse_expr.c73
-rw-r--r--src/backend/parser/parse_node.c21
3 files changed, 77 insertions, 22 deletions
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index 55f50713b31..00ce2a9927f 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -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,
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 5791215a95f..3da003fd09a 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.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:
{
/*
diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c
index 4836159805b..a8dfa2666bb 100644
--- a/src/backend/parser/parse_node.c
+++ b/src/backend/parser/parse_node.c
@@ -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;
@@ -197,16 +197,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.
*/
foreach(idx, indirection)
@@ -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,