From a70b0cadc1142e92b2354a0ca3cd47aaeb0c148e Mon Sep 17 00:00:00 2001 From: Mark Dilger Date: Tue, 4 Feb 2020 12:25:05 -0800 Subject: [PATCH v2 2/3] Using a Bitmapset of tags rather than a string array. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit EventTriggerCacheItem no longer holds an array of palloc’d tag strings in sorted order, but rather just a Bitmapset over the CommandTags. This makes the code a little simpler and easier to read, in my opinion. In filter_event_trigger, rather than running bsearch through a sorted array of strings, it just runs bms_is_member. --- src/backend/commands/event_trigger.c | 12 +++++------- src/backend/utils/cache/evtcache.c | 27 +++++++++++++-------------- src/include/commands/event_trigger.h | 2 +- src/include/utils/evtcache.h | 3 +-- src/pl/plpgsql/src/pl_exec.c | 2 +- 5 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index 6cd9437367..96f3a06ff3 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -820,7 +820,7 @@ get_event_trigger_oid(const char *trigname, bool missing_ok) * tags matching. */ static bool -filter_event_trigger(const char **tag, EventTriggerCacheItem *item) +filter_event_trigger(CommandTag tag, EventTriggerCacheItem *item) { /* * Filter by session replication role, knowing that we never see disabled @@ -838,9 +838,7 @@ filter_event_trigger(const char **tag, EventTriggerCacheItem *item) } /* Filter by tags, if any were specified. */ - if (item->ntags != 0 && bsearch(tag, item->tag, - item->ntags, sizeof(char *), - pg_qsort_strcmp) == NULL) + if (!bms_is_empty(item->tagset) && !bms_is_member(tag, item->tagset)) return false; /* if we reach that point, we're not filtering out this item */ @@ -857,7 +855,7 @@ EventTriggerCommonSetup(Node *parsetree, EventTriggerEvent event, const char *eventstr, EventTriggerData *trigdata) { - const char *tag; + CommandTag tag; List *cachelist; ListCell *lc; List *runlist = NIL; @@ -902,7 +900,7 @@ EventTriggerCommonSetup(Node *parsetree, return NIL; /* Get the command tag. */ - tag = GetCommandTagName(CreateCommandTag(parsetree)); + tag = CreateCommandTag(parsetree); /* * Filter list of event triggers by command tag, and copy them into our @@ -915,7 +913,7 @@ EventTriggerCommonSetup(Node *parsetree, { EventTriggerCacheItem *item = lfirst(lc); - if (filter_event_trigger(&tag, item)) + if (filter_event_trigger(tag, item)) { /* We must plan to fire this trigger. */ runlist = lappend_oid(runlist, item->fnoid); diff --git a/src/backend/utils/cache/evtcache.c b/src/backend/utils/cache/evtcache.c index 1b63048a77..a960d7ca80 100644 --- a/src/backend/utils/cache/evtcache.c +++ b/src/backend/utils/cache/evtcache.c @@ -51,7 +51,7 @@ static EventTriggerCacheStateType EventTriggerCacheState = ETCS_NEEDS_REBUILD; static void BuildEventTriggerCache(void); static void InvalidateEventCacheCallback(Datum arg, int cacheid, uint32 hashvalue); -static int DecodeTextArrayToCString(Datum array, char ***cstringp); +static void DecodeTextArrayToBitmapset(Datum array, Bitmapset **bms); /* * Search the event cache by trigger event. @@ -180,10 +180,7 @@ BuildEventTriggerCache(void) evttags = heap_getattr(tup, Anum_pg_event_trigger_evttags, RelationGetDescr(rel), &evttags_isnull); if (!evttags_isnull) - { - item->ntags = DecodeTextArrayToCString(evttags, &item->tag); - qsort(item->tag, item->ntags, sizeof(char *), pg_qsort_strcmp); - } + DecodeTextArrayToBitmapset(evttags, &item->tagset); /* Add to cache entry. */ entry = hash_search(cache, &event, HASH_ENTER, &found); @@ -215,18 +212,18 @@ BuildEventTriggerCache(void) } /* - * Decode text[] to an array of C strings. + * Decode text[] to a Bitmapset of CommandTags. * * We could avoid a bit of overhead here if we were willing to duplicate some * of the logic from deconstruct_array, but it doesn't seem worth the code * complexity. */ -static int -DecodeTextArrayToCString(Datum array, char ***cstringp) +static void +DecodeTextArrayToBitmapset(Datum array, Bitmapset **tagset) { ArrayType *arr = DatumGetArrayTypeP(array); Datum *elems; - char **cstring; + Bitmapset *bms; int i; int nelems; @@ -234,13 +231,15 @@ DecodeTextArrayToCString(Datum array, char ***cstringp) elog(ERROR, "expected 1-D text array"); deconstruct_array(arr, TEXTOID, -1, false, 'i', &elems, NULL, &nelems); - cstring = palloc(nelems * sizeof(char *)); - for (i = 0; i < nelems; ++i) - cstring[i] = TextDatumGetCString(elems[i]); + for (bms = NULL, i = 0; i < nelems; ++i) + { + char *str = TextDatumGetCString(elems[i]); + bms = bms_add_member(bms, GetCommandTagEnum(str)); + pfree(str); + } pfree(elems); - *cstringp = cstring; - return nelems; + *tagset = bms; } /* diff --git a/src/include/commands/event_trigger.h b/src/include/commands/event_trigger.h index faa2958b89..5123c4b850 100644 --- a/src/include/commands/event_trigger.h +++ b/src/include/commands/event_trigger.h @@ -25,7 +25,7 @@ typedef struct EventTriggerData NodeTag type; const char *event; /* event name */ Node *parsetree; /* parse tree */ - const char *tag; /* command tag */ + CommandTag tag; } EventTriggerData; #define AT_REWRITE_ALTER_PERSISTENCE 0x01 diff --git a/src/include/utils/evtcache.h b/src/include/utils/evtcache.h index 6c3ff81ba3..bc8ce48061 100644 --- a/src/include/utils/evtcache.h +++ b/src/include/utils/evtcache.h @@ -28,8 +28,7 @@ typedef struct { Oid fnoid; /* function to be called */ char enabled; /* as SESSION_REPLICATION_ROLE_* */ - int ntags; /* number of command tags */ - char **tag; /* command tags in SORTED order */ + Bitmapset *tagset; /* command tags, or NULL if empty */ } EventTriggerCacheItem; extern List *EventCacheLookup(EventTriggerEvent event); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 8a0f31b4b8..8ac2b67417 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -1473,7 +1473,7 @@ plpgsql_fulfill_promise(PLpgSQL_execstate *estate, case PLPGSQL_PROMISE_TG_TAG: if (estate->evtrigdata == NULL) elog(ERROR, "event trigger promise is not in an event trigger function"); - assign_text_var(estate, var, estate->evtrigdata->tag); + assign_text_var(estate, var, GetCommandTagName(estate->evtrigdata->tag)); break; default: -- 2.21.1 (Apple Git-122.3)