1
0
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:
Robert Haas
2014-02-19 11:13:44 -05:00
parent 694e3d139a
commit 6f289c2b7d
7 changed files with 45 additions and 172 deletions

View File

@ -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);
}