aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/pl/plpgsql/src/pl_comp.c8
-rw-r--r--src/pl/plpgsql/src/pl_exec.c72
-rw-r--r--src/pl/plpgsql/src/plpgsql.h5
3 files changed, 64 insertions, 21 deletions
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 535fea9257c..a80235cd2aa 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -1267,9 +1267,11 @@ make_datum_param(PLpgSQL_expr *expr, int dno, int location)
param = makeNode(Param);
param->paramkind = PARAM_EXTERN;
param->paramid = dno + 1;
- param->paramtype = exec_get_datum_type(estate, datum);
- param->paramtypmod = -1;
- param->paramcollid = exec_get_datum_collation(estate, datum);
+ exec_get_datum_type_info(estate,
+ datum,
+ &param->paramtype,
+ &param->paramtypmod,
+ &param->paramcollid);
param->location = location;
return (Node *) param;
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 8ca9689efc8..4331a5c8df4 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -4307,29 +4307,63 @@ exec_get_datum_type(PLpgSQL_execstate *estate,
}
/*
- * exec_get_datum_collation Get collation of a PLpgSQL_datum
+ * exec_get_datum_type_info Get datatype etc of a PLpgSQL_datum
+ *
+ * An extended version of exec_get_datum_type, which also retrieves the
+ * typmod and collation of the datum.
*/
-Oid
-exec_get_datum_collation(PLpgSQL_execstate *estate,
- PLpgSQL_datum *datum)
+void
+exec_get_datum_type_info(PLpgSQL_execstate *estate,
+ PLpgSQL_datum *datum,
+ Oid *typeid, int32 *typmod, Oid *collation)
{
- Oid collid;
-
switch (datum->dtype)
{
case PLPGSQL_DTYPE_VAR:
{
PLpgSQL_var *var = (PLpgSQL_var *) datum;
- collid = var->datatype->collation;
+ *typeid = var->datatype->typoid;
+ *typmod = var->datatype->atttypmod;
+ *collation = var->datatype->collation;
break;
}
case PLPGSQL_DTYPE_ROW:
+ {
+ PLpgSQL_row *row = (PLpgSQL_row *) datum;
+
+ if (!row->rowtupdesc) /* should not happen */
+ elog(ERROR, "row variable has no tupdesc");
+ /* Make sure we have a valid type/typmod setting */
+ BlessTupleDesc(row->rowtupdesc);
+ *typeid = row->rowtupdesc->tdtypeid;
+ /* do NOT return the mutable typmod of a RECORD variable */
+ *typmod = -1;
+ /* composite types are never collatable */
+ *collation = InvalidOid;
+ break;
+ }
+
case PLPGSQL_DTYPE_REC:
- /* composite types are never collatable */
- collid = InvalidOid;
- break;
+ {
+ PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
+
+ if (rec->tupdesc == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("record \"%s\" is not assigned yet",
+ rec->refname),
+ errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
+ /* Make sure we have a valid type/typmod setting */
+ BlessTupleDesc(rec->tupdesc);
+ *typeid = rec->tupdesc->tdtypeid;
+ /* do NOT return the mutable typmod of a RECORD variable */
+ *typmod = -1;
+ /* composite types are never collatable */
+ *collation = InvalidOid;
+ break;
+ }
case PLPGSQL_DTYPE_RECFIELD:
{
@@ -4350,21 +4384,27 @@ exec_get_datum_collation(PLpgSQL_execstate *estate,
(errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("record \"%s\" has no field \"%s\"",
rec->refname, recfield->fieldname)));
- /* XXX there's no SPI_getcollid, as yet */
+ *typeid = SPI_gettypeid(rec->tupdesc, fno);
+ /* XXX there's no SPI_gettypmod, for some reason */
+ if (fno > 0)
+ *typmod = rec->tupdesc->attrs[fno - 1]->atttypmod;
+ else
+ *typmod = -1;
+ /* XXX there's no SPI_getcollation either */
if (fno > 0)
- collid = rec->tupdesc->attrs[fno - 1]->attcollation;
+ *collation = rec->tupdesc->attrs[fno - 1]->attcollation;
else /* no system column types have collation */
- collid = InvalidOid;
+ *collation = InvalidOid;
break;
}
default:
elog(ERROR, "unrecognized dtype: %d", datum->dtype);
- collid = InvalidOid; /* keep compiler quiet */
+ *typeid = InvalidOid; /* keep compiler quiet */
+ *typmod = -1;
+ *collation = InvalidOid;
break;
}
-
- return collid;
}
/* ----------
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index e50d7eb45fe..89103aea8c5 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -905,8 +905,9 @@ extern void plpgsql_subxact_cb(SubXactEvent event, SubTransactionId mySubid,
SubTransactionId parentSubid, void *arg);
extern Oid exec_get_datum_type(PLpgSQL_execstate *estate,
PLpgSQL_datum *datum);
-extern Oid exec_get_datum_collation(PLpgSQL_execstate *estate,
- PLpgSQL_datum *datum);
+extern void exec_get_datum_type_info(PLpgSQL_execstate *estate,
+ PLpgSQL_datum *datum,
+ Oid *typeid, int32 *typmod, Oid *collation);
/* ----------
* Functions for namespace handling in pl_funcs.c