105{
106 bool retval = false;
111 int num_columns = 0;
112 int num_rows = 0;
113 int field_for_rows;
114 int field_for_columns;
115 int field_for_data;
116 int sort_field_for_columns;
117 int rn;
118
121
123 {
124 pg_log_error(
"\\crosstabview: statement did not return a result set");
125 goto error_return;
126 }
127
129 {
130 pg_log_error(
"\\crosstabview: query must return at least three columns");
131 goto error_return;
132 }
133
134
136 field_for_rows = 0;
137 else
138 {
140 if (field_for_rows < 0)
141 goto error_return;
142 }
143
144
146 field_for_columns = 1;
147 else
148 {
150 if (field_for_columns < 0)
151 goto error_return;
152 }
153
154
155 if (field_for_columns == field_for_rows)
156 {
157 pg_log_error(
"\\crosstabview: vertical and horizontal headers must be different columns");
158 goto error_return;
159 }
160
161
163 {
165
166
167
168
169
170
172 {
173 pg_log_error(
"\\crosstabview: data column must be specified when query returns more than three columns");
174 goto error_return;
175 }
176
177 field_for_data = -1;
179 {
180 if (
i != field_for_rows &&
i != field_for_columns)
181 {
183 break;
184 }
185 }
186 Assert(field_for_data >= 0);
187 }
188 else
189 {
191 if (field_for_data < 0)
192 goto error_return;
193 }
194
195
197 sort_field_for_columns = -1;
198 else
199 {
201 if (sort_field_for_columns < 0)
202 goto error_return;
203 }
204
205
206
207
208
209
210
212 {
214 char *val1;
215
216
219 val1 = NULL;
220
221 if (sort_field_for_columns >= 0 &&
223 val1 =
PQgetvalue(res, rn, sort_field_for_columns);
224
226
228 {
229 pg_log_error(
"\\crosstabview: maximum number of columns (%d) exceeded",
231 goto error_return;
232 }
233
234
237
239 }
240
241
242
243
244
245 num_columns = piv_columns.
count;
246 num_rows = piv_rows.
count;
247
250
253
256
257
258
259
260
261 if (sort_field_for_columns >= 0)
262 rankSort(num_columns, array_columns);
263
264
265
266
268 num_columns, array_columns, field_for_columns,
269 num_rows, array_rows, field_for_rows,
270 field_for_data);
271
272error_return:
277
278 return retval;
279}
static int avlCollectFields(avl_tree *tree, avl_node *node, pivot_field *fields, int idx)
static void avlFree(avl_tree *tree, avl_node *node)
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)
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)
#define CROSSTABVIEW_MAX_COLUMNS
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
ExecStatusType PQresultStatus(const PGresult *res)
int PQntuples(const PGresult *res)
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
int PQnfields(const PGresult *res)
void * pg_malloc(size_t size)
Assert(PointerIsAligned(start, uint64))
#define pg_log_error(...)