diff --git a/src/backend/commands/discard.c b/src/backend/commands/discard.c index 57d3d7dd9b..e376573612 100644 --- a/src/backend/commands/discard.c +++ b/src/backend/commands/discard.c @@ -19,13 +19,14 @@ #include "commands/discard.h" #include "commands/prepare.h" #include "commands/sequence.h" +#include "commands/trigger.h" #include "utils/guc.h" #include "utils/portal.h" static void DiscardAll(bool isTopLevel); /* - * DISCARD { ALL | SEQUENCES | TEMP | PLANS } + * DISCARD { ALL | SEQUENCES | TEMP | PLANS | RIPLANS } */ void DiscardCommand(DiscardStmt *stmt, bool isTopLevel) @@ -48,6 +49,10 @@ DiscardCommand(DiscardStmt *stmt, bool isTopLevel) ResetTempTableNamespace(); break; + case DISCARD_RIPLANS: + ResetRIPlanCache(); + break; + default: elog(ERROR, "unrecognized DISCARD target: %d", stmt->target); } @@ -73,6 +78,7 @@ DiscardAll(bool isTopLevel) Async_UnlistenAll(); LockReleaseAll(USER_LOCKMETHOD, true); ResetPlanCache(); + ResetRIPlanCache(); ResetTempTableNamespace(); ResetSequenceCaches(); } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 652be0b96d..bede6c0b85 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -685,7 +685,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); RANGE READ REAL REASSIGN RECHECK RECURSIVE REF REFERENCES REFERENCING REFRESH REINDEX RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA - RESET RESTART RESTRICT RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK ROLLUP + RESET RESTART RESTRICT RETURNING RETURNS REVOKE RIGHT RIPLANS ROLE ROLLBACK ROLLUP ROUTINE ROUTINES ROW ROWS RULE SAVEPOINT SCHEMA SCHEMAS SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE SEQUENCES @@ -1830,7 +1830,7 @@ CheckPointStmt: /***************************************************************************** * - * DISCARD { ALL | TEMP | PLANS | SEQUENCES } + * DISCARD { ALL | TEMP | PLANS | SEQUENCES | RIPLANS } * *****************************************************************************/ @@ -1865,7 +1865,12 @@ DiscardStmt: n->target = DISCARD_SEQUENCES; $$ = (Node *) n; } - + | DISCARD RIPLANS + { + DiscardStmt *n = makeNode(DiscardStmt); + n->target = DISCARD_RIPLANS; + $$ = (Node *) n; + } ; @@ -15656,6 +15661,7 @@ type_func_name_keyword: | OUTER_P | OVERLAPS | RIGHT + | RIPLANS | SIMILAR | TABLESAMPLE | VERBOSE @@ -16053,6 +16059,7 @@ bare_label_keyword: | RETURNS | REVOKE | RIGHT + | RIPLANS | ROLE | ROLLBACK | ROLLUP diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 05bb698cf4..48e087e28b 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -2822,6 +2822,9 @@ CreateCommandTag(Node *parsetree) case DISCARD_SEQUENCES: tag = CMDTAG_DISCARD_SEQUENCES; break; + case DISCARD_RIPLANS: + tag = CMDTAG_DISCARD_RIPLANS; + break; default: tag = CMDTAG_UNKNOWN; } diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c index 6e3a41062f..daa1dac088 100644 --- a/src/backend/utils/adt/ri_triggers.c +++ b/src/backend/utils/adt/ri_triggers.c @@ -2646,7 +2646,6 @@ ri_HashPreparedPlan(RI_QueryKey *key, SPIPlanPtr plan) entry->plan = plan; } - /* * ri_KeysEqual - * @@ -2887,3 +2886,30 @@ RI_FKey_trigger_type(Oid tgfoid) return RI_TRIGGER_NONE; } + +/* + * ResetRIPlanCache - + * + * Delete all plans from our private SPI query plan hashtable. + */ +void +ResetRIPlanCache(void) +{ + HASH_SEQ_STATUS seq; + RI_QueryHashEntry *entry; + + /* nothing cached */ + if(!ri_query_cache) + return; + + /* walk over cache */ + hash_seq_init(&seq, ri_query_cache); + while((entry = hash_seq_search(&seq)) != NULL) + { + /* Relase the plancache entry */ + SPI_freeplan(entry->plan); + + /* Now we can remove the hash table entry */ + hash_search(ri_query_cache, &entry->key, HASH_REMOVE, NULL); + } +} diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index 9f0208ac49..ad05d2bc34 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -3097,7 +3097,7 @@ psql_completion(const char *text, int start, int end) /* DISCARD */ else if (Matches("DISCARD")) - COMPLETE_WITH("ALL", "PLANS", "SEQUENCES", "TEMP"); + COMPLETE_WITH("ALL", "PLANS", "SEQUENCES", "TEMP", "RIPLANS"); /* DO */ else if (Matches("DO")) diff --git a/src/include/commands/trigger.h b/src/include/commands/trigger.h index 9e557cfbce..76ec9bf57b 100644 --- a/src/include/commands/trigger.h +++ b/src/include/commands/trigger.h @@ -250,6 +250,7 @@ extern bool AfterTriggerPendingOnRel(Oid relid); /* * in utils/adt/ri_triggers.c */ +extern void ResetRIPlanCache(void); extern bool RI_FKey_pk_upd_check_required(Trigger *trigger, Relation pk_rel, TupleTableSlot *old_slot, TupleTableSlot *new_slot); extern bool RI_FKey_fk_upd_check_required(Trigger *trigger, Relation fk_rel, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 236832a2ca..616a40673d 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -3349,7 +3349,8 @@ typedef enum DiscardMode DISCARD_ALL, DISCARD_PLANS, DISCARD_SEQUENCES, - DISCARD_TEMP + DISCARD_TEMP, + DISCARD_RIPLANS } DiscardMode; typedef struct DiscardStmt diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h index 28083aaac9..1a6b5d0671 100644 --- a/src/include/parser/kwlist.h +++ b/src/include/parser/kwlist.h @@ -350,6 +350,7 @@ PG_KEYWORD("returning", RETURNING, RESERVED_KEYWORD, AS_LABEL) PG_KEYWORD("returns", RETURNS, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("revoke", REVOKE, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("right", RIGHT, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL) +PG_KEYWORD("riplans", RIPLANS, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL) PG_KEYWORD("role", ROLE, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("rollback", ROLLBACK, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("rollup", ROLLUP, UNRESERVED_KEYWORD, BARE_LABEL) diff --git a/src/include/tcop/cmdtaglist.h b/src/include/tcop/cmdtaglist.h index 9ba24d4ca9..391db5af7e 100644 --- a/src/include/tcop/cmdtaglist.h +++ b/src/include/tcop/cmdtaglist.h @@ -133,6 +133,7 @@ PG_CMDTAG(CMDTAG_DISCARD_ALL, "DISCARD ALL", false, false, false) PG_CMDTAG(CMDTAG_DISCARD_PLANS, "DISCARD PLANS", false, false, false) PG_CMDTAG(CMDTAG_DISCARD_SEQUENCES, "DISCARD SEQUENCES", false, false, false) PG_CMDTAG(CMDTAG_DISCARD_TEMP, "DISCARD TEMP", false, false, false) +PG_CMDTAG(CMDTAG_DISCARD_RIPLANS, "DISCARD RIPLANS", false, false, false) PG_CMDTAG(CMDTAG_DO, "DO", false, false, false) PG_CMDTAG(CMDTAG_DROP_ACCESS_METHOD, "DROP ACCESS METHOD", true, false, false) PG_CMDTAG(CMDTAG_DROP_AGGREGATE, "DROP AGGREGATE", true, false, false)