Daniel Verite wrote: > > regression=# select * from pg_class \crosstabview relnatts > > \crosstabview: missing second argument > > regression-# > > Fixed. This was modelled after the behavior of: > select 1 \badcommand > but I've changed to mimic what happens with: > select 1 \g /some/invalid/path > the query buffer is not discarded by the error but the prompt > is ready for a fresh new command.
Works for me. > > * A few examples in docs. The psql manpage should have at least two new > > examples showing the crosstab features, one with the simplest case you > > can think of, and another one showing all the features. > > Added that in the EXAMPLES section at the very end of the manpage. Ok. Seems a bit too short to me, and I don't like the fact that you can't actually run it because you need to create the my_table beforehand. I think it'd be better if you used a VALUES clause there, so that the reader can cut'n paste into psql to start to play with the feature. > > * In the "if (cont.cells[idx] != NULL && cont.cells[idx][0] != '\0')" > > block (line 497 in the attached), can't we do the same thing by using > > psprintf? > > In that block, we can't pass a cell contents as a valist and be done with > that cell, because duplicates of (col value,row value) may happen > at any iteration of the upper loop over PQntuples(results). Any cell really > may need reallocation unpredictably until that loop is done, whereas > psprintf starts by allocating a new buffer unconditionally, so it doesn't > look to me like it could help to simplify that block. I don't know what you mean, but here's what I meant. -- Álvaro Herrera http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index b3510b9..0216dae 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -496,12 +496,12 @@ printCrosstab(const PGresult *results, int num_columns, { src_col = colsG[i]; - content = (!PQgetisnull(results, rn, src_col)) ? + content = !PQgetisnull(results, rn, src_col) ? PQgetvalue(results, rn, src_col) : (popt.nullPrint ? popt.nullPrint : ""); } - if (cont.cells[idx] != NULL && cont.cells[idx][0] != '\0') + if (cont.cells[idx] != NULL) { /* * Multiple values for the same (row,col) are projected @@ -509,12 +509,9 @@ printCrosstab(const PGresult *results, int num_columns, * previous content of the cell from the new value by a * newline. */ - int content_size; char *new_content; int idx2; - content_size = strlen(cont.cells[idx]) + 2 + strlen(content) + 1; - /* * idx2 is an index into allocated_cells. It differs from * idx (index into cont.cells), because vertical and @@ -524,34 +521,17 @@ printCrosstab(const PGresult *results, int num_columns, idx2 = (row_number * num_columns) + col_number; if (allocated_cells[idx2] != NULL) - { - new_content = pg_realloc(allocated_cells[idx2], content_size); - } + new_content = psprintf("%s%s%s", + allocated_cells[idx2], + i == 0 ? "\n" : " ", + content); else - { - /* - * At this point, cont.cells[idx] still contains a - * PQgetvalue() pointer. Just after, it will contain - * a new pointer maintained in allocated_cells[], and - * freed at the end of this function. - */ - new_content = pg_malloc(content_size); - strcpy(new_content, cont.cells[idx]); - } - cont.cells[idx] = new_content; - allocated_cells[idx2] = new_content; + new_content = psprintf("%s", content); - /* - * Contents that are on adjacent columns in the source - * results get separated by one space in the target. - * Contents that are on different rows in the source get - * separated by newlines in the target. - */ - if (i == 0) - strcat(new_content, "\n"); - else - strcat(new_content, " "); - strcat(new_content, content); + cont.cells[idx] = new_content; + if (allocated_cells[idx2] != NULL) + pg_free(allocated_cells[idx2]); + allocated_cells[idx2] = new_content; } else {
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers