63 const char *query_string,
72#define SH_PREFIX pgsa_stash_name_table
73#define SH_ELEMENT_TYPE pgsa_stash_name
74#define SH_KEY_TYPE uint64
75#define SH_KEY pgsa_stash_id
76#define SH_HASH_KEY(tb, key) hash_bytes((const unsigned char *) &(key), sizeof(uint64))
77#define SH_EQUAL(tb, a, b) (a == b)
78#define SH_SCOPE extern
96 "Save and restore advice stash contents across restarts.",
109 "Interval between advice stash saves, in seconds.",
122 "Name of the advice stash to be used in this session.",
151 const char *query_string,
int cursorOptions,
192 key.pgsa_stash_id = stash_id;
193 key.queryId =
parse->queryId;
198 advice_string = NULL;
205 if (advice_string != NULL)
206 elog(
DEBUG2,
"supplying automatic advice for stash \"%s\", query ID %" PRId64
": %s",
209 return advice_string;
329 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
330 errmsg(
"stash modifications are not allowed because \"%s\" has not been loaded yet",
343 if (stash_name[0] ==
'\0')
345 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
346 errmsg(
"advice stash name may not be zero length"));
351 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
352 errmsg(
"advice stash names may not be longer than %d bytes",
361 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
362 errmsg(
"advice stash name must not contain non-ASCII characters"));
371 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
372 errmsg(
"advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores"));
382 char *stash_name = *
newval;
412 GUC_check_errdetail(
"advice stash name must begin with a letter or underscore and contain only letters, digits, and underscores");
434 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
435 errmsg(
"advice stash \"%s\" already exists", stash_name));
459 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
460 errmsg(
"advice stash \"%s\" does not exist", stash_name));
467 key.pgsa_stash_id = stash_id;
468 key.queryId = queryId;
503 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
504 errmsg(
"advice stash \"%s\" does not exist", stash_name));
607 if (*
str >=
'0' && *
str <=
'9')
614 if ((
c <
'0' ||
c >
'9') && (
c <
'a' ||
c >
'z') &&
615 (
c <
'A' ||
c >
'Z') &&
c !=
'_')
677 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
678 errmsg(
"advice stash \"%s\" does not exist", stash_name));
686 key.pgsa_stash_id = stash_id;
687 key.queryId = queryId;
699 errcode(ERRCODE_OUT_OF_MEMORY),
701 errdetail(
"could not insert advice string into shared hash table"));
738 strcpy(worker.
bgw_name,
"pg_stash_advice worker");
739 strcpy(worker.
bgw_type,
"pg_stash_advice worker");
764 (
errcode(ERRCODE_INSUFFICIENT_RESOURCES),
765 errmsg(
"could not register background process"),
766 errhint(
"You may need to increase \"max_worker_processes\".")));
770 (
errcode(ERRCODE_INSUFFICIENT_RESOURCES),
771 errmsg(
"could not start background process"),
772 errhint(
"More details may be available in the server log.")));
static bool pg_atomic_test_set_flag(volatile pg_atomic_flag *ptr)
static bool pg_atomic_unlocked_test_flag(volatile pg_atomic_flag *ptr)
static uint64 pg_atomic_add_fetch_u64(volatile pg_atomic_uint64 *ptr, int64 add_)
static void pg_atomic_init_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
static void pg_atomic_init_flag(volatile pg_atomic_flag *ptr)
void RegisterBackgroundWorker(BackgroundWorker *worker)
BgwHandleStatus WaitForBackgroundWorkerStartup(BackgroundWorkerHandle *handle, pid_t *pidp)
bool RegisterDynamicBackgroundWorker(BackgroundWorker *worker, BackgroundWorkerHandle **handle)
@ BgWorkerStart_ConsistentState
#define BGWORKER_SHMEM_ACCESS
#define BGW_DEFAULT_RESTART_INTERVAL
#define Assert(condition)
void * load_external_function(const char *filename, const char *funcname, bool signalNotFound, void **filehandle)
dsa_area * dsa_attach(dsa_handle handle)
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
void dsa_pin_mapping(dsa_area *area)
dsa_handle dsa_get_handle(dsa_area *area)
void dsa_free(dsa_area *area, dsa_pointer dp)
void dsa_pin(dsa_area *area)
#define dsa_create(tranche_id)
#define dsa_allocate(area, size)
#define InvalidDsaPointer
#define DSA_HANDLE_INVALID
#define DsaPointerIsValid(x)
void dshash_memcpy(void *dest, const void *src, size_t size, void *arg)
void dshash_delete_entry(dshash_table *hash_table, void *entry)
void dshash_strcpy(void *dest, const void *src, size_t size, void *arg)
void dshash_release_lock(dshash_table *hash_table, void *entry)
void dshash_seq_init(dshash_seq_status *status, dshash_table *hash_table, bool exclusive)
void * dshash_find(dshash_table *hash_table, const void *key, bool exclusive)
dshash_hash dshash_strhash(const void *v, size_t size, void *arg)
dshash_table_handle dshash_get_hash_table_handle(dshash_table *hash_table)
dshash_table * dshash_attach(dsa_area *area, const dshash_parameters *params, dshash_table_handle handle, void *arg)
void dshash_seq_term(dshash_seq_status *status)
int dshash_strcmp(const void *a, const void *b, size_t size, void *arg)
dshash_hash dshash_memhash(const void *v, size_t size, void *arg)
void * dshash_seq_next(dshash_seq_status *status)
dshash_table * dshash_create(dsa_area *area, const dshash_parameters *params, void *arg)
int dshash_memcmp(const void *a, const void *b, size_t size, void *arg)
void * dshash_find_or_insert_extended(dshash_table *hash_table, const void *key, bool *found, int flags)
void dshash_delete_current(dshash_seq_status *status)
#define DSHASH_HANDLE_INVALID
dsa_pointer dshash_table_handle
#define DSHASH_INSERT_NO_OOM
#define dshash_find_or_insert(hash_table, key, found)
void * GetNamedDSMSegment(const char *name, size_t size, void(*init_callback)(void *ptr, void *arg), bool *found, void *arg)
int errcode(int sqlerrcode)
int errhint(const char *fmt,...) pg_attribute_printf(1
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define ereport(elevel,...)
void GUC_check_errcode(int sqlerrcode)
void DefineCustomStringVariable(const char *name, const char *short_desc, const char *long_desc, char **valueAddr, const char *bootValue, GucContext context, int flags, GucStringCheckHook check_hook, GucStringAssignHook assign_hook, GucShowHook show_hook)
void DefineCustomBoolVariable(const char *name, const char *short_desc, const char *long_desc, bool *valueAddr, bool bootValue, GucContext context, int flags, GucBoolCheckHook check_hook, GucBoolAssignHook assign_hook, GucShowHook show_hook)
void MarkGUCPrefixReserved(const char *className)
void DefineCustomIntVariable(const char *name, const char *short_desc, const char *long_desc, int *valueAddr, int bootValue, int minValue, int maxValue, GucContext context, int flags, GucIntCheckHook check_hook, GucIntAssignHook assign_hook, GucShowHook show_hook)
#define GUC_check_errdetail
bool LWLockHeldByMe(LWLock *lock)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
int LWLockNewTrancheId(const char *name)
bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode)
void LWLockRelease(LWLock *lock)
void LWLockInitialize(LWLock *lock, int tranche_id)
char * pstrdup(const char *in)
MemoryContext TopMemoryContext
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
bool process_shared_preload_libraries_in_progress
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
char *(* pg_plan_advice_advisor_hook)(PlannerGlobal *glob, Query *parse, const char *query_string, int cursorOptions, ExplainState *es)
static rewind_source * source
bool pg_stash_advice_persist
static char * pgsa_advisor(PlannerGlobal *glob, Query *parse, const char *query_string, int cursorOptions, ExplainState *es)
dshash_table * pgsa_entry_dshash
dshash_table * pgsa_stash_dshash
static MemoryContext pg_stash_advice_mcxt
void pgsa_create_stash(char *stash_name)
void pgsa_drop_stash(char *stash_name)
void pgsa_set_advice_string(char *stash_name, int64 queryId, char *advice_string)
void pgsa_start_worker(void)
static bool pgsa_is_identifier(char *str)
void pgsa_reset_all_stashes(void)
uint64 pgsa_lookup_stash_id(char *stash_name)
static dshash_parameters pgsa_stash_dshash_parameters
static char * pg_stash_advice_stash_name
static bool pgsa_check_stash_name_guc(char **newval, void **extra, GucSource source)
void pgsa_check_stash_name(char *stash_name)
pgsa_shared_state * pgsa_state
static dshash_parameters pgsa_entry_dshash_parameters
static void pgsa_init_shared_state(void *ptr, void *arg)
int pg_stash_advice_persist_interval
void pgsa_clear_advice_string(char *stash_name, int64 queryId)
void pgsa_check_lockout(void)
bool pg_is_ascii(const char *str)
char bgw_function_name[BGW_MAXLEN]
char bgw_name[BGW_MAXLEN]
char bgw_type[BGW_MAXLEN]
BgWorkerStartTime bgw_start_time
char bgw_library_name[MAXPGPATH]
dsa_pointer advice_string
dshash_table_handle entry_hash
dshash_table_handle stash_hash
pg_atomic_uint64 change_count
pg_atomic_flag stashes_ready