Commit 92ed9294 authored by Thomas G. Lockhart's avatar Thomas G. Lockhart

Allow floating point constants for "def_arg" numeric arguments.

 Used in the generic "CREATE xxx" parsing.
Do some automatic type conversion for inserts from other columns.
Previous trouble with "resjunk" regression test remains for now.
parent fa838876
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.12 1998/05/09 23:22:15 thomas Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.13 1998/07/08 14:04:09 thomas Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -204,8 +204,7 @@ Oid param_type(int t); /* used in parse_expr.c */ ...@@ -204,8 +204,7 @@ Oid param_type(int t); /* used in parse_expr.c */
%type <ival> sub_type %type <ival> sub_type
%type <list> OptCreateAs, CreateAsList %type <list> OptCreateAs, CreateAsList
%type <node> CreateAsElement %type <node> CreateAsElement
%type <value> NumConst %type <value> NumericOnly, FloatOnly, IntegerOnly
%type <value> IntegerOnly
%type <attr> event_object, attr %type <attr> event_object, attr
%type <sortgroupby> groupby %type <sortgroupby> groupby
%type <sortgroupby> sortby %type <sortgroupby> sortby
...@@ -1180,6 +1179,20 @@ OptSeqElem: CACHE IntegerOnly ...@@ -1180,6 +1179,20 @@ OptSeqElem: CACHE IntegerOnly
} }
; ;
NumericOnly: FloatOnly { $$ = $1; }
| IntegerOnly { $$ = $1; }
FloatOnly: FCONST
{
$$ = makeFloat($1);
}
| '-' FCONST
{
$$ = makeFloat($2);
$$->val.dval = - $$->val.dval;
}
;
IntegerOnly: Iconst IntegerOnly: Iconst
{ {
$$ = makeInteger($1); $$ = makeInteger($1);
...@@ -1384,7 +1397,7 @@ def_elem: def_name '=' def_arg ...@@ -1384,7 +1397,7 @@ def_elem: def_name '=' def_arg
def_arg: ColId { $$ = (Node *)makeString($1); } def_arg: ColId { $$ = (Node *)makeString($1); }
| all_Op { $$ = (Node *)makeString($1); } | all_Op { $$ = (Node *)makeString($1); }
| NumConst { $$ = (Node *)$1; /* already a Value */ } | NumericOnly { $$ = (Node *)$1; }
| Sconst { $$ = (Node *)makeString($1); } | Sconst { $$ = (Node *)makeString($1); }
| SETOF ColId | SETOF ColId
{ {
...@@ -4442,10 +4455,6 @@ ParamNo: PARAM ...@@ -4442,10 +4455,6 @@ ParamNo: PARAM
} }
; ;
NumConst: Iconst { $$ = makeInteger($1); }
| FCONST { $$ = makeFloat($1); }
;
Iconst: ICONST { $$ = $1; }; Iconst: ICONST { $$ = $1; };
Sconst: SCONST { $$ = $1; }; Sconst: SCONST { $$ = $1; };
UserId: IDENT { $$ = $1; }; UserId: IDENT { $$ = $1; };
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.18 1998/06/05 03:49:18 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.19 1998/07/08 14:04:10 thomas Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -198,29 +198,31 @@ find_targetlist_entry(ParseState *pstate, SortGroupBy *sortgroupby, List *tlist) ...@@ -198,29 +198,31 @@ find_targetlist_entry(ParseState *pstate, SortGroupBy *sortgroupby, List *tlist)
List *p_target = tlist; List *p_target = tlist;
TargetEntry *tent = makeNode(TargetEntry); TargetEntry *tent = makeNode(TargetEntry);
if (sortgroupby->range) { if (sortgroupby->range) {
Attr *missingTarget = (Attr *)makeNode(Attr); Attr *missingAttr = (Attr *)makeNode(Attr);
missingTarget->type = T_Attr; missingAttr->type = T_Attr;
missingTarget->relname = palloc(strlen(sortgroupby->range) + 1); missingAttr->relname = palloc(strlen(sortgroupby->range) + 1);
strcpy(missingTarget->relname, sortgroupby->range); strcpy(missingAttr->relname, sortgroupby->range);
missingTarget->attrs = lcons(makeString(sortgroupby->name), NIL); missingAttr->attrs = lcons(makeString(sortgroupby->name), NIL);
transformTargetId(pstate, (Node*)missingTarget, tent, sortgroupby->name, TRUE); tent = transformTargetIdent(pstate, (Node *)missingAttr, tent,
&missingAttr->relname, NULL,
missingAttr->relname, TRUE);
} }
else { else {
Ident *missingTarget = (Ident *)makeNode(Ident); Ident *missingIdent = (Ident *)makeNode(Ident);
missingTarget->type = T_Ident; missingIdent->type = T_Ident;
missingTarget->name = palloc(strlen(sortgroupby->name) + 1); missingIdent->name = palloc(strlen(sortgroupby->name) + 1);
strcpy(missingTarget->name, sortgroupby->name); strcpy(missingIdent->name, sortgroupby->name);
transformTargetId(pstate, (Node*)missingTarget, tent, sortgroupby->name, TRUE); tent = transformTargetIdent(pstate, (Node *)missingIdent, tent,
&missingIdent->name, NULL,
missingIdent->name, TRUE);
} }
/* Add to the end of the target list */ /* Add to the end of the target list */
while (lnext(p_target) != NIL) { while (lnext(p_target) != NIL) {
p_target = lnext(p_target); p_target = lnext(p_target);
...@@ -457,7 +459,7 @@ transformUnionClause(List *unionClause, List *targetlist) ...@@ -457,7 +459,7 @@ transformUnionClause(List *unionClause, List *targetlist)
Node *expr; Node *expr;
expr = ((TargetEntry *)lfirst(next_target))->expr; expr = ((TargetEntry *)lfirst(next_target))->expr;
expr = coerce_target_expr(NULL, expr, itype, otype); expr = CoerceTargetExpr(NULL, expr, itype, otype);
if (expr == NULL) if (expr == NULL)
{ {
elog(ERROR,"Unable to transform %s to %s" elog(ERROR,"Unable to transform %s to %s"
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.2 1998/05/29 14:00:20 thomas Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.3 1998/07/08 14:04:10 thomas Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -273,6 +273,7 @@ TypeCategory(Oid inType) ...@@ -273,6 +273,7 @@ TypeCategory(Oid inType)
case (INT2OID): case (INT2OID):
case (INT4OID): case (INT4OID):
case (INT8OID):
case (FLOAT4OID): case (FLOAT4OID):
case (FLOAT8OID): case (FLOAT8OID):
case (CASHOID): case (CASHOID):
...@@ -387,6 +388,7 @@ PromoteTypeToNext(Oid inType) ...@@ -387,6 +388,7 @@ PromoteTypeToNext(Oid inType)
break; break;
case (INT4OID): case (INT4OID):
case (INT8OID):
case (FLOAT4OID): case (FLOAT4OID):
result = FLOAT8OID; result = FLOAT8OID;
break; break;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.30 1998/06/15 19:28:54 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.31 1998/07/08 14:04:10 thomas Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -312,6 +312,10 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) ...@@ -312,6 +312,10 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
case T_Expr: case T_Expr:
case T_Var: case T_Var:
case T_Const: case T_Const:
/* T_Param comes from implicit function calls in INSERT/VALUE statements.
* - thomas 1998-06-11
*/
case T_Param:
{ {
result = (Node *) expr; result = (Node *) expr;
break; break;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.19 1998/06/15 19:28:55 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.20 1998/07/08 14:04:10 thomas Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -153,7 +153,6 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, ...@@ -153,7 +153,6 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
Oid *true_oid_array; Oid *true_oid_array;
Node *retval; Node *retval;
bool retset; bool retset;
bool exists;
bool attisset = false; bool attisset = false;
Oid toid = (Oid) 0; Oid toid = (Oid) 0;
Expr *expr; Expr *expr;
...@@ -370,16 +369,18 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, ...@@ -370,16 +369,18 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
rettype = toid; rettype = toid;
retset = true; retset = true;
true_oid_array = oid_array; true_oid_array = oid_array;
exists = true;
} }
else else
{ {
bool exists;
exists = func_get_detail(funcname, nargs, oid_array, &funcid, exists = func_get_detail(funcname, nargs, oid_array, &funcid,
&rettype, &retset, &true_oid_array); &rettype, &retset, &true_oid_array);
} if (!exists)
elog(ERROR, "No such function '%s' with the specified attributes",
funcname);
if (!exists) }
elog(ERROR, "No such attribute or function '%s'", funcname);
/* got it */ /* got it */
funcnode = makeNode(Func); funcnode = makeNode(Func);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.11 1998/02/26 04:33:34 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.12 1998/07/08 14:04:11 thomas Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "nodes/makefuncs.h" #include "nodes/makefuncs.h"
#include "parser/parse_relation.h" #include "parser/parse_relation.h"
#include "parser/parse_coerce.h"
#include "utils/acl.h" #include "utils/acl.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
...@@ -371,9 +372,8 @@ attnumTypeId(Relation rd, int attid) ...@@ -371,9 +372,8 @@ attnumTypeId(Relation rd, int attid)
return (rd->rd_att->attrs[attid - 1]->atttypid); return (rd->rd_att->attrs[attid - 1]->atttypid);
} }
/* /* handleTargetColname()
* handleTargetColname - * Use column names from insert.
* use column names from insert
*/ */
void void
handleTargetColname(ParseState *pstate, char **resname, handleTargetColname(ParseState *pstate, char **resname,
...@@ -395,9 +395,8 @@ handleTargetColname(ParseState *pstate, char **resname, ...@@ -395,9 +395,8 @@ handleTargetColname(ParseState *pstate, char **resname,
checkTargetTypes(pstate, *resname, refname, colname); checkTargetTypes(pstate, *resname, refname, colname);
} }
/* /* checkTargetTypes()
* checkTargetTypes - * Checks value and target column types.
* checks value and target column types
*/ */
static void static void
checkTargetTypes(ParseState *pstate, char *target_colname, checkTargetTypes(ParseState *pstate, char *target_colname,
...@@ -432,6 +431,27 @@ checkTargetTypes(ParseState *pstate, char *target_colname, ...@@ -432,6 +431,27 @@ checkTargetTypes(ParseState *pstate, char *target_colname,
resdomno_target = attnameAttNum(pstate->p_target_relation, target_colname); resdomno_target = attnameAttNum(pstate->p_target_relation, target_colname);
attrtype_target = attnumTypeId(pstate->p_target_relation, resdomno_target); attrtype_target = attnumTypeId(pstate->p_target_relation, resdomno_target);
#if FALSE
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);
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) if (attrtype_id != attrtype_target)
elog(ERROR, "Type of %s does not match target column %s", elog(ERROR, "Type of %s does not match target column %s",
colname, target_colname); colname, target_colname);
...@@ -446,5 +466,5 @@ checkTargetTypes(ParseState *pstate, char *target_colname, ...@@ -446,5 +466,5 @@ checkTargetTypes(ParseState *pstate, char *target_colname,
get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target)) get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target))
elog(ERROR, "Length of %s is longer than length of target column %s", elog(ERROR, "Length of %s is longer than length of target column %s",
colname, target_colname); colname, target_colname);
#endif
} }
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.16 1998/06/15 19:28:55 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.17 1998/07/08 14:04:11 thomas Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -30,67 +30,169 @@ ...@@ -30,67 +30,169 @@
#include "utils/syscache.h" #include "utils/syscache.h"
static List *expandAllTables(ParseState *pstate); static List *ExpandAllTables(ParseState *pstate);
static char *figureColname(Node *expr, Node *resval); static char *FigureColname(Node *expr, Node *resval);
static TargetEntry * static TargetEntry *
make_targetlist_expr(ParseState *pstate, MakeTargetlistExpr(ParseState *pstate,
char *colname, char *colname,
Node *expr, Node *expr,
List *arrayRef); List *arrayRef);
Node * Node *
size_target_expr(ParseState *pstate, SizeTargetExpr(ParseState *pstate,
Node *expr, Node *expr,
Oid attrtype, Oid attrtype,
int16 attrtypmod); int16 attrtypmod);
/* /* transformTargetIdent()
* transformTargetId - transforms an Ident Node to a Target Entry * Transforms an Ident Node to a Target Entry
* Created this a function to allow the ORDER/GROUP BY clause be able * Created this function to allow the ORDER/GROUP BY clause to be able
* to construct a TargetEntry from an Ident. * to construct a TargetEntry from an Ident.
* *
* resjunk = TRUE will hide the target entry in the final result tuple. * resjunk = TRUE will hide the target entry in the final result tuple.
* daveh@insightdist.com 5/20/98 * daveh@insightdist.com 5/20/98
*
* Added more conversion logic to match up types from source to target.
* - thomas 1998-06-02
*/ */
void TargetEntry *
transformTargetId(ParseState *pstate, transformTargetIdent(ParseState *pstate,
Node *node, #if FALSE
TargetEntry *tent, Ident *ident,
char *resname, #else
int16 resjunk) Node *node,
#endif
TargetEntry *tent,
char **resname,
char *refname,
char *colname,
int16 resjunk)
{ {
Node *expr; Node *expr = NULL;
Oid type_id; Oid attrtype_target;
int16 type_mod;
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: more expressions than target columns");
}
if (pstate->p_is_insert || pstate->p_is_update)
{
Oid attrtype_id;
int resdomno_id,
resdomno_target;
RangeTblEntry *rte;
char *target_colname;
int16 attrtypmod,
attrtypmod_target;
target_colname = *resname;
if (target_colname == NULL || colname == NULL)
return (tent);
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;
}
resdomno_id = get_attnum(rte->relid, colname);
attrtype_id = get_atttype(rte->relid, resdomno_id);
attrtypmod = get_atttypmod(rte->relid, resdomno_id);
resdomno_target = attnameAttNum(pstate->p_target_relation, target_colname);
attrtype_target = attnumTypeId(pstate->p_target_relation, resdomno_target);
attrtypmod_target = get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target);
#ifdef PARSEDEBUG
printf("transformTargetIdent- transform type %d to %d\n",
attrtype_id, attrtype_target);
#endif
if ((attrtype_id != attrtype_target)
|| ((attrtypmod_target >= 0) && (attrtypmod_target != attrtypmod)))
{
if (can_coerce_type(1, &attrtype_id, &attrtype_target))
{
expr = coerce_type(pstate, node, attrtype_id, attrtype_target);
expr = transformExpr(pstate, expr, EXPR_COLUMN_FIRST);
tent = MakeTargetlistExpr(pstate, *resname, expr, FALSE);
expr = tent->expr;
}
else
{
#if TRUE
elog(ERROR, "Unable to convert %s to %s for column %s",
typeidTypeName(attrtype_id), typeidTypeName(attrtype_target),
target_colname);
#else
elog(ERROR, "Type or size of %s(%d) does not match target column %s(%d)",
colname, attrtypmod, target_colname, attrtypmod_target);
#endif
}
}
}
/* /*
* here we want to look for column names only, not * here we want to look for column names only, not
* relation names (even though they can be stored in * relation names (even though they can be stored in
* Ident nodes, too) * Ident nodes, too)
*/ */
expr = transformExpr(pstate, node, EXPR_COLUMN_FIRST); if (expr == NULL)
type_id = exprType(expr); {
if (nodeTag(expr) == T_Var) char *name;
type_mod = ((Var *) expr)->vartypmod; int16 type_mod;
else
type_mod = -1;
tent->resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
(Oid) type_id,
type_mod,
resname,
(Index) 0,
(Oid) 0,
resjunk);
tent->expr = expr; name = ((*resname != NULL)? *resname: colname);
return;
}
#ifdef PARSEDEBUG
printf("transformTargetIdent- call transformIdent()\n");
#endif
#if FALSE
expr = transformIdent(pstate, (Node *) ident, EXPR_COLUMN_FIRST);
#else
expr = transformExpr(pstate, node, EXPR_COLUMN_FIRST);
#endif
attrtype_target = exprType(expr);
if (nodeTag(expr) == T_Var)
type_mod = ((Var *) expr)->vartypmod;
else
type_mod = -1;
/* #ifdef PARSEDEBUG
* transformTargetList - printf("transformTargetIdent- attrtype_target = %d; type_mod = %d\n", attrtype_target, type_mod);
* turns a list of ResTarget's into a list of TargetEntry's #endif
tent->resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
(Oid) attrtype_target,
type_mod,
name,
(Index) 0,
(Oid) 0,
resjunk);
tent->expr = expr;
}
return (tent);
} /* transformTargetIdent() */
/* transformTargetList()
* Turns a list of ResTarget's into a list of TargetEntry's.
*/ */
List * List *
transformTargetList(ParseState *pstate, List *targetlist) transformTargetList(ParseState *pstate, List *targetlist)
...@@ -100,20 +202,23 @@ transformTargetList(ParseState *pstate, List *targetlist) ...@@ -100,20 +202,23 @@ transformTargetList(ParseState *pstate, List *targetlist)
while (targetlist != NIL) while (targetlist != NIL)
{ {
ResTarget *res = (ResTarget *) lfirst(targetlist); ResTarget *res = (ResTarget *) lfirst(targetlist);
TargetEntry *tent = makeNode(TargetEntry); TargetEntry *tent = makeNode(TargetEntry);
switch (nodeTag(res->val)) switch (nodeTag(res->val))
{ {
case T_Ident: case T_Ident:
{ {
char *identname; char *identname;
#if FALSE
char *resname; char *resname;
#endif
#ifdef PARSEDEBUG
printf("transformTargetList: decode T_Ident\n");
#endif
identname = ((Ident *) res->val)->name; identname = ((Ident *) res->val)->name;
handleTargetColname(pstate, &res->name, NULL, identname); tent = transformTargetIdent(pstate, (Node *)res->val, tent, &res->name, NULL, identname, FALSE);
resname = (res->name) ? res->name : identname;
transformTargetId(pstate, (Node*)res->val, tent, resname, FALSE);
break; break;
} }
case T_ParamNo: case T_ParamNo:
...@@ -121,8 +226,11 @@ transformTargetList(ParseState *pstate, List *targetlist) ...@@ -121,8 +226,11 @@ transformTargetList(ParseState *pstate, List *targetlist)
case T_A_Const: case T_A_Const:
case T_A_Expr: case T_A_Expr:
{ {
Node *expr = transformExpr(pstate, (Node *) res->val, EXPR_COLUMN_FIRST); Node *expr = transformExpr(pstate, (Node *) res->val, EXPR_COLUMN_FIRST);
#ifdef PARSEDEBUG
printf("transformTargetList: decode T_Expr\n");
#endif
handleTargetColname(pstate, &res->name, NULL, NULL); handleTargetColname(pstate, &res->name, NULL, NULL);
/* note indirection has not been transformed */ /* note indirection has not been transformed */
if (pstate->p_is_insert && res->indirection != NIL) if (pstate->p_is_insert && res->indirection != NIL)
...@@ -183,9 +291,9 @@ transformTargetList(ParseState *pstate, List *targetlist) ...@@ -183,9 +291,9 @@ transformTargetList(ParseState *pstate, List *targetlist)
constval = makeNode(Value); constval = makeNode(Value);
constval->type = T_String; constval->type = T_String;
constval->val.str = save_str; constval->val.str = save_str;
tent = make_targetlist_expr(pstate, res->name, tent = MakeTargetlistExpr(pstate, res->name,
(Node *) make_const(constval), (Node *) make_const(constval),
NULL); NULL);
pfree(save_str); pfree(save_str);
} }
else else
...@@ -201,7 +309,7 @@ transformTargetList(ParseState *pstate, List *targetlist) ...@@ -201,7 +309,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
* at the yacc grammar for why a name can be * at the yacc grammar for why a name can be
* missing. -ay * missing. -ay
*/ */
colname = figureColname(expr, res->val); colname = FigureColname(expr, res->val);
} }
if (res->indirection) if (res->indirection)
{ {
...@@ -217,8 +325,8 @@ transformTargetList(ParseState *pstate, List *targetlist) ...@@ -217,8 +325,8 @@ transformTargetList(ParseState *pstate, List *targetlist)
} }
} }
res->name = colname; res->name = colname;
tent = make_targetlist_expr(pstate, res->name, expr, tent = MakeTargetlistExpr(pstate, res->name, expr,
res->indirection); res->indirection);
} }
break; break;
} }
...@@ -240,9 +348,9 @@ transformTargetList(ParseState *pstate, List *targetlist) ...@@ -240,9 +348,9 @@ transformTargetList(ParseState *pstate, List *targetlist)
if (att->relname != NULL && !strcmp(att->relname, "*")) if (att->relname != NULL && !strcmp(att->relname, "*"))
{ {
if (tail_p_target == NIL) if (tail_p_target == NIL)
p_target = tail_p_target = expandAllTables(pstate); p_target = tail_p_target = ExpandAllTables(pstate);
else else
lnext(tail_p_target) = expandAllTables(pstate); lnext(tail_p_target) = ExpandAllTables(pstate);
while (lnext(tail_p_target) != NIL) while (lnext(tail_p_target) != NIL)
/* make sure we point to the last target entry */ /* make sure we point to the last target entry */
...@@ -291,6 +399,9 @@ transformTargetList(ParseState *pstate, List *targetlist) ...@@ -291,6 +399,9 @@ transformTargetList(ParseState *pstate, List *targetlist)
* Target item is fully specified: ie. * Target item is fully specified: ie.
* relation.attribute * relation.attribute
*/ */
#ifdef PARSEDEBUG
printf("transformTargetList: decode T_Attr\n");
#endif
result = ParseNestedFuncOrColumn(pstate, att, &pstate->p_last_resno, EXPR_COLUMN_FIRST); result = ParseNestedFuncOrColumn(pstate, att, &pstate->p_last_resno, EXPR_COLUMN_FIRST);
handleTargetColname(pstate, &res->name, att->relname, attrname); handleTargetColname(pstate, &res->name, att->relname, attrname);
if (att->indirection != NIL) if (att->indirection != NIL)
...@@ -348,15 +459,15 @@ transformTargetList(ParseState *pstate, List *targetlist) ...@@ -348,15 +459,15 @@ transformTargetList(ParseState *pstate, List *targetlist)
Node * Node *
coerce_target_expr(ParseState *pstate, CoerceTargetExpr(ParseState *pstate,
Node *expr, Node *expr,
Oid type_id, Oid type_id,
Oid attrtype) Oid attrtype)
{ {
if (can_coerce_type(1, &type_id, &attrtype)) if (can_coerce_type(1, &type_id, &attrtype))
{ {
#ifdef PARSEDEBUG #ifdef PARSEDEBUG
printf("parse_target: coerce type from %s to %s\n", printf("CoerceTargetExpr: coerce type from %s to %s\n",
typeidTypeName(type_id), typeidTypeName(attrtype)); typeidTypeName(type_id), typeidTypeName(attrtype));
#endif #endif
expr = coerce_type(pstate, expr, type_id, attrtype); expr = coerce_type(pstate, expr, type_id, attrtype);
...@@ -368,7 +479,7 @@ printf("parse_target: coerce type from %s to %s\n", ...@@ -368,7 +479,7 @@ printf("parse_target: coerce type from %s to %s\n",
{ {
Oid text_id = TEXTOID; Oid text_id = TEXTOID;
#ifdef PARSEDEBUG #ifdef PARSEDEBUG
printf("parse_target: try coercing from %s to %s via text\n", printf("CoerceTargetExpr: try coercing from %s to %s via text\n",
typeidTypeName(type_id), typeidTypeName(attrtype)); typeidTypeName(type_id), typeidTypeName(attrtype));
#endif #endif
if (type_id == TEXTOID) if (type_id == TEXTOID)
...@@ -385,18 +496,18 @@ printf("parse_target: try coercing from %s to %s via text\n", ...@@ -385,18 +496,18 @@ printf("parse_target: try coercing from %s to %s via text\n",
expr = NULL; expr = NULL;
return expr; return expr;
} /* coerce_target_expr() */ } /* CoerceTargetExpr() */
/* size_target_expr() /* SizeTargetExpr()
* Apparently going to a fixed-length string? * Apparently going to a fixed-length string?
* Then explicitly size for storage... * Then explicitly size for storage...
*/ */
Node * Node *
size_target_expr(ParseState *pstate, SizeTargetExpr(ParseState *pstate,
Node *expr, Node *expr,
Oid attrtype, Oid attrtype,
int16 attrtypmod) int16 attrtypmod)
{ {
int i; int i;
HeapTuple ftup; HeapTuple ftup;
...@@ -407,7 +518,7 @@ size_target_expr(ParseState *pstate, ...@@ -407,7 +518,7 @@ size_target_expr(ParseState *pstate,
A_Const *cons; A_Const *cons;
#ifdef PARSEDEBUG #ifdef PARSEDEBUG
printf("parse_target: ensure target fits storage\n"); printf("SizeTargetExpr: ensure target fits storage\n");
#endif #endif
funcname = typeidTypeName(attrtype); funcname = typeidTypeName(attrtype);
oid_array[0] = attrtype; oid_array[0] = attrtype;
...@@ -415,7 +526,7 @@ printf("parse_target: ensure target fits storage\n"); ...@@ -415,7 +526,7 @@ printf("parse_target: ensure target fits storage\n");
for (i = 2; i < 8; i++) oid_array[i] = InvalidOid; for (i = 2; i < 8; i++) oid_array[i] = InvalidOid;
#ifdef PARSEDEBUG #ifdef PARSEDEBUG
printf("parse_target: look for conversion function %s(%s,%s)\n", printf("SizeTargetExpr: look for conversion function %s(%s,%s)\n",
funcname, typeidTypeName(attrtype), typeidTypeName(INT4OID)); funcname, typeidTypeName(attrtype), typeidTypeName(INT4OID));
#endif #endif
...@@ -429,7 +540,7 @@ printf("parse_target: look for conversion function %s(%s,%s)\n", ...@@ -429,7 +540,7 @@ printf("parse_target: look for conversion function %s(%s,%s)\n",
if (HeapTupleIsValid(ftup)) if (HeapTupleIsValid(ftup))
{ {
#ifdef PARSEDEBUG #ifdef PARSEDEBUG
printf("parse_target: found conversion function for sizing\n"); printf("SizeTargetExpr: found conversion function for sizing\n");
#endif #endif
func = makeNode(FuncCall); func = makeNode(FuncCall);
func->funcname = funcname; func->funcname = funcname;
...@@ -444,25 +555,24 @@ printf("parse_target: found conversion function for sizing\n"); ...@@ -444,25 +555,24 @@ printf("parse_target: found conversion function for sizing\n");
#ifdef PARSEDEBUG #ifdef PARSEDEBUG
else else
{ {
printf("parse_target: no conversion function for sizing\n"); printf("SizeTargetExpr: no conversion function for sizing\n");
} }
#endif #endif
return expr; return expr;
} /* size_target_expr() */ } /* SizeTargetExpr() */
/* make_targetlist_expr() /* MakeTargetlistExpr()
* Make a TargetEntry from an expression * Make a TargetEntry from an expression.
* * arrayRef is a list of transformed A_Indices.
* arrayRef is a list of transformed A_Indices
* *
* For type mismatches between expressions and targets, use the same * For type mismatches between expressions and targets, use the same
* techniques as for function and operator type coersion. * techniques as for function and operator type coersion.
* - thomas 1998-05-08 * - thomas 1998-05-08
*/ */
static TargetEntry * static TargetEntry *
make_targetlist_expr(ParseState *pstate, MakeTargetlistExpr(ParseState *pstate,
char *colname, char *colname,
Node *expr, Node *expr,
List *arrayRef) List *arrayRef)
...@@ -478,7 +588,7 @@ make_targetlist_expr(ParseState *pstate, ...@@ -478,7 +588,7 @@ make_targetlist_expr(ParseState *pstate,
Resdom *resnode; Resdom *resnode;
if (expr == NULL) if (expr == NULL)
elog(ERROR, "make_targetlist_expr: invalid use of NULL expression"); elog(ERROR, "MakeTargetlistExpr: invalid use of NULL expression");
type_id = exprType(expr); type_id = exprType(expr);
if (nodeTag(expr) == T_Var) if (nodeTag(expr) == T_Var)
...@@ -515,28 +625,26 @@ make_targetlist_expr(ParseState *pstate, ...@@ -515,28 +625,26 @@ make_targetlist_expr(ParseState *pstate,
else else
typelem = attrtype; typelem = attrtype;
expr = coerce_target_expr(pstate, expr, type_id, typelem); expr = CoerceTargetExpr(pstate, expr, type_id, typelem);
if (!HeapTupleIsValid(expr)) if (!HeapTupleIsValid(expr))
{
elog(ERROR, "parser: attribute '%s' is of type '%s'" elog(ERROR, "parser: attribute '%s' is of type '%s'"
" but expression is of type '%s'" " but expression is of type '%s'"
"\n\tYou will need to rewrite or cast the expression", "\n\tYou will need to rewrite or cast the expression",
colname, colname,
typeidTypeName(attrtype), typeidTypeName(attrtype),
typeidTypeName(type_id)); typeidTypeName(type_id));
}
} }
#ifdef PARSEDEBUG #ifdef PARSEDEBUG
printf("parse_target: attrtypmod is %d\n", (int4) attrtypmod); printf("MakeTargetlistExpr: attrtypmod is %d\n", (int4) attrtypmod);
#endif #endif
/* Apparently going to a fixed-length string? /* Apparently going to a fixed-length string?
* Then explicitly size for storage... * Then explicitly size for storage...
*/ */
if (attrtypmod > 0) if (attrtypmod > 0)
expr = size_target_expr(pstate, expr, attrtype, attrtypmod); expr = SizeTargetExpr(pstate, expr, attrtype, attrtypmod);
} }
if (arrayRef != NIL) if (arrayRef != NIL)
...@@ -583,8 +691,8 @@ printf("parse_target: attrtypmod is %d\n", (int4) attrtypmod); ...@@ -583,8 +691,8 @@ printf("parse_target: attrtypmod is %d\n", (int4) attrtypmod);
attrtype = type_id; attrtype = type_id;
attrtypmod = type_mod; attrtypmod = type_mod;
} }
tent = makeNode(TargetEntry);
tent = makeNode(TargetEntry);
resnode = makeResdom((AttrNumber) resdomno, resnode = makeResdom((AttrNumber) resdomno,
(Oid) attrtype, (Oid) attrtype,
attrtypmod, attrtypmod,
...@@ -597,7 +705,7 @@ printf("parse_target: attrtypmod is %d\n", (int4) attrtypmod); ...@@ -597,7 +705,7 @@ printf("parse_target: attrtypmod is %d\n", (int4) attrtypmod);
tent->expr = expr; tent->expr = expr;
return tent; return tent;
} /* make_targetlist_expr() */ } /* MakeTargetlistExpr() */
/* /*
...@@ -656,12 +764,12 @@ makeTargetNames(ParseState *pstate, List *cols) ...@@ -656,12 +764,12 @@ makeTargetNames(ParseState *pstate, List *cols)
} }
/* /*
* expandAllTables - * ExpandAllTables -
* turns '*' (in the target list) into a list of attributes * turns '*' (in the target list) into a list of attributes
* (of all relations in the range table) * (of all relations in the range table)
*/ */
static List * static List *
expandAllTables(ParseState *pstate) ExpandAllTables(ParseState *pstate)
{ {
List *target = NIL; List *target = NIL;
List *legit_rtable = NIL; List *legit_rtable = NIL;
...@@ -720,13 +828,13 @@ expandAllTables(ParseState *pstate) ...@@ -720,13 +828,13 @@ expandAllTables(ParseState *pstate)
} }
/* /*
* figureColname - * FigureColname -
* if the name of the resulting column is not specified in the target * if the name of the resulting column is not specified in the target
* list, we have to guess. * list, we have to guess.
* *
*/ */
static char * static char *
figureColname(Node *expr, Node *resval) FigureColname(Node *expr, Node *resval)
{ {
switch (nodeTag(expr)) switch (nodeTag(expr))
{ {
......
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