mirror of
https://github.com/postgres/postgres.git
synced 2025-05-01 01:04:50 +03:00
Factor out duplicate code for computing values of PLpgSQL_datum items.
This is to help localize the changes needed for adding a new kind of PLpgSQL_datum (like, say, an array element...)
This commit is contained in:
parent
6ba159f9cf
commit
316c5cbfd3
@ -3,7 +3,7 @@
|
||||
* procedural language
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.54 2003/01/31 00:31:53 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.55 2003/03/25 00:34:23 tgl Exp $
|
||||
*
|
||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||
*
|
||||
@ -696,7 +696,7 @@ plpgsql_parse_dblword(char *word)
|
||||
new = malloc(sizeof(PLpgSQL_recfield));
|
||||
new->dtype = PLPGSQL_DTYPE_RECFIELD;
|
||||
new->fieldname = strdup(cp[1]);
|
||||
new->recno = ns->itemno;
|
||||
new->recparentno = ns->itemno;
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *) new);
|
||||
|
||||
@ -799,7 +799,7 @@ plpgsql_parse_tripword(char *word)
|
||||
new = malloc(sizeof(PLpgSQL_recfield));
|
||||
new->dtype = PLPGSQL_DTYPE_RECFIELD;
|
||||
new->fieldname = strdup(cp[2]);
|
||||
new->recno = ns->itemno;
|
||||
new->recparentno = ns->itemno;
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *) new);
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* procedural language
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.81 2003/03/09 02:19:13 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.82 2003/03/25 00:34:23 tgl Exp $
|
||||
*
|
||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||
*
|
||||
@ -130,6 +130,12 @@ static void exec_assign_expr(PLpgSQL_execstate * estate,
|
||||
static void exec_assign_value(PLpgSQL_execstate * estate,
|
||||
PLpgSQL_datum * target,
|
||||
Datum value, Oid valtype, bool *isNull);
|
||||
static void exec_eval_datum(PLpgSQL_execstate *estate,
|
||||
PLpgSQL_datum *datum,
|
||||
Oid expectedtypeid,
|
||||
Oid *typeid,
|
||||
Datum *value,
|
||||
bool *isnull);
|
||||
static Datum exec_eval_expr(PLpgSQL_execstate * estate,
|
||||
PLpgSQL_expr * expr,
|
||||
bool *isNull,
|
||||
@ -1766,6 +1772,9 @@ exec_init_tuple_store(PLpgSQL_execstate * estate)
|
||||
static int
|
||||
exec_stmt_raise(PLpgSQL_execstate * estate, PLpgSQL_stmt_raise * stmt)
|
||||
{
|
||||
Oid paramtypeid;
|
||||
Datum paramvalue;
|
||||
bool paramisnull;
|
||||
HeapTuple typetup;
|
||||
Form_pg_type typeStruct;
|
||||
FmgrInfo finfo_output;
|
||||
@ -1774,10 +1783,6 @@ exec_stmt_raise(PLpgSQL_execstate * estate, PLpgSQL_stmt_raise * stmt)
|
||||
char c[2] = {0, 0};
|
||||
char *cp;
|
||||
PLpgSQL_dstring ds;
|
||||
PLpgSQL_var *var;
|
||||
PLpgSQL_rec *rec;
|
||||
PLpgSQL_recfield *recfield;
|
||||
int fno;
|
||||
|
||||
plpgsql_dstring_init(&ds);
|
||||
|
||||
@ -1804,83 +1809,31 @@ exec_stmt_raise(PLpgSQL_execstate * estate, PLpgSQL_stmt_raise * stmt)
|
||||
plpgsql_dstring_append(&ds, c);
|
||||
continue;
|
||||
}
|
||||
switch (estate->datums[stmt->params[pidx]]->dtype)
|
||||
exec_eval_datum(estate, estate->datums[stmt->params[pidx]],
|
||||
InvalidOid,
|
||||
¶mtypeid, ¶mvalue, ¶misnull);
|
||||
if (paramisnull)
|
||||
{
|
||||
case PLPGSQL_DTYPE_VAR:
|
||||
var = (PLpgSQL_var *)
|
||||
(estate->datums[stmt->params[pidx]]);
|
||||
if (var->isnull)
|
||||
extval = "<NULL>";
|
||||
else
|
||||
{
|
||||
typetup = SearchSysCache(TYPEOID,
|
||||
ObjectIdGetDatum(var->datatype->typoid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(typetup))
|
||||
elog(ERROR, "cache lookup for type %u failed",
|
||||
var->datatype->typoid);
|
||||
typeStruct = (Form_pg_type) GETSTRUCT(typetup);
|
||||
|
||||
fmgr_info(typeStruct->typoutput, &finfo_output);
|
||||
extval = DatumGetCString(FunctionCall3(&finfo_output,
|
||||
var->value,
|
||||
ObjectIdGetDatum(typeStruct->typelem),
|
||||
Int32GetDatum(var->datatype->atttypmod)));
|
||||
ReleaseSysCache(typetup);
|
||||
}
|
||||
plpgsql_dstring_append(&ds, extval);
|
||||
break;
|
||||
|
||||
case PLPGSQL_DTYPE_RECFIELD:
|
||||
recfield = (PLpgSQL_recfield *)
|
||||
(estate->datums[stmt->params[pidx]]);
|
||||
rec = (PLpgSQL_rec *)
|
||||
(estate->datums[recfield->recno]);
|
||||
if (!HeapTupleIsValid(rec->tup))
|
||||
extval = "<NULL>";
|
||||
else
|
||||
{
|
||||
fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
|
||||
if (fno == SPI_ERROR_NOATTRIBUTE)
|
||||
elog(ERROR, "record \"%s\" has no field named \"%s\"", rec->refname, recfield->fieldname);
|
||||
extval = SPI_getvalue(rec->tup, rec->tupdesc, fno);
|
||||
if (extval == NULL)
|
||||
extval = "<NULL>";
|
||||
}
|
||||
plpgsql_dstring_append(&ds, extval);
|
||||
break;
|
||||
|
||||
case PLPGSQL_DTYPE_TRIGARG:
|
||||
{
|
||||
PLpgSQL_trigarg *trigarg;
|
||||
int value;
|
||||
Oid valtype;
|
||||
bool valisnull = false;
|
||||
|
||||
trigarg = (PLpgSQL_trigarg *)
|
||||
(estate->datums[stmt->params[pidx]]);
|
||||
value = (int) exec_eval_expr(estate, trigarg->argnum,
|
||||
&valisnull, &valtype);
|
||||
exec_eval_cleanup(estate);
|
||||
if (valisnull)
|
||||
extval = "<INDEX_IS_NULL>";
|
||||
else
|
||||
{
|
||||
if (value < 0 || value >= estate->trig_nargs)
|
||||
extval = "<OUT_OF_RANGE>";
|
||||
else
|
||||
extval = DatumGetCString(DirectFunctionCall1(textout,
|
||||
estate->trig_argv[value]));
|
||||
}
|
||||
plpgsql_dstring_append(&ds, extval);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
c[0] = '?';
|
||||
plpgsql_dstring_append(&ds, c);
|
||||
break;
|
||||
extval = "<NULL>";
|
||||
}
|
||||
else
|
||||
{
|
||||
typetup = SearchSysCache(TYPEOID,
|
||||
ObjectIdGetDatum(paramtypeid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(typetup))
|
||||
elog(ERROR, "cache lookup for type %u failed",
|
||||
paramtypeid);
|
||||
typeStruct = (Form_pg_type) GETSTRUCT(typetup);
|
||||
|
||||
fmgr_info(typeStruct->typoutput, &finfo_output);
|
||||
extval = DatumGetCString(FunctionCall3(&finfo_output,
|
||||
paramvalue,
|
||||
ObjectIdGetDatum(typeStruct->typelem),
|
||||
Int32GetDatum(-1)));
|
||||
ReleaseSysCache(typetup);
|
||||
}
|
||||
plpgsql_dstring_append(&ds, extval);
|
||||
pidx++;
|
||||
continue;
|
||||
}
|
||||
@ -1985,11 +1938,7 @@ static void
|
||||
exec_prepare_plan(PLpgSQL_execstate * estate,
|
||||
PLpgSQL_expr * expr)
|
||||
{
|
||||
PLpgSQL_var *var;
|
||||
PLpgSQL_rec *rec;
|
||||
PLpgSQL_recfield *recfield;
|
||||
int i;
|
||||
int fno;
|
||||
_SPI_plan *spi_plan;
|
||||
void *plan;
|
||||
Oid *argtypes;
|
||||
@ -2004,33 +1953,12 @@ exec_prepare_plan(PLpgSQL_execstate * estate,
|
||||
|
||||
for (i = 0; i < expr->nparams; i++)
|
||||
{
|
||||
switch (estate->datums[expr->params[i]]->dtype)
|
||||
{
|
||||
case PLPGSQL_DTYPE_VAR:
|
||||
var = (PLpgSQL_var *) (estate->datums[expr->params[i]]);
|
||||
argtypes[i] = var->datatype->typoid;
|
||||
break;
|
||||
Datum paramval;
|
||||
bool paramisnull;
|
||||
|
||||
case PLPGSQL_DTYPE_RECFIELD:
|
||||
recfield = (PLpgSQL_recfield *) (estate->datums[expr->params[i]]);
|
||||
rec = (PLpgSQL_rec *) (estate->datums[recfield->recno]);
|
||||
|
||||
if (!HeapTupleIsValid(rec->tup))
|
||||
elog(ERROR, "record \"%s\" is unassigned yet", rec->refname);
|
||||
fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
|
||||
if (fno == SPI_ERROR_NOATTRIBUTE)
|
||||
elog(ERROR, "record \"%s\" has no field named \"%s\"", rec->refname, recfield->fieldname);
|
||||
argtypes[i] = SPI_gettypeid(rec->tupdesc, fno);
|
||||
break;
|
||||
|
||||
case PLPGSQL_DTYPE_TRIGARG:
|
||||
argtypes[i] = (Oid) TEXTOID;
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "unknown parameter dtype %d in exec_run_select()",
|
||||
estate->datums[expr->params[i]]->dtype);
|
||||
}
|
||||
exec_eval_datum(estate, estate->datums[expr->params[i]],
|
||||
InvalidOid,
|
||||
&argtypes[i], ¶mval, ¶misnull);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2059,19 +1987,11 @@ static int
|
||||
exec_stmt_execsql(PLpgSQL_execstate * estate,
|
||||
PLpgSQL_stmt_execsql * stmt)
|
||||
{
|
||||
PLpgSQL_var *var;
|
||||
PLpgSQL_rec *rec;
|
||||
PLpgSQL_recfield *recfield;
|
||||
PLpgSQL_trigarg *trigarg;
|
||||
int tgargno;
|
||||
Oid tgargoid;
|
||||
int fno;
|
||||
int i;
|
||||
Datum *values;
|
||||
char *nulls;
|
||||
int rc;
|
||||
PLpgSQL_expr *expr = stmt->sqlstmt;
|
||||
bool isnull;
|
||||
|
||||
/*
|
||||
* On the first call for this expression generate the plan
|
||||
@ -2087,59 +2007,17 @@ exec_stmt_execsql(PLpgSQL_execstate * estate,
|
||||
|
||||
for (i = 0; i < expr->nparams; i++)
|
||||
{
|
||||
switch (estate->datums[expr->params[i]]->dtype)
|
||||
{
|
||||
case PLPGSQL_DTYPE_VAR:
|
||||
var = (PLpgSQL_var *) (estate->datums[expr->params[i]]);
|
||||
values[i] = var->value;
|
||||
if (var->isnull)
|
||||
nulls[i] = 'n';
|
||||
else
|
||||
nulls[i] = ' ';
|
||||
break;
|
||||
PLpgSQL_datum *datum = estate->datums[expr->params[i]];
|
||||
Oid paramtypeid;
|
||||
bool paramisnull;
|
||||
|
||||
case PLPGSQL_DTYPE_RECFIELD:
|
||||
recfield = (PLpgSQL_recfield *) (estate->datums[expr->params[i]]);
|
||||
rec = (PLpgSQL_rec *) (estate->datums[recfield->recno]);
|
||||
|
||||
if (!HeapTupleIsValid(rec->tup))
|
||||
elog(ERROR, "record \"%s\" is unassigned yet", rec->refname);
|
||||
fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
|
||||
if (fno == SPI_ERROR_NOATTRIBUTE)
|
||||
elog(ERROR, "record \"%s\" has no field named \"%s\"", rec->refname, recfield->fieldname);
|
||||
|
||||
if (expr->plan_argtypes[i] != SPI_gettypeid(rec->tupdesc, fno))
|
||||
elog(ERROR, "type of %s.%s doesn't match that when preparing the plan", rec->refname, recfield->fieldname);
|
||||
|
||||
values[i] = SPI_getbinval(rec->tup, rec->tupdesc, fno, &isnull);
|
||||
if (isnull)
|
||||
nulls[i] = 'n';
|
||||
else
|
||||
nulls[i] = ' ';
|
||||
break;
|
||||
|
||||
case PLPGSQL_DTYPE_TRIGARG:
|
||||
trigarg = (PLpgSQL_trigarg *) (estate->datums[expr->params[i]]);
|
||||
tgargno = (int) exec_eval_expr(estate, trigarg->argnum,
|
||||
&isnull, &tgargoid);
|
||||
exec_eval_cleanup(estate);
|
||||
if (isnull || tgargno < 0 || tgargno >= estate->trig_nargs)
|
||||
{
|
||||
values[i] = 0;
|
||||
nulls[i] = 'n';
|
||||
}
|
||||
else
|
||||
{
|
||||
values[i] = estate->trig_argv[tgargno];
|
||||
nulls[i] = ' ';
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "unknown parameter dtype %d in exec_stmt_execsql()", estate->datums[expr->params[i]]->dtype);
|
||||
}
|
||||
exec_eval_datum(estate, datum, expr->plan_argtypes[i],
|
||||
¶mtypeid, &values[i], ¶misnull);
|
||||
if (paramisnull)
|
||||
nulls[i] = 'n';
|
||||
else
|
||||
nulls[i] = ' ';
|
||||
}
|
||||
nulls[i] = '\0';
|
||||
|
||||
/*
|
||||
* Execute the plan
|
||||
@ -2485,17 +2363,9 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
|
||||
char *curname = NULL;
|
||||
PLpgSQL_expr *query = NULL;
|
||||
Portal portal;
|
||||
|
||||
PLpgSQL_var *var;
|
||||
PLpgSQL_rec *rec;
|
||||
PLpgSQL_recfield *recfield;
|
||||
PLpgSQL_trigarg *trigarg;
|
||||
int tgargno;
|
||||
Oid tgargoid;
|
||||
int i;
|
||||
Datum *values;
|
||||
char *nulls;
|
||||
int fno;
|
||||
bool isnull;
|
||||
|
||||
|
||||
@ -2654,60 +2524,17 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
|
||||
|
||||
for (i = 0; i < query->nparams; i++)
|
||||
{
|
||||
switch (estate->datums[query->params[i]]->dtype)
|
||||
{
|
||||
case PLPGSQL_DTYPE_VAR:
|
||||
var = (PLpgSQL_var *) (estate->datums[query->params[i]]);
|
||||
values[i] = var->value;
|
||||
if (var->isnull)
|
||||
nulls[i] = 'n';
|
||||
else
|
||||
nulls[i] = ' ';
|
||||
break;
|
||||
PLpgSQL_datum *datum = estate->datums[query->params[i]];
|
||||
Oid paramtypeid;
|
||||
bool paramisnull;
|
||||
|
||||
case PLPGSQL_DTYPE_RECFIELD:
|
||||
recfield = (PLpgSQL_recfield *) (estate->datums[query->params[i]]);
|
||||
rec = (PLpgSQL_rec *) (estate->datums[recfield->recno]);
|
||||
|
||||
if (!HeapTupleIsValid(rec->tup))
|
||||
elog(ERROR, "record \"%s\" is unassigned yet", rec->refname);
|
||||
fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
|
||||
if (fno == SPI_ERROR_NOATTRIBUTE)
|
||||
elog(ERROR, "record \"%s\" has no field named \"%s\"", rec->refname, recfield->fieldname);
|
||||
|
||||
if (query->plan_argtypes[i] != SPI_gettypeid(rec->tupdesc, fno))
|
||||
elog(ERROR, "type of %s.%s doesn't match that when preparing the plan", rec->refname, recfield->fieldname);
|
||||
|
||||
values[i] = SPI_getbinval(rec->tup, rec->tupdesc, fno, &isnull);
|
||||
if (isnull)
|
||||
nulls[i] = 'n';
|
||||
else
|
||||
nulls[i] = ' ';
|
||||
break;
|
||||
|
||||
case PLPGSQL_DTYPE_TRIGARG:
|
||||
trigarg = (PLpgSQL_trigarg *) (estate->datums[query->params[i]]);
|
||||
tgargno = (int) exec_eval_expr(estate, trigarg->argnum,
|
||||
&isnull, &tgargoid);
|
||||
exec_eval_cleanup(estate);
|
||||
if (isnull || tgargno < 0 || tgargno >= estate->trig_nargs)
|
||||
{
|
||||
values[i] = 0;
|
||||
nulls[i] = 'n';
|
||||
}
|
||||
else
|
||||
{
|
||||
values[i] = estate->trig_argv[tgargno];
|
||||
nulls[i] = ' ';
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "unknown parameter dtype %d in exec_stmt_open()",
|
||||
estate->datums[query->params[i]]->dtype);
|
||||
}
|
||||
exec_eval_datum(estate, datum, query->plan_argtypes[i],
|
||||
¶mtypeid, &values[i], ¶misnull);
|
||||
if (paramisnull)
|
||||
nulls[i] = 'n';
|
||||
else
|
||||
nulls[i] = ' ';
|
||||
}
|
||||
nulls[i] = '\0';
|
||||
|
||||
/* ----------
|
||||
* Open the cursor
|
||||
@ -2892,7 +2719,7 @@ exec_assign_value(PLpgSQL_execstate * estate,
|
||||
case PLPGSQL_DTYPE_VAR:
|
||||
|
||||
/*
|
||||
* Target field is a variable
|
||||
* Target is a variable
|
||||
*/
|
||||
var = (PLpgSQL_var *) target;
|
||||
|
||||
@ -2936,10 +2763,10 @@ exec_assign_value(PLpgSQL_execstate * estate,
|
||||
case PLPGSQL_DTYPE_RECFIELD:
|
||||
|
||||
/*
|
||||
* Target field is a record
|
||||
* Target is a field of a record
|
||||
*/
|
||||
recfield = (PLpgSQL_recfield *) target;
|
||||
rec = (PLpgSQL_rec *) (estate->datums[recfield->recno]);
|
||||
rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
|
||||
|
||||
/*
|
||||
* Check that there is already a tuple in the record. We need
|
||||
@ -3035,6 +2862,89 @@ exec_assign_value(PLpgSQL_execstate * estate,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* exec_eval_datum Get current value of a PLpgSQL_datum
|
||||
*
|
||||
* The type oid, value in Datum format, and null flag are returned.
|
||||
*
|
||||
* If expectedtypeid isn't InvalidOid, it is checked against the actual type.
|
||||
*
|
||||
* This obviously only handles scalar datums (not whole records or rows);
|
||||
* at present it doesn't need to handle PLpgSQL_expr datums, either.
|
||||
*
|
||||
* NOTE: caller must not modify the returned value, since it points right
|
||||
* at the stored value in the case of pass-by-reference datatypes.
|
||||
*/
|
||||
static void
|
||||
exec_eval_datum(PLpgSQL_execstate *estate,
|
||||
PLpgSQL_datum *datum,
|
||||
Oid expectedtypeid,
|
||||
Oid *typeid,
|
||||
Datum *value,
|
||||
bool *isnull)
|
||||
{
|
||||
PLpgSQL_var *var;
|
||||
PLpgSQL_rec *rec;
|
||||
PLpgSQL_recfield *recfield;
|
||||
PLpgSQL_trigarg *trigarg;
|
||||
int tgargno;
|
||||
Oid tgargoid;
|
||||
int fno;
|
||||
|
||||
switch (datum->dtype)
|
||||
{
|
||||
case PLPGSQL_DTYPE_VAR:
|
||||
var = (PLpgSQL_var *) datum;
|
||||
*typeid = var->datatype->typoid;
|
||||
*value = var->value;
|
||||
*isnull = var->isnull;
|
||||
if (expectedtypeid != InvalidOid && expectedtypeid != *typeid)
|
||||
elog(ERROR, "type of %s doesn't match that when preparing the plan",
|
||||
var->refname);
|
||||
break;
|
||||
|
||||
case PLPGSQL_DTYPE_RECFIELD:
|
||||
recfield = (PLpgSQL_recfield *) datum;
|
||||
rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
|
||||
if (!HeapTupleIsValid(rec->tup))
|
||||
elog(ERROR, "record \"%s\" is unassigned yet", rec->refname);
|
||||
fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
|
||||
if (fno == SPI_ERROR_NOATTRIBUTE)
|
||||
elog(ERROR, "record \"%s\" has no field named \"%s\"",
|
||||
rec->refname, recfield->fieldname);
|
||||
*typeid = SPI_gettypeid(rec->tupdesc, fno);
|
||||
*value = SPI_getbinval(rec->tup, rec->tupdesc, fno, isnull);
|
||||
if (expectedtypeid != InvalidOid && expectedtypeid != *typeid)
|
||||
elog(ERROR, "type of %s.%s doesn't match that when preparing the plan",
|
||||
rec->refname, recfield->fieldname);
|
||||
break;
|
||||
|
||||
case PLPGSQL_DTYPE_TRIGARG:
|
||||
trigarg = (PLpgSQL_trigarg *) datum;
|
||||
*typeid = TEXTOID;
|
||||
tgargno = (int) exec_eval_expr(estate, trigarg->argnum,
|
||||
isnull, &tgargoid);
|
||||
exec_eval_cleanup(estate);
|
||||
if (*isnull || tgargno < 0 || tgargno >= estate->trig_nargs)
|
||||
{
|
||||
*value = (Datum) 0;
|
||||
*isnull = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
*value = estate->trig_argv[tgargno];
|
||||
*isnull = false;
|
||||
}
|
||||
if (expectedtypeid != InvalidOid && expectedtypeid != *typeid)
|
||||
elog(ERROR, "type of tgargv[%d] doesn't match that when preparing the plan",
|
||||
tgargno);
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "unknown datum dtype %d in exec_eval_datum()",
|
||||
datum->dtype);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------
|
||||
* exec_eval_expr Evaluate an expression and return
|
||||
@ -3103,18 +3013,10 @@ static int
|
||||
exec_run_select(PLpgSQL_execstate * estate,
|
||||
PLpgSQL_expr * expr, int maxtuples, Portal *portalP)
|
||||
{
|
||||
PLpgSQL_var *var;
|
||||
PLpgSQL_rec *rec;
|
||||
PLpgSQL_recfield *recfield;
|
||||
PLpgSQL_trigarg *trigarg;
|
||||
int tgargno;
|
||||
Oid tgargoid;
|
||||
int i;
|
||||
Datum *values;
|
||||
char *nulls;
|
||||
int rc;
|
||||
int fno;
|
||||
bool isnull;
|
||||
|
||||
/*
|
||||
* On the first call for this expression generate the plan
|
||||
@ -3130,60 +3032,17 @@ exec_run_select(PLpgSQL_execstate * estate,
|
||||
|
||||
for (i = 0; i < expr->nparams; i++)
|
||||
{
|
||||
switch (estate->datums[expr->params[i]]->dtype)
|
||||
{
|
||||
case PLPGSQL_DTYPE_VAR:
|
||||
var = (PLpgSQL_var *) (estate->datums[expr->params[i]]);
|
||||
values[i] = var->value;
|
||||
if (var->isnull)
|
||||
nulls[i] = 'n';
|
||||
else
|
||||
nulls[i] = ' ';
|
||||
break;
|
||||
PLpgSQL_datum *datum = estate->datums[expr->params[i]];
|
||||
Oid paramtypeid;
|
||||
bool paramisnull;
|
||||
|
||||
case PLPGSQL_DTYPE_RECFIELD:
|
||||
recfield = (PLpgSQL_recfield *) (estate->datums[expr->params[i]]);
|
||||
rec = (PLpgSQL_rec *) (estate->datums[recfield->recno]);
|
||||
|
||||
if (!HeapTupleIsValid(rec->tup))
|
||||
elog(ERROR, "record \"%s\" is unassigned yet", rec->refname);
|
||||
fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
|
||||
if (fno == SPI_ERROR_NOATTRIBUTE)
|
||||
elog(ERROR, "record \"%s\" has no field named \"%s\"", rec->refname, recfield->fieldname);
|
||||
|
||||
if (expr->plan_argtypes[i] != SPI_gettypeid(rec->tupdesc, fno))
|
||||
elog(ERROR, "type of %s.%s doesn't match that when preparing the plan", rec->refname, recfield->fieldname);
|
||||
|
||||
values[i] = SPI_getbinval(rec->tup, rec->tupdesc, fno, &isnull);
|
||||
if (isnull)
|
||||
nulls[i] = 'n';
|
||||
else
|
||||
nulls[i] = ' ';
|
||||
break;
|
||||
|
||||
case PLPGSQL_DTYPE_TRIGARG:
|
||||
trigarg = (PLpgSQL_trigarg *) (estate->datums[expr->params[i]]);
|
||||
tgargno = (int) exec_eval_expr(estate, trigarg->argnum,
|
||||
&isnull, &tgargoid);
|
||||
exec_eval_cleanup(estate);
|
||||
if (isnull || tgargno < 0 || tgargno >= estate->trig_nargs)
|
||||
{
|
||||
values[i] = 0;
|
||||
nulls[i] = 'n';
|
||||
}
|
||||
else
|
||||
{
|
||||
values[i] = estate->trig_argv[tgargno];
|
||||
nulls[i] = ' ';
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "unknown parameter dtype %d in exec_eval_expr()",
|
||||
estate->datums[expr->params[i]]->dtype);
|
||||
}
|
||||
exec_eval_datum(estate, datum, expr->plan_argtypes[i],
|
||||
¶mtypeid, &values[i], ¶misnull);
|
||||
if (paramisnull)
|
||||
nulls[i] = 'n';
|
||||
else
|
||||
nulls[i] = ' ';
|
||||
}
|
||||
nulls[i] = '\0';
|
||||
|
||||
/*
|
||||
* If a portal was requested, put the query into the portal
|
||||
@ -3231,15 +3090,7 @@ exec_eval_simple_expr(PLpgSQL_execstate * estate,
|
||||
Oid *rettype)
|
||||
{
|
||||
Datum retval;
|
||||
PLpgSQL_var *var;
|
||||
PLpgSQL_rec *rec;
|
||||
PLpgSQL_recfield *recfield;
|
||||
PLpgSQL_trigarg *trigarg;
|
||||
int tgargno;
|
||||
Oid tgargoid;
|
||||
int fno;
|
||||
int i;
|
||||
bool isnull;
|
||||
ExprContext *econtext;
|
||||
ParamListInfo paramLI;
|
||||
|
||||
@ -3264,54 +3115,13 @@ exec_eval_simple_expr(PLpgSQL_execstate * estate,
|
||||
*/
|
||||
for (i = 0; i < expr->nparams; i++, paramLI++)
|
||||
{
|
||||
PLpgSQL_datum *datum = estate->datums[expr->params[i]];
|
||||
Oid paramtypeid;
|
||||
|
||||
paramLI->kind = PARAM_NUM;
|
||||
paramLI->id = i + 1;
|
||||
|
||||
switch (estate->datums[expr->params[i]]->dtype)
|
||||
{
|
||||
case PLPGSQL_DTYPE_VAR:
|
||||
var = (PLpgSQL_var *) (estate->datums[expr->params[i]]);
|
||||
paramLI->isnull = var->isnull;
|
||||
paramLI->value = var->value;
|
||||
break;
|
||||
|
||||
case PLPGSQL_DTYPE_RECFIELD:
|
||||
recfield = (PLpgSQL_recfield *) (estate->datums[expr->params[i]]);
|
||||
rec = (PLpgSQL_rec *) (estate->datums[recfield->recno]);
|
||||
|
||||
if (!HeapTupleIsValid(rec->tup))
|
||||
elog(ERROR, "record \"%s\" is unassigned yet", rec->refname);
|
||||
fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
|
||||
if (fno == SPI_ERROR_NOATTRIBUTE)
|
||||
elog(ERROR, "record \"%s\" has no field named \"%s\"", rec->refname, recfield->fieldname);
|
||||
|
||||
if (expr->plan_argtypes[i] != SPI_gettypeid(rec->tupdesc, fno))
|
||||
elog(ERROR, "type of %s.%s doesn't match that when preparing the plan", rec->refname, recfield->fieldname);
|
||||
|
||||
paramLI->value = SPI_getbinval(rec->tup, rec->tupdesc, fno, &isnull);
|
||||
paramLI->isnull = isnull;
|
||||
break;
|
||||
|
||||
case PLPGSQL_DTYPE_TRIGARG:
|
||||
trigarg = (PLpgSQL_trigarg *) (estate->datums[expr->params[i]]);
|
||||
tgargno = (int) exec_eval_expr(estate, trigarg->argnum,
|
||||
&isnull, &tgargoid);
|
||||
exec_eval_cleanup(estate);
|
||||
if (isnull || tgargno < 0 || tgargno >= estate->trig_nargs)
|
||||
{
|
||||
paramLI->value = 0;
|
||||
paramLI->isnull = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
paramLI->value = estate->trig_argv[tgargno];
|
||||
paramLI->isnull = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "unknown parameter dtype %d in exec_eval_simple_expr()", estate->datums[expr->params[i]]->dtype);
|
||||
}
|
||||
exec_eval_datum(estate, datum, expr->plan_argtypes[i],
|
||||
¶mtypeid, ¶mLI->value, ¶mLI->isnull);
|
||||
}
|
||||
paramLI->kind = PARAM_INVALID;
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* procedural language
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.23 2002/09/05 00:43:07 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.24 2003/03/25 00:34:23 tgl Exp $
|
||||
*
|
||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||
*
|
||||
@ -1019,7 +1019,9 @@ plpgsql_dumptree(PLpgSQL_function * func)
|
||||
printf("REC %s\n", ((PLpgSQL_rec *) d)->refname);
|
||||
break;
|
||||
case PLPGSQL_DTYPE_RECFIELD:
|
||||
printf("RECFIELD %-16s of REC %d\n", ((PLpgSQL_recfield *) d)->fieldname, ((PLpgSQL_recfield *) d)->recno);
|
||||
printf("RECFIELD %-16s of REC %d\n",
|
||||
((PLpgSQL_recfield *) d)->fieldname,
|
||||
((PLpgSQL_recfield *) d)->recparentno);
|
||||
break;
|
||||
case PLPGSQL_DTYPE_TRIGARG:
|
||||
printf("TRIGARG ");
|
||||
|
@ -3,7 +3,7 @@
|
||||
* procedural language
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.31 2002/12/15 16:17:59 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.32 2003/03/25 00:34:24 tgl Exp $
|
||||
*
|
||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||
*
|
||||
@ -152,6 +152,10 @@ typedef struct
|
||||
} PLpgSQL_type;
|
||||
|
||||
|
||||
/*
|
||||
* PLpgSQL_datum is the common supertype for PLpgSQL_expr, PLpgSQL_var,
|
||||
* PLpgSQL_row, PLpgSQL_rec, PLpgSQL_recfield, PLpgSQL_trigarg
|
||||
*/
|
||||
typedef struct
|
||||
{ /* Generic datum array item */
|
||||
int dtype;
|
||||
@ -209,7 +213,7 @@ typedef struct
|
||||
|
||||
|
||||
typedef struct
|
||||
{ /* Record of undefined structure */
|
||||
{ /* Record of non-fixed structure */
|
||||
int dtype;
|
||||
int recno;
|
||||
char *refname;
|
||||
@ -223,11 +227,11 @@ typedef struct
|
||||
|
||||
|
||||
typedef struct
|
||||
{ /* Field in record */
|
||||
{ /* Field in record */
|
||||
int dtype;
|
||||
int rfno;
|
||||
char *fieldname;
|
||||
int recno;
|
||||
int recparentno; /* recno of parent record */
|
||||
} PLpgSQL_recfield;
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user