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:
parent
04b40923d6
commit
08c33c426b
@ -127,7 +127,7 @@ SELECT * FROM crosstab('SELECT rowid, attribute, val FROM ct where rowclass = ''
|
|||||||
-- hash based crosstab
|
-- hash based crosstab
|
||||||
--
|
--
|
||||||
create table cth(id serial, rowid text, rowdt timestamp, attribute text, val text);
|
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','temperature','42');
|
||||||
insert into cth values(DEFAULT,'test1','01 March 2003','test_result','PASS');
|
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
|
-- the next line is intentionally left commented and is therefore a "missing" attribute
|
||||||
|
@ -1295,35 +1295,100 @@ build_tuplestore_recursively(char *key_fld,
|
|||||||
int ret;
|
int ret;
|
||||||
int proc;
|
int proc;
|
||||||
int serial_column;
|
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)
|
if (max_depth > 0 && level > max_depth)
|
||||||
return tupstore;
|
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 */
|
/* Build initial sql statement */
|
||||||
if (!show_serial)
|
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,
|
key_fld,
|
||||||
parent_key_fld,
|
parent_key_fld,
|
||||||
relname,
|
relname,
|
||||||
parent_key_fld,
|
parent_key_fld,
|
||||||
start_with,
|
start_with,
|
||||||
key_fld);
|
key_fld, key_fld, parent_key_fld);
|
||||||
serial_column = 0;
|
serial_column = 0;
|
||||||
}
|
}
|
||||||
else
|
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,
|
key_fld,
|
||||||
parent_key_fld,
|
parent_key_fld,
|
||||||
relname,
|
relname,
|
||||||
parent_key_fld,
|
parent_key_fld,
|
||||||
start_with,
|
start_with,
|
||||||
key_fld,
|
key_fld, key_fld, parent_key_fld,
|
||||||
orderby_fld);
|
orderby_fld);
|
||||||
serial_column = 1;
|
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 */
|
/* Retrieve the desired rows */
|
||||||
ret = SPI_exec(sql->data, 0);
|
ret = SPI_exec(sql->data, 0);
|
||||||
proc = SPI_processed;
|
proc = SPI_processed;
|
||||||
@ -1331,34 +1396,12 @@ build_tuplestore_recursively(char *key_fld,
|
|||||||
/* Check for qualifying tuples */
|
/* Check for qualifying tuples */
|
||||||
if ((ret == SPI_OK_SELECT) && (proc > 0))
|
if ((ret == SPI_OK_SELECT) && (proc > 0))
|
||||||
{
|
{
|
||||||
HeapTuple tuple;
|
|
||||||
HeapTuple spi_tuple;
|
HeapTuple spi_tuple;
|
||||||
SPITupleTable *tuptable = SPI_tuptable;
|
SPITupleTable *tuptable = SPI_tuptable;
|
||||||
TupleDesc spi_tupdesc = tuptable->tupdesc;
|
TupleDesc spi_tupdesc = tuptable->tupdesc;
|
||||||
int i;
|
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 */
|
/* First time through, do a little more setup */
|
||||||
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 */
|
|
||||||
if (level == 0)
|
if (level == 0)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -1373,45 +1416,6 @@ build_tuplestore_recursively(char *key_fld,
|
|||||||
errmsg("invalid return type"),
|
errmsg("invalid return type"),
|
||||||
errdetail("Return and SQL tuple descriptions are " \
|
errdetail("Return and SQL tuple descriptions are " \
|
||||||
"incompatible.")));
|
"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++)
|
for (i = 0; i < proc; i++)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user