8000 Rewrite aqo_cardinality_error in C. · postgrespro/aqo@3286434 · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 3286434

Browse files
danolivoAlena Rybakina
authored and
Alena Rybakina
committed
Rewrite aqo_cardinality_error in C.
One more step towards true relocatability.
1 parent 1f2144e commit 3286434

File tree

2 files changed

+95
-38
lines changed

2 files changed

+95
-38
lines changed

aqo--1.4--1.5.sql

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -167,44 +167,8 @@ COMMENT ON FUNCTION aqo_cleanup() IS
167167
--
168168
CREATE OR REPLACE FUNCTION aqo_cardinality_error(controlled boolean)
169169
RETURNS TABLE(num bigint, id bigint, fshash bigint, error float, nexecs bigint)
170-
AS $$
171-
BEGIN
172-
IF (controlled) THEN
173-
RETURN QUERY
174-
SELECT
175-
row_number() OVER (ORDER BY (cerror, query_id, fs_hash) DESC) AS nn,
176-
query_id, fs_hash, cerror, execs
177-
FROM (
178-
SELECT
179-
aq.queryid AS query_id,
180-
aq.fs AS fs_hash,
181-
cardinality_error_with_aqo[array_length(cardinality_error_with_aqo, 1)] AS cerror,
182-
executions_with_aqo AS execs
183-
FROM aqo_queries aq JOIN aqo_query_stat aqs
184-
ON aq.queryid = aqs.queryid
185-
WHERE TRUE = ANY (SELECT unnest(cardinality_error_with_aqo) IS NOT NULL)
186-
) AS q1
187-
ORDER BY nn ASC;
188-
ELSE
189-
RETURN QUERY
190-
SELECT
191-
row_number() OVER (ORDER BY (cerror, query_id, fs_hash) DESC) AS nn,
192-
query_id, fs_hash, cerror, execs
193-
FROM (
194-
SELECT
195-
aq.queryid AS query_id,
196-
aq.fs AS fs_hash,
197-
(SELECT AVG(t) FROM unnest(cardinality_error_without_aqo) t) AS cerror,
198-
executions_without_aqo AS execs
199-
FROM aqo_queries aq JOIN aqo_query_stat aqs
200-
ON aq.queryid = aqs.queryid
201-
WHERE TRUE = ANY (SELECT unnest(cardinality_error_without_aqo) IS NOT NULL)
202-
) AS q1
203-
ORDER BY (nn) ASC;
204-
END IF;
205-
END;
206-
$$ LANGUAGE plpgsql;
207-
170+
AS 'MODULE_PATHNAME', 'aqo_cardinality_error'
171+
LANGUAGE C STRICT VOLATILE;
208172
COMMENT ON FUNCTION aqo_cardinality_error(boolean) IS
209173
'Get cardinality error of queries the last time they were executed. Order queries according to an error value.';
210174

storage.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ PG_FUNCTION_INFO_V1(aqo_queries_update);
102102
PG_FUNCTION_INFO_V1(aqo_reset);
103103
PG_FUNCTION_INFO_V1(aqo_cleanup);
104104
PG_FUNCTION_INFO_V1(aqo_drop_class);
105+
PG_FUNCTION_INFO_V1(aqo_cardinality_error);
105106

106107

107108
bool
@@ -2203,3 +2204,95 @@ aqo_drop_class(PG_FUNCTION_ARGS)
22032204

