82 int num_columns,
pivot_field *piv_columns,
int field_for_columns,
83 int num_rows,
pivot_field *piv_rows,
int field_for_rows,
114 int field_for_columns;
116 int sort_field_for_columns;
124 pg_log_error(
"\\crosstabview: statement did not return a result set");
130 pg_log_error(
"\\crosstabview: query must return at least three columns");
140 if (field_for_rows < 0)
146 field_for_columns = 1;
150 if (field_for_columns < 0)
155 if (field_for_columns == field_for_rows)
157 pg_log_error(
"\\crosstabview: vertical and horizontal headers must be different columns");
173 pg_log_error(
"\\crosstabview: data column must be specified when query returns more than three columns");
180 if (
i != field_for_rows &&
i != field_for_columns)
186 Assert(field_for_data >= 0);
191 if (field_for_data < 0)
197 sort_field_for_columns = -1;
201 if (sort_field_for_columns < 0)
221 if (sort_field_for_columns >= 0 &&
229 pg_log_error(
"\\crosstabview: maximum number of columns (%d) exceeded",
245 num_columns = piv_columns.
count;
246 num_rows = piv_rows.
count;
261 if (sort_field_for_columns >= 0)
262 rankSort(num_columns, array_columns);
268 num_columns, array_columns, field_for_columns,
269 num_rows, array_rows, field_for_rows,
287 int num_columns,
pivot_field *piv_columns,
int field_for_columns,
288 int num_rows,
pivot_field *piv_rows,
int field_for_rows,
305 PQfname(result, field_for_rows),
315 horiz_map = (
int *)
pg_malloc(
sizeof(
int) * num_columns);
316 for (
i = 0;
i < num_columns;
i++)
317 horiz_map[piv_columns[
i].rank] =
i;
324 for (
i = 0;
i < num_columns;
i++)
328 colname = piv_columns[horiz_map[
i]].
name ?
329 piv_columns[horiz_map[
i]].
name :
337 for (
i = 0;
i < num_rows;
i++)
339 int k = piv_rows[
i].
rank;
341 cont.
cells[k * (num_columns + 1)] = piv_rows[
i].
name ?
345 cont.
cellsadded = num_rows * (num_columns + 1);
350 for (rn = 0; rn <
PQntuples(result); rn++)
369 row_number = rp->
rank;
383 col_number = cp->
rank;
386 if (col_number >= 0 && row_number >= 0)
391 idx = 1 + col_number + row_number * (num_columns + 1);
398 pg_log_error(
"\\crosstabview: query result contains multiple data values for row \"%s\", column \"%s\"",
418 if (cont.
cells[
i] == NULL)
441 tree->end->children[0] =
tree->end->children[1] =
tree->end;
460 if (node ==
tree->root)
463 if (node !=
tree->end)
513 int dir = (1 -
b) / 2;
519 if (current !=
tree->end)
533 if (current ==
tree->end)
539 new_node->
field = field;
579 if (node ==
tree->end)
594 hmap = (
int *)
pg_malloc(
sizeof(
int) * num_columns * 2);
595 for (
i = 0;
i < num_columns;
i++)
602 strspn(
val + 1,
"0123456789") == strlen(
val + 1)) ||
603 strspn(
val,
"0123456789") == strlen(
val)))
605 hmap[
i * 2] = atoi(
val);
618 for (
i = 0;
i < num_columns;
i++)
620 piv_columns[hmap[
i * 2 + 1]].
rank =
i;
640 if (
arg[0] && strspn(
arg,
"0123456789") == strlen(
arg))
646 pg_log_error(
"\\crosstabview: column number %d is out of range 1..%d",
702 return pa->
name ? -1 : 0;
Datum idx(PG_FUNCTION_ARGS)
#define Assert(condition)
static void avlUpdateHeight(avl_node *n)
static int avlCollectFields(avl_tree *tree, avl_node *node, pivot_field *fields, int idx)
static int pivotFieldCompare(const void *a, const void *b)
static void avlInsertNode(avl_tree *tree, avl_node **node, pivot_field field)
static int rankCompare(const void *a, const void *b)
struct _avl_tree avl_tree
static void avlFree(avl_tree *tree, avl_node *node)
static avl_node * avlRotate(avl_node **current, int dir)
static bool printCrosstab(const PGresult *result, int num_columns, pivot_field *piv_columns, int field_for_columns, int num_rows, pivot_field *piv_rows, int field_for_rows, int field_for_data)
static void rankSort(int num_columns, pivot_field *piv_columns)
bool PrintResultInCrosstab(const PGresult *res)
static int avlBalance(avl_node *n)
static int indexOfColumn(char *arg, const PGresult *res)
static void avlInit(avl_tree *tree)
static void avlMergeValue(avl_tree *tree, char *name, char *sort_value)
struct _avl_node avl_node
struct _pivot_field pivot_field
static void avlAdjustBalance(avl_tree *tree, avl_node **node)
#define CROSSTABVIEW_MAX_COLUMNS
static void PGresult * res
Oid PQftype(const PGresult *res, int field_num)
ExecStatusType PQresultStatus(const PGresult *res)
int PQntuples(const PGresult *res)
char * PQfname(const PGresult *res, int field_num)
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
int PQnfields(const PGresult *res)
void * pg_malloc0(size_t size)
void * pg_malloc(size_t size)
void printTableInit(printTableContent *const content, const printTableOpt *opt, const char *title, const int ncolumns, const int nrows)
void printTableCleanup(printTableContent *const content)
char column_type_alignment(Oid ftype)
void printTable(const printTableContent *cont, FILE *fout, bool is_pager, FILE *flog)
void printTableAddHeader(printTableContent *const content, char *header, const bool translate, const char align)
static int pg_cmp_s32(int32 a, int32 b)
#define pg_log_error(...)
#define qsort(a, b, c, d)
void dequote_downcase_identifier(char *str, bool downcase, int encoding)
static int cmp(const chr *x, const chr *y, size_t len)
static int before(chr x, chr y)
struct _avl_node * children[2]