Commit 7f76eab1 authored by Tom Lane's avatar Tom Lane

Rewrite parser's handling of INSERT ... SELECT so that processing

of the SELECT part of the statement is just like a plain SELECT.  All
INSERT-specific processing happens after the SELECT parsing is done.
This eliminates many problems, e.g. INSERT ... SELECT ... GROUP BY using
the wrong column labels.  Ensure that DEFAULT clauses are coerced to
the target column type, whether or not stored clause produces the right
type.  Substantial cleanup of parser's array support.
parent c9814427
......@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.57 1999/07/17 20:16:57 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.58 1999/07/19 00:26:15 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -86,31 +86,44 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
bool *isNull,
bool *isDone)
{
bool dummy;
int i = 0,
j = 0;
ArrayType *array_scanner;
List *upperIndexpr,
*lowerIndexpr;
Node *assgnexpr;
List *elt;
int i = 0,
j = 0;
IntArray upper,
lower;
int *lIndex;
char *dataPtr;
bool dummy;
*isNull = false;
array_scanner = (ArrayType *) ExecEvalExpr(arrayRef->refexpr,
econtext,
isNull,
isDone);
if (*isNull)
return (Datum) NULL;
upperIndexpr = arrayRef->refupperindexpr;
if (arrayRef->refexpr != NULL)
{
array_scanner = (ArrayType *) ExecEvalExpr(arrayRef->refexpr,
econtext,
isNull,
isDone);
if (*isNull)
return (Datum) NULL;
}
else
{
/* Null refexpr indicates we are doing an INSERT into an array column.
* For now, we just take the refassgnexpr (which the parser will have
* ensured is an array value) and return it as-is, ignoring any
* subscripts that may have been supplied in the INSERT column list.
* This is a kluge, but it's not real clear what the semantics ought
* to be...
*/
array_scanner = NULL;
}
foreach(elt, upperIndexpr)
foreach(elt, arrayRef->refupperindexpr)
{
if (i >= MAXDIM)
elog(ERROR, "ExecEvalArrayRef: can only handle %d dimensions",
MAXDIM);
upper.indx[i++] = (int32) ExecEvalExpr((Node *) lfirst(elt),
econtext,
isNull,
......@@ -119,12 +132,14 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
return (Datum) NULL;
}
lowerIndexpr = arrayRef->reflowerindexpr;
lIndex = NULL;
if (lowerIndexpr != NIL)
if (arrayRef->reflowerindexpr != NIL)
{
foreach(elt, lowerIndexpr)
foreach(elt, arrayRef->reflowerindexpr)
{
if (j >= MAXDIM)
elog(ERROR, "ExecEvalArrayRef: can only handle %d dimensions",
MAXDIM);
lower.indx[j++] = (int32) ExecEvalExpr((Node *) lfirst(elt),
econtext,
isNull,
......@@ -137,30 +152,42 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
"ExecEvalArrayRef: upper and lower indices mismatch");
lIndex = lower.indx;
}
else
{
lIndex = NULL;
}
assgnexpr = arrayRef->refassgnexpr;
if (assgnexpr != NULL)
if (arrayRef->refassgnexpr != NULL)
{
dataPtr = (char *) ExecEvalExpr((Node *)
assgnexpr, econtext,
isNull, &dummy);
Datum sourceData = ExecEvalExpr(arrayRef->refassgnexpr,
econtext,
isNull,
&dummy);
if (*isNull)
return (Datum) NULL;
execConstByVal = arrayRef->refelembyval;
execConstLen = arrayRef->refelemlength;
if (array_scanner == NULL)
return sourceData; /* XXX do something else? */
if (lIndex == NULL)
return (Datum) array_set(array_scanner, i, upper.indx, dataPtr,
return (Datum) array_set(array_scanner, i, upper.indx,
(char *) sourceData,
arrayRef->refelembyval,
arrayRef->refelemlength,
arrayRef->refattrlength, isNull);
return (Datum) array_assgn(array_scanner, i, upper.indx,
lower.indx,
(ArrayType *) dataPtr,
(ArrayType *) sourceData,
arrayRef->refelembyval,
arrayRef->refelemlength, isNull);
}
execConstByVal = arrayRef->refelembyval;
execConstLen = arrayRef->refelemlength;
if (lIndex == NULL)
return (Datum) array_ref(array_scanner, i, upper.indx,
arrayRef->refelembyval,
......
This diff is collapsed.
This diff is collapsed.
......@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.54 1999/07/17 20:17:23 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.55 1999/07/19 00:26:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -30,7 +30,7 @@ static Node *parser_typecast(Value *expr, TypeName *typename, int32 atttypmod);
static Node *transformAttr(ParseState *pstate, Attr *att, int precedence);
static Node *transformIdent(ParseState *pstate, Ident *ident, int precedence);
static Node *transformIndirection(ParseState *pstate, Node *basenode,
List *indirection, int precedence);
List *indirection);
/*
* transformExpr -
......@@ -81,7 +81,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
param->paramtype = (Oid) toid;
param->param_tlist = (List *) NULL;
result = transformIndirection(pstate, (Node *) param,
pno->indirection, precedence);
pno->indirection);
break;
}
case T_A_Expr:
......@@ -467,37 +467,12 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
}
static Node *
transformIndirection(ParseState *pstate, Node *basenode,
List *indirection, int precedence)
transformIndirection(ParseState *pstate, Node *basenode, List *indirection)
{
List *idx;
if (indirection == NIL)
return basenode;
foreach (idx, indirection)
{
A_Indices *ai = (A_Indices *) lfirst(idx);
Node *lexpr = NULL,
*uexpr;
/* uidx is always present, but lidx might be null */
if (ai->lidx != NULL)
{
lexpr = transformExpr(pstate, ai->lidx, precedence);
if (exprType(lexpr) != INT4OID)
elog(ERROR, "array index expressions must be int4's");
}
uexpr = transformExpr(pstate, ai->uidx, precedence);
if (exprType(uexpr) != INT4OID)
elog(ERROR, "array index expressions must be int4's");
ai->lidx = lexpr;
ai->uidx = uexpr;
/*
* note we reuse the list of A_Indices nodes, make sure
* we don't free them! Otherwise, make a new list here
*/
}
return (Node *) make_array_ref(basenode, indirection);
return (Node *) transformArraySubscripts(pstate, basenode,
indirection, false, NULL);
}
static Node *
......@@ -505,11 +480,9 @@ transformAttr(ParseState *pstate, Attr *att, int precedence)
{
Node *basenode;
/* what if att->attrs == "*"? */
basenode = ParseNestedFuncOrColumn(pstate, att, &pstate->p_last_resno,
precedence);
return transformIndirection(pstate, basenode,
att->indirection, precedence);
return transformIndirection(pstate, basenode, att->indirection);
}
static Node *
......@@ -555,7 +528,7 @@ transformIdent(ParseState *pstate, Ident *ident, int precedence)
Oid
exprType(Node *expr)
{
Oid type = (Oid) 0;
Oid type = (Oid) InvalidOid;
if (!expr)
return type;
......@@ -622,6 +595,42 @@ exprType(Node *expr)
return type;
}
/*
* exprTypmod -
* returns the type-specific attrmod of the expression, if it can be
* determined. In most cases, it can't and we return -1.
*/
int32
exprTypmod(Node *expr)
{
if (!expr)
return -1;
switch (nodeTag(expr))
{
case T_Var:
return ((Var *) expr)->vartypmod;
case T_Const:
{
/* Be smart about string constants... */
Const *con = (Const *) expr;
switch (con->consttype)
{
case BPCHAROID:
if (! con->constisnull)
return VARSIZE(DatumGetPointer(con->constvalue));
break;
default:
break;
}
}
break;
default:
break;
}
return -1;
}
static Node *
parser_typecast(Value *expr, TypeName *typename, int32 atttypmod)
{
......
......@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.28 1999/07/17 20:17:24 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.29 1999/07/19 00:26:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -24,6 +24,7 @@
#include "parser/parse_node.h"
#include "parser/parse_oper.h"
#include "parser/parse_relation.h"
#include "parser/parse_target.h"
#include "parser/parse_type.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
......@@ -222,164 +223,184 @@ make_var(ParseState *pstate, Oid relid, char *refname,
}
/*
* make_array_ref() -- Make an array reference node.
* transformArraySubscripts()
* Transform array subscripting. This is used for both
* array fetch and array assignment.
*
* Array references can hang off of arbitrary nested dot (or
* function invocation) expressions. This routine takes a
* tree generated by ParseFunc() and an array index and
* generates a new array reference tree. We do some simple
* typechecking to be sure the dereference is valid in the
* type system, but we don't do any bounds checking here.
* In an array fetch, we are given a source array value and we produce an
* expression that represents the result of extracting a single array element
* or an array slice.
*
* indirection is a list of A_Indices
* In an array assignment, we are given a destination array value plus a
* source value that is to be assigned to a single element or a slice of
* that array. We produce an expression that represents the new array value
* with the source data inserted into the right part of the array.
*
* pstate Parse state
* arrayBase Already-transformed expression for the array as a whole
* indirection Untransformed list of subscripts (must not be NIL)
* forceSlice If true, treat subscript as array slice in all cases
* assignFrom NULL for array fetch, else transformed expression for source.
*/
ArrayRef *
make_array_ref(Node *expr,
List *indirection)
ArrayRef *
transformArraySubscripts(ParseState *pstate,
Node *arrayBase,
List *indirection,
bool forceSlice,
Node *assignFrom)
{
Oid typearray;
Oid typearray,
typeelement,
typeresult;
HeapTuple type_tuple;
Form_pg_type type_struct_array,
type_struct_element;
ArrayRef *aref;
Oid reftype;
bool isSlice = forceSlice;
List *upperIndexpr = NIL;
List *lowerIndexpr = NIL;
List *idx;
ArrayRef *aref;
typearray = exprType(expr);
/* Get the type tuple for the array */
typearray = exprType(arrayBase);
type_tuple = SearchSysCacheTuple(TYPOID,
ObjectIdGetDatum(typearray),
0, 0, 0);
if (!HeapTupleIsValid(type_tuple))
elog(ERROR, "make_array_ref: Cache lookup failed for type %u\n",
elog(ERROR, "transformArraySubscripts: Cache lookup failed for array type %u",
typearray);
/* get the array type struct from the type tuple */
type_struct_array = (Form_pg_type) GETSTRUCT(type_tuple);
if (type_struct_array->typelem == InvalidOid)
elog(ERROR, "make_array_ref: type %s is not an array",
typeelement = type_struct_array->typelem;
if (typeelement == InvalidOid)
elog(ERROR, "transformArraySubscripts: type %s is not an array",
type_struct_array->typname);
/* get the type tuple for the element type */
/* Get the type tuple for the array element type */
type_tuple = SearchSysCacheTuple(TYPOID,
ObjectIdGetDatum(type_struct_array->typelem),
ObjectIdGetDatum(typeelement),
0, 0, 0);
if (!HeapTupleIsValid(type_tuple))
elog(ERROR, "make_array_ref: Cache lookup failed for type %u\n",
typearray);
elog(ERROR, "transformArraySubscripts: Cache lookup failed for array element type %u",
typeelement);
type_struct_element = (Form_pg_type) GETSTRUCT(type_tuple);
while (indirection != NIL)
/*
* A list containing only single subscripts refers to a single array
* element. If any of the items are double subscripts (lower:upper),
* then the subscript expression means an array slice operation.
* In this case, we supply a default lower bound of 1 for any items
* that contain only a single subscript.
* The forceSlice parameter forces us to treat the operation as a
* slice, even if no lower bounds are mentioned. Otherwise,
* we have to prescan the indirection list to see if there are any
* double subscripts.
*/
if (! isSlice)
{
A_Indices *ind = lfirst(indirection);
if (ind->lidx)
/*
* XXX assumes all lower indices non null in this case
*/
lowerIndexpr = lappend(lowerIndexpr, ind->lidx);
upperIndexpr = lappend(upperIndexpr, ind->uidx);
indirection = lnext(indirection);
foreach (idx, indirection)
{
A_Indices *ai = (A_Indices *) lfirst(idx);
if (ai->lidx != NULL)
{
isSlice = true;
break;
}
}
}
aref = makeNode(ArrayRef);
aref->refattrlength = type_struct_array->typlen;
aref->refelemlength = type_struct_element->typlen;
aref->refelemtype = type_struct_array->typelem;
aref->refelembyval = type_struct_element->typbyval;
aref->refupperindexpr = upperIndexpr;
aref->reflowerindexpr = lowerIndexpr;
aref->refexpr = expr;
aref->refassgnexpr = NULL;
if (lowerIndexpr == NIL) /* accessing a single array element */
reftype = aref->refelemtype;
/* 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)
typeresult = typearray;
else
/* request to clip a part of the array, the result is another array */
reftype = typearray;
typeresult = typeelement;
/*
* we change it to reflect the true type; since the original
* refelemtype doesn't seem to get used anywhere. - ay 10/94
* Transform the subscript expressions.
*/
aref->refelemtype = reftype;
return aref;
}
/* make_array_set()
*/
ArrayRef *
make_array_set(Expr *target_expr,
List *upperIndexpr,
List *lowerIndexpr,
Expr *expr)
{
Oid typearray;
HeapTuple type_tuple;
Form_pg_type type_struct_array;
Form_pg_type type_struct_element;
ArrayRef *aref;
Oid reftype;
typearray = exprType((Node *) target_expr);
type_tuple = SearchSysCacheTuple(TYPOID,
ObjectIdGetDatum(typearray),
0, 0, 0);
if (!HeapTupleIsValid(type_tuple))
elog(ERROR, "make_array_ref: Cache lookup failed for type %u\n",
typearray);
/* get the array type struct from the type tuple */
type_struct_array = (Form_pg_type) GETSTRUCT(type_tuple);
foreach (idx, indirection)
{
A_Indices *ai = (A_Indices *) lfirst(idx);
Node *subexpr;
if (type_struct_array->typelem == InvalidOid)
elog(ERROR, "make_array_ref: type %s is not an array",
type_struct_array->typname);
/* get the type tuple for the element type */
type_tuple = SearchSysCacheTuple(TYPOID,
ObjectIdGetDatum(type_struct_array->typelem),
0, 0, 0);
if (isSlice)
{
if (ai->lidx)
{
subexpr = transformExpr(pstate, ai->lidx, EXPR_COLUMN_FIRST);
/* If it's not int4 already, try to coerce */
subexpr = CoerceTargetExpr(pstate, subexpr,
exprType(subexpr), INT4OID);
if (subexpr == NULL)
elog(ERROR, "array index expressions must be integers");
}
else
{
/* Make a constant 1 */
subexpr = (Node *) makeConst(INT4OID,
sizeof(int32),
Int32GetDatum(1),
false,
true, /* pass by value */
false,
false);
}
lowerIndexpr = lappend(lowerIndexpr, subexpr);
}
subexpr = transformExpr(pstate, ai->uidx, EXPR_COLUMN_FIRST);
/* If it's not int4 already, try to coerce */
subexpr = CoerceTargetExpr(pstate, subexpr,
exprType(subexpr), INT4OID);
if (subexpr == NULL)
elog(ERROR, "array index expressions must be integers");
upperIndexpr = lappend(upperIndexpr, subexpr);
}
if (!HeapTupleIsValid(type_tuple))
elog(ERROR, "make_array_ref: Cache lookup failed for type %u\n",
typearray);
/*
* If doing an array store, coerce the source value to the right type.
*/
if (assignFrom != NULL)
{
Oid typesource = exprType(assignFrom);
Oid typeneeded = isSlice ? typearray : typeelement;
type_struct_element = (Form_pg_type) GETSTRUCT(type_tuple);
if (typesource != InvalidOid)
{
if (typesource != typeneeded)
{
assignFrom = CoerceTargetExpr(pstate, assignFrom,
typesource, typeneeded);
if (assignFrom == NULL)
elog(ERROR, "Array assignment requires type '%s'"
" but expression is of type '%s'"
"\n\tYou will need to rewrite or cast the expression",
typeidTypeName(typeneeded),
typeidTypeName(typesource));
}
}
}
/*
* Ready to build the ArrayRef node.
*/
aref = makeNode(ArrayRef);
aref->refattrlength = type_struct_array->typlen;
aref->refelemlength = type_struct_element->typlen;
aref->refelemtype = type_struct_array->typelem;
aref->refelemtype = typeresult; /* XXX should save element type too */
aref->refelembyval = type_struct_element->typbyval;
aref->refupperindexpr = upperIndexpr;
aref->reflowerindexpr = lowerIndexpr;
aref->refexpr = (Node *) target_expr;
aref->refassgnexpr = (Node *) expr;
/* accessing a single array element? */
if (lowerIndexpr == NIL)
reftype = aref->refelemtype;
/* otherwise, request to set a part of the array, by another array */
else
reftype = typearray;
aref->refelemtype = reftype;
aref->refexpr = arrayBase;
aref->refassgnexpr = assignFrom;
return aref;
}
/*
*
* make_const -
*
* - takes a lispvalue, (as returned to the yacc routine by the lexer)
......
......@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.25 1999/07/17 20:17:25 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.26 1999/07/19 00:26:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -25,10 +25,8 @@
#include "utils/builtins.h"
#include "utils/lsyscache.h"
static void checkTargetTypes(ParseState *pstate, char *target_colname,
char *refname, char *colname);
struct
static struct
{
char *field;
int code;
......@@ -97,7 +95,6 @@ refnameRangeTablePosn(ParseState *pstate, char *refname, int *sublevels_up)
int index;
List *temp;
if (sublevels_up)
*sublevels_up = 0;
......@@ -175,7 +172,7 @@ colnameRangeTableEntry(ParseState *pstate, char *colname)
/*
* put new entry in pstate p_rtable structure, or return pointer
* if pstate null
*/
*/
RangeTblEntry *
addRangeTableEntry(ParseState *pstate,
char *relname,
......@@ -239,38 +236,31 @@ addRangeTableEntry(ParseState *pstate,
List *
expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
{
List *te_list = NIL;
RangeTblEntry *rte;
Relation rel;
List *te_tail = NIL,
*te_head = NIL;
Var *varnode;
int varattno,
maxattrs;
RangeTblEntry *rte;
rte = refnameRangeTableEntry(pstate, refname);
if (rte == NULL)
rte = addRangeTableEntry(pstate, relname, refname, FALSE, FALSE);
rel = heap_open(rte->relid);
if (rel == NULL)
elog(ERROR, "Unable to expand all -- heap_open failed on %s",
rte->refname);
maxattrs = RelationGetNumberOfAttributes(rel);
for (varattno = 0; varattno <= maxattrs - 1; varattno++)
for (varattno = 0; varattno < maxattrs; varattno++)
{
char *attrname;
char *resname = NULL;
Var *varnode;
TargetEntry *te = makeNode(TargetEntry);
attrname = pstrdup((rel->rd_att->attrs[varattno]->attname).data);
varnode = (Var *) make_var(pstate, rte->relid, refname, attrname);
handleTargetColname(pstate, &resname, refname, attrname);
if (resname != NULL)
attrname = resname;
attrname = pstrdup(rel->rd_att->attrs[varattno]->attname.data);
varnode = make_var(pstate, rte->relid, refname, attrname);
/*
* Even if the elements making up a set are complex, the set
......@@ -285,15 +275,12 @@ expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
(Oid) 0,
false);
te->expr = (Node *) varnode;
if (te_head == NIL)
te_head = te_tail = lcons(te, NIL);
else
te_tail = lappend(te_tail, te);
te_list = lappend(te_list, te);
}
heap_close(rel);
return te_head;
return te_list;
}
/*
......@@ -378,102 +365,3 @@ attnumTypeId(Relation rd, int attid)
*/
return rd->rd_att->attrs[attid - 1]->atttypid;
}
/* handleTargetColname()
* Use column names from insert.
*/
void
handleTargetColname(ParseState *pstate, char **resname,
char *refname, char *colname)
{
if (pstate->p_is_insert)
{
if (pstate->p_insert_columns != NIL)
{
Ident *id = lfirst(pstate->p_insert_columns);
*resname = id->name;
pstate->p_insert_columns = lnext(pstate->p_insert_columns);
}
else
elog(ERROR, "INSERT has more expressions than target columns");
}
if (pstate->p_is_insert || pstate->p_is_update)
checkTargetTypes(pstate, *resname, refname, colname);
}
/* checkTargetTypes()
* Checks value and target column types.
*/
static void
checkTargetTypes(ParseState *pstate, char *target_colname,
char *refname, char *colname)
{
Oid attrtype_id,
attrtype_target;
int resdomno_id,
resdomno_target;
RangeTblEntry *rte;
if (target_colname == NULL || colname == NULL)
return;
if (refname != NULL)
rte = refnameRangeTableEntry(pstate, refname);
else
{
rte = colnameRangeTableEntry(pstate, colname);
if (rte == (RangeTblEntry *) NULL)
elog(ERROR, "Attribute %s not found", colname);
refname = rte->refname;
}
/*
if (pstate->p_is_insert && rte == pstate->p_target_rangetblentry)
elog(ERROR, "'%s' not available in this context", colname);
*/
resdomno_id = get_attnum(rte->relid, colname);
attrtype_id = get_atttype(rte->relid, resdomno_id);
resdomno_target = attnameAttNum(pstate->p_target_relation, target_colname);
attrtype_target = attnumTypeId(pstate->p_target_relation, resdomno_target);
#ifdef NOT_USED
if ((attrtype_id != attrtype_target)
|| (get_atttypmod(rte->relid, resdomno_id) !=
get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target)))
{
if (can_coerce_type(1, &attrtype_id, &attrtype_target))
{
Node *expr = coerce_type(pstate, expr, attrtype_id,
attrtype_target,
get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target));
elog(ERROR, "Type %s(%d) can be coerced to match target column %s(%d)",
colname, get_atttypmod(rte->relid, resdomno_id),
target_colname, get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target));
}
else
{
elog(ERROR, "Type or size of %s(%d) does not match target column %s(%d)",
colname, get_atttypmod(rte->relid, resdomno_id),
target_colname, get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target));
}
}
#else
if (attrtype_id != attrtype_target)
elog(ERROR, "Type of '%s' does not match target column '%s'",
colname, target_colname);
if (attrtype_id == BPCHAROID &&
get_atttypmod(rte->relid, resdomno_id) !=
get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target))
elog(ERROR, "Length of '%s' is not equal to the length of target column '%s'",
colname, target_colname);
if (attrtype_id == VARCHAROID &&
get_atttypmod(rte->relid, resdomno_id) >
get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target))
elog(ERROR, "Length of '%s' is longer than length of target column '%s'",
colname, target_colname);
#endif
}
This diff is collapsed.
......@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_clause.h,v 1.11 1999/07/15 23:04:01 momjian Exp $
* $Id: parse_clause.h,v 1.12 1999/07/19 00:26:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -15,8 +15,10 @@
#include "parser/parse_node.h"
extern void makeRangeTable(ParseState *pstate, char *relname, List *frmList, Node **qual);
extern Node *transformWhereClause(ParseState *pstate, Node *where, Node *using);
extern void makeRangeTable(ParseState *pstate, List *frmList, Node **qual);
extern void setTargetTable(ParseState *pstate, char *relname);
extern Node *transformWhereClause(ParseState *pstate, Node *where,
Node *using);
extern List *transformGroupClause(ParseState *pstate, List *grouplist,
List *targetlist);
extern List *transformSortClause(ParseState *pstate,
......
/*-------------------------------------------------------------------------
*
* parse_exer.h
* parse_expr.h
*
*
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_expr.h,v 1.13 1999/07/15 23:04:02 momjian Exp $
* $Id: parse_expr.h,v 1.14 1999/07/19 00:26:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -16,8 +16,12 @@
#include "parser/parse_node.h"
#include "parser/parse_type.h"
#define EXPR_COLUMN_FIRST 1
#define EXPR_RELATION_FIRST 2
extern Node *transformExpr(ParseState *pstate, Node *expr, int precedence);
extern Oid exprType(Node *expr);
extern int32 exprTypmod(Node *expr);
extern Node *parser_typecast2(Node *expr, Oid exprType, Type tp, int32 attypmod);
#endif /* PARSE_EXPR_H */
......@@ -5,7 +5,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_node.h,v 1.14 1999/07/15 23:04:02 momjian Exp $
* $Id: parse_node.h,v 1.15 1999/07/19 00:26:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -20,7 +20,6 @@ typedef struct ParseState
{
int p_last_resno;
List *p_rtable;
List *p_insert_columns;
struct ParseState *parentParseState;
bool p_hasAggs;
bool p_hasSubLinks;
......@@ -36,12 +35,11 @@ extern ParseState *make_parsestate(ParseState *parentParseState);
extern Expr *make_op(char *opname, Node *ltree, Node *rtree);
extern Var *make_var(ParseState *pstate, Oid relid, char *refname,
char *attrname);
extern ArrayRef *make_array_ref(Node *expr,
List *indirection);
extern ArrayRef *make_array_set(Expr *target_expr,
List *upperIndexpr,
List *lowerIndexpr,
Expr *expr);
extern ArrayRef *transformArraySubscripts(ParseState *pstate,
Node *arrayBase,
List *indirection,
bool forceSlice,
Node *assignFrom);
extern Const *make_const(Value *value);
#endif /* PARSE_NODE_H */
/*-------------------------------------------------------------------------
*
* parse_query.h
* prototypes for parse_query.c.
* parse_relation.h
* prototypes for parse_relation.c.
*
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_relation.h,v 1.11 1999/07/15 23:04:03 momjian Exp $
* $Id: parse_relation.h,v 1.12 1999/07/19 00:26:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PARSE_QUERY_H
#define PARSE_RANGE_H
#ifndef PARSE_RELATION_H
#define PARSE_RELATION_H
#include "parser/parse_node.h"
......@@ -30,7 +30,5 @@ extern int attnameAttNum(Relation rd, char *a);
extern bool attnameIsSet(Relation rd, char *name);
extern int attnumAttNelems(Relation rd, int attid);
extern Oid attnumTypeId(Relation rd, int attid);
extern void handleTargetColname(ParseState *pstate, char **resname,
char *refname, char *colname);
#endif /* PARSE_RANGE_H */
#endif /* PARSE_RELATION_H */
......@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_target.h,v 1.14 1999/07/15 23:04:03 momjian Exp $
* $Id: parse_target.h,v 1.15 1999/07/19 00:26:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -15,23 +15,14 @@
#include "parser/parse_node.h"
#define EXPR_COLUMN_FIRST 1
#define EXPR_RELATION_FIRST 2
extern List *transformTargetList(ParseState *pstate, List *targetlist);
extern List *makeTargetNames(ParseState *pstate, List *cols);
extern TargetEntry *MakeTargetEntryIdent(ParseState *pstate,
Node *node,
char **resname,
char *refname,
char *colname,
bool resjunk);
extern TargetEntry *transformTargetEntry(ParseState *pstate,
Node *node, Node *expr,
char *colname, bool resjunk);
extern void updateTargetListEntry(ParseState *pstate, TargetEntry *tle,
char *colname, List *indirection);
extern Node *CoerceTargetExpr(ParseState *pstate, Node *expr,
Oid type_id, Oid attrtype);
TargetEntry *MakeTargetEntryExpr(ParseState *pstate,
char *colname,
Node *expr,
List *arrayRef,
bool resjunk);
Oid type_id, Oid attrtype);
extern List *makeTargetNames(ParseState *pstate, List *cols);
#endif /* PARSE_TARGET_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment