81 int num_columns,
pivot_field *piv_columns,
int field_for_columns,
82 int num_rows,
pivot_field *piv_rows,
int field_for_rows,
113 int field_for_columns;
115 int sort_field_for_columns;
123 pg_log_error(
"\\crosstabview: statement did not return a result set");
129 pg_log_error(
"\\crosstabview: query must return at least three columns");
139 if (field_for_rows < 0)
145 field_for_columns = 1;
149 if (field_for_columns < 0)
154 if (field_for_columns == field_for_rows)
156 pg_log_error(
"\\crosstabview: vertical and horizontal headers must be different columns");
172 pg_log_error(
"\\crosstabview: data column must be specified when query returns more than three columns");
179 if (
i != field_for_rows &&
i != field_for_columns)
185 Assert(field_for_data >= 0);
190 if (field_for_data < 0)
196 sort_field_for_columns = -1;
200 if (sort_field_for_columns < 0)
220 if (sort_field_for_columns >= 0 &&
228 pg_log_error(
"\\crosstabview: maximum number of columns (%d) exceeded",
244 num_columns = piv_columns.
count;
245 num_rows = piv_rows.
count;
260 if (sort_field_for_columns >= 0)
261 rankSort(num_columns, array_columns);
267 num_columns, array_columns, field_for_columns,
268 num_rows, array_rows, field_for_rows,
286 int num_columns,
pivot_field *piv_columns,
int field_for_columns,
287 int num_rows,
pivot_field *piv_rows,
int field_for_rows,
304 PQfname(result, field_for_rows),
314 horiz_map = (
int *)
pg_malloc(
sizeof(
int) * num_columns);
315 for (
i = 0;
i < num_columns;
i++)
316 horiz_map[piv_columns[
i].rank] =
i;
323 for (
i = 0;
i < num_columns;
i++)
327 colname = piv_columns[horiz_map[
i]].
name ?
328 piv_columns[horiz_map[
i]].
name :
336 for (
i = 0;
i < num_rows;
i++)
338 int k = piv_rows[
i].
rank;
340 cont.
cells[k * (num_columns + 1)] = piv_rows[
i].
name ?
344 cont.
cellsadded = num_rows * (num_columns + 1);
349 for (rn = 0; rn <
PQntuples(result); rn++)
368 row_number = rp->
rank;
382 col_number = cp->
rank;
385 if (col_number >= 0 && row_number >= 0)
390 idx = 1 + col_number + row_number * (num_columns + 1);
397 pg_log_error(
"\\crosstabview: query result contains multiple data values for row \"%s\", column \"%s\"",
417 if (cont.
cells[
i] == NULL)
459 if (node == tree->
root)
462 if (node != tree->
end)
512 int dir = (1 -
b) / 2;
518 if (current != tree->
end)
532 if (current == tree->
end)
538 new_node->
field = field;
578 if (node == tree->
end)
593 hmap = (
int *)
pg_malloc(
sizeof(
int) * num_columns * 2);
594 for (
i = 0;
i < num_columns;
i++)
601 strspn(
val + 1,
"0123456789") == strlen(
val + 1)) ||
602 strspn(
val,
"0123456789") == strlen(
val)))
604 hmap[
i * 2] = atoi(
val);
617 for (
i = 0;
i < num_columns;
i++)
619 piv_columns[hmap[
i * 2 + 1]].
rank =
i;
639 if (
arg[0] && strspn(
arg,
"0123456789") == strlen(
arg))
645 pg_log_error(
"\\crosstabview: column number %d is out of range 1..%d",
701 return pa->
name ? -1 : 0;
712 return *((
const int *)
a) - *((
const int *)
b);
Datum idx(PG_FUNCTION_ARGS)
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)
Assert(fmt[strlen(fmt) - 1] !='\n')
#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]