diff --git a/hypopg--0.0.3.sql b/hypopg--0.0.3.sql index df3fd33..d9c4630 100644 --- a/hypopg--0.0.3.sql +++ b/hypopg--0.0.3.sql @@ -19,10 +19,12 @@ hypopg_add_index_internal(IN relid oid, IN accessmethod text, IN ncolumns int, IN indexkeys smallint, - IN indexcollations Oid, - IN opfamily Oid, - IN opcintype Oid) - RETURNS bool + IN indexcollations oid, + IN opfamily oid, + IN opcintype oid, + OUT indexrelid oid, + OUT indexname text) + RETURNS SETOF record LANGUAGE c COST 100 AS '$libdir/hypopg', 'hypopg_add_index_internal'; @@ -38,12 +40,12 @@ hypopg_drop_index(IN indexid oid) LANGUAGE c COST 100 AS '$libdir/hypopg', 'hypopg_drop_index'; -CREATE FUNCTION hypopg(OUT indexname text, OUT indexrelid Oid, - OUT indrelid Oid, OUT innatts integer, +CREATE FUNCTION hypopg(OUT indexname text, OUT indexrelid oid, + OUT indrelid oid, OUT innatts integer, OUT indisunique boolean, OUT indkey int2vector, OUT indcollation oidvector, OUT indclass oidvector, OUT indoption oidvector, OUT indexprs pg_node_tree, - OUT indpred pg_node_tree, OUT amid Oid) + OUT indpred pg_node_tree, OUT amid oid) RETURNS SETOF record LANGUAGE c COST 100 AS '$libdir/hypopg', 'hypopg'; @@ -62,8 +64,13 @@ LANGUAGE sql; CREATE FUNCTION -hypopg_add_index(IN _nspname name, IN _relname name, IN _attname name, IN _amname text) - RETURNS bool +hypopg_add_index(IN _nspname name, + IN _relname name, + IN _attname name, + IN _amname text, + OUT indexrelid oid, + OUT indexname text) + RETURNS SETOF record AS $_$ SELECT hypopg_add_index_internal( @@ -94,7 +101,7 @@ $_$ LANGUAGE sql; CREATE FUNCTION -hypopg_relation_size(IN indexid Oid) +hypopg_relation_size(IN indexid oid) RETURNS bigint LANGUAGE c COST 100 AS '$libdir/hypopg', 'hypopg_relation_size'; diff --git a/hypopg.c b/hypopg.c index 857fd83..c0f73d3 100644 --- a/hypopg.c +++ b/hypopg.c @@ -123,7 +123,7 @@ static Oid hypoGetNewOid(Oid relid); static void addHypoEntry(hypoEntry *entry); static void entry_reset(void); -static bool entry_store(Oid relid, +static const hypoEntry *entry_store(Oid relid, char *indexname, char *accessMethod, int ncolumns, @@ -349,7 +349,7 @@ entry_reset(void) /* Simplified function to add an hypotehtical index, with inly 1 column index */ -static bool +static const hypoEntry * entry_store(Oid relid, char *indexname, char *accessMethod, @@ -375,7 +375,7 @@ entry_store(Oid relid, addHypoEntry(entry); - return true; + return entry; } /* Create an hypothetical index from its CREATE INDEX parsetree @@ -818,8 +818,54 @@ hypopg_add_index_internal(PG_FUNCTION_ARGS) Oid indexcollations = PG_GETARG_OID(5); Oid opfamily = PG_GETARG_OID(6); Oid opcintype = PG_GETARG_OID(7); + ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; + const hypoEntry *entry; + MemoryContext per_query_ctx; + MemoryContext oldcontext; + TupleDesc tupdesc; + Tuplestorestate *tupstore; + Datum values[HYPO_NB_COLS]; + bool nulls[HYPO_NB_COLS]; - return entry_store(relid, indexname, accessMethod, ncolumns, indexkeys, indexcollations, opfamily, opcintype); + /* check to see if caller supports us returning a tuplestore */ + if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("set-valued function called in context that cannot accept a set"))); + if (!(rsinfo->allowedModes & SFRM_Materialize)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("materialize mode required, but it is not " \ + "allowed in this context"))); + + per_query_ctx = rsinfo->econtext->ecxt_per_query_memory; + oldcontext = MemoryContextSwitchTo(per_query_ctx); + + /* Build a tuple descriptor for our result type */ + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + + tupstore = tuplestore_begin_heap(true, false, work_mem); + rsinfo->returnMode = SFRM_Materialize; + rsinfo->setResult = tupstore; + rsinfo->setDesc = tupdesc; + + MemoryContextSwitchTo(oldcontext); + + memset(values, 0, sizeof(values)); + memset(nulls, 0, sizeof(nulls)); + + entry = entry_store(relid, indexname, accessMethod, ncolumns, indexkeys, indexcollations, opfamily, opcintype); + + values[0] = ObjectIdGetDatum(entry->oid); + values[1] = CStringGetTextDatum(strdup(entry->indexname)); + + tuplestore_putvalues(tupstore, tupdesc, values, nulls); + + /* clean up and return the tuplestore */ + tuplestore_donestoring(tupstore); + + return (Datum) 0; } /* @@ -835,7 +881,6 @@ hypopg(PG_FUNCTION_ARGS) Tuplestorestate *tupstore; ListCell *lc; - /* check to see if caller supports us returning a tuplestore */ if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo)) ereport(ERROR,