mirror of
https://github.com/postgres/postgres.git
synced 2025-11-22 12:22:45 +03:00
Add a debugging option to stress-test outfuncs.c and readfuncs.c.
In the normal course of operation, query trees will be serialized only if they are stored as views or rules; and plan trees will be serialized only if they get passed to parallel-query workers. This leaves an awful lot of opportunity for bugs/oversights to not get detected, as indeed we've just been reminded of the hard way. To improve matters, this patch adds a new compile option WRITE_READ_PARSE_PLAN_TREES, which is modeled on the longstanding option COPY_PARSE_PLAN_TREES; but instead of passing all parse and plan trees through copyObject, it passes them through nodeToString + stringToNode. Enabling this option in a buildfarm animal or two will catch problems at least for cases that are exercised by the regression tests. A small problem with this idea is that readfuncs.c historically has discarded location fields, on the reasonable grounds that parse locations in a retrieved view are not relevant to the current query. But doing that in WRITE_READ_PARSE_PLAN_TREES breaks pg_stat_statements, and it could cause problems for future improvements that might try to report error locations at runtime. To fix that, provide a variant behavior in readfuncs.c that makes it restore location fields when told to. In passing, const-ify the string arguments of stringToNode and its subsidiary functions, just because it annoyed me that they weren't const already. Discussion: https://postgr.es/m/17114.1537138992@sss.pgh.pa.us
This commit is contained in:
@@ -28,18 +28,30 @@
|
||||
|
||||
|
||||
/* Static state for pg_strtok */
|
||||
static char *pg_strtok_ptr = NULL;
|
||||
static const char *pg_strtok_ptr = NULL;
|
||||
|
||||
/* State flag that determines how readfuncs.c should treat location fields */
|
||||
#ifdef WRITE_READ_PARSE_PLAN_TREES
|
||||
bool restore_location_fields = false;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* stringToNode -
|
||||
* returns a Node with a given legal ASCII representation
|
||||
* builds a Node tree from its string representation (assumed valid)
|
||||
*
|
||||
* restore_loc_fields instructs readfuncs.c whether to restore location
|
||||
* fields rather than set them to -1. This is currently only supported
|
||||
* in builds with the WRITE_READ_PARSE_PLAN_TREES debugging flag set.
|
||||
*/
|
||||
void *
|
||||
stringToNode(char *str)
|
||||
static void *
|
||||
stringToNodeInternal(const char *str, bool restore_loc_fields)
|
||||
{
|
||||
char *save_strtok;
|
||||
void *retval;
|
||||
const char *save_strtok;
|
||||
#ifdef WRITE_READ_PARSE_PLAN_TREES
|
||||
bool save_restore_location_fields;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We save and restore the pre-existing state of pg_strtok. This makes the
|
||||
@@ -51,13 +63,45 @@ stringToNode(char *str)
|
||||
|
||||
pg_strtok_ptr = str; /* point pg_strtok at the string to read */
|
||||
|
||||
/*
|
||||
* If enabled, likewise save/restore the location field handling flag.
|
||||
*/
|
||||
#ifdef WRITE_READ_PARSE_PLAN_TREES
|
||||
save_restore_location_fields = restore_location_fields;
|
||||
restore_location_fields = restore_loc_fields;
|
||||
#endif
|
||||
|
||||
retval = nodeRead(NULL, 0); /* do the reading */
|
||||
|
||||
pg_strtok_ptr = save_strtok;
|
||||
|
||||
#ifdef WRITE_READ_PARSE_PLAN_TREES
|
||||
restore_location_fields = save_restore_location_fields;
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Externally visible entry points
|
||||
*/
|
||||
void *
|
||||
stringToNode(const char *str)
|
||||
{
|
||||
return stringToNodeInternal(str, false);
|
||||
}
|
||||
|
||||
#ifdef WRITE_READ_PARSE_PLAN_TREES
|
||||
|
||||
void *
|
||||
stringToNodeWithLocations(const char *str)
|
||||
{
|
||||
return stringToNodeInternal(str, true);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* the lisp token parser
|
||||
@@ -104,11 +148,11 @@ stringToNode(char *str)
|
||||
* code should add backslashes to a string constant to ensure it is treated
|
||||
* as a single token.
|
||||
*/
|
||||
char *
|
||||
const char *
|
||||
pg_strtok(int *length)
|
||||
{
|
||||
char *local_str; /* working pointer to string */
|
||||
char *ret_str; /* start of token to return */
|
||||
const char *local_str; /* working pointer to string */
|
||||
const char *ret_str; /* start of token to return */
|
||||
|
||||
local_str = pg_strtok_ptr;
|
||||
|
||||
@@ -166,7 +210,7 @@ pg_strtok(int *length)
|
||||
* any protective backslashes in the token are removed.
|
||||
*/
|
||||
char *
|
||||
debackslash(char *token, int length)
|
||||
debackslash(const char *token, int length)
|
||||
{
|
||||
char *result = palloc(length + 1);
|
||||
char *ptr = result;
|
||||
@@ -198,10 +242,10 @@ debackslash(char *token, int length)
|
||||
* Assumption: the ascii representation is legal
|
||||
*/
|
||||
static NodeTag
|
||||
nodeTokenType(char *token, int length)
|
||||
nodeTokenType(const char *token, int length)
|
||||
{
|
||||
NodeTag retval;
|
||||
char *numptr;
|
||||
const char *numptr;
|
||||
int numlen;
|
||||
|
||||
/*
|
||||
@@ -269,7 +313,7 @@ nodeTokenType(char *token, int length)
|
||||
* this should only be invoked from within a stringToNode operation).
|
||||
*/
|
||||
void *
|
||||
nodeRead(char *token, int tok_len)
|
||||
nodeRead(const char *token, int tok_len)
|
||||
{
|
||||
Node *result;
|
||||
NodeTag type;
|
||||
|
||||
Reference in New Issue
Block a user