22042205
PG_RETURN_INT32(cnt);
22052206
}
2207+
2208+
typedef enum {
2209+
AQE_NN = 0, AQE_QUERYID, AQE_FS, AQE_CERROR, AQE_NEXECS, AQE_TOTAL_NCOLS
2210+
} ce_output_order;
2211+
2212+
/*
2213+
* Show cardinality error gathered on last execution.
2214+
* Skip entries with empty stat slots. XXX: is it possible?
2215+
*/
2216+
Datum
2217+
aqo_cardinality_error(PG_FUNCTION_ARGS)
2218+
{
2219+
bool controlled = PG_GETARG_BOOL(0);
2220+
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
2221+
TupleDesc tupDesc;
2222+
MemoryContext per_query_ctx;
2223+
MemoryContext oldcontext;
2224+
Tuplestorestate *tupstore;
2225+
Datum values[AQE_TOTAL_NCOLS];
2226+
bool nulls[AQE_TOTAL_NCOLS];
2227+
HASH_SEQ_STATUS hash_seq;
2228+
QueriesEntry *qentry;
2229+
StatEntry *sentry;
2230+
int counter = 0;
2231+
2232+
/* check to see if caller supports us returning a tuplestore */
2233+
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
2234+
ereport(ERROR,
2235+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2236+
errmsg("set-valued function called in context that cannot accept a set")));
2237+
if (!(rsinfo->allowedModes & SFRM_Materialize))
2238+
ereport(ERROR,
2239+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2240+
errmsg("materialize mode required, but it is not allowed in this context")));
2241+
2242+
/* Switch into long-lived context to construct returned data structures */
2243+
per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
2244+
oldcontext = MemoryContextSwitchTo(per_query_ctx);
2245+
2246+
/* Build a tuple descriptor for our result type */
2247+
if (get_call_result_type(fcinfo, NULL, &tupDesc) != TYPEFUNC_COMPOSITE)
2248+
elog(ERROR, "return type must be a row type");
2249+
Assert(tupDesc->natts == AQE_TOTAL_NCOLS);
2250+
2251+
tupstore = tuplestore_begin_heap(true, false, work_mem);
2252+
rsinfo->returnMode = SFRM_Materialize;
2253+
rsinfo->setResult = tupstore;
2254+
rsinfo->setDesc = tupDesc;
2255+
2256+
MemoryContextSwitchTo(oldcontext);
2257+
2258+
LWLockAcquire(&aqo_state->queries_lock, LW_SHARED);
2259+
LWLockAcquire(&aqo_state->stat_lock, LW_SHARED);
2260+
2261+
hash_seq_init(&hash_seq, queries_htab);
2262+
while ((qentry = hash_seq_search(&hash_seq)) != NULL)
2263+
{
2264+
bool found;
2265+
double *ce;
2266+
int64 nexecs;
2267+
int nvals;
2268+
2269+
memset(nulls, 0, AQE_TOTAL_NCOLS * sizeof(nulls[0]));
2270+
2271+
sentry = (StatEntry *) hash_search(stat_htab, &qentry->queryid,
2272+
HASH_FIND, &found);
2273+
if (!found)
2274+
/* Statistics not found by some reason. Just go further */
2275+
continue;
2276+
2277+
nvals = controlled ? sentry->cur_stat_slot_aqo : sentry->cur_stat_slot;
2278+
if (nvals == 0)
2279+
/* No one stat slot filled */
2280+
continue;
2281+
2282+
nexecs = controlled ? sentry->execs_with_aqo : sentry->execs_without_aqo;
2283+
ce = controlled ? sentry->est_error_aqo : sentry->est_error;
2284+
2285+
values[AQE_NN] = Int32GetDatum(counter++);
2286+
values[AQE_QUERYID] = Int64GetDatum(qentry->queryid);
2287+
values[AQE_FS] = Int64GetDatum(qentry->fs);
2288+
values[AQE_NEXECS] = Int64GetDatum(nexecs);
2289+
values[AQE_CERROR] = Float8GetDatum(ce[nvals - 1]);
2290+
tuplestore_putvalues(tupstore, tupDesc, values, nulls);
2291+
}
2292+
2293+
LWLockRelease(&aqo_state->stat_lock);
2294+
LWLockRelease(&aqo_state->queries_lock);
2295+
2296+
tuplestore_donestoring(tupstore);
2297+
return (Datum) 0;
2298+
}

0 commit comments

Comments
 (0)
0