public inbox for [email protected]help / color / mirror / Atom feed
[PATCH 2/8] Move IS [NOT] NULL handling from BRIN support functions 2+ messages / 2 participants [nested] [flat]
* [PATCH 2/8] Move IS [NOT] NULL handling from BRIN support functions @ 2020-09-17 15:26 Tomas Vondra <[email protected]> 0 siblings, 0 replies; 2+ messages in thread From: Tomas Vondra @ 2020-09-17 15:26 UTC (permalink / raw) The handling of IS [NOT] NULL clauses is independent of an opclass, and most of the code was exactly the same in both minmax and inclusion. So instead move the code from support procedures to the AM methods etc. This simplifies the code quite a bit - especially the support procedures quite a bit, as they don't need to care about NULL values and flags at all. It also means the IS [NOT] NULL clauses can be evaluated without invoking the support procedure at all. Author: Tomas Vondra <[email protected]> Author: Nikita Glukhov <[email protected]> Reviewed-by: Alvaro Herrera <[email protected]> Reviewed-by: Mark Dilger <[email protected]> Reviewed-by: Alexander Korotkov <[email protected]> Reviewed-by: Masahiko Sawada <[email protected]> Reviewed-by: John Naylor <[email protected]> Discussion: https://postgr.es/m/[email protected] --- src/backend/access/brin/brin.c | 293 +++++++++++++++++------ src/backend/access/brin/brin_inclusion.c | 106 +------- src/backend/access/brin/brin_minmax.c | 103 +------- src/include/access/brin_internal.h | 3 + 4 files changed, 239 insertions(+), 266 deletions(-) diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c index dc187153aa..14da9ed17f 100644 --- a/src/backend/access/brin/brin.c +++ b/src/backend/access/brin/brin.c @@ -35,6 +35,7 @@ #include "storage/freespace.h" #include "utils/acl.h" #include "utils/builtins.h" +#include "utils/datum.h" #include "utils/index_selfuncs.h" #include "utils/memutils.h" #include "utils/rel.h" @@ -77,7 +78,9 @@ static void form_and_insert_tuple(BrinBuildState *state); static void union_tuples(BrinDesc *bdesc, BrinMemTuple *a, BrinTuple *b); static void brin_vacuum_scan(Relation idxrel, BufferAccessStrategy strategy); - +static bool add_values_to_range(Relation idxRel, BrinDesc *bdesc, + BrinMemTuple *dtup, Datum *values, bool *nulls); +static bool check_null_keys(BrinValues *bval, ScanKey *nullkeys, int nnullkeys); /* * BRIN handler function: return IndexAmRoutine with access method parameters @@ -179,7 +182,6 @@ brininsert(Relation idxRel, Datum *values, bool *nulls, OffsetNumber off; BrinTuple *brtup; BrinMemTuple *dtup; - int keyno; CHECK_FOR_INTERRUPTS(); @@ -243,31 +245,7 @@ brininsert(Relation idxRel, Datum *values, bool *nulls, dtup = brin_deform_tuple(bdesc, brtup, NULL); - /* - * Compare the key values of the new tuple to the stored index values; - * our deformed tuple will get updated if the new tuple doesn't fit - * the original range (note this means we can't break out of the loop - * early). Make a note of whether this happens, so that we know to - * insert the modified tuple later. - */ - for (keyno = 0; keyno < bdesc->bd_tupdesc->natts; keyno++) - { - Datum result; - BrinValues *bval; - FmgrInfo *addValue; - - bval = &dtup->bt_columns[keyno]; - addValue = index_getprocinfo(idxRel, keyno + 1, - BRIN_PROCNUM_ADDVALUE); - result = FunctionCall4Coll(addValue, - idxRel->rd_indcollation[keyno], - PointerGetDatum(bdesc), - PointerGetDatum(bval), - values[keyno], - nulls[keyno]); - /* if that returned true, we need to insert the updated tuple */ - need_insert |= DatumGetBool(result); - } + need_insert = add_values_to_range(idxRel, bdesc, dtup, values, nulls); if (!need_insert) { @@ -390,8 +368,10 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm) BrinMemTuple *dtup; BrinTuple *btup = NULL; Size btupsz = 0; - ScanKey **keys; - int *nkeys; + ScanKey **keys, + **nullkeys; + int *nkeys, + *nnullkeys; int keyno; opaque = (BrinOpaque *) scan->opaque; @@ -416,10 +396,13 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm) /* * Make room for per-attribute lists of scan keys that we'll pass to the - * consistent support procedure. + * consistent support procedure. We keep null and regular keys separate, + * so that we can easily pass regular keys to the consistent function. */ keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts); + nullkeys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts); nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts); + nnullkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts); /* * Preprocess the scan keys - split them into per-attribute arrays. @@ -440,23 +423,24 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm) TupleDescAttr(bdesc->bd_tupdesc, keyattno - 1)->attcollation)); - /* First time we see this index attribute, so init as needed. */ - if (!keys[keyattno-1]) + /* + * First time we see this index attribute, so init as needed. + * + * This is a bit of an overkill - we don't know how many scan + * keys are there for a given attribute, so we simply allocate + * the largest number possible (as if all scan keys belonged to + * the same attribute). This may waste a bit of memory, but we + * only expect small number of scan keys in general, so this + * should be negligible, and it's probably cheaper than having + * to repalloc repeatedly. + */ + if (consistentFn[keyattno - 1].fn_oid == InvalidOid) { FmgrInfo *tmp; - /* - * This is a bit of an overkill - we don't know how many - * scan keys are there for this attribute, so we simply - * allocate the largest number possible. This may waste - * a bit of memory, but we only expect small number of - * scan keys in general, so this should be negligible, - * and it's cheaper than having to repalloc repeatedly. - */ - keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys); - - /* First time this column, so look up consistent function */ - Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid); + /* No key/null arrays for this attribute. */ + Assert((keys[keyattno - 1] == NULL) && (nkeys[keyattno - 1] == 0)); + Assert((nullkeys[keyattno - 1] == NULL) && (nnullkeys[keyattno - 1] == 0)); tmp = index_getprocinfo(idxRel, keyattno, BRIN_PROCNUM_CONSISTENT); @@ -464,9 +448,23 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm) CurrentMemoryContext); } - /* Add key to the per-attribute array. */ - keys[keyattno - 1][nkeys[keyattno - 1]] = key; - nkeys[keyattno - 1]++; + /* Add key to the proper per-attribute array. */ + if (key->sk_flags & SK_ISNULL) + { + if (!nullkeys[keyattno - 1]) + nullkeys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys); + + nullkeys[keyattno - 1][nnullkeys[keyattno - 1]] = key; + nnullkeys[keyattno - 1]++; + } + else + { + if (!keys[keyattno - 1]) + keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys); + + keys[keyattno - 1][nkeys[keyattno - 1]] = key; + nkeys[keyattno - 1]++; + } } /* allocate an initial in-memory tuple, out of the per-range memcxt */ @@ -544,15 +542,57 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm) BrinValues *bval; Datum add; - /* skip attributes without any san keys */ - if (nkeys[attno - 1] == 0) + /* + * skip attributes without any scan keys (both regular + * and IS [NOT] NULL) + */ + if (nkeys[attno - 1] == 0 && nnullkeys[attno - 1] == 0) continue; bval = &dtup->bt_columns[attno - 1]; + /* + * First check if there are any IS [NOT] NULL scan keys, + * and if we're violating them. In that case we can + * terminate early, without invoking the support function. + * + * As there may be more keys, we can only detemine mismatch + * within this loop. + */ + if (bdesc->bd_info[attno - 1]->oi_regular_nulls && + !check_null_keys(bval, nullkeys[attno - 1], + nnullkeys[attno - 1])) + { + /* + * If any of the IS [NOT] NULL keys failed, the page + * range as a whole can't pass. So terminate the loop. + */ + addrange = false; + break; + } + + /* + * So either there are no IS [NOT] NULL keys, or all passed. + * If there are no regular scan keys, we're done - the page + * range matches. If there are regular keys, but the page + * range is marked as 'all nulls' it can't possibly pass + * (we're assuming the operators are strict). + */ + + /* No regular scan keys - page range as a whole passes. */ + if (!nkeys[attno - 1]) + continue; + Assert((nkeys[attno - 1] > 0) && (nkeys[attno - 1] <= scan->numberOfKeys)); + /* If it is all nulls, it cannot possibly be consistent. */ + if (bval->bv_allnulls) + { + addrange = false; + break; + } + /* * Check whether the scan key is consistent with the page * range values; if so, have the pages in the range added @@ -695,7 +735,6 @@ brinbuildCallback(Relation index, { BrinBuildState *state = (BrinBuildState *) brstate; BlockNumber thisblock; - int i; thisblock = ItemPointerGetBlockNumber(tid); @@ -724,25 +763,8 @@ brinbuildCallback(Relation index, } /* Accumulate the current tuple into the running state */ - for (i = 0; i < state->bs_bdesc->bd_tupdesc->natts; i++) - { - FmgrInfo *addValue; - BrinValues *col; - Form_pg_attribute attr = TupleDescAttr(state->bs_bdesc->bd_tupdesc, i); - - col = &state->bs_dtuple->bt_columns[i]; - addValue = index_getprocinfo(index, i + 1, - BRIN_PROCNUM_ADDVALUE); - - /* - * Update dtuple state, if and as necessary. - */ - FunctionCall4Coll(addValue, - attr->attcollation, - PointerGetDatum(state->bs_bdesc), - PointerGetDatum(col), - values[i], isnull[i]); - } + (void) add_values_to_range(index, state->bs_bdesc, state->bs_dtuple, + values, isnull); } /* @@ -1521,6 +1543,39 @@ union_tuples(BrinDesc *bdesc, BrinMemTuple *a, BrinTuple *b) FmgrInfo *unionFn; BrinValues *col_a = &a->bt_columns[keyno]; BrinValues *col_b = &db->bt_columns[keyno]; + BrinOpcInfo *opcinfo = bdesc->bd_info[keyno]; + + if (opcinfo->oi_regular_nulls) + { + /* Adjust "hasnulls". */ + if (!col_a->bv_hasnulls && col_b->bv_hasnulls) + col_a->bv_hasnulls = true; + + /* If there are no values in B, there's nothing left to do. */ + if (col_b->bv_allnulls) + continue; + + /* + * Adjust "allnulls". If A doesn't have values, just copy the + * values from B into A, and we're done. We cannot run the + * operators in this case, because values in A might contain + * garbage. Note we already established that B contains values. + */ + if (col_a->bv_allnulls) + { + int i; + + col_a->bv_allnulls = false; + + for (i = 0; i < opcinfo->oi_nstored; i++) + col_a->bv_values[i] = + datumCopy(col_b->bv_values[i], + opcinfo->oi_typcache[i]->typbyval, + opcinfo->oi_typcache[i]->typlen); + + continue; + } + } unionFn = index_getprocinfo(bdesc->bd_index, keyno + 1, BRIN_PROCNUM_UNION); @@ -1574,3 +1629,103 @@ brin_vacuum_scan(Relation idxrel, BufferAccessStrategy strategy) */ FreeSpaceMapVacuum(idxrel); } + +static bool +add_values_to_range(Relation idxRel, BrinDesc *bdesc, BrinMemTuple *dtup, + Datum *values, bool *nulls) +{ + int keyno; + bool modified = false; + + /* + * Compare the key values of the new tuple to the stored index values; + * our deformed tuple will get updated if the new tuple doesn't fit + * the original range (note this means we can't break out of the loop + * early). Make a note of whether this happens, so that we know to + * insert the modified tuple later. + */ + for (keyno = 0; keyno < bdesc->bd_tupdesc->natts; keyno++) + { + Datum result; + BrinValues *bval; + FmgrInfo *addValue; + + bval = &dtup->bt_columns[keyno]; + + if (bdesc->bd_info[keyno]->oi_regular_nulls && nulls[keyno]) + { + /* + * If the new value is null, we record that we saw it if it's + * the first one; otherwise, there's nothing to do. + */ + if (!bval->bv_hasnulls) + { + bval->bv_hasnulls = true; + modified = true; + } + + continue; + } + + addValue = index_getprocinfo(idxRel, keyno + 1, + BRIN_PROCNUM_ADDVALUE); + result = FunctionCall4Coll(addValue, + idxRel->rd_indcollation[keyno], + PointerGetDatum(bdesc), + PointerGetDatum(bval), + values[keyno], + nulls[keyno]); + /* if that returned true, we need to insert the updated tuple */ + modified |= DatumGetBool(result); + } + + return modified; +} + +static bool +check_null_keys(BrinValues *bval, ScanKey *nullkeys, int nnullkeys) +{ + int keyno; + + /* + * First check if there are any IS [NOT] NULL scan keys, and if we're + * violating them. + */ + for (keyno = 0; keyno < nnullkeys; keyno++) + { + ScanKey key = nullkeys[keyno]; + + Assert(key->sk_attno == bval->bv_attno); + + /* Handle only IS NULL/IS NOT NULL tests */ + if (!(key->sk_flags & SK_ISNULL)) + continue; + + if (key->sk_flags & SK_SEARCHNULL) + { + /* IS NULL scan key, but range has no NULLs */ + if (!bval->bv_allnulls && !bval->bv_hasnulls) + return false; + } + else if (key->sk_flags & SK_SEARCHNOTNULL) + { + /* + * For IS NOT NULL, we can only skip ranges that are known to + * have only nulls. + */ + if (bval->bv_allnulls) + return false; + } + else + { + /* + * Neither IS NULL nor IS NOT NULL was used; assume all indexable + * operators are strict and thus return false with NULL value in + * the scan key. + */ + return false; + } + } + + return true; +} diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c index 215bc794d3..f4730be3b9 100644 --- a/src/backend/access/brin/brin_inclusion.c +++ b/src/backend/access/brin/brin_inclusion.c @@ -110,6 +110,7 @@ brin_inclusion_opcinfo(PG_FUNCTION_ARGS) */ result = palloc0(MAXALIGN(SizeofBrinOpcInfo(3)) + sizeof(InclusionOpaque)); result->oi_nstored = 3; + result->oi_regular_nulls = true; result->oi_opaque = (InclusionOpaque *) MAXALIGN((char *) result + SizeofBrinOpcInfo(3)); @@ -141,7 +142,7 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS) BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0); BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1); Datum newval = PG_GETARG_DATUM(2); - bool isnull = PG_GETARG_BOOL(3); + bool isnull PG_USED_FOR_ASSERTS_ONLY = PG_GETARG_BOOL(3); Oid colloid = PG_GET_COLLATION(); FmgrInfo *finfo; Datum result; @@ -149,18 +150,7 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS) AttrNumber attno; Form_pg_attribute attr; - /* - * If the new value is null, we record that we saw it if it's the first - * one; otherwise, there's nothing to do. - */ - if (isnull) - { - if (column->bv_hasnulls) - PG_RETURN_BOOL(false); - - column->bv_hasnulls = true; - PG_RETURN_BOOL(true); - } + Assert(!isnull); attno = column->bv_attno; attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1); @@ -264,63 +254,6 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS) int nkeys = PG_GETARG_INT32(3); Oid colloid = PG_GET_COLLATION(); int keyno; - bool regular_keys = false; - - /* - * First check if there are any IS NULL scan keys, and if we're - * violating them. In that case we can terminate early, without - * inspecting the ranges. - */ - for (keyno = 0; keyno < nkeys; keyno++) - { - ScanKey key = keys[keyno]; - - Assert(key->sk_attno == column->bv_attno); - - /* handle IS NULL/IS NOT NULL tests */ - if (key->sk_flags & SK_ISNULL) - { - if (key->sk_flags & SK_SEARCHNULL) - { - if (column->bv_allnulls || column->bv_hasnulls) - continue; /* this key is fine, continue */ - - PG_RETURN_BOOL(false); - } - - /* - * For IS NOT NULL, we can only skip ranges that are known to have - * only nulls. - */ - if (key->sk_flags & SK_SEARCHNOTNULL) - { - if (column->bv_allnulls) - PG_RETURN_BOOL(false); - - continue; - } - - /* - * Neither IS NULL nor IS NOT NULL was used; assume all indexable - * operators are strict and return false. - */ - PG_RETURN_BOOL(false); - } - else - /* note we have regular (non-NULL) scan keys */ - regular_keys = true; - } - - /* - * If the page range is all nulls, it cannot possibly be consistent if - * there are some regular scan keys. - */ - if (column->bv_allnulls && regular_keys) - PG_RETURN_BOOL(false); - - /* If there are no regular keys, the page range is considered consistent. */ - if (!regular_keys) - PG_RETURN_BOOL(true); /* It has to be checked, if it contains elements that are not mergeable. */ if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE])) @@ -331,9 +264,8 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS) { ScanKey key = keys[keyno]; - /* ignore IS NULL/IS NOT NULL tests handled above */ - if (key->sk_flags & SK_ISNULL) - continue; + /* NULL keys are handled and filtered-out in bringetbitmap */ + Assert(!(key->sk_flags & SK_ISNULL)); /* * When there are multiple scan keys, failure to meet the @@ -572,37 +504,11 @@ brin_inclusion_union(PG_FUNCTION_ARGS) Datum result; Assert(col_a->bv_attno == col_b->bv_attno); - - /* Adjust "hasnulls". */ - if (!col_a->bv_hasnulls && col_b->bv_hasnulls) - col_a->bv_hasnulls = true; - - /* If there are no values in B, there's nothing left to do. */ - if (col_b->bv_allnulls) - PG_RETURN_VOID(); + Assert(!col_a->bv_allnulls && !col_b->bv_allnulls); attno = col_a->bv_attno; attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1); - /* - * Adjust "allnulls". If A doesn't have values, just copy the values from - * B into A, and we're done. We cannot run the operators in this case, - * because values in A might contain garbage. Note we already established - * that B contains values. - */ - if (col_a->bv_allnulls) - { - col_a->bv_allnulls = false; - col_a->bv_values[INCLUSION_UNION] = - datumCopy(col_b->bv_values[INCLUSION_UNION], - attr->attbyval, attr->attlen); - col_a->bv_values[INCLUSION_UNMERGEABLE] = - col_b->bv_values[INCLUSION_UNMERGEABLE]; - col_a->bv_values[INCLUSION_CONTAINS_EMPTY] = - col_b->bv_values[INCLUSION_CONTAINS_EMPTY]; - PG_RETURN_VOID(); - } - /* If B includes empty elements, mark A similarly, if needed. */ if (!DatumGetBool(col_a->bv_values[INCLUSION_CONTAINS_EMPTY]) && DatumGetBool(col_b->bv_values[INCLUSION_CONTAINS_EMPTY])) diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c index 12878ff3a0..6c8852d404 100644 --- a/src/backend/access/brin/brin_minmax.c +++ b/src/backend/access/brin/brin_minmax.c @@ -48,6 +48,7 @@ brin_minmax_opcinfo(PG_FUNCTION_ARGS) result = palloc0(MAXALIGN(SizeofBrinOpcInfo(2)) + sizeof(MinmaxOpaque)); result->oi_nstored = 2; + result->oi_regular_nulls = true; result->oi_opaque = (MinmaxOpaque *) MAXALIGN((char *) result + SizeofBrinOpcInfo(2)); result->oi_typcache[0] = result->oi_typcache[1] = @@ -69,7 +70,7 @@ brin_minmax_add_value(PG_FUNCTION_ARGS) BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0); BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1); Datum newval = PG_GETARG_DATUM(2); - bool isnull = PG_GETARG_DATUM(3); + bool isnull PG_USED_FOR_ASSERTS_ONLY = PG_GETARG_DATUM(3); Oid colloid = PG_GET_COLLATION(); FmgrInfo *cmpFn; Datum compar; @@ -77,18 +78,7 @@ brin_minmax_add_value(PG_FUNCTION_ARGS) Form_pg_attribute attr; AttrNumber attno; - /* - * If the new value is null, we record that we saw it if it's the first - * one; otherwise, there's nothing to do. - */ - if (isnull) - { - if (column->bv_hasnulls) - PG_RETURN_BOOL(false); - - column->bv_hasnulls = true; - PG_RETURN_BOOL(true); - } + Assert(!isnull); attno = column->bv_attno; attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1); @@ -152,72 +142,14 @@ brin_minmax_consistent(PG_FUNCTION_ARGS) int nkeys = PG_GETARG_INT32(3); Oid colloid = PG_GET_COLLATION(); int keyno; - bool regular_keys = false; - - /* - * First check if there are any IS NULL scan keys, and if we're - * violating them. In that case we can terminate early, without - * inspecting the ranges. - */ - for (keyno = 0; keyno < nkeys; keyno++) - { - ScanKey key = keys[keyno]; - - Assert(key->sk_attno == column->bv_attno); - - /* handle IS NULL/IS NOT NULL tests */ - if (key->sk_flags & SK_ISNULL) - { - if (key->sk_flags & SK_SEARCHNULL) - { - if (column->bv_allnulls || column->bv_hasnulls) - continue; /* this key is fine, continue */ - - PG_RETURN_BOOL(false); - } - - /* - * For IS NOT NULL, we can only skip ranges that are known to have - * only nulls. - */ - if (key->sk_flags & SK_SEARCHNOTNULL) - { - if (column->bv_allnulls) - PG_RETURN_BOOL(false); - - continue; - } - - /* - * Neither IS NULL nor IS NOT NULL was used; assume all indexable - * operators are strict and return false. - */ - PG_RETURN_BOOL(false); - } - else - /* note we have regular (non-NULL) scan keys */ - regular_keys = true; - } - - /* - * If the page range is all nulls, it cannot possibly be consistent if - * there are some regular scan keys. - */ - if (column->bv_allnulls && regular_keys) - PG_RETURN_BOOL(false); - - /* If there are no regular keys, the page range is considered consistent. */ - if (!regular_keys) - PG_RETURN_BOOL(true); /* Check that the range is consistent with all scan keys. */ for (keyno = 0; keyno < nkeys; keyno++) { ScanKey key = keys[keyno]; - /* ignore IS NULL/IS NOT NULL tests handled above */ - if (key->sk_flags & SK_ISNULL) - continue; + /* NULL keys are handled and filtered-out in bringetbitmap */ + Assert(!(key->sk_flags & SK_ISNULL)); /* * When there are multiple scan keys, failure to meet the @@ -308,34 +240,11 @@ brin_minmax_union(PG_FUNCTION_ARGS) bool needsadj; Assert(col_a->bv_attno == col_b->bv_attno); - - /* Adjust "hasnulls" */ - if (!col_a->bv_hasnulls && col_b->bv_hasnulls) - col_a->bv_hasnulls = true; - - /* If there are no values in B, there's nothing left to do */ - if (col_b->bv_allnulls) - PG_RETURN_VOID(); + Assert(!col_a->bv_allnulls && !col_b->bv_allnulls); attno = col_a->bv_attno; attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1); - /* - * Adjust "allnulls". If A doesn't have values, just copy the values from - * B into A, and we're done. We cannot run the operators in this case, - * because values in A might contain garbage. Note we already established - * that B contains values. - */ - if (col_a->bv_allnulls) - { - col_a->bv_allnulls = false; - col_a->bv_values[0] = datumCopy(col_b->bv_values[0], - attr->attbyval, attr->attlen); - col_a->bv_values[1] = datumCopy(col_b->bv_values[1], - attr->attbyval, attr->attlen); - PG_RETURN_VOID(); - } - /* Adjust minimum, if B's min is less than A's min */ finfo = minmax_get_strategy_procinfo(bdesc, attno, attr->atttypid, BTLessStrategyNumber); diff --git a/src/include/access/brin_internal.h b/src/include/access/brin_internal.h index 78c89a6961..79440ebe7b 100644 --- a/src/include/access/brin_internal.h +++ b/src/include/access/brin_internal.h @@ -27,6 +27,9 @@ typedef struct BrinOpcInfo /* Number of columns stored in an index column of this opclass */ uint16 oi_nstored; + /* Regular processing of NULLs in BrinValues? */ + bool oi_regular_nulls; + /* Opaque pointer for the opclass' private use */ void *oi_opaque; -- 2.26.2 --------------FA974B75A0C3E9CA18CE7207 Content-Type: text/x-patch; charset=UTF-8; name="0003-Optimize-allocations-in-bringetbitmap-20210122.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename*0="0003-Optimize-allocations-in-bringetbitmap-20210122.patch" ^ permalink raw reply [nested|flat] 2+ messages in thread
* Generate pg_stat_get_xact*() functions with Macros @ 2023-01-05 13:48 Drouvot, Bertrand <[email protected]> 0 siblings, 0 replies; 2+ messages in thread From: Drouvot, Bertrand @ 2023-01-05 13:48 UTC (permalink / raw) To: PostgreSQL Hackers <[email protected]> Hi hackers, Please find attached a patch proposal to $SUBJECT. This is the same kind of work that has been done in 83a1a1b566 and 8018ffbf58 but this time for the pg_stat_get_xact*() functions (as suggested by Andres in [1]). The function names remain the same, but some fields have to be renamed. While at it, I also took the opportunity to create the macros for pg_stat_get_xact_function_total_time(), pg_stat_get_xact_function_self_time() and pg_stat_get_function_total_time(), pg_stat_get_function_self_time() (even if the same code pattern is only repeated two 2 times). Now that this patch renames some fields, I think that, for consistency, those ones should be renamed too (aka remove the f_ and t_ prefixes): PgStat_FunctionCounts.f_numcalls PgStat_StatFuncEntry.f_numcalls PgStat_TableCounts.t_truncdropped PgStat_TableCounts.t_delta_live_tuples PgStat_TableCounts.t_delta_dead_tuples PgStat_TableCounts.t_changed_tuples But I think it would be better to do it in a follow-up patch (once this one get committed). [1]: https://www.postgresql.org/message-id/20230105002733.ealhzubjaiqis6ua%40awork3.anarazel.de Looking forward to your feedback, Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com diff --git a/src/backend/utils/activity/pgstat_function.c b/src/backend/utils/activity/pgstat_function.c index 6139a27fee..77af8541e0 100644 --- a/src/backend/utils/activity/pgstat_function.c +++ b/src/backend/utils/activity/pgstat_function.c @@ -124,7 +124,7 @@ pgstat_init_function_usage(FunctionCallInfo fcinfo, fcu->fs = &pending->f_counts; /* save stats for this function, later used to compensate for recursion */ - fcu->save_f_total_time = pending->f_counts.f_total_time; + fcu->save_total_time = pending->f_counts.total_time; /* save current backend-wide total time */ fcu->save_total = total_func_time; @@ -168,19 +168,19 @@ pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize) INSTR_TIME_ADD(total_func_time, f_self); /* - * Compute the new f_total_time as the total elapsed time added to the - * pre-call value of f_total_time. This is necessary to avoid + * Compute the new total_time as the total elapsed time added to the + * pre-call value of total_time. This is necessary to avoid * double-counting any time taken by recursive calls of myself. (We do * not need any similar kluge for self time, since that already excludes * any recursive calls.) */ - INSTR_TIME_ADD(f_total, fcu->save_f_total_time); + INSTR_TIME_ADD(f_total, fcu->save_total_time); /* update counters in function stats table */ if (finalize) fs->f_numcalls++; - fs->f_total_time = f_total; - INSTR_TIME_ADD(fs->f_self_time, f_self); + fs->total_time = f_total; + INSTR_TIME_ADD(fs->self_time, f_self); } /* @@ -204,10 +204,10 @@ pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) return false; shfuncent->stats.f_numcalls += localent->f_counts.f_numcalls; - shfuncent->stats.f_total_time += - INSTR_TIME_GET_MICROSEC(localent->f_counts.f_total_time); - shfuncent->stats.f_self_time += - INSTR_TIME_GET_MICROSEC(localent->f_counts.f_self_time); + shfuncent->stats.total_time += + INSTR_TIME_GET_MICROSEC(localent->f_counts.total_time); + shfuncent->stats.self_time += + INSTR_TIME_GET_MICROSEC(localent->f_counts.self_time); pgstat_unlock_entry(entry_ref); diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_relation.c index 1730425de1..625cd2a96f 100644 --- a/src/backend/utils/activity/pgstat_relation.c +++ b/src/backend/utils/activity/pgstat_relation.c @@ -371,9 +371,9 @@ pgstat_count_heap_update(Relation rel, bool hot) ensure_tabstat_xact_level(pgstat_info); pgstat_info->trans->tuples_updated++; - /* t_tuples_hot_updated is nontransactional, so just advance it */ + /* tuples_hot_updated is nontransactional, so just advance it */ if (hot) - pgstat_info->t_counts.t_tuples_hot_updated++; + pgstat_info->t_counts.tuples_hot_updated++; } } @@ -501,9 +501,9 @@ AtEOXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit) if (!isCommit) restore_truncdrop_counters(trans); /* count attempted actions regardless of commit/abort */ - tabstat->t_counts.t_tuples_inserted += trans->tuples_inserted; - tabstat->t_counts.t_tuples_updated += trans->tuples_updated; - tabstat->t_counts.t_tuples_deleted += trans->tuples_deleted; + tabstat->t_counts.tuples_inserted += trans->tuples_inserted; + tabstat->t_counts.tuples_updated += trans->tuples_updated; + tabstat->t_counts.tuples_deleted += trans->tuples_deleted; if (isCommit) { tabstat->t_counts.t_truncdropped = trans->truncdropped; @@ -607,9 +607,9 @@ AtEOSubXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit, in /* first restore values obliterated by truncate/drop */ restore_truncdrop_counters(trans); /* count attempted actions regardless of commit/abort */ - tabstat->t_counts.t_tuples_inserted += trans->tuples_inserted; - tabstat->t_counts.t_tuples_updated += trans->tuples_updated; - tabstat->t_counts.t_tuples_deleted += trans->tuples_deleted; + tabstat->t_counts.tuples_inserted += trans->tuples_inserted; + tabstat->t_counts.tuples_updated += trans->tuples_updated; + tabstat->t_counts.tuples_deleted += trans->tuples_deleted; /* inserted tuples are dead, deleted tuples are unaffected */ tabstat->t_counts.t_delta_dead_tuples += trans->tuples_inserted + trans->tuples_updated; @@ -691,9 +691,9 @@ pgstat_twophase_postcommit(TransactionId xid, uint16 info, pgstat_info = pgstat_prep_relation_pending(rec->t_id, rec->t_shared); /* Same math as in AtEOXact_PgStat, commit case */ - pgstat_info->t_counts.t_tuples_inserted += rec->tuples_inserted; - pgstat_info->t_counts.t_tuples_updated += rec->tuples_updated; - pgstat_info->t_counts.t_tuples_deleted += rec->tuples_deleted; + pgstat_info->t_counts.tuples_inserted += rec->tuples_inserted; + pgstat_info->t_counts.tuples_updated += rec->tuples_updated; + pgstat_info->t_counts.tuples_deleted += rec->tuples_deleted; pgstat_info->t_counts.t_truncdropped = rec->t_truncdropped; if (rec->t_truncdropped) { @@ -733,9 +733,9 @@ pgstat_twophase_postabort(TransactionId xid, uint16 info, rec->tuples_updated = rec->updated_pre_truncdrop; rec->tuples_deleted = rec->deleted_pre_truncdrop; } - pgstat_info->t_counts.t_tuples_inserted += rec->tuples_inserted; - pgstat_info->t_counts.t_tuples_updated += rec->tuples_updated; - pgstat_info->t_counts.t_tuples_deleted += rec->tuples_deleted; + pgstat_info->t_counts.tuples_inserted += rec->tuples_inserted; + pgstat_info->t_counts.tuples_updated += rec->tuples_updated; + pgstat_info->t_counts.tuples_deleted += rec->tuples_deleted; pgstat_info->t_counts.t_delta_dead_tuples += rec->tuples_inserted + rec->tuples_updated; } @@ -779,19 +779,19 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) /* add the values to the shared entry. */ tabentry = &shtabstats->stats; - tabentry->numscans += lstats->t_counts.t_numscans; - if (lstats->t_counts.t_numscans) + tabentry->numscans += lstats->t_counts.numscans; + if (lstats->t_counts.numscans) { TimestampTz t = GetCurrentTransactionStopTimestamp(); if (t > tabentry->lastscan) tabentry->lastscan = t; } - tabentry->tuples_returned += lstats->t_counts.t_tuples_returned; - tabentry->tuples_fetched += lstats->t_counts.t_tuples_fetched; - tabentry->tuples_inserted += lstats->t_counts.t_tuples_inserted; - tabentry->tuples_updated += lstats->t_counts.t_tuples_updated; - tabentry->tuples_deleted += lstats->t_counts.t_tuples_deleted; - tabentry->tuples_hot_updated += lstats->t_counts.t_tuples_hot_updated; + tabentry->tuples_returned += lstats->t_counts.tuples_returned; + tabentry->tuples_fetched += lstats->t_counts.tuples_fetched; + tabentry->tuples_inserted += lstats->t_counts.tuples_inserted; + tabentry->tuples_updated += lstats->t_counts.tuples_updated; + tabentry->tuples_deleted += lstats->t_counts.tuples_deleted; + tabentry->tuples_hot_updated += lstats->t_counts.tuples_hot_updated; /* * If table was truncated/dropped, first reset the live/dead counters. @@ -806,9 +806,9 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) tabentry->live_tuples += lstats->t_counts.t_delta_live_tuples; tabentry->dead_tuples += lstats->t_counts.t_delta_dead_tuples; tabentry->mod_since_analyze += lstats->t_counts.t_changed_tuples; - tabentry->ins_since_vacuum += lstats->t_counts.t_tuples_inserted; - tabentry->blocks_fetched += lstats->t_counts.t_blocks_fetched; - tabentry->blocks_hit += lstats->t_counts.t_blocks_hit; + tabentry->ins_since_vacuum += lstats->t_counts.tuples_inserted; + tabentry->blocks_fetched += lstats->t_counts.blocks_fetched; + tabentry->blocks_hit += lstats->t_counts.blocks_hit; /* Clamp live_tuples in case of negative delta_live_tuples */ tabentry->live_tuples = Max(tabentry->live_tuples, 0); @@ -819,13 +819,13 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) /* The entry was successfully flushed, add the same to database stats */ dbentry = pgstat_prep_database_pending(dboid); - dbentry->tuples_returned += lstats->t_counts.t_tuples_returned; - dbentry->tuples_fetched += lstats->t_counts.t_tuples_fetched; - dbentry->tuples_inserted += lstats->t_counts.t_tuples_inserted; - dbentry->tuples_updated += lstats->t_counts.t_tuples_updated; - dbentry->tuples_deleted += lstats->t_counts.t_tuples_deleted; - dbentry->blocks_fetched += lstats->t_counts.t_blocks_fetched; - dbentry->blocks_hit += lstats->t_counts.t_blocks_hit; + dbentry->tuples_returned += lstats->t_counts.tuples_returned; + dbentry->tuples_fetched += lstats->t_counts.tuples_fetched; + dbentry->tuples_inserted += lstats->t_counts.tuples_inserted; + dbentry->tuples_updated += lstats->t_counts.tuples_updated; + dbentry->tuples_deleted += lstats->t_counts.tuples_deleted; + dbentry->blocks_fetched += lstats->t_counts.blocks_fetched; + dbentry->blocks_hit += lstats->t_counts.blocks_hit; return true; } diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index 6cddd74aa7..27bb928db4 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -148,29 +148,24 @@ pg_stat_get_function_calls(PG_FUNCTION_ARGS) PG_RETURN_INT64(funcentry->f_numcalls); } -Datum -pg_stat_get_function_total_time(PG_FUNCTION_ARGS) -{ - Oid funcid = PG_GETARG_OID(0); - PgStat_StatFuncEntry *funcentry; - - if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL) - PG_RETURN_NULL(); - /* convert counter from microsec to millisec for display */ - PG_RETURN_FLOAT8(((double) funcentry->f_total_time) / 1000.0); +#define PG_STAT_GET_FUNCENTRY_FLOAT8(stat) \ +Datum \ +CppConcat(pg_stat_get_function_,stat)(PG_FUNCTION_ARGS) \ +{ \ + Oid funcid = PG_GETARG_OID(0); \ + PgStat_StatFuncEntry *funcentry; \ + \ + if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL) \ + PG_RETURN_NULL(); \ + /* convert counter from microsec to millisec for display */ \ + PG_RETURN_FLOAT8(((double) funcentry->stat) / 1000.0); \ } -Datum -pg_stat_get_function_self_time(PG_FUNCTION_ARGS) -{ - Oid funcid = PG_GETARG_OID(0); - PgStat_StatFuncEntry *funcentry; +/* pg_stat_get_function_total_time */ +PG_STAT_GET_FUNCENTRY_FLOAT8(total_time) - if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL) - PG_RETURN_NULL(); - /* convert counter from microsec to millisec for display */ - PG_RETURN_FLOAT8(((double) funcentry->f_self_time) / 1000.0); -} +/* pg_stat_get_function_self_time */ +PG_STAT_GET_FUNCENTRY_FLOAT8(self_time) Datum pg_stat_get_backend_idset(PG_FUNCTION_ARGS) @@ -1345,158 +1340,70 @@ pg_stat_get_slru(PG_FUNCTION_ARGS) return (Datum) 0; } -Datum -pg_stat_get_xact_numscans(PG_FUNCTION_ARGS) -{ - Oid relid = PG_GETARG_OID(0); - int64 result; - PgStat_TableStatus *tabentry; - - if ((tabentry = find_tabstat_entry(relid)) == NULL) - result = 0; - else - result = (int64) (tabentry->t_counts.t_numscans); - - PG_RETURN_INT64(result); -} - -Datum -pg_stat_get_xact_tuples_returned(PG_FUNCTION_ARGS) -{ - Oid relid = PG_GETARG_OID(0); - int64 result; - PgStat_TableStatus *tabentry; - - if ((tabentry = find_tabstat_entry(relid)) == NULL) - result = 0; - else - result = (int64) (tabentry->t_counts.t_tuples_returned); - - PG_RETURN_INT64(result); -} - -Datum -pg_stat_get_xact_tuples_fetched(PG_FUNCTION_ARGS) -{ - Oid relid = PG_GETARG_OID(0); - int64 result; - PgStat_TableStatus *tabentry; - - if ((tabentry = find_tabstat_entry(relid)) == NULL) - result = 0; - else - result = (int64) (tabentry->t_counts.t_tuples_fetched); - - PG_RETURN_INT64(result); -} - -Datum -pg_stat_get_xact_tuples_inserted(PG_FUNCTION_ARGS) -{ - Oid relid = PG_GETARG_OID(0); - int64 result; - PgStat_TableStatus *tabentry; - PgStat_TableXactStatus *trans; - - if ((tabentry = find_tabstat_entry(relid)) == NULL) - result = 0; - else - { - result = tabentry->t_counts.t_tuples_inserted; - /* live subtransactions' counts aren't in t_tuples_inserted yet */ - for (trans = tabentry->trans; trans != NULL; trans = trans->upper) - result += trans->tuples_inserted; - } - - PG_RETURN_INT64(result); -} - -Datum -pg_stat_get_xact_tuples_updated(PG_FUNCTION_ARGS) -{ - Oid relid = PG_GETARG_OID(0); - int64 result; - PgStat_TableStatus *tabentry; - PgStat_TableXactStatus *trans; - - if ((tabentry = find_tabstat_entry(relid)) == NULL) - result = 0; - else - { - result = tabentry->t_counts.t_tuples_updated; - /* live subtransactions' counts aren't in t_tuples_updated yet */ - for (trans = tabentry->trans; trans != NULL; trans = trans->upper) - result += trans->tuples_updated; - } - - PG_RETURN_INT64(result); -} - -Datum -pg_stat_get_xact_tuples_deleted(PG_FUNCTION_ARGS) -{ - Oid relid = PG_GETARG_OID(0); - int64 result; - PgStat_TableStatus *tabentry; - PgStat_TableXactStatus *trans; - - if ((tabentry = find_tabstat_entry(relid)) == NULL) - result = 0; - else - { - result = tabentry->t_counts.t_tuples_deleted; - /* live subtransactions' counts aren't in t_tuples_deleted yet */ - for (trans = tabentry->trans; trans != NULL; trans = trans->upper) - result += trans->tuples_deleted; - } - - PG_RETURN_INT64(result); -} - -Datum -pg_stat_get_xact_tuples_hot_updated(PG_FUNCTION_ARGS) -{ - Oid relid = PG_GETARG_OID(0); - int64 result; - PgStat_TableStatus *tabentry; - - if ((tabentry = find_tabstat_entry(relid)) == NULL) - result = 0; - else - result = (int64) (tabentry->t_counts.t_tuples_hot_updated); - - PG_RETURN_INT64(result); -} - -Datum -pg_stat_get_xact_blocks_fetched(PG_FUNCTION_ARGS) -{ - Oid relid = PG_GETARG_OID(0); - int64 result; - PgStat_TableStatus *tabentry; - - if ((tabentry = find_tabstat_entry(relid)) == NULL) - result = 0; - else - result = (int64) (tabentry->t_counts.t_blocks_fetched); - - PG_RETURN_INT64(result); -} - -Datum -pg_stat_get_xact_blocks_hit(PG_FUNCTION_ARGS) -{ - Oid relid = PG_GETARG_OID(0); - int64 result; - PgStat_TableStatus *tabentry; - - if ((tabentry = find_tabstat_entry(relid)) == NULL) - result = 0; - else - result = (int64) (tabentry->t_counts.t_blocks_hit); - - PG_RETURN_INT64(result); -} +#define PG_STAT_GET_XACT_RELENTRY_INT64(stat) \ +Datum \ +CppConcat(pg_stat_get_xact_,stat)(PG_FUNCTION_ARGS) \ +{ \ + Oid relid = PG_GETARG_OID(0); \ + int64 result; \ + PgStat_TableStatus *tabentry; \ + \ + if ((tabentry = find_tabstat_entry(relid)) == NULL) \ + result = 0; \ + else \ + result = (int64) (tabentry->t_counts.stat); \ + \ + PG_RETURN_INT64(result); \ +} + +/* pg_stat_get_xact_numscans */ +PG_STAT_GET_XACT_RELENTRY_INT64(numscans) + +/* pg_stat_get_xact_tuples_returned */ +PG_STAT_GET_XACT_RELENTRY_INT64(tuples_returned) + +/* pg_stat_get_xact_tuples_fetched */ +PG_STAT_GET_XACT_RELENTRY_INT64(tuples_fetched) + +/* pg_stat_get_xact_tuples_hot_updated */ +PG_STAT_GET_XACT_RELENTRY_INT64(tuples_hot_updated) + +/* pg_stat_get_xact_blocks_fetched */ +PG_STAT_GET_XACT_RELENTRY_INT64(blocks_fetched) + +/* pg_stat_get_xact_blocks_hit */ +PG_STAT_GET_XACT_RELENTRY_INT64(blocks_hit) + +#define PG_STAT_GET_XACT_WITH_SUBTRANS_RELENTRY_INT64(stat) \ +Datum \ +CppConcat(pg_stat_get_xact_,stat)(PG_FUNCTION_ARGS) \ +{ \ + Oid relid = PG_GETARG_OID(0); \ + int64 result; \ + PgStat_TableStatus *tabentry; \ + PgStat_TableXactStatus *trans; \ + \ + if ((tabentry = find_tabstat_entry(relid)) == NULL) \ + result = 0; \ + else \ + { \ + result = tabentry->t_counts.stat; \ + /* live subtransactions' counts aren't in the stat yet */ \ + for (trans = tabentry->trans; trans != NULL; trans = trans->upper) \ + result += trans->stat; \ + } \ + \ + PG_RETURN_INT64(result); \ +} + +/* pg_stat_get_xact_tuples_inserted */ +PG_STAT_GET_XACT_WITH_SUBTRANS_RELENTRY_INT64(tuples_inserted) + +/* pg_stat_get_xact_tuples_updated */ +PG_STAT_GET_XACT_WITH_SUBTRANS_RELENTRY_INT64(tuples_updated) + +/* pg_stat_get_xact_tuples_deleted */ +PG_STAT_GET_XACT_WITH_SUBTRANS_RELENTRY_INT64(tuples_deleted) Datum pg_stat_get_xact_function_calls(PG_FUNCTION_ARGS) @@ -1509,28 +1416,23 @@ pg_stat_get_xact_function_calls(PG_FUNCTION_ARGS) PG_RETURN_INT64(funcentry->f_counts.f_numcalls); } -Datum -pg_stat_get_xact_function_total_time(PG_FUNCTION_ARGS) -{ - Oid funcid = PG_GETARG_OID(0); - PgStat_BackendFunctionEntry *funcentry; - - if ((funcentry = find_funcstat_entry(funcid)) == NULL) - PG_RETURN_NULL(); - PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(funcentry->f_counts.f_total_time)); +#define PG_STAT_GET_XACT_FUNCENTRY_FLOAT8(stat) \ +Datum \ +CppConcat(pg_stat_get_xact_function_,stat)(PG_FUNCTION_ARGS) \ +{ \ + Oid funcid = PG_GETARG_OID(0); \ + PgStat_BackendFunctionEntry *funcentry; \ + \ + if ((funcentry = find_funcstat_entry(funcid)) == NULL) \ + PG_RETURN_NULL(); \ + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(funcentry->f_counts.stat)); \ } -Datum -pg_stat_get_xact_function_self_time(PG_FUNCTION_ARGS) -{ - Oid funcid = PG_GETARG_OID(0); - PgStat_BackendFunctionEntry *funcentry; - - if ((funcentry = find_funcstat_entry(funcid)) == NULL) - PG_RETURN_NULL(); - PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(funcentry->f_counts.f_self_time)); -} +/* pg_stat_get_xact_function_total_time */ +PG_STAT_GET_XACT_FUNCENTRY_FLOAT8(total_time) +/* pg_stat_get_xact_function_self_time */ +PG_STAT_GET_XACT_FUNCENTRY_FLOAT8(self_time) /* Get the timestamp of the current statistics snapshot */ Datum diff --git a/src/include/pgstat.h b/src/include/pgstat.h index d3e965d744..d26d0d8324 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -106,8 +106,8 @@ typedef int64 PgStat_Counter; typedef struct PgStat_FunctionCounts { PgStat_Counter f_numcalls; - instr_time f_total_time; - instr_time f_self_time; + instr_time total_time; + instr_time self_time; } PgStat_FunctionCounts; /* ---------- @@ -128,7 +128,7 @@ typedef struct PgStat_FunctionCallUsage /* NULL means we are not tracking the current function call */ PgStat_FunctionCounts *fs; /* Total time previously charged to function, as of function start */ - instr_time save_f_total_time; + instr_time save_total_time; /* Backend-wide total time as of function start */ instr_time save_total; /* system clock as of function start */ @@ -167,23 +167,23 @@ typedef struct PgStat_BackendSubEntry */ typedef struct PgStat_TableCounts { - PgStat_Counter t_numscans; + PgStat_Counter numscans; - PgStat_Counter t_tuples_returned; - PgStat_Counter t_tuples_fetched; + PgStat_Counter tuples_returned; + PgStat_Counter tuples_fetched; - PgStat_Counter t_tuples_inserted; - PgStat_Counter t_tuples_updated; - PgStat_Counter t_tuples_deleted; - PgStat_Counter t_tuples_hot_updated; + PgStat_Counter tuples_inserted; + PgStat_Counter tuples_updated; + PgStat_Counter tuples_deleted; + PgStat_Counter tuples_hot_updated; bool t_truncdropped; PgStat_Counter t_delta_live_tuples; PgStat_Counter t_delta_dead_tuples; PgStat_Counter t_changed_tuples; - PgStat_Counter t_blocks_fetched; - PgStat_Counter t_blocks_hit; + PgStat_Counter blocks_fetched; + PgStat_Counter blocks_hit; } PgStat_TableCounts; /* ---------- @@ -315,8 +315,8 @@ typedef struct PgStat_StatFuncEntry { PgStat_Counter f_numcalls; - PgStat_Counter f_total_time; /* times in microseconds */ - PgStat_Counter f_self_time; + PgStat_Counter total_time; /* times in microseconds */ + PgStat_Counter self_time; } PgStat_StatFuncEntry; typedef struct PgStat_StatReplSlotEntry @@ -525,37 +525,37 @@ extern void pgstat_report_analyze(Relation rel, #define pgstat_count_heap_scan(rel) \ do { \ if (pgstat_should_count_relation(rel)) \ - (rel)->pgstat_info->t_counts.t_numscans++; \ + (rel)->pgstat_info->t_counts.numscans++; \ } while (0) #define pgstat_count_heap_getnext(rel) \ do { \ if (pgstat_should_count_relation(rel)) \ - (rel)->pgstat_info->t_counts.t_tuples_returned++; \ + (rel)->pgstat_info->t_counts.tuples_returned++; \ } while (0) #define pgstat_count_heap_fetch(rel) \ do { \ if (pgstat_should_count_relation(rel)) \ - (rel)->pgstat_info->t_counts.t_tuples_fetched++; \ + (rel)->pgstat_info->t_counts.tuples_fetched++; \ } while (0) #define pgstat_count_index_scan(rel) \ do { \ if (pgstat_should_count_relation(rel)) \ - (rel)->pgstat_info->t_counts.t_numscans++; \ + (rel)->pgstat_info->t_counts.numscans++; \ } while (0) #define pgstat_count_index_tuples(rel, n) \ do { \ if (pgstat_should_count_relation(rel)) \ - (rel)->pgstat_info->t_counts.t_tuples_returned += (n); \ + (rel)->pgstat_info->t_counts.tuples_returned += (n); \ } while (0) #define pgstat_count_buffer_read(rel) \ do { \ if (pgstat_should_count_relation(rel)) \ - (rel)->pgstat_info->t_counts.t_blocks_fetched++; \ + (rel)->pgstat_info->t_counts.blocks_fetched++; \ } while (0) #define pgstat_count_buffer_hit(rel) \ do { \ if (pgstat_should_count_relation(rel)) \ - (rel)->pgstat_info->t_counts.t_blocks_hit++; \ + (rel)->pgstat_info->t_counts.blocks_hit++; \ } while (0) extern void pgstat_count_heap_insert(Relation rel, PgStat_Counter n); Attachments: [text/plain] v1-0001-generate-pg_stat_get_xact-functions-with-macros.patch (21.2K, ../../[email protected]/2-v1-0001-generate-pg_stat_get_xact-functions-with-macros.patch) download | inline diff: diff --git a/src/backend/utils/activity/pgstat_function.c b/src/backend/utils/activity/pgstat_function.c index 6139a27fee..77af8541e0 100644 --- a/src/backend/utils/activity/pgstat_function.c +++ b/src/backend/utils/activity/pgstat_function.c @@ -124,7 +124,7 @@ pgstat_init_function_usage(FunctionCallInfo fcinfo, fcu->fs = &pending->f_counts; /* save stats for this function, later used to compensate for recursion */ - fcu->save_f_total_time = pending->f_counts.f_total_time; + fcu->save_total_time = pending->f_counts.total_time; /* save current backend-wide total time */ fcu->save_total = total_func_time; @@ -168,19 +168,19 @@ pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize) INSTR_TIME_ADD(total_func_time, f_self); /* - * Compute the new f_total_time as the total elapsed time added to the - * pre-call value of f_total_time. This is necessary to avoid + * Compute the new total_time as the total elapsed time added to the + * pre-call value of total_time. This is necessary to avoid * double-counting any time taken by recursive calls of myself. (We do * not need any similar kluge for self time, since that already excludes * any recursive calls.) */ - INSTR_TIME_ADD(f_total, fcu->save_f_total_time); + INSTR_TIME_ADD(f_total, fcu->save_total_time); /* update counters in function stats table */ if (finalize) fs->f_numcalls++; - fs->f_total_time = f_total; - INSTR_TIME_ADD(fs->f_self_time, f_self); + fs->total_time = f_total; + INSTR_TIME_ADD(fs->self_time, f_self); } /* @@ -204,10 +204,10 @@ pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) return false; shfuncent->stats.f_numcalls += localent->f_counts.f_numcalls; - shfuncent->stats.f_total_time += - INSTR_TIME_GET_MICROSEC(localent->f_counts.f_total_time); - shfuncent->stats.f_self_time += - INSTR_TIME_GET_MICROSEC(localent->f_counts.f_self_time); + shfuncent->stats.total_time += + INSTR_TIME_GET_MICROSEC(localent->f_counts.total_time); + shfuncent->stats.self_time += + INSTR_TIME_GET_MICROSEC(localent->f_counts.self_time); pgstat_unlock_entry(entry_ref); diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_relation.c index 1730425de1..625cd2a96f 100644 --- a/src/backend/utils/activity/pgstat_relation.c +++ b/src/backend/utils/activity/pgstat_relation.c @@ -371,9 +371,9 @@ pgstat_count_heap_update(Relation rel, bool hot) ensure_tabstat_xact_level(pgstat_info); pgstat_info->trans->tuples_updated++; - /* t_tuples_hot_updated is nontransactional, so just advance it */ + /* tuples_hot_updated is nontransactional, so just advance it */ if (hot) - pgstat_info->t_counts.t_tuples_hot_updated++; + pgstat_info->t_counts.tuples_hot_updated++; } } @@ -501,9 +501,9 @@ AtEOXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit) if (!isCommit) restore_truncdrop_counters(trans); /* count attempted actions regardless of commit/abort */ - tabstat->t_counts.t_tuples_inserted += trans->tuples_inserted; - tabstat->t_counts.t_tuples_updated += trans->tuples_updated; - tabstat->t_counts.t_tuples_deleted += trans->tuples_deleted; + tabstat->t_counts.tuples_inserted += trans->tuples_inserted; + tabstat->t_counts.tuples_updated += trans->tuples_updated; + tabstat->t_counts.tuples_deleted += trans->tuples_deleted; if (isCommit) { tabstat->t_counts.t_truncdropped = trans->truncdropped; @@ -607,9 +607,9 @@ AtEOSubXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit, in /* first restore values obliterated by truncate/drop */ restore_truncdrop_counters(trans); /* count attempted actions regardless of commit/abort */ - tabstat->t_counts.t_tuples_inserted += trans->tuples_inserted; - tabstat->t_counts.t_tuples_updated += trans->tuples_updated; - tabstat->t_counts.t_tuples_deleted += trans->tuples_deleted; + tabstat->t_counts.tuples_inserted += trans->tuples_inserted; + tabstat->t_counts.tuples_updated += trans->tuples_updated; + tabstat->t_counts.tuples_deleted += trans->tuples_deleted; /* inserted tuples are dead, deleted tuples are unaffected */ tabstat->t_counts.t_delta_dead_tuples += trans->tuples_inserted + trans->tuples_updated; @@ -691,9 +691,9 @@ pgstat_twophase_postcommit(TransactionId xid, uint16 info, pgstat_info = pgstat_prep_relation_pending(rec->t_id, rec->t_shared); /* Same math as in AtEOXact_PgStat, commit case */ - pgstat_info->t_counts.t_tuples_inserted += rec->tuples_inserted; - pgstat_info->t_counts.t_tuples_updated += rec->tuples_updated; - pgstat_info->t_counts.t_tuples_deleted += rec->tuples_deleted; + pgstat_info->t_counts.tuples_inserted += rec->tuples_inserted; + pgstat_info->t_counts.tuples_updated += rec->tuples_updated; + pgstat_info->t_counts.tuples_deleted += rec->tuples_deleted; pgstat_info->t_counts.t_truncdropped = rec->t_truncdropped; if (rec->t_truncdropped) { @@ -733,9 +733,9 @@ pgstat_twophase_postabort(TransactionId xid, uint16 info, rec->tuples_updated = rec->updated_pre_truncdrop; rec->tuples_deleted = rec->deleted_pre_truncdrop; } - pgstat_info->t_counts.t_tuples_inserted += rec->tuples_inserted; - pgstat_info->t_counts.t_tuples_updated += rec->tuples_updated; - pgstat_info->t_counts.t_tuples_deleted += rec->tuples_deleted; + pgstat_info->t_counts.tuples_inserted += rec->tuples_inserted; + pgstat_info->t_counts.tuples_updated += rec->tuples_updated; + pgstat_info->t_counts.tuples_deleted += rec->tuples_deleted; pgstat_info->t_counts.t_delta_dead_tuples += rec->tuples_inserted + rec->tuples_updated; } @@ -779,19 +779,19 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) /* add the values to the shared entry. */ tabentry = &shtabstats->stats; - tabentry->numscans += lstats->t_counts.t_numscans; - if (lstats->t_counts.t_numscans) + tabentry->numscans += lstats->t_counts.numscans; + if (lstats->t_counts.numscans) { TimestampTz t = GetCurrentTransactionStopTimestamp(); if (t > tabentry->lastscan) tabentry->lastscan = t; } - tabentry->tuples_returned += lstats->t_counts.t_tuples_returned; - tabentry->tuples_fetched += lstats->t_counts.t_tuples_fetched; - tabentry->tuples_inserted += lstats->t_counts.t_tuples_inserted; - tabentry->tuples_updated += lstats->t_counts.t_tuples_updated; - tabentry->tuples_deleted += lstats->t_counts.t_tuples_deleted; - tabentry->tuples_hot_updated += lstats->t_counts.t_tuples_hot_updated; + tabentry->tuples_returned += lstats->t_counts.tuples_returned; + tabentry->tuples_fetched += lstats->t_counts.tuples_fetched; + tabentry->tuples_inserted += lstats->t_counts.tuples_inserted; + tabentry->tuples_updated += lstats->t_counts.tuples_updated; + tabentry->tuples_deleted += lstats->t_counts.tuples_deleted; + tabentry->tuples_hot_updated += lstats->t_counts.tuples_hot_updated; /* * If table was truncated/dropped, first reset the live/dead counters. @@ -806,9 +806,9 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) tabentry->live_tuples += lstats->t_counts.t_delta_live_tuples; tabentry->dead_tuples += lstats->t_counts.t_delta_dead_tuples; tabentry->mod_since_analyze += lstats->t_counts.t_changed_tuples; - tabentry->ins_since_vacuum += lstats->t_counts.t_tuples_inserted; - tabentry->blocks_fetched += lstats->t_counts.t_blocks_fetched; - tabentry->blocks_hit += lstats->t_counts.t_blocks_hit; + tabentry->ins_since_vacuum += lstats->t_counts.tuples_inserted; + tabentry->blocks_fetched += lstats->t_counts.blocks_fetched; + tabentry->blocks_hit += lstats->t_counts.blocks_hit; /* Clamp live_tuples in case of negative delta_live_tuples */ tabentry->live_tuples = Max(tabentry->live_tuples, 0); @@ -819,13 +819,13 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) /* The entry was successfully flushed, add the same to database stats */ dbentry = pgstat_prep_database_pending(dboid); - dbentry->tuples_returned += lstats->t_counts.t_tuples_returned; - dbentry->tuples_fetched += lstats->t_counts.t_tuples_fetched; - dbentry->tuples_inserted += lstats->t_counts.t_tuples_inserted; - dbentry->tuples_updated += lstats->t_counts.t_tuples_updated; - dbentry->tuples_deleted += lstats->t_counts.t_tuples_deleted; - dbentry->blocks_fetched += lstats->t_counts.t_blocks_fetched; - dbentry->blocks_hit += lstats->t_counts.t_blocks_hit; + dbentry->tuples_returned += lstats->t_counts.tuples_returned; + dbentry->tuples_fetched += lstats->t_counts.tuples_fetched; + dbentry->tuples_inserted += lstats->t_counts.tuples_inserted; + dbentry->tuples_updated += lstats->t_counts.tuples_updated; + dbentry->tuples_deleted += lstats->t_counts.tuples_deleted; + dbentry->blocks_fetched += lstats->t_counts.blocks_fetched; + dbentry->blocks_hit += lstats->t_counts.blocks_hit; return true; } diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index 6cddd74aa7..27bb928db4 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -148,29 +148,24 @@ pg_stat_get_function_calls(PG_FUNCTION_ARGS) PG_RETURN_INT64(funcentry->f_numcalls); } -Datum -pg_stat_get_function_total_time(PG_FUNCTION_ARGS) -{ - Oid funcid = PG_GETARG_OID(0); - PgStat_StatFuncEntry *funcentry; - - if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL) - PG_RETURN_NULL(); - /* convert counter from microsec to millisec for display */ - PG_RETURN_FLOAT8(((double) funcentry->f_total_time) / 1000.0); +#define PG_STAT_GET_FUNCENTRY_FLOAT8(stat) \ +Datum \ +CppConcat(pg_stat_get_function_,stat)(PG_FUNCTION_ARGS) \ +{ \ + Oid funcid = PG_GETARG_OID(0); \ + PgStat_StatFuncEntry *funcentry; \ + \ + if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL) \ + PG_RETURN_NULL(); \ + /* convert counter from microsec to millisec for display */ \ + PG_RETURN_FLOAT8(((double) funcentry->stat) / 1000.0); \ } -Datum -pg_stat_get_function_self_time(PG_FUNCTION_ARGS) -{ - Oid funcid = PG_GETARG_OID(0); - PgStat_StatFuncEntry *funcentry; +/* pg_stat_get_function_total_time */ +PG_STAT_GET_FUNCENTRY_FLOAT8(total_time) - if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL) - PG_RETURN_NULL(); - /* convert counter from microsec to millisec for display */ - PG_RETURN_FLOAT8(((double) funcentry->f_self_time) / 1000.0); -} +/* pg_stat_get_function_self_time */ +PG_STAT_GET_FUNCENTRY_FLOAT8(self_time) Datum pg_stat_get_backend_idset(PG_FUNCTION_ARGS) @@ -1345,158 +1340,70 @@ pg_stat_get_slru(PG_FUNCTION_ARGS) return (Datum) 0; } -Datum -pg_stat_get_xact_numscans(PG_FUNCTION_ARGS) -{ - Oid relid = PG_GETARG_OID(0); - int64 result; - PgStat_TableStatus *tabentry; - - if ((tabentry = find_tabstat_entry(relid)) == NULL) - result = 0; - else - result = (int64) (tabentry->t_counts.t_numscans); - - PG_RETURN_INT64(result); -} - -Datum -pg_stat_get_xact_tuples_returned(PG_FUNCTION_ARGS) -{ - Oid relid = PG_GETARG_OID(0); - int64 result; - PgStat_TableStatus *tabentry; - - if ((tabentry = find_tabstat_entry(relid)) == NULL) - result = 0; - else - result = (int64) (tabentry->t_counts.t_tuples_returned); - - PG_RETURN_INT64(result); -} - -Datum -pg_stat_get_xact_tuples_fetched(PG_FUNCTION_ARGS) -{ - Oid relid = PG_GETARG_OID(0); - int64 result; - PgStat_TableStatus *tabentry; - - if ((tabentry = find_tabstat_entry(relid)) == NULL) - result = 0; - else - result = (int64) (tabentry->t_counts.t_tuples_fetched); - - PG_RETURN_INT64(result); -} - -Datum -pg_stat_get_xact_tuples_inserted(PG_FUNCTION_ARGS) -{ - Oid relid = PG_GETARG_OID(0); - int64 result; - PgStat_TableStatus *tabentry; - PgStat_TableXactStatus *trans; - - if ((tabentry = find_tabstat_entry(relid)) == NULL) - result = 0; - else - { - result = tabentry->t_counts.t_tuples_inserted; - /* live subtransactions' counts aren't in t_tuples_inserted yet */ - for (trans = tabentry->trans; trans != NULL; trans = trans->upper) - result += trans->tuples_inserted; - } - - PG_RETURN_INT64(result); -} - -Datum -pg_stat_get_xact_tuples_updated(PG_FUNCTION_ARGS) -{ - Oid relid = PG_GETARG_OID(0); - int64 result; - PgStat_TableStatus *tabentry; - PgStat_TableXactStatus *trans; - - if ((tabentry = find_tabstat_entry(relid)) == NULL) - result = 0; - else - { - result = tabentry->t_counts.t_tuples_updated; - /* live subtransactions' counts aren't in t_tuples_updated yet */ - for (trans = tabentry->trans; trans != NULL; trans = trans->upper) - result += trans->tuples_updated; - } - - PG_RETURN_INT64(result); -} - -Datum -pg_stat_get_xact_tuples_deleted(PG_FUNCTION_ARGS) -{ - Oid relid = PG_GETARG_OID(0); - int64 result; - PgStat_TableStatus *tabentry; - PgStat_TableXactStatus *trans; - - if ((tabentry = find_tabstat_entry(relid)) == NULL) - result = 0; - else - { - result = tabentry->t_counts.t_tuples_deleted; - /* live subtransactions' counts aren't in t_tuples_deleted yet */ - for (trans = tabentry->trans; trans != NULL; trans = trans->upper) - result += trans->tuples_deleted; - } - - PG_RETURN_INT64(result); -} - -Datum -pg_stat_get_xact_tuples_hot_updated(PG_FUNCTION_ARGS) -{ - Oid relid = PG_GETARG_OID(0); - int64 result; - PgStat_TableStatus *tabentry; - - if ((tabentry = find_tabstat_entry(relid)) == NULL) - result = 0; - else - result = (int64) (tabentry->t_counts.t_tuples_hot_updated); - - PG_RETURN_INT64(result); -} - -Datum -pg_stat_get_xact_blocks_fetched(PG_FUNCTION_ARGS) -{ - Oid relid = PG_GETARG_OID(0); - int64 result; - PgStat_TableStatus *tabentry; - - if ((tabentry = find_tabstat_entry(relid)) == NULL) - result = 0; - else - result = (int64) (tabentry->t_counts.t_blocks_fetched); - - PG_RETURN_INT64(result); -} - -Datum -pg_stat_get_xact_blocks_hit(PG_FUNCTION_ARGS) -{ - Oid relid = PG_GETARG_OID(0); - int64 result; - PgStat_TableStatus *tabentry; - - if ((tabentry = find_tabstat_entry(relid)) == NULL) - result = 0; - else - result = (int64) (tabentry->t_counts.t_blocks_hit); - - PG_RETURN_INT64(result); -} +#define PG_STAT_GET_XACT_RELENTRY_INT64(stat) \ +Datum \ +CppConcat(pg_stat_get_xact_,stat)(PG_FUNCTION_ARGS) \ +{ \ + Oid relid = PG_GETARG_OID(0); \ + int64 result; \ + PgStat_TableStatus *tabentry; \ + \ + if ((tabentry = find_tabstat_entry(relid)) == NULL) \ + result = 0; \ + else \ + result = (int64) (tabentry->t_counts.stat); \ + \ + PG_RETURN_INT64(result); \ +} + +/* pg_stat_get_xact_numscans */ +PG_STAT_GET_XACT_RELENTRY_INT64(numscans) + +/* pg_stat_get_xact_tuples_returned */ +PG_STAT_GET_XACT_RELENTRY_INT64(tuples_returned) + +/* pg_stat_get_xact_tuples_fetched */ +PG_STAT_GET_XACT_RELENTRY_INT64(tuples_fetched) + +/* pg_stat_get_xact_tuples_hot_updated */ +PG_STAT_GET_XACT_RELENTRY_INT64(tuples_hot_updated) + +/* pg_stat_get_xact_blocks_fetched */ +PG_STAT_GET_XACT_RELENTRY_INT64(blocks_fetched) + +/* pg_stat_get_xact_blocks_hit */ +PG_STAT_GET_XACT_RELENTRY_INT64(blocks_hit) + +#define PG_STAT_GET_XACT_WITH_SUBTRANS_RELENTRY_INT64(stat) \ +Datum \ +CppConcat(pg_stat_get_xact_,stat)(PG_FUNCTION_ARGS) \ +{ \ + Oid relid = PG_GETARG_OID(0); \ + int64 result; \ + PgStat_TableStatus *tabentry; \ + PgStat_TableXactStatus *trans; \ + \ + if ((tabentry = find_tabstat_entry(relid)) == NULL) \ + result = 0; \ + else \ + { \ + result = tabentry->t_counts.stat; \ + /* live subtransactions' counts aren't in the stat yet */ \ + for (trans = tabentry->trans; trans != NULL; trans = trans->upper) \ + result += trans->stat; \ + } \ + \ + PG_RETURN_INT64(result); \ +} + +/* pg_stat_get_xact_tuples_inserted */ +PG_STAT_GET_XACT_WITH_SUBTRANS_RELENTRY_INT64(tuples_inserted) + +/* pg_stat_get_xact_tuples_updated */ +PG_STAT_GET_XACT_WITH_SUBTRANS_RELENTRY_INT64(tuples_updated) + +/* pg_stat_get_xact_tuples_deleted */ +PG_STAT_GET_XACT_WITH_SUBTRANS_RELENTRY_INT64(tuples_deleted) Datum pg_stat_get_xact_function_calls(PG_FUNCTION_ARGS) @@ -1509,28 +1416,23 @@ pg_stat_get_xact_function_calls(PG_FUNCTION_ARGS) PG_RETURN_INT64(funcentry->f_counts.f_numcalls); } -Datum -pg_stat_get_xact_function_total_time(PG_FUNCTION_ARGS) -{ - Oid funcid = PG_GETARG_OID(0); - PgStat_BackendFunctionEntry *funcentry; - - if ((funcentry = find_funcstat_entry(funcid)) == NULL) - PG_RETURN_NULL(); - PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(funcentry->f_counts.f_total_time)); +#define PG_STAT_GET_XACT_FUNCENTRY_FLOAT8(stat) \ +Datum \ +CppConcat(pg_stat_get_xact_function_,stat)(PG_FUNCTION_ARGS) \ +{ \ + Oid funcid = PG_GETARG_OID(0); \ + PgStat_BackendFunctionEntry *funcentry; \ + \ + if ((funcentry = find_funcstat_entry(funcid)) == NULL) \ + PG_RETURN_NULL(); \ + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(funcentry->f_counts.stat)); \ } -Datum -pg_stat_get_xact_function_self_time(PG_FUNCTION_ARGS) -{ - Oid funcid = PG_GETARG_OID(0); - PgStat_BackendFunctionEntry *funcentry; - - if ((funcentry = find_funcstat_entry(funcid)) == NULL) - PG_RETURN_NULL(); - PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(funcentry->f_counts.f_self_time)); -} +/* pg_stat_get_xact_function_total_time */ +PG_STAT_GET_XACT_FUNCENTRY_FLOAT8(total_time) +/* pg_stat_get_xact_function_self_time */ +PG_STAT_GET_XACT_FUNCENTRY_FLOAT8(self_time) /* Get the timestamp of the current statistics snapshot */ Datum diff --git a/src/include/pgstat.h b/src/include/pgstat.h index d3e965d744..d26d0d8324 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -106,8 +106,8 @@ typedef int64 PgStat_Counter; typedef struct PgStat_FunctionCounts { PgStat_Counter f_numcalls; - instr_time f_total_time; - instr_time f_self_time; + instr_time total_time; + instr_time self_time; } PgStat_FunctionCounts; /* ---------- @@ -128,7 +128,7 @@ typedef struct PgStat_FunctionCallUsage /* NULL means we are not tracking the current function call */ PgStat_FunctionCounts *fs; /* Total time previously charged to function, as of function start */ - instr_time save_f_total_time; + instr_time save_total_time; /* Backend-wide total time as of function start */ instr_time save_total; /* system clock as of function start */ @@ -167,23 +167,23 @@ typedef struct PgStat_BackendSubEntry */ typedef struct PgStat_TableCounts { - PgStat_Counter t_numscans; + PgStat_Counter numscans; - PgStat_Counter t_tuples_returned; - PgStat_Counter t_tuples_fetched; + PgStat_Counter tuples_returned; + PgStat_Counter tuples_fetched; - PgStat_Counter t_tuples_inserted; - PgStat_Counter t_tuples_updated; - PgStat_Counter t_tuples_deleted; - PgStat_Counter t_tuples_hot_updated; + PgStat_Counter tuples_inserted; + PgStat_Counter tuples_updated; + PgStat_Counter tuples_deleted; + PgStat_Counter tuples_hot_updated; bool t_truncdropped; PgStat_Counter t_delta_live_tuples; PgStat_Counter t_delta_dead_tuples; PgStat_Counter t_changed_tuples; - PgStat_Counter t_blocks_fetched; - PgStat_Counter t_blocks_hit; + PgStat_Counter blocks_fetched; + PgStat_Counter blocks_hit; } PgStat_TableCounts; /* ---------- @@ -315,8 +315,8 @@ typedef struct PgStat_StatFuncEntry { PgStat_Counter f_numcalls; - PgStat_Counter f_total_time; /* times in microseconds */ - PgStat_Counter f_self_time; + PgStat_Counter total_time; /* times in microseconds */ + PgStat_Counter self_time; } PgStat_StatFuncEntry; typedef struct PgStat_StatReplSlotEntry @@ -525,37 +525,37 @@ extern void pgstat_report_analyze(Relation rel, #define pgstat_count_heap_scan(rel) \ do { \ if (pgstat_should_count_relation(rel)) \ - (rel)->pgstat_info->t_counts.t_numscans++; \ + (rel)->pgstat_info->t_counts.numscans++; \ } while (0) #define pgstat_count_heap_getnext(rel) \ do { \ if (pgstat_should_count_relation(rel)) \ - (rel)->pgstat_info->t_counts.t_tuples_returned++; \ + (rel)->pgstat_info->t_counts.tuples_returned++; \ } while (0) #define pgstat_count_heap_fetch(rel) \ do { \ if (pgstat_should_count_relation(rel)) \ - (rel)->pgstat_info->t_counts.t_tuples_fetched++; \ + (rel)->pgstat_info->t_counts.tuples_fetched++; \ } while (0) #define pgstat_count_index_scan(rel) \ do { \ if (pgstat_should_count_relation(rel)) \ - (rel)->pgstat_info->t_counts.t_numscans++; \ + (rel)->pgstat_info->t_counts.numscans++; \ } while (0) #define pgstat_count_index_tuples(rel, n) \ do { \ if (pgstat_should_count_relation(rel)) \ - (rel)->pgstat_info->t_counts.t_tuples_returned += (n); \ + (rel)->pgstat_info->t_counts.tuples_returned += (n); \ } while (0) #define pgstat_count_buffer_read(rel) \ do { \ if (pgstat_should_count_relation(rel)) \ - (rel)->pgstat_info->t_counts.t_blocks_fetched++; \ + (rel)->pgstat_info->t_counts.blocks_fetched++; \ } while (0) #define pgstat_count_buffer_hit(rel) \ do { \ if (pgstat_should_count_relation(rel)) \ - (rel)->pgstat_info->t_counts.t_blocks_hit++; \ + (rel)->pgstat_info->t_counts.blocks_hit++; \ } while (0) extern void pgstat_count_heap_insert(Relation rel, PgStat_Counter n); ^ permalink raw reply [nested|flat] 2+ messages in thread
end of thread, other threads:[~2023-01-05 13:48 UTC | newest] Thread overview: 2+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2020-09-17 15:26 [PATCH 2/8] Move IS [NOT] NULL handling from BRIN support functions Tomas Vondra <[email protected]> 2023-01-05 13:48 Generate pg_stat_get_xact*() functions with Macros Drouvot, Bertrand <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox