Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit21f428e

Browse files
committed
Don't call data type input functions in GUC check hooks
Instead of calling pg_lsn_in() in check_recovery_target_lsn andtimestamptz_in() in check_recovery_target_time, reorganize therespective code so that we don't raise any errors in the check hooks.The previous code tried to use PG_TRY/PG_CATCH to handle errors in away that is not safe, so now the code contains no ereport() calls andcan operate safely within the GUC error handling system.Moreover, since the interpretation of the recovery_target_time stringmay depend on the time zone, we cannot do the final processing of thatstring until all the GUC processing is done. Instead,check_recovery_target_time() now does some parsing for syntaxchecking, but the actual conversion to a timestamptz value is donelater in the recovery code that uses it.Reported-by: Andres Freund <andres@anarazel.de>Reviewed-by: Michael Paquier <michael@paquier.xyz>Discussion:https://www.postgresql.org/message-id/flat/20190611061115.njjwkagvxp4qujhp%40alap3.anarazel.de
1 parent666cbae commit21f428e

File tree

5 files changed

+85
-74
lines changed

5 files changed

+85
-74
lines changed

‎src/backend/access/transam/xlog.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,8 @@ RecoveryTargetType recoveryTarget = RECOVERY_TARGET_UNSET;
272272
boolrecoveryTargetInclusive= true;
273273
intrecoveryTargetAction=RECOVERY_TARGET_ACTION_PAUSE;
274274
TransactionIdrecoveryTargetXid;
275-
TimestampTzrecoveryTargetTime;
275+
char*recovery_target_time_string;
276+
staticTimestampTzrecoveryTargetTime;
276277
constchar*recoveryTargetName;
277278
XLogRecPtrrecoveryTargetLSN;
278279
intrecovery_min_apply_delay=0;
@@ -5409,6 +5410,18 @@ validateRecoveryParameters(void)
54095410
!EnableHotStandby)
54105411
recoveryTargetAction=RECOVERY_TARGET_ACTION_SHUTDOWN;
54115412

5413+
/*
5414+
* Final parsing of recovery_target_time string; see also
5415+
* check_recovery_target_time().
5416+
*/
5417+
if (recoveryTarget==RECOVERY_TARGET_TIME)
5418+
{
5419+
recoveryTargetTime=DatumGetTimestampTz(DirectFunctionCall3(timestamptz_in,
5420+
CStringGetDatum(recovery_target_time_string),
5421+
ObjectIdGetDatum(InvalidOid),
5422+
Int32GetDatum(-1)));
5423+
}
5424+
54125425
/*
54135426
* If user specified recovery_target_timeline, validate it or compute the
54145427
* "latest" value. We can't do this until after we've gotten the restore

‎src/backend/utils/adt/pg_lsn.c

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,9 @@
2525
* Formatting and conversion routines.
2626
*---------------------------------------------------------*/
2727

28-
Datum
29-
pg_lsn_in(PG_FUNCTION_ARGS)
28+
XLogRecPtr
29+
pg_lsn_in_internal(constchar*str,bool*have_error)
3030
{
31-
char*str=PG_GETARG_CSTRING(0);
3231
intlen1,
3332
len2;
3433
uint32id,
@@ -38,16 +37,16 @@ pg_lsn_in(PG_FUNCTION_ARGS)
3837
/* Sanity check input format. */
3938
len1=strspn(str,"0123456789abcdefABCDEF");
4039
if (len1<1||len1>MAXPG_LSNCOMPONENT||str[len1]!='/')
41-
ereport(ERROR,
42-
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
43-
errmsg("invalid input syntax for type %s: \"%s\"",
44-
"pg_lsn",str)));
40+
{
41+
*have_error= true;
42+
returnInvalidXLogRecPtr;
43+
}
4544
len2=strspn(str+len1+1,"0123456789abcdefABCDEF");
4645
if (len2<1||len2>MAXPG_LSNCOMPONENT||str[len1+1+len2]!='\0')
47-
ereport(ERROR,
48-
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
49-
errmsg("invalid input syntax for type %s: \"%s\"",
50-
"pg_lsn",str)));
46+
{
47+
*have_error= true;
48+
returnInvalidXLogRecPtr;
49+
}
5150

5251
/* Decode result. */
5352
id= (uint32)strtoul(str,NULL,16);
@@ -57,6 +56,23 @@ pg_lsn_in(PG_FUNCTION_ARGS)
5756
PG_RETURN_LSN(result);
5857
}
5958

59+
Datum
60+
pg_lsn_in(PG_FUNCTION_ARGS)
61+
{
62+
char*str=PG_GETARG_CSTRING(0);
63+
XLogRecPtrresult;
64+
boolhave_error= false;
65+
66+
result=pg_lsn_in_internal(str,&have_error);
67+
if (have_error)
68+
ereport(ERROR,
69+
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
70+
errmsg("invalid input syntax for type %s: \"%s\"",
71+
"pg_lsn",str)));
72+
73+
PG_RETURN_LSN(result);
74+
}
75+
6076
Datum
6177
pg_lsn_out(PG_FUNCTION_ARGS)
6278
{

‎src/backend/utils/misc/guc.c

Lines changed: 41 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,6 @@ static bool assert_enabled;
579579
staticchar*recovery_target_timeline_string;
580580
staticchar*recovery_target_string;
581581
staticchar*recovery_target_xid_string;
582-
staticchar*recovery_target_time_string;
583582
staticchar*recovery_target_name_string;
584583
staticchar*recovery_target_lsn_string;
585584

@@ -11572,53 +11571,59 @@ assign_recovery_target_xid(const char *newval, void *extra)
1157211571
recoveryTarget=RECOVERY_TARGET_UNSET;
1157311572
}
1157411573

11574+
/*
11575+
* The interpretation of the recovery_target_time string can depend on the
11576+
* time zone setting, so we need to wait until after all GUC processing is
11577+
* done before we can do the final parsing of the string. This check function
11578+
* only does a parsing pass to catch syntax errors, but we store the string
11579+
* and parse it again when we need to use it.
11580+
*/
1157511581
staticbool
1157611582
check_recovery_target_time(char**newval,void**extra,GucSourcesource)
1157711583
{
1157811584
if (strcmp(*newval,"")!=0)
1157911585
{
11580-
TimestampTztime;
11581-
TimestampTz*myextra;
11582-
MemoryContextoldcontext=CurrentMemoryContext;
11583-
1158411586
/* reject some special values */
11585-
if (strcmp(*newval,"epoch")==0||
11586-
strcmp(*newval,"infinity")==0||
11587-
strcmp(*newval,"-infinity")==0||
11588-
strcmp(*newval,"now")==0||
11587+
if (strcmp(*newval,"now")==0||
1158911588
strcmp(*newval,"today")==0||
1159011589
strcmp(*newval,"tomorrow")==0||
1159111590
strcmp(*newval,"yesterday")==0)
1159211591
{
1159311592
return false;
1159411593
}
1159511594

11596-
PG_TRY();
11597-
{
11598-
time=DatumGetTimestampTz(DirectFunctionCall3(timestamptz_in,
11599-
CStringGetDatum(*newval),
11600-
ObjectIdGetDatum(InvalidOid),
11601-
Int32GetDatum(-1)));
11602-
}
11603-
PG_CATCH();
11595+
/*
11596+
* parse timestamp value (see also timestamptz_in())
11597+
*/
1160411598
{
11605-
ErrorData*edata;
11606-
11607-
/* Save error info */
11608-
MemoryContextSwitchTo(oldcontext);
11609-
edata=CopyErrorData();
11610-
FlushErrorState();
11611-
11612-
/* Pass the error message */
11613-
GUC_check_errdetail("%s",edata->message);
11614-
FreeErrorData(edata);
11615-
return false;
11599+
char*str=*newval;
11600+
fsec_tfsec;
11601+
structpg_tmtt,
11602+
*tm=&tt;
11603+
inttz;
11604+
intdtype;
11605+
intnf;
11606+
intdterr;
11607+
char*field[MAXDATEFIELDS];
11608+
intftype[MAXDATEFIELDS];
11609+
charworkbuf[MAXDATELEN+MAXDATEFIELDS];
11610+
TimestampTztimestamp;
11611+
11612+
dterr=ParseDateTime(str,workbuf,sizeof(workbuf),
11613+
field,ftype,MAXDATEFIELDS,&nf);
11614+
if (dterr==0)
11615+
dterr=DecodeDateTime(field,ftype,nf,&dtype,tm,&fsec,&tz);
11616+
if (dterr!=0)
11617+
return false;
11618+
if (dtype!=DTK_DATE)
11619+
return false;
11620+
11621+
if (tm2timestamp(tm,fsec,&tz,&timestamp)!=0)
11622+
{
11623+
GUC_check_errdetail("timestamp out of range: \"%s\"",str);
11624+
return false;
11625+
}
1161611626
}
11617-
PG_END_TRY();
11618-
11619-
myextra= (TimestampTz*)guc_malloc(ERROR,sizeof(TimestampTz));
11620-
*myextra=time;
11621-
*extra= (void*)myextra;
1162211627
}
1162311628
return true;
1162411629
}
@@ -11631,10 +11636,7 @@ assign_recovery_target_time(const char *newval, void *extra)
1163111636
error_multiple_recovery_targets();
1163211637

1163311638
if (newval&&strcmp(newval,"")!=0)
11634-
{
1163511639
recoveryTarget=RECOVERY_TARGET_TIME;
11636-
recoveryTargetTime=*((TimestampTz*)extra);
11637-
}
1163811640
else
1163911641
recoveryTarget=RECOVERY_TARGET_UNSET;
1164011642
}
@@ -11675,33 +11677,11 @@ check_recovery_target_lsn(char **newval, void **extra, GucSource source)
1167511677
{
1167611678
XLogRecPtrlsn;
1167711679
XLogRecPtr*myextra;
11678-
MemoryContextoldcontext=CurrentMemoryContext;
11679-
11680-
/*
11681-
* Convert the LSN string given by the user to XLogRecPtr form.
11682-
*/
11683-
PG_TRY();
11684-
{
11685-
lsn=DatumGetLSN(DirectFunctionCall3(pg_lsn_in,
11686-
CStringGetDatum(*newval),
11687-
ObjectIdGetDatum(InvalidOid),
11688-
Int32GetDatum(-1)));
11689-
}
11690-
PG_CATCH();
11691-
{
11692-
ErrorData*edata;
11693-
11694-
/* Save error info */
11695-
MemoryContextSwitchTo(oldcontext);
11696-
edata=CopyErrorData();
11697-
FlushErrorState();
11680+
boolhave_error= false;
1169811681

11699-
/* Pass the error message */
11700-
GUC_check_errdetail("%s",edata->message);
11701-
FreeErrorData(edata);
11682+
lsn=pg_lsn_in_internal(*newval,&have_error);
11683+
if (have_error)
1170211684
return false;
11703-
}
11704-
PG_END_TRY();
1170511685

1170611686
myextra= (XLogRecPtr*)guc_malloc(ERROR,sizeof(XLogRecPtr));
1170711687
*myextra=lsn;

‎src/include/access/xlog.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ extern char *PrimarySlotName;
132132

133133
/* indirectly set via GUC system */
134134
externTransactionIdrecoveryTargetXid;
135-
externTimestampTzrecoveryTargetTime;
135+
externchar*recovery_target_time_string;
136136
externconstchar*recoveryTargetName;
137137
externXLogRecPtrrecoveryTargetLSN;
138138
externRecoveryTargetTyperecoveryTarget;

‎src/include/utils/pg_lsn.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,6 @@
2424
#definePG_GETARG_LSN(n) DatumGetLSN(PG_GETARG_DATUM(n))
2525
#definePG_RETURN_LSN(x) return LSNGetDatum(x)
2626

27+
externXLogRecPtrpg_lsn_in_internal(constchar*str,bool*have_error);
28+
2729
#endif/* PG_LSN_H */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp