PG_MODULE_MAGIC;
-static int load_categories_hash(char *cats_sql, MemoryContext per_query_ctx);
+static HTAB *load_categories_hash(char *cats_sql, MemoryContext per_query_ctx);
static Tuplestorestate *get_crosstab_tuplestore(char *sql,
- int num_categories,
+ HTAB *crosstab_hash,
TupleDesc tupdesc,
MemoryContext per_query_ctx);
static void validateConnectbyTupleDesc(TupleDesc tupdesc, bool show_branch, bool show_serial);
/* sign, 10 digits, '\0' */
#define INT32_STRLEN 12
-/* hash table support */
-static HTAB *crosstab_HashTable;
-
-/* The information we cache about loaded procedures */
+/* stored info for a crosstab category */
typedef struct crosstab_cat_desc
{
- char *catname;
+ char *catname; /* full category name */
int attidx; /* zero based */
} crosstab_cat_desc;
#define MAX_CATNAME_LEN NAMEDATALEN
#define INIT_CATS 64
-#define crosstab_HashTableLookup(CATNAME, CATDESC) \
+#define crosstab_HashTableLookup(HASHTAB, CATNAME, CATDESC) \
do { \
crosstab_HashEnt *hentry; char key[MAX_CATNAME_LEN]; \
\
MemSet(key, 0, MAX_CATNAME_LEN); \
snprintf(key, MAX_CATNAME_LEN - 1, "%s", CATNAME); \
- hentry = (crosstab_HashEnt*) hash_search(crosstab_HashTable, \
+ hentry = (crosstab_HashEnt*) hash_search(HASHTAB, \
key, HASH_FIND, NULL); \
if (hentry) \
CATDESC = hentry->catdesc; \
CATDESC = NULL; \
} while(0)
-#define crosstab_HashTableInsert(CATDESC) \
+#define crosstab_HashTableInsert(HASHTAB, CATDESC) \
do { \
crosstab_HashEnt *hentry; bool found; char key[MAX_CATNAME_LEN]; \
\
MemSet(key, 0, MAX_CATNAME_LEN); \
snprintf(key, MAX_CATNAME_LEN - 1, "%s", CATDESC->catname); \
- hentry = (crosstab_HashEnt*) hash_search(crosstab_HashTable, \
+ hentry = (crosstab_HashEnt*) hash_search(HASHTAB, \
key, HASH_ENTER, &found); \
if (found) \
ereport(ERROR, \
TupleDesc tupdesc;
MemoryContext per_query_ctx;
MemoryContext oldcontext;
- int num_categories;
+ HTAB *crosstab_hash;
/* check to see if caller supports us returning a tuplestore */
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
"crosstab function are not compatible")));
/* load up the categories hash table */
- num_categories = load_categories_hash(cats_sql, per_query_ctx);
+ crosstab_hash = load_categories_hash(cats_sql, per_query_ctx);
/* let the caller know we're sending back a tuplestore */
rsinfo->returnMode = SFRM_Materialize;
/* now go build it */
rsinfo->setResult = get_crosstab_tuplestore(sql,
- num_categories,
+ crosstab_hash,
tupdesc,
per_query_ctx);
/*
* load up the categories hash table
*/
-static int
+static HTAB *
load_categories_hash(char *cats_sql, MemoryContext per_query_ctx)
{
+ HTAB *crosstab_hash;
HASHCTL ctl;
int ret;
int proc;
MemoryContext SPIcontext;
- int num_categories = 0;
/* initialize the category hash table */
+ MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = MAX_CATNAME_LEN;
ctl.entrysize = sizeof(crosstab_HashEnt);
+ ctl.hcxt = per_query_ctx;
/*
* use INIT_CATS, defined above as a guess of how many hash table entries
* to create, initially
*/
- crosstab_HashTable = hash_create("crosstab hash", INIT_CATS, &ctl, HASH_ELEM);
+ crosstab_hash = hash_create("crosstab hash",
+ INIT_CATS,
+ &ctl,
+ HASH_ELEM | HASH_CONTEXT);
/* Connect to SPI manager */
if ((ret = SPI_connect()) < 0)
/* Retrieve the category name rows */
ret = SPI_execute(cats_sql, true, 0);
- num_categories = proc = SPI_processed;
+ proc = SPI_processed;
/* Check for qualifying tuples */
if ((ret == SPI_OK_SELECT) && (proc > 0))
catdesc->attidx = i;
/* Add the proc description block to the hashtable */
- crosstab_HashTableInsert(catdesc);
+ crosstab_HashTableInsert(crosstab_hash, catdesc);
MemoryContextSwitchTo(SPIcontext);
}
/* internal error */
elog(ERROR, "load_categories_hash: SPI_finish() failed");
- return num_categories;
+ return crosstab_hash;
}
/*
*/
static Tuplestorestate *
get_crosstab_tuplestore(char *sql,
- int num_categories,
+ HTAB *crosstab_hash,
TupleDesc tupdesc,
MemoryContext per_query_ctx)
{
Tuplestorestate *tupstore;
+ int num_categories = hash_get_num_entries(crosstab_hash);
AttInMetadata *attinmeta = TupleDescGetAttInMetadata(tupdesc);
char **values;
HeapTuple tuple;
if (catname != NULL)
{
- crosstab_HashTableLookup(catname, catdesc);
+ crosstab_HashTableLookup(crosstab_hash, catname, catdesc);
if (catdesc)
values[catdesc->attidx + ncols - 2] =