mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Switch various builtin functions to use pg_lsn instead of text.
The functions in slotfuncs.c don't exist in any released version, but the changes to xlogfuncs.c represent backward-incompatibilities. Per discussion, we're hoping that the queries using these functions are few enough and simple enough that this won't cause too much breakage for users. Michael Paquier, reviewed by Andres Freund and further modified by me.
This commit is contained in:
@ -30,11 +30,10 @@
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/numeric.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/pg_lsn.h"
|
||||
#include "utils/timestamp.h"
|
||||
#include "storage/fd.h"
|
||||
|
||||
static void validate_xlog_location(char *str);
|
||||
|
||||
|
||||
/*
|
||||
* pg_start_backup: set up for taking an on-line backup dump
|
||||
@ -52,7 +51,6 @@ pg_start_backup(PG_FUNCTION_ARGS)
|
||||
bool fast = PG_GETARG_BOOL(1);
|
||||
char *backupidstr;
|
||||
XLogRecPtr startpoint;
|
||||
char startxlogstr[MAXFNAMELEN];
|
||||
|
||||
backupidstr = text_to_cstring(backupid);
|
||||
|
||||
@ -63,9 +61,7 @@ pg_start_backup(PG_FUNCTION_ARGS)
|
||||
|
||||
startpoint = do_pg_start_backup(backupidstr, fast, NULL, NULL);
|
||||
|
||||
snprintf(startxlogstr, sizeof(startxlogstr), "%X/%X",
|
||||
(uint32) (startpoint >> 32), (uint32) startpoint);
|
||||
PG_RETURN_TEXT_P(cstring_to_text(startxlogstr));
|
||||
PG_RETURN_LSN(startpoint);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -85,7 +81,6 @@ Datum
|
||||
pg_stop_backup(PG_FUNCTION_ARGS)
|
||||
{
|
||||
XLogRecPtr stoppoint;
|
||||
char stopxlogstr[MAXFNAMELEN];
|
||||
|
||||
if (!superuser() && !has_rolreplication(GetUserId()))
|
||||
ereport(ERROR,
|
||||
@ -94,9 +89,7 @@ pg_stop_backup(PG_FUNCTION_ARGS)
|
||||
|
||||
stoppoint = do_pg_stop_backup(NULL, true, NULL);
|
||||
|
||||
snprintf(stopxlogstr, sizeof(stopxlogstr), "%X/%X",
|
||||
(uint32) (stoppoint >> 32), (uint32) stoppoint);
|
||||
PG_RETURN_TEXT_P(cstring_to_text(stopxlogstr));
|
||||
PG_RETURN_LSN(stoppoint);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -106,7 +99,6 @@ Datum
|
||||
pg_switch_xlog(PG_FUNCTION_ARGS)
|
||||
{
|
||||
XLogRecPtr switchpoint;
|
||||
char location[MAXFNAMELEN];
|
||||
|
||||
if (!superuser())
|
||||
ereport(ERROR,
|
||||
@ -124,9 +116,7 @@ pg_switch_xlog(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* As a convenience, return the WAL location of the switch record
|
||||
*/
|
||||
snprintf(location, sizeof(location), "%X/%X",
|
||||
(uint32) (switchpoint >> 32), (uint32) switchpoint);
|
||||
PG_RETURN_TEXT_P(cstring_to_text(location));
|
||||
PG_RETURN_LSN(switchpoint);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -138,7 +128,6 @@ pg_create_restore_point(PG_FUNCTION_ARGS)
|
||||
text *restore_name = PG_GETARG_TEXT_P(0);
|
||||
char *restore_name_str;
|
||||
XLogRecPtr restorepoint;
|
||||
char location[MAXFNAMELEN];
|
||||
|
||||
if (!superuser())
|
||||
ereport(ERROR,
|
||||
@ -169,9 +158,7 @@ pg_create_restore_point(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* As a convenience, return the WAL location of the restore point record
|
||||
*/
|
||||
snprintf(location, sizeof(location), "%X/%X",
|
||||
(uint32) (restorepoint >> 32), (uint32) restorepoint);
|
||||
PG_RETURN_TEXT_P(cstring_to_text(location));
|
||||
PG_RETURN_LSN(restorepoint);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -185,7 +172,6 @@ Datum
|
||||
pg_current_xlog_location(PG_FUNCTION_ARGS)
|
||||
{
|
||||
XLogRecPtr current_recptr;
|
||||
char location[MAXFNAMELEN];
|
||||
|
||||
if (RecoveryInProgress())
|
||||
ereport(ERROR,
|
||||
@ -195,9 +181,7 @@ pg_current_xlog_location(PG_FUNCTION_ARGS)
|
||||
|
||||
current_recptr = GetXLogWriteRecPtr();
|
||||
|
||||
snprintf(location, sizeof(location), "%X/%X",
|
||||
(uint32) (current_recptr >> 32), (uint32) current_recptr);
|
||||
PG_RETURN_TEXT_P(cstring_to_text(location));
|
||||
PG_RETURN_LSN(current_recptr);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -209,7 +193,6 @@ Datum
|
||||
pg_current_xlog_insert_location(PG_FUNCTION_ARGS)
|
||||
{
|
||||
XLogRecPtr current_recptr;
|
||||
char location[MAXFNAMELEN];
|
||||
|
||||
if (RecoveryInProgress())
|
||||
ereport(ERROR,
|
||||
@ -219,9 +202,7 @@ pg_current_xlog_insert_location(PG_FUNCTION_ARGS)
|
||||
|
||||
current_recptr = GetXLogInsertRecPtr();
|
||||
|
||||
snprintf(location, sizeof(location), "%X/%X",
|
||||
(uint32) (current_recptr >> 32), (uint32) current_recptr);
|
||||
PG_RETURN_TEXT_P(cstring_to_text(location));
|
||||
PG_RETURN_LSN(current_recptr);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -234,16 +215,13 @@ Datum
|
||||
pg_last_xlog_receive_location(PG_FUNCTION_ARGS)
|
||||
{
|
||||
XLogRecPtr recptr;
|
||||
char location[MAXFNAMELEN];
|
||||
|
||||
recptr = GetWalRcvWriteRecPtr(NULL, NULL);
|
||||
|
||||
if (recptr == 0)
|
||||
PG_RETURN_NULL();
|
||||
|
||||
snprintf(location, sizeof(location), "%X/%X",
|
||||
(uint32) (recptr >> 32), (uint32) recptr);
|
||||
PG_RETURN_TEXT_P(cstring_to_text(location));
|
||||
PG_RETURN_LSN(recptr);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -256,16 +234,13 @@ Datum
|
||||
pg_last_xlog_replay_location(PG_FUNCTION_ARGS)
|
||||
{
|
||||
XLogRecPtr recptr;
|
||||
char location[MAXFNAMELEN];
|
||||
|
||||
recptr = GetXLogReplayRecPtr(NULL);
|
||||
|
||||
if (recptr == 0)
|
||||
PG_RETURN_NULL();
|
||||
|
||||
snprintf(location, sizeof(location), "%X/%X",
|
||||
(uint32) (recptr >> 32), (uint32) recptr);
|
||||
PG_RETURN_TEXT_P(cstring_to_text(location));
|
||||
PG_RETURN_LSN(recptr);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -279,13 +254,9 @@ pg_last_xlog_replay_location(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
pg_xlogfile_name_offset(PG_FUNCTION_ARGS)
|
||||
{
|
||||
text *location = PG_GETARG_TEXT_P(0);
|
||||
char *locationstr;
|
||||
uint32 hi,
|
||||
lo;
|
||||
XLogSegNo xlogsegno;
|
||||
uint32 xrecoff;
|
||||
XLogRecPtr locationpoint;
|
||||
XLogRecPtr locationpoint = PG_GETARG_LSN(0);
|
||||
char xlogfilename[MAXFNAMELEN];
|
||||
Datum values[2];
|
||||
bool isnull[2];
|
||||
@ -299,20 +270,6 @@ pg_xlogfile_name_offset(PG_FUNCTION_ARGS)
|
||||
errmsg("recovery is in progress"),
|
||||
errhint("pg_xlogfile_name_offset() cannot be executed during recovery.")));
|
||||
|
||||
/*
|
||||
* Read input and parse
|
||||
*/
|
||||
locationstr = text_to_cstring(location);
|
||||
|
||||
validate_xlog_location(locationstr);
|
||||
|
||||
if (sscanf(locationstr, "%X/%X", &hi, &lo) != 2)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("could not parse transaction log location \"%s\"",
|
||||
locationstr)));
|
||||
locationpoint = ((uint64) hi) << 32 | lo;
|
||||
|
||||
/*
|
||||
* Construct a tuple descriptor for the result row. This must match this
|
||||
* function's pg_proc entry!
|
||||
@ -359,12 +316,8 @@ pg_xlogfile_name_offset(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
pg_xlogfile_name(PG_FUNCTION_ARGS)
|
||||
{
|
||||
text *location = PG_GETARG_TEXT_P(0);
|
||||
char *locationstr;
|
||||
uint32 hi,
|
||||
lo;
|
||||
XLogSegNo xlogsegno;
|
||||
XLogRecPtr locationpoint;
|
||||
XLogRecPtr locationpoint = PG_GETARG_LSN(0);
|
||||
char xlogfilename[MAXFNAMELEN];
|
||||
|
||||
if (RecoveryInProgress())
|
||||
@ -373,17 +326,6 @@ pg_xlogfile_name(PG_FUNCTION_ARGS)
|
||||
errmsg("recovery is in progress"),
|
||||
errhint("pg_xlogfile_name() cannot be executed during recovery.")));
|
||||
|
||||
locationstr = text_to_cstring(location);
|
||||
|
||||
validate_xlog_location(locationstr);
|
||||
|
||||
if (sscanf(locationstr, "%X/%X", &hi, &lo) != 2)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("could not parse transaction log location \"%s\"",
|
||||
locationstr)));
|
||||
locationpoint = ((uint64) hi) << 32 | lo;
|
||||
|
||||
XLByteToPrevSeg(locationpoint, xlogsegno);
|
||||
XLogFileName(xlogfilename, ThisTimeLineID, xlogsegno);
|
||||
|
||||
@ -481,82 +423,17 @@ pg_is_in_recovery(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_BOOL(RecoveryInProgress());
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate the text form of a transaction log location.
|
||||
* (Just using sscanf() input allows incorrect values such as
|
||||
* negatives, so we have to be a bit more careful about that).
|
||||
*/
|
||||
static void
|
||||
validate_xlog_location(char *str)
|
||||
{
|
||||
#define MAXLSNCOMPONENT 8
|
||||
|
||||
int len1,
|
||||
len2;
|
||||
|
||||
len1 = strspn(str, "0123456789abcdefABCDEF");
|
||||
if (len1 < 1 || len1 > MAXLSNCOMPONENT || str[len1] != '/')
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for transaction log location: \"%s\"", str)));
|
||||
|
||||
len2 = strspn(str + len1 + 1, "0123456789abcdefABCDEF");
|
||||
if (len2 < 1 || len2 > MAXLSNCOMPONENT || str[len1 + 1 + len2] != '\0')
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||
errmsg("invalid input syntax for transaction log location: \"%s\"", str)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the difference in bytes between two WAL locations.
|
||||
*/
|
||||
Datum
|
||||
pg_xlog_location_diff(PG_FUNCTION_ARGS)
|
||||
{
|
||||
text *location1 = PG_GETARG_TEXT_P(0);
|
||||
text *location2 = PG_GETARG_TEXT_P(1);
|
||||
char *str1,
|
||||
*str2;
|
||||
XLogRecPtr loc1,
|
||||
loc2;
|
||||
Numeric result;
|
||||
uint64 bytes1,
|
||||
bytes2;
|
||||
uint32 hi,
|
||||
lo;
|
||||
Datum result;
|
||||
|
||||
/*
|
||||
* Read and parse input
|
||||
*/
|
||||
str1 = text_to_cstring(location1);
|
||||
str2 = text_to_cstring(location2);
|
||||
|
||||
validate_xlog_location(str1);
|
||||
validate_xlog_location(str2);
|
||||
|
||||
if (sscanf(str1, "%X/%X", &hi, &lo) != 2)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("could not parse transaction log location \"%s\"", str1)));
|
||||
loc1 = ((uint64) hi) << 32 | lo;
|
||||
|
||||
if (sscanf(str2, "%X/%X", &hi, &lo) != 2)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("could not parse transaction log location \"%s\"", str2)));
|
||||
loc2 = ((uint64) hi) << 32 | lo;
|
||||
|
||||
bytes1 = (uint64) loc1;
|
||||
bytes2 = (uint64) loc2;
|
||||
|
||||
/*
|
||||
* result = bytes1 - bytes2.
|
||||
*
|
||||
* XXX: this won't handle values higher than 2^63 correctly.
|
||||
*/
|
||||
result = DatumGetNumeric(DirectFunctionCall2(numeric_sub,
|
||||
DirectFunctionCall1(int8_numeric, Int64GetDatum((int64) bytes1)),
|
||||
DirectFunctionCall1(int8_numeric, Int64GetDatum((int64) bytes2))));
|
||||
result = DirectFunctionCall2(pg_lsn_mi,
|
||||
PG_GETARG_DATUM(0),
|
||||
PG_GETARG_DATUM(1));
|
||||
|
||||
PG_RETURN_NUMERIC(result);
|
||||
}
|
||||
|
Reference in New Issue
Block a user