| 351 | */ |
| 352 | PG_FUNCTION_INFO_V1(crosstab); |
| 353 | Datum |
| 354 | crosstab(PG_FUNCTION_ARGS) |
| 355 | { |
| 356 | char *sql = text_to_cstring(PG_GETARG_TEXT_PP(0)); |
| 357 | ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; |
| 358 | Tuplestorestate *tupstore; |
| 359 | TupleDesc tupdesc; |
| 360 | uint64 call_cntr; |
| 361 | uint64 max_calls; |
| 362 | AttInMetadata *attinmeta; |
| 363 | SPITupleTable *spi_tuptable; |
| 364 | TupleDesc spi_tupdesc; |
| 365 | bool firstpass; |
| 366 | char *lastrowid; |
| 367 | int i; |
| 368 | int num_categories; |
| 369 | MemoryContext per_query_ctx; |
| 370 | MemoryContext oldcontext; |
| 371 | int ret; |
| 372 | uint64 proc; |
| 373 | |
| 374 | /* check to see if caller supports us returning a tuplestore */ |
| 375 | if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo)) |
| 376 | ereport(ERROR, |
| 377 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 378 | errmsg("set-valued function called in context that cannot accept a set"))); |
| 379 | if (!(rsinfo->allowedModes & SFRM_Materialize)) |
| 380 | ereport(ERROR, |
| 381 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 382 | errmsg("materialize mode required, but it is not allowed in this context"))); |
| 383 | |
| 384 | per_query_ctx = rsinfo->econtext->ecxt_per_query_memory; |
| 385 | |
| 386 | /* Connect to SPI manager */ |
| 387 | if ((ret = SPI_connect()) < 0) |
| 388 | /* internal error */ |
| 389 | elog(ERROR, "crosstab: SPI_connect returned %d", ret); |
| 390 | |
| 391 | /* Retrieve the desired rows */ |
| 392 | ret = SPI_execute(sql, true, 0); |
| 393 | proc = SPI_processed; |
| 394 | |
| 395 | /* If no qualifying tuples, fall out early */ |
| 396 | if (ret != SPI_OK_SELECT || proc == 0) |
| 397 | { |
| 398 | SPI_finish(); |
| 399 | rsinfo->isDone = ExprEndResult; |
| 400 | PG_RETURN_NULL(); |
| 401 | } |
| 402 | |
| 403 | spi_tuptable = SPI_tuptable; |
| 404 | spi_tupdesc = spi_tuptable->tupdesc; |
| 405 | |
| 406 | /*---------- |
| 407 | * The provided SQL query must always return three columns. |
| 408 | * |
| 409 | * 1. rowname |
| 410 | * the label or identifier for each row in the final result |
nothing calls this directly
no test coverage detected