Files
Robert HaasandLukas Fittl 48ed0549ca pg_stash_advice: Allow stashed advice to be persisted to disk.
If pg_stash_advice.persist = true, stashed advice will be written to
pg_stash_advice.tsv in the data directory, periodically and at
shutdown. On restart, stash modifications are locked out until this
file has been reloaded, but queries will not be, so there may be a
short window after startup during which previously-stashed advice is
not automatically applied.

Author: Robert Haas <[email protected]>
Co-authored-by: Lukas Fittl <[email protected]>
Discussion: https://postgr.es/m/CA+Tgmob87qsWa-VugofU6epuV0H5XjWZGMbQas4Q-ADKmvSyBg@mail.gmail.com
2026-04-07 10:11:36 -04:00

112 lines
2.9 KiB
C

/*-------------------------------------------------------------------------
*
* pg_stash_advice.h
* main header for pg_stash_advice contrib module
*
* This module allows plan advice strings (as used and generated by
* pg_plan_advice) to be "stashed" in dynamic shared memory and, from
* there, automatically be applied to queries as they are planned.
* You can create any number of advice stashes, each of which is
* identified by a human-readable, ASCII identifier, and each of them is
* essentially a query ID -> advice_string mapping.
*
* Copyright (c) 2016-2026, PostgreSQL Global Development Group
*
* contrib/pg_stash_advice/pg_stash_advice.h
*
*-------------------------------------------------------------------------
*/
#ifndef PG_STASH_ADVICE_H
#define PG_STASH_ADVICE_H
#include "lib/dshash.h"
#include "storage/lwlock.h"
#define PGSA_DUMP_FILE "pg_stash_advice.tsv"
/*
* The key that we use to find a particular stash entry.
*/
typedef struct pgsa_entry_key
{
uint64 pgsa_stash_id;
int64 queryId;
} pgsa_entry_key;
/*
* A single stash entry.
*/
typedef struct pgsa_entry
{
pgsa_entry_key key;
dsa_pointer advice_string;
} pgsa_entry;
/*
* The stash itself is just a mapping from a name to a stash ID.
*/
typedef struct pgsa_stash
{
char name[NAMEDATALEN];
uint64 pgsa_stash_id;
} pgsa_stash;
/*
* Top-level shared state object for pg_stash_advice.
*/
typedef struct pgsa_shared_state
{
LWLock lock;
int dsa_tranche;
int stash_tranche;
int entry_tranche;
uint64 next_stash_id;
dsa_handle area;
dshash_table_handle stash_hash;
dshash_table_handle entry_hash;
pid_t bgworker_pid;
pg_atomic_flag stashes_ready;
pg_atomic_uint64 change_count;
} pgsa_shared_state;
/* For stash ID -> stash name hash table */
typedef struct pgsa_stash_name
{
uint32 status;
uint64 pgsa_stash_id;
char *name;
} pgsa_stash_name;
/* Declare stash ID -> stash name hash table */
#define SH_PREFIX pgsa_stash_name_table
#define SH_ELEMENT_TYPE pgsa_stash_name
#define SH_KEY_TYPE uint64
#define SH_SCOPE extern
#define SH_DECLARE
#include "lib/simplehash.h"
/* Shared memory pointers */
extern pgsa_shared_state *pgsa_state;
extern dsa_area *pgsa_dsa_area;
extern dshash_table *pgsa_stash_dshash;
extern dshash_table *pgsa_entry_dshash;
/* GUC variables */
extern bool pg_stash_advice_persist;
extern int pg_stash_advice_persist_interval;
/* Function prototypes */
extern void pgsa_attach(void);
extern void pgsa_check_lockout(void);
extern void pgsa_check_stash_name(char *stash_name);
extern void pgsa_clear_advice_string(char *stash_name, int64 queryId);
extern void pgsa_create_stash(char *stash_name);
extern void pgsa_drop_stash(char *stash_name);
extern uint64 pgsa_lookup_stash_id(char *stash_name);
extern void pgsa_reset_all_stashes(void);
extern void pgsa_set_advice_string(char *stash_name, int64 queryId,
char *advice_string);
extern void pgsa_start_worker(void);
#endif