summaryrefslogtreecommitdiff
path: root/contrib/tablefunc/tablefunc.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tablefunc/tablefunc.c')
-rw-r--r--contrib/tablefunc/tablefunc.c162
1 files changed, 106 insertions, 56 deletions
diff --git a/contrib/tablefunc/tablefunc.c b/contrib/tablefunc/tablefunc.c
index a220c336961..be99d855bf5 100644
--- a/contrib/tablefunc/tablefunc.c
+++ b/contrib/tablefunc/tablefunc.c
@@ -137,24 +137,16 @@ do { \
hentry = (crosstab_HashEnt*) hash_search(crosstab_HashTable, \
key, HASH_ENTER, &found); \
if (hentry == NULL) \
- elog(ERROR, "out of memory in crosstab_HashTable"); \
+ ereport(ERROR, \
+ (errcode(ERRCODE_OUT_OF_MEMORY), \
+ errmsg("out of memory"))); \
if (found) \
- elog(ERROR, "trying to use a category name more than once"); \
+ ereport(ERROR, \
+ (errcode(ERRCODE_DUPLICATE_OBJECT), \
+ errmsg("duplicate category name"))); \
hentry->catdesc = CATDESC; \
} while(0)
-#define crosstab_HashTableDelete(CATNAME) \
-do { \
- crosstab_HashEnt *hentry; char key[MAX_CATNAME_LEN]; \
- \
- MemSet(key, 0, MAX_CATNAME_LEN); \
- snprintf(key, MAX_CATNAME_LEN - 1, "%s", CATNAME); \
- hentry = (crosstab_HashEnt*) hash_search(crosstab_HashTable, \
- key, HASH_REMOVE, NULL); \
- if (hentry == NULL) \
- elog(WARNING, "trying to delete function name that does not exist."); \
-} while(0)
-
/* hash table */
typedef struct crosstab_hashent
{
@@ -389,6 +381,7 @@ crosstab(PG_FUNCTION_ARGS)
/* Connect to SPI manager */
if ((ret = SPI_connect()) < 0)
+ /* internal error */
elog(ERROR, "crosstab: SPI_connect returned %d", ret);
/* Retrieve the desired rows */
@@ -410,8 +403,11 @@ crosstab(PG_FUNCTION_ARGS)
* in the final result
*/
if (spi_tupdesc->natts != 3)
- elog(ERROR, "crosstab: provided SQL must return 3 columns;"
- " a rowid, a category, and a values column");
+ 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.")));
}
else
{
@@ -437,7 +433,9 @@ crosstab(PG_FUNCTION_ARGS)
else if (functyptype == 'p' && functypeid == RECORDOID)
{
if (fcinfo->nargs != 2)
- elog(ERROR, "Wrong number of arguments specified for function");
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("wrong number of arguments")));
else
{
int num_categories = PG_GETARG_INT32(1);
@@ -446,7 +444,9 @@ crosstab(PG_FUNCTION_ARGS)
}
}
else
- elog(ERROR, "crosstab: return type must be a row type");
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("return type must be a row type")));
/*
* Check that return tupdesc is compatible with the one we got
@@ -454,8 +454,10 @@ crosstab(PG_FUNCTION_ARGS)
* attributes
*/
if (!compatCrosstabTupleDescs(tupdesc, spi_tupdesc))
- elog(ERROR, "crosstab: return and sql tuple descriptions are"
- " incompatible");
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("return and sql tuple descriptions are " \
+ "incompatible")));
/* allocate a slot for a tuple with this tupdesc */
slot = TupleDescGetSlot(tupdesc);
@@ -706,8 +708,10 @@ crosstab_hash(PG_FUNCTION_ARGS)
/* check to see if caller supports us returning a tuplestore */
if (!rsinfo || !(rsinfo->allowedModes & SFRM_Materialize))
- elog(ERROR, "crosstab: materialize mode required, but it is not "
- "allowed in this context");
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("materialize mode required, but it is not " \
+ "allowed in this context")));
per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
oldcontext = MemoryContextSwitchTo(per_query_ctx);
@@ -723,8 +727,10 @@ crosstab_hash(PG_FUNCTION_ARGS)
* function to complain if needed.
*/
if (tupdesc->natts < 2)
- elog(ERROR, "crosstab: query-specified return tuple and " \
- "crosstab function are not compatible");
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("query-specified return tuple and " \
+ "crosstab function are not compatible")));
/* load up the categories hash table */
num_categories = load_categories_hash(cats_sql, per_query_ctx);
@@ -775,6 +781,7 @@ load_categories_hash(char *cats_sql, MemoryContext per_query_ctx)
/* Connect to SPI manager */
if ((ret = SPI_connect()) < 0)
+ /* internal error */
elog(ERROR, "load_categories_hash: SPI_connect returned %d", ret);
/* Retrieve the category name rows */
@@ -793,8 +800,10 @@ load_categories_hash(char *cats_sql, MemoryContext per_query_ctx)
* category - the label or identifier for each column
*/
if (spi_tupdesc->natts != 1)
- elog(ERROR, "load_categories_hash: provided categories SQL must " \
- "return 1 column of at least one row");
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("provided \"categories\" SQL must " \
+ "return 1 column of at least one row")));
for (i = 0; i < proc; i++)
{
@@ -824,11 +833,14 @@ load_categories_hash(char *cats_sql, MemoryContext per_query_ctx)
{
/* no qualifying tuples */
SPI_finish();
- elog(ERROR, "load_categories_hash: provided categories SQL must " \
- "return 1 column of at least one row");
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("provided \"categories\" SQL must " \
+ "return 1 column of at least one row")));
}
if (SPI_finish() != SPI_OK_FINISH)
+ /* internal error */
elog(ERROR, "load_categories_hash: SPI_finish() failed");
return num_categories;
@@ -856,6 +868,7 @@ get_crosstab_tuplestore(char *sql,
/* Connect to SPI manager */
if ((ret = SPI_connect()) < 0)
+ /* internal error */
elog(ERROR, "get_crosstab_tuplestore: SPI_connect returned %d", ret);
/* Now retrieve the crosstab source rows */
@@ -887,17 +900,22 @@ get_crosstab_tuplestore(char *sql,
* time we encounter a particular rowname.
*/
if (ncols < 3)
- elog(ERROR, "get_crosstab_tuplestore: provided source SQL must " \
- "return at least 3 columns; a rowid, a category, " \
- "and a values column");
+ 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.")));
result_ncols = (ncols - 2) + num_categories;
/* Recheck to make sure we tuple descriptor still looks reasonable */
if (tupdesc->natts != result_ncols)
- elog(ERROR, "get_crosstab_tuplestore: query-specified return " \
- "tuple has %d columns but crosstab returns %d",
- tupdesc->natts, result_ncols);
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid return type"),
+ errdetail("query-specified return " \
+ "tuple has %d columns but crosstab " \
+ "returns %d", tupdesc->natts, result_ncols)));
/* allocate space */
values = (char **) palloc(result_ncols * sizeof(char *));
@@ -985,6 +1003,7 @@ get_crosstab_tuplestore(char *sql,
}
if (SPI_finish() != SPI_OK_FINISH)
+ /* internal error */
elog(ERROR, "get_crosstab_tuplestore: SPI_finish() failed");
tuplestore_donestoring(tupstore);
@@ -1048,8 +1067,10 @@ connectby_text(PG_FUNCTION_ARGS)
/* check to see if caller supports us returning a tuplestore */
if (!rsinfo || !(rsinfo->allowedModes & SFRM_Materialize))
- elog(ERROR, "connectby: materialize mode required, but it is not "
- "allowed in this context");
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("materialize mode required, but it is not " \
+ "allowed in this context")));
if (fcinfo->nargs == 6)
{
@@ -1074,8 +1095,10 @@ connectby_text(PG_FUNCTION_ARGS)
/* check to see if caller supports us returning a tuplestore */
if (!rsinfo || !(rsinfo->allowedModes & SFRM_Materialize))
- elog(ERROR, "connectby requires Materialize mode, but it is not "
- "allowed in this context");
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("materialize mode required, but it is not " \
+ "allowed in this context")));
/* OK, go to work */
rsinfo->returnMode = SFRM_Materialize;
@@ -1122,6 +1145,7 @@ connectby(char *relname,
/* Connect to SPI manager */
if ((ret = SPI_connect()) < 0)
+ /* internal error */
elog(ERROR, "connectby: SPI_connect returned %d", ret);
/* switch to longer term context to create the tuple store */
@@ -1226,8 +1250,11 @@ build_tuplestore_recursively(char *key_fld,
*/
if (!compatConnectbyTupleDescs(tupdesc, spi_tupdesc))
- elog(ERROR, "connectby: return and sql tuple descriptions are "
- "incompatible");
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid return type"),
+ errdetail("Return and SQL tuple descriptions are " \
+ "incompatible.")));
/* root value is the one we initially start with */
values[0] = start_with;
@@ -1346,30 +1373,44 @@ validateConnectbyTupleDesc(TupleDesc tupdesc, bool show_branch)
if (show_branch)
{
if (tupdesc->natts != CONNECTBY_NCOLS)
- elog(ERROR, "Query-specified return tuple not valid for Connectby: "
- "wrong number of columns");
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid return type"),
+ errdetail("Query-specified return tuple has " \
+ "wrong number of columns.")));
}
else
{
if (tupdesc->natts != CONNECTBY_NCOLS_NOBRANCH)
- elog(ERROR, "Query-specified return tuple not valid for Connectby: "
- "wrong number of columns");
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid return type"),
+ errdetail("Query-specified return tuple has " \
+ "wrong number of columns.")));
}
/* check that the types of the first two columns match */
if (tupdesc->attrs[0]->atttypid != tupdesc->attrs[1]->atttypid)
- elog(ERROR, "Query-specified return tuple not valid for Connectby: "
- "first two columns must be the same type");
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid return type"),
+ errdetail("First two columns must be the same type.")));
/* check that the type of the third column is INT4 */
if (tupdesc->attrs[2]->atttypid != INT4OID)
- elog(ERROR, "Query-specified return tuple not valid for Connectby: "
- "third column must be type %s", format_type_be(INT4OID));
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid return type"),
+ errdetail("Third column must be type %s.",
+ format_type_be(INT4OID))));
/* check that the type of the fourth column is TEXT if applicable */
if (show_branch && tupdesc->attrs[3]->atttypid != TEXTOID)
- elog(ERROR, "Query-specified return tuple not valid for Connectby: "
- "fourth column must be type %s", format_type_be(TEXTOID));
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid return type"),
+ errdetail("Fourth column must be type %s.",
+ format_type_be(TEXTOID))));
/* OK, the tupdesc is valid for our purposes */
}
@@ -1387,15 +1428,21 @@ compatConnectbyTupleDescs(TupleDesc ret_tupdesc, TupleDesc sql_tupdesc)
ret_atttypid = ret_tupdesc->attrs[0]->atttypid;
sql_atttypid = sql_tupdesc->attrs[0]->atttypid;
if (ret_atttypid != sql_atttypid)
- elog(ERROR, "compatConnectbyTupleDescs: SQL key field datatype does "
- "not match return key field datatype");
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid return type"),
+ errdetail("SQL key field datatype does " \
+ "not match return key field datatype.")));
/* check the parent_key_fld types match */
ret_atttypid = ret_tupdesc->attrs[1]->atttypid;
sql_atttypid = sql_tupdesc->attrs[1]->atttypid;
if (ret_atttypid != sql_atttypid)
- elog(ERROR, "compatConnectbyTupleDescs: SQL parent key field datatype "
- "does not match return parent key field datatype");
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid return type"),
+ errdetail("SQL parent key field datatype does " \
+ "not match return parent key field datatype.")));
/* OK, the two tupdescs are compatible for our purposes */
return true;
@@ -1417,8 +1464,11 @@ compatCrosstabTupleDescs(TupleDesc ret_tupdesc, TupleDesc sql_tupdesc)
ret_atttypid = ret_tupdesc->attrs[0]->atttypid;
sql_atttypid = sql_tupdesc->attrs[0]->atttypid;
if (ret_atttypid != sql_atttypid)
- elog(ERROR, "compatCrosstabTupleDescs: SQL rowid datatype does not match"
- " return rowid datatype");
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid return type"),
+ errdetail("SQL rowid datatype does not match " \
+ "return rowid datatype.")));
/*
* - attribute [1] of the sql tuple is the category; no need to check