1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-18 17:42:25 +03:00

Add option list to CHECKPOINT command.

This commit adds the boilerplate code for supporting a list of
options in CHECKPOINT commands.  No actual options are supported
yet, but follow-up commits will add support for MODE and
FLUSH_UNLOGGED.  While at it, this commit refactors the code for
executing CHECKPOINT commands to its own function since it's about
to become significantly larger.

Author: Christoph Berg <myon@debian.org>
Reviewed-by: Fujii Masao <masao.fujii@oss.nttdata.com>
Discussion: https://postgr.es/m/aDnaKTEf-0dLiEfz%40msg.df7cb.de
This commit is contained in:
Nathan Bossart
2025-07-11 11:51:25 -05:00
parent bb938e2c3c
commit a4f126516e
9 changed files with 64 additions and 12 deletions

View File

@ -21,7 +21,9 @@ PostgreSQL documentation
<refsynopsisdiv> <refsynopsisdiv>
<synopsis> <synopsis>
CHECKPOINT CHECKPOINT [ ( option [, ...] ) ]
<phrase>where <replaceable class="parameter">option</replaceable> can be one of:</phrase>
</synopsis> </synopsis>
</refsynopsisdiv> </refsynopsisdiv>
@ -58,6 +60,13 @@ CHECKPOINT
</para> </para>
</refsect1> </refsect1>
<refsect1>
<title>Parameters</title>
<para>
</para>
</refsect1>
<refsect1> <refsect1>
<title>Compatibility</title> <title>Compatibility</title>

View File

@ -2034,6 +2034,13 @@ CheckPointStmt:
$$ = (Node *) n; $$ = (Node *) n;
} }
| CHECKPOINT '(' utility_option_list ')'
{
CheckPointStmt *n = makeNode(CheckPointStmt);
$$ = (Node *) n;
n->options = $3;
}
; ;

View File

@ -42,6 +42,7 @@
#include "access/xlog.h" #include "access/xlog.h"
#include "access/xlog_internal.h" #include "access/xlog_internal.h"
#include "access/xlogrecovery.h" #include "access/xlogrecovery.h"
#include "catalog/pg_authid.h"
#include "libpq/pqsignal.h" #include "libpq/pqsignal.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "pgstat.h" #include "pgstat.h"
@ -61,6 +62,7 @@
#include "storage/shmem.h" #include "storage/shmem.h"
#include "storage/smgr.h" #include "storage/smgr.h"
#include "storage/spin.h" #include "storage/spin.h"
#include "utils/acl.h"
#include "utils/guc.h" #include "utils/guc.h"
#include "utils/memutils.h" #include "utils/memutils.h"
#include "utils/resowner.h" #include "utils/resowner.h"
@ -976,6 +978,35 @@ CheckpointerShmemInit(void)
} }
} }
/*
* ExecCheckpoint
* Primary entry point for manual CHECKPOINT commands
*
* This is mainly a wrapper for RequestCheckpoint().
*/
void
ExecCheckpoint(ParseState *pstate, CheckPointStmt *stmt)
{
foreach_ptr(DefElem, opt, stmt->options)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("unrecognized CHECKPOINT option \"%s\"", opt->defname),
parser_errposition(pstate, opt->location)));
if (!has_privs_of_role(GetUserId(), ROLE_PG_CHECKPOINT))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
/* translator: %s is name of an SQL command (e.g., CHECKPOINT) */
errmsg("permission denied to execute %s command",
"CHECKPOINT"),
errdetail("Only roles with privileges of the \"%s\" role may execute this command.",
"pg_checkpoint")));
RequestCheckpoint(CHECKPOINT_WAIT |
CHECKPOINT_FAST |
(RecoveryInProgress() ? 0 : CHECKPOINT_FORCE));
}
/* /*
* RequestCheckpoint * RequestCheckpoint
* Called in backend processes to request a checkpoint * Called in backend processes to request a checkpoint

View File

@ -943,17 +943,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
break; break;
case T_CheckPointStmt: case T_CheckPointStmt:
if (!has_privs_of_role(GetUserId(), ROLE_PG_CHECKPOINT)) ExecCheckpoint(pstate, (CheckPointStmt *) parsetree);
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
/* translator: %s is name of a SQL command, eg CHECKPOINT */
errmsg("permission denied to execute %s command",
"CHECKPOINT"),
errdetail("Only roles with privileges of the \"%s\" role may execute this command.",
"pg_checkpoint")));
RequestCheckpoint(CHECKPOINT_FAST | CHECKPOINT_WAIT |
(RecoveryInProgress() ? 0 : CHECKPOINT_FORCE));
break; break;
/* /*

View File

@ -3153,6 +3153,9 @@ match_previous_words(int pattern_id,
COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_procedures); COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_procedures);
else if (Matches("CALL", MatchAny)) else if (Matches("CALL", MatchAny))
COMPLETE_WITH("("); COMPLETE_WITH("(");
/* CHECKPOINT */
else if (Matches("CHECKPOINT"))
COMPLETE_WITH("(");
/* CLOSE */ /* CLOSE */
else if (Matches("CLOSE")) else if (Matches("CLOSE"))
COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_cursors, COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_cursors,

View File

@ -4047,6 +4047,7 @@ typedef struct RefreshMatViewStmt
typedef struct CheckPointStmt typedef struct CheckPointStmt
{ {
NodeTag type; NodeTag type;
List *options; /* list of DefElem nodes */
} CheckPointStmt; } CheckPointStmt;
/* ---------------------- /* ----------------------

View File

@ -15,6 +15,7 @@
#ifndef _BGWRITER_H #ifndef _BGWRITER_H
#define _BGWRITER_H #define _BGWRITER_H
#include "parser/parse_node.h"
#include "storage/block.h" #include "storage/block.h"
#include "storage/relfilelocator.h" #include "storage/relfilelocator.h"
#include "storage/smgr.h" #include "storage/smgr.h"
@ -30,6 +31,7 @@ extern PGDLLIMPORT double CheckPointCompletionTarget;
pg_noreturn extern void BackgroundWriterMain(const void *startup_data, size_t startup_data_len); pg_noreturn extern void BackgroundWriterMain(const void *startup_data, size_t startup_data_len);
pg_noreturn extern void CheckpointerMain(const void *startup_data, size_t startup_data_len); pg_noreturn extern void CheckpointerMain(const void *startup_data, size_t startup_data_len);
extern void ExecCheckpoint(ParseState *pstate, CheckPointStmt *stmt);
extern void RequestCheckpoint(int flags); extern void RequestCheckpoint(int flags);
extern void CheckpointWriteDelay(int flags, double progress); extern void CheckpointWriteDelay(int flags, double progress);

View File

@ -926,6 +926,12 @@ DROP TABLE test_stats_temp;
-- Checkpoint twice: The checkpointer reports stats after reporting completion -- Checkpoint twice: The checkpointer reports stats after reporting completion
-- of the checkpoint. But after a second checkpoint we'll see at least the -- of the checkpoint. But after a second checkpoint we'll see at least the
-- results of the first. -- results of the first.
--
-- While at it, test checkpoint options.
CHECKPOINT (WRONG);
ERROR: unrecognized CHECKPOINT option "wrong"
LINE 1: CHECKPOINT (WRONG);
^
CHECKPOINT; CHECKPOINT;
CHECKPOINT; CHECKPOINT;
SELECT num_requested > :rqst_ckpts_before FROM pg_stat_checkpointer; SELECT num_requested > :rqst_ckpts_before FROM pg_stat_checkpointer;

View File

@ -439,6 +439,9 @@ DROP TABLE test_stats_temp;
-- Checkpoint twice: The checkpointer reports stats after reporting completion -- Checkpoint twice: The checkpointer reports stats after reporting completion
-- of the checkpoint. But after a second checkpoint we'll see at least the -- of the checkpoint. But after a second checkpoint we'll see at least the
-- results of the first. -- results of the first.
--
-- While at it, test checkpoint options.
CHECKPOINT (WRONG);
CHECKPOINT; CHECKPOINT;
CHECKPOINT; CHECKPOINT;