mirror of
https://github.com/postgres/postgres.git
synced 2025-04-22 23:02:54 +03:00
DEFAULT is handled by analyze.c now.
This commit is contained in:
parent
c927f80fe4
commit
defb10a450
@ -26,7 +26,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.26 1997/09/18 20:20:29 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.27 1997/10/12 07:09:02 vadim Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -1245,6 +1245,7 @@ ExecReplace(TupleTableSlot *slot,
|
||||
ExecARUpdateTriggers(resultRelationDesc, tupleid, tuple);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static HeapTuple
|
||||
ExecAttrDefault(Relation rel, HeapTuple tuple)
|
||||
{
|
||||
@ -1309,6 +1310,7 @@ ExecAttrDefault(Relation rel, HeapTuple tuple)
|
||||
return (newtuple);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
static char *
|
||||
ExecRelCheck(Relation rel, HeapTuple tuple)
|
||||
@ -1375,8 +1377,10 @@ ExecConstraints(char *caller, Relation rel, HeapTuple tuple)
|
||||
|
||||
Assert(rel->rd_att->constr);
|
||||
|
||||
#if 0
|
||||
if (rel->rd_att->constr->num_defval > 0)
|
||||
newtuple = tuple = ExecAttrDefault(rel, tuple);
|
||||
#endif
|
||||
|
||||
if (rel->rd_att->constr->has_not_null)
|
||||
{
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.44 1997/09/18 20:20:58 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.45 1997/10/12 07:09:20 vadim Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -303,6 +303,7 @@ static Query *
|
||||
transformInsertStmt(ParseState *pstate, AppendStmt *stmt)
|
||||
{
|
||||
Query *qry = makeNode(Query); /* make a new query tree */
|
||||
List *icolumns;
|
||||
|
||||
qry->commandType = CMD_INSERT;
|
||||
pstate->p_is_insert = true;
|
||||
@ -313,10 +314,74 @@ transformInsertStmt(ParseState *pstate, AppendStmt *stmt)
|
||||
qry->uniqueFlag = NULL;
|
||||
|
||||
/* fix the target list */
|
||||
pstate->p_insert_columns = makeTargetNames(pstate, stmt->cols);
|
||||
|
||||
icolumns = pstate->p_insert_columns = makeTargetNames(pstate, stmt->cols);
|
||||
|
||||
qry->targetList = transformTargetList(pstate, stmt->targetList);
|
||||
|
||||
|
||||
/* DEFAULT handling */
|
||||
if (length(qry->targetList) < pstate->p_target_relation->rd_att->natts &&
|
||||
pstate->p_target_relation->rd_att->constr &&
|
||||
pstate->p_target_relation->rd_att->constr->num_defval > 0)
|
||||
{
|
||||
AttributeTupleForm *att = pstate->p_target_relation->rd_att->attrs;
|
||||
AttrDefault *defval = pstate->p_target_relation->rd_att->constr->defval;
|
||||
int ndef = pstate->p_target_relation->rd_att->constr->num_defval;
|
||||
|
||||
/*
|
||||
* if stmt->cols == NIL then makeTargetNames returns list of all
|
||||
* attrs: have to shorter icolumns list...
|
||||
*/
|
||||
if (stmt->cols == NIL)
|
||||
{
|
||||
List *extrl;
|
||||
int i = length(qry->targetList);
|
||||
|
||||
foreach (extrl, icolumns)
|
||||
{
|
||||
if (--i <= 0)
|
||||
break;
|
||||
}
|
||||
freeList (lnext(extrl));
|
||||
lnext(extrl) = NIL;
|
||||
}
|
||||
|
||||
while (ndef-- > 0)
|
||||
{
|
||||
List *tl;
|
||||
Ident *id;
|
||||
TargetEntry *te;
|
||||
|
||||
foreach (tl, icolumns)
|
||||
{
|
||||
id = (Ident *) lfirst(tl);
|
||||
if (!namestrcmp(&(att[defval[ndef].adnum - 1]->attname), id->name))
|
||||
break;
|
||||
}
|
||||
if (tl != NIL) /* something given for this attr */
|
||||
continue;
|
||||
/*
|
||||
* Nothing given for this attr with DEFAULT expr, so
|
||||
* add new TargetEntry to qry->targetList.
|
||||
* Note, that we set resno to defval[ndef].adnum:
|
||||
* it's what transformTargetList()->make_targetlist_expr()
|
||||
* does for INSERT ... SELECT. But for INSERT ... VALUES
|
||||
* pstate->p_last_resno is used. It doesn't matter for
|
||||
* "normal" using (planner creates proper target list
|
||||
* in preptlist.c), but may break RULEs in some way.
|
||||
* It seems better to create proper target list here...
|
||||
*/
|
||||
te = makeNode(TargetEntry);
|
||||
te->resdom = makeResdom(defval[ndef].adnum,
|
||||
att[defval[ndef].adnum - 1]->atttypid,
|
||||
att[defval[ndef].adnum - 1]->attlen,
|
||||
pstrdup(nameout(&(att[defval[ndef].adnum - 1]->attname))),
|
||||
0, 0, 0);
|
||||
te->fjoin = NULL;
|
||||
te->expr = (Node *) stringToNode(defval[ndef].adbin);
|
||||
qry->targetList = lappend (qry->targetList, te);
|
||||
}
|
||||
}
|
||||
|
||||
/* fix where clause */
|
||||
qry->qual = transformWhereClause(pstate, stmt->whereClause);
|
||||
|
||||
@ -1098,10 +1163,20 @@ makeTargetNames(ParseState *pstate, List *cols)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach(tl, cols)
|
||||
/* elog on failure */
|
||||
varattno(pstate->p_target_relation, ((Ident *) lfirst(tl))->name);
|
||||
|
||||
{
|
||||
List *nxt;
|
||||
char *name = ((Ident *) lfirst(tl))->name;
|
||||
|
||||
/* elog on failure */
|
||||
varattno(pstate->p_target_relation, name);
|
||||
foreach(nxt, lnext(tl))
|
||||
if (!strcmp(name, ((Ident *) lfirst(nxt))->name))
|
||||
elog (WARN, "Attribute %s should be specified only once", name);
|
||||
}
|
||||
}
|
||||
|
||||
return cols;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user