1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

Document get_call_result_type() and friends; mark TypeGetTupleDesc()

and RelationNameGetTupleDesc() as deprecated; remove uses of the
latter in the contrib library.  Along the way, clean up crosstab()
code and documentation a little.
This commit is contained in:
Tom Lane
2005-05-30 23:09:07 +00:00
parent b215fae891
commit 978129f28e
12 changed files with 373 additions and 231 deletions

View File

@ -51,8 +51,6 @@ static void validateConnectbyTupleDesc(TupleDesc tupdesc, bool show_branch, bool
static bool compatCrosstabTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2);
static bool compatConnectbyTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2);
static void get_normal_pair(float8 *x1, float8 *x2);
static TupleDesc make_crosstab_tupledesc(TupleDesc spi_tupdesc,
int num_categories);
static Tuplestorestate *connectby(char *relname,
char *key_fld,
char *parent_key_fld,
@ -332,12 +330,14 @@ get_normal_pair(float8 *x1, float8 *x2)
* NOTES:
* 1. SQL result must be ordered by 1,2.
* 2. The number of values columns depends on the tuple description
* of the function's declared return type.
* 2. Missing values (i.e. not enough adjacent rows of same rowid to
* of the function's declared return type. The return type's columns
* must match the datatypes of the SQL query's result. The datatype
* of the category column can be anything, however.
* 3. Missing values (i.e. not enough adjacent rows of same rowid to
* fill the number of result values columns) are filled in with nulls.
* 3. Extra values (i.e. too many adjacent rows of same rowid to fill
* 4. Extra values (i.e. too many adjacent rows of same rowid to fill
* the number of result values columns) are skipped.
* 4. Rows with all nulls in the values columns are skipped.
* 5. Rows with all nulls in the values columns are skipped.
*/
PG_FUNCTION_INFO_V1(crosstab);
Datum
@ -360,10 +360,7 @@ crosstab(PG_FUNCTION_ARGS)
if (SRF_IS_FIRSTCALL())
{
char *sql = GET_STR(PG_GETARG_TEXT_P(0));
Oid funcid = fcinfo->flinfo->fn_oid;
Oid functypeid;
char functyptype;
TupleDesc tupdesc = NULL;
TupleDesc tupdesc;
int ret;
int proc;
@ -391,20 +388,23 @@ crosstab(PG_FUNCTION_ARGS)
spi_tuptable = SPI_tuptable;
spi_tupdesc = spi_tuptable->tupdesc;
/*
/*----------
* The provided SQL query must always return three columns.
*
* 1. rowname the label or identifier for each row in the final
* result 2. category the label or identifier for each column
* in the final result 3. values the value for each column
* in the final result
* 1. rowname
* the label or identifier for each row in the final result
* 2. category
* the label or identifier for each column in the final result
* 3. values
* the value for each column in the final result
*----------
*/
if (spi_tupdesc->natts != 3)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid source data SQL statement"),
errdetail("The provided SQL must return 3 " \
" columns; rowid, category, and values.")));
errdetail("The provided SQL must return 3 "
"columns: rowid, category, and values.")));
}
else
{
@ -416,39 +416,31 @@ crosstab(PG_FUNCTION_ARGS)
/* SPI switches context on us, so reset it */
MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
/* get the typeid that represents our return type */
functypeid = get_func_rettype(funcid);
/* check typtype to see if we have a predetermined return type */
functyptype = get_typtype(functypeid);
if (functyptype == 'c')
/* get a tuple descriptor for our result type */
switch (get_call_result_type(fcinfo, NULL, &tupdesc))
{
/* Build a tuple description for a named composite type */
tupdesc = TypeGetTupleDesc(functypeid, NIL);
}
else if (functypeid == RECORDOID)
{
if (fcinfo->nargs != 2)
case TYPEFUNC_COMPOSITE:
/* success */
break;
case TYPEFUNC_RECORD:
/* failed to determine actual type of RECORD */
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("wrong number of arguments")));
else
{
int num_categories = PG_GETARG_INT32(1);
tupdesc = make_crosstab_tupledesc(spi_tupdesc, num_categories);
}
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("function returning record called in context "
"that cannot accept type record")));
break;
default:
/* result type isn't composite */
elog(ERROR, "return type must be a row type");
break;
}
else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("return type must be a row type")));
/* make sure we have a persistent copy of the tupdesc */
tupdesc = CreateTupleDescCopy(tupdesc);
/*
* Check that return tupdesc is compatible with the one we got
* from ret_relname, at least based on number and type of
* attributes
* Check that return tupdesc is compatible with the data we got
* from SPI, at least based on number and type of attributes
*/
if (!compatCrosstabTupleDescs(tupdesc, spi_tupdesc))
ereport(ERROR,
@ -679,8 +671,8 @@ crosstab(PG_FUNCTION_ARGS)
* 1. SQL result must be ordered by 1.
* 2. The number of values columns depends on the tuple description
* of the function's declared return type.
* 2. Missing values (i.e. missing category) are filled in with nulls.
* 3. Extra values (i.e. not in category results) are skipped.
* 3. Missing values (i.e. missing category) are filled in with nulls.
* 4. Extra values (i.e. not in category results) are skipped.
*/
PG_FUNCTION_INFO_V1(crosstab_hash);
Datum
@ -1628,52 +1620,6 @@ compatCrosstabTupleDescs(TupleDesc ret_tupdesc, TupleDesc sql_tupdesc)
return true;
}
static TupleDesc
make_crosstab_tupledesc(TupleDesc spi_tupdesc, int num_categories)
{
Form_pg_attribute sql_attr;
Oid sql_atttypid;
TupleDesc tupdesc;
int natts;
AttrNumber attnum;
char attname[NAMEDATALEN];
int i;
/*
* We need to build a tuple description with one column for the
* rowname, and num_categories columns for the values. Each must be of
* the same type as the corresponding spi result input column.
*/
natts = num_categories + 1;
tupdesc = CreateTemplateTupleDesc(natts, false);
/* first the rowname column */
attnum = 1;
sql_attr = spi_tupdesc->attrs[0];
sql_atttypid = sql_attr->atttypid;
strcpy(attname, "rowname");
TupleDescInitEntry(tupdesc, attnum, attname, sql_atttypid,
-1, 0);
/* now the category values columns */
sql_attr = spi_tupdesc->attrs[2];
sql_atttypid = sql_attr->atttypid;
for (i = 0; i < num_categories; i++)
{
attnum++;
sprintf(attname, "category_%d", i + 1);
TupleDescInitEntry(tupdesc, attnum, attname, sql_atttypid,
-1, 0);
}
return tupdesc;
}
/*
* Return a properly quoted literal value.
* Uses quote_literal in quote.c