Attached is a patch for contrib/tablefunc. It fixes two issues raised by

Lars Boegild Thomsen (full email below) and also corrects the regression
expected output for a recent backend message adjustment. Please apply.

Joe Conway
This commit is contained in:
Tom Lane 2003-10-02 03:51:40 +00:00
parent 04b40923d6
commit 08c33c426b
2 changed files with 71 additions and 67 deletions

View File

@ -127,7 +127,7 @@ SELECT * FROM crosstab('SELECT rowid, attribute, val FROM ct where rowclass = ''
-- hash based crosstab
--
create table cth(id serial, rowid text, rowdt timestamp, attribute text, val text);
NOTICE: CREATE TABLE will create implicit sequence "cth_id_seq" for SERIAL column "cth.id"
NOTICE: CREATE TABLE will create implicit sequence "cth_id_seq" for "serial" column "cth.id"
insert into cth values(DEFAULT,'test1','01 March 2003','temperature','42');
insert into cth values(DEFAULT,'test1','01 March 2003','test_result','PASS');
-- the next line is intentionally left commented and is therefore a "missing" attribute

View File

@ -1295,35 +1295,100 @@ build_tuplestore_recursively(char *key_fld,
int ret;
int proc;
int serial_column;
StringInfo branchstr = NULL;
StringInfo chk_branchstr = NULL;
StringInfo chk_current_key = NULL;
char **values;
char *current_key;
char *current_key_parent;
char current_level[INT32_STRLEN];
char serial_str[INT32_STRLEN];
char *current_branch;
HeapTuple tuple;
if (max_depth > 0 && level > max_depth)
return tupstore;
/* start a new branch */
branchstr = makeStringInfo();
/* need these to check for recursion */
chk_branchstr = makeStringInfo();
chk_current_key = makeStringInfo();
/* Build initial sql statement */
if (!show_serial)
{
appendStringInfo(sql, "SELECT %s, %s FROM %s WHERE %s = '%s' AND %s IS NOT NULL",
appendStringInfo(sql, "SELECT %s, %s FROM %s WHERE %s = '%s' AND %s IS NOT NULL AND %s <> %s",
key_fld,
parent_key_fld,
relname,
parent_key_fld,
start_with,
key_fld);
key_fld, key_fld, parent_key_fld);
serial_column = 0;
}
else
{
appendStringInfo(sql, "SELECT %s, %s FROM %s WHERE %s = '%s' AND %s IS NOT NULL ORDER BY %s",
appendStringInfo(sql, "SELECT %s, %s FROM %s WHERE %s = '%s' AND %s IS NOT NULL AND %s <> %s ORDER BY %s",
key_fld,
parent_key_fld,
relname,
parent_key_fld,
start_with,
key_fld,
key_fld, key_fld, parent_key_fld,
orderby_fld);
serial_column = 1;
}
if (show_branch)
values = (char **) palloc((CONNECTBY_NCOLS + serial_column) * sizeof(char *));
else
values = (char **) palloc((CONNECTBY_NCOLS_NOBRANCH + serial_column) * sizeof(char *));
/* First time through, do a little setup */
if (level == 0)
{
/* root value is the one we initially start with */
values[0] = start_with;
/* root value has no parent */
values[1] = NULL;
/* root level is 0 */
sprintf(current_level, "%d", level);
values[2] = current_level;
/* root branch is just starting root value */
if (show_branch)
values[3] = start_with;
/* root starts the serial with 1 */
if (show_serial)
{
sprintf(serial_str, "%d", (*serial)++);
if (show_branch)
values[4] = serial_str;
else
values[3] = serial_str;
}
/* construct the tuple */
tuple = BuildTupleFromCStrings(attinmeta, values);
/* switch to long lived context while storing the tuple */
oldcontext = MemoryContextSwitchTo(per_query_ctx);
/* now store it */
tuplestore_puttuple(tupstore, tuple);
/* now reset the context */
MemoryContextSwitchTo(oldcontext);
/* increment level */
level++;
}
/* Retrieve the desired rows */
ret = SPI_exec(sql->data, 0);
proc = SPI_processed;
@ -1331,34 +1396,12 @@ build_tuplestore_recursively(char *key_fld,
/* Check for qualifying tuples */
if ((ret == SPI_OK_SELECT) && (proc > 0))
{
HeapTuple tuple;
HeapTuple spi_tuple;
SPITupleTable *tuptable = SPI_tuptable;
TupleDesc spi_tupdesc = tuptable->tupdesc;
int i;
char *current_key;
char *current_key_parent;
char current_level[INT32_STRLEN];
char serial_str[INT32_STRLEN];
char *current_branch;
char **values;
StringInfo branchstr = NULL;
StringInfo chk_branchstr = NULL;
StringInfo chk_current_key = NULL;
/* start a new branch */
branchstr = makeStringInfo();
/* need these to check for recursion */
chk_branchstr = makeStringInfo();
chk_current_key = makeStringInfo();
if (show_branch)
values = (char **) palloc((CONNECTBY_NCOLS + serial_column) * sizeof(char *));
else
values = (char **) palloc((CONNECTBY_NCOLS_NOBRANCH + serial_column) * sizeof(char *));
/* First time through, do a little setup */
/* First time through, do a little more setup */
if (level == 0)
{
/*
@ -1373,45 +1416,6 @@ build_tuplestore_recursively(char *key_fld,
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;
/* root value has no parent */
values[1] = NULL;
/* root level is 0 */
sprintf(current_level, "%d", level);
values[2] = current_level;
/* root branch is just starting root value */
if (show_branch)
values[3] = start_with;
/* root starts the serial with 1 */
if (show_serial)
{
sprintf(serial_str, "%d", (*serial)++);
if (show_branch)
values[4] = serial_str;
else
values[3] = serial_str;
}
/* construct the tuple */
tuple = BuildTupleFromCStrings(attinmeta, values);
/* switch to long lived context while storing the tuple */
oldcontext = MemoryContextSwitchTo(per_query_ctx);
/* now store it */
tuplestore_puttuple(tupstore, tuple);
/* now reset the context */
MemoryContextSwitchTo(oldcontext);
/* increment level */
level++;
}
for (i = 0; i < proc; i++)