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

Commit2d04277

Browse files
committed
Make serialization of Nodes' scalar-array fields more robust.
When the ability to print variable-length-array fields was firstadded to outfuncs.c, there was no corresponding read capability,as it was used only for debug dumps of planner-internal Nodes.Not a lot of thought seems to have been put into the output format:it's just the space-separated array elements and nothing else.Later such fields appeared in Plan nodes, and still later we grewread support so that Plans could be transferred to parallel workers,but the original text format wasn't rethought. It seems inadequateto me because (a) no cross-check is possible that we got the rightnumber of array entries, (b) we can't tell the difference betweena NULL pointer and a zero-length array, and (c) except forWRITE_INDEX_ARRAY, we'd crash if a non-zero length is specifiedwhen the pointer is NULL, a situation that can arise in some fieldsthat we currently conveniently avoid printing.Since we're currently in a campaign to make the Node infrastructuregenerally more it-just-works-without-thinking-about-it, now seemslike a good time to improve this.Let's adopt a format similar to that used for Lists, that is "<>"for a NULL pointer or "(item item item)" otherwise. Also retoolthe code to not have so many copies of the identical logic.I bumped catversion out of an abundance of caution, although I thinkthat we don't use any such array fields in Nodes that can get intothe catalogs.Discussion:https://postgr.es/m/1528424.1658272135@sss.pgh.pa.us
1 parentf77ff08 commit2d04277

File tree

3 files changed

+88
-123
lines changed

3 files changed

+88
-123
lines changed

‎src/backend/nodes/outfuncs.c

Lines changed: 48 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include<ctype.h>
1818

19+
#include"access/attnum.h"
1920
#include"lib/stringinfo.h"
2021
#include"miscadmin.h"
2122
#include"nodes/bitmapset.h"
@@ -96,48 +97,30 @@ static void outChar(StringInfo str, char c);
9697
(appendStringInfoString(str, " :" CppAsString(fldname) " "), \
9798
outBitmapset(str, node->fldname))
9899

100+
/* Write a variable-length array of AttrNumber */
99101
#defineWRITE_ATTRNUMBER_ARRAY(fldname,len) \
100-
do { \
101-
appendStringInfoString(str, " :" CppAsString(fldname) " "); \
102-
for (int i = 0; i < len; i++) \
103-
appendStringInfo(str, " %d", node->fldname[i]); \
104-
} while(0)
102+
(appendStringInfoString(str, " :" CppAsString(fldname) " "), \
103+
writeAttrNumberCols(str, node->fldname, len))
105104

105+
/* Write a variable-length array of Oid */
106106
#defineWRITE_OID_ARRAY(fldname,len) \
107-
do { \
108-
appendStringInfoString(str, " :" CppAsString(fldname) " "); \
109-
for (int i = 0; i < len; i++) \
110-
appendStringInfo(str, " %u", node->fldname[i]); \
111-
} while(0)
107+
(appendStringInfoString(str, " :" CppAsString(fldname) " "), \
108+
writeOidCols(str, node->fldname, len))
112109

113-
/*
114-
* This macro supports the case that the field is NULL. For the other array
115-
* macros, that is currently not needed.
116-
*/
110+
/* Write a variable-length array of Index */
117111
#defineWRITE_INDEX_ARRAY(fldname,len) \
118-
do { \
119-
appendStringInfoString(str, " :" CppAsString(fldname) " "); \
120-
if (node->fldname) \
121-
for (int i = 0; i < len; i++) \
122-
appendStringInfo(str, " %u", node->fldname[i]); \
123-
else \
124-
appendStringInfoString(str, "<>"); \
125-
} while(0)
112+
(appendStringInfoString(str, " :" CppAsString(fldname) " "), \
113+
writeIndexCols(str, node->fldname, len))
126114

115+
/* Write a variable-length array of int */
127116
#defineWRITE_INT_ARRAY(fldname,len) \
128-
do { \
129-
appendStringInfoString(str, " :" CppAsString(fldname) " "); \
130-
for (int i = 0; i < len; i++) \
131-
appendStringInfo(str, " %d", node->fldname[i]); \
132-
} while(0)
117+
(appendStringInfoString(str, " :" CppAsString(fldname) " "), \
118+
writeIntCols(str, node->fldname, len))
133119

120+
/* Write a variable-length array of bool */
134121
#defineWRITE_BOOL_ARRAY(fldname,len) \
135-
do { \
136-
appendStringInfoString(str, " :" CppAsString(fldname) " "); \
137-
for (int i = 0; i < len; i++) \
138-
appendStringInfo(str, " %s", booltostr(node->fldname[i])); \
139-
} while(0)
140-
122+
(appendStringInfoString(str, " :" CppAsString(fldname) " "), \
123+
writeBoolCols(str, node->fldname, len))
141124

142125
#definebooltostr(x) ((x) ? "true" : "false")
143126

@@ -196,6 +179,38 @@ outChar(StringInfo str, char c)
196179
outToken(str,in);
197180
}
198181

182+
/*
183+
* common implementation for scalar-array-writing functions
184+
*
185+
* The data format is either "<>" for a NULL pointer or "(item item item)".
186+
* fmtstr must include a leading space, and the rest of it must produce
187+
* something that will be seen as a single simple token by pg_strtok().
188+
* convfunc can be empty, or the name of a conversion macro or function.
189+
*/
190+
#defineWRITE_SCALAR_ARRAY(fnname,datatype,fmtstr,convfunc) \
191+
static void \
192+
fnname(StringInfo str, const datatype *arr, int len) \
193+
{ \
194+
if (arr != NULL) \
195+
{ \
196+
appendStringInfoChar(str, '('); \
197+
for (int i = 0; i < len; i++) \
198+
appendStringInfo(str, fmtstr, convfunc(arr[i])); \
199+
appendStringInfoChar(str, ')'); \
200+
} \
201+
else \
202+
appendStringInfoString(str, "<>"); \
203+
}
204+
205+
WRITE_SCALAR_ARRAY(writeAttrNumberCols,AttrNumber," %d",)
206+
WRITE_SCALAR_ARRAY(writeOidCols,Oid," %u",)
207+
WRITE_SCALAR_ARRAY(writeIndexCols,Index," %u",)
208+
WRITE_SCALAR_ARRAY(writeIntCols,int," %d",)
209+
WRITE_SCALAR_ARRAY(writeBoolCols,bool," %s",booltostr)
210+
211+
/*
212+
* Print a List.
213+
*/
199214
staticvoid
200215
_outList(StringInfostr,constList*node)
201216
{

‎src/backend/nodes/readfuncs.c

Lines changed: 39 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -502,97 +502,47 @@ readDatum(bool typbyval)
502502
}
503503

504504
/*
505-
* readAttrNumberCols
506-
*/
507-
AttrNumber*
508-
readAttrNumberCols(intnumCols)
509-
{
510-
inttokenLength,
511-
i;
512-
constchar*token;
513-
AttrNumber*attr_vals;
514-
515-
if (numCols <=0)
516-
returnNULL;
517-
518-
attr_vals= (AttrNumber*)palloc(numCols*sizeof(AttrNumber));
519-
for (i=0;i<numCols;i++)
520-
{
521-
token=pg_strtok(&tokenLength);
522-
attr_vals[i]=atoi(token);
523-
}
524-
525-
returnattr_vals;
526-
}
527-
528-
/*
529-
* readOidCols
530-
*/
531-
Oid*
532-
readOidCols(intnumCols)
533-
{
534-
inttokenLength,
535-
i;
536-
constchar*token;
537-
Oid*oid_vals;
538-
539-
if (numCols <=0)
540-
returnNULL;
541-
542-
oid_vals= (Oid*)palloc(numCols*sizeof(Oid));
543-
for (i=0;i<numCols;i++)
544-
{
545-
token=pg_strtok(&tokenLength);
546-
oid_vals[i]=atooid(token);
547-
}
548-
549-
returnoid_vals;
550-
}
551-
552-
/*
553-
* readIntCols
505+
* common implementation for scalar-array-reading functions
506+
*
507+
* The data format is either "<>" for a NULL pointer (in which case numCols
508+
* is ignored) or "(item item item)" where the number of items must equal
509+
* numCols. The convfunc must be okay with stopping at whitespace or a
510+
* right parenthesis, since pg_strtok won't null-terminate the token.
554511
*/
555-
int*
556-
readIntCols(intnumCols)
557-
{
558-
inttokenLength,
559-
i;
560-
constchar*token;
561-
int*int_vals;
562-
563-
if (numCols <=0)
564-
returnNULL;
565-
566-
int_vals= (int*)palloc(numCols*sizeof(int));
567-
for (i=0;i<numCols;i++)
568-
{
569-
token=pg_strtok(&tokenLength);
570-
int_vals[i]=atoi(token);
571-
}
572-
573-
returnint_vals;
512+
#defineREAD_SCALAR_ARRAY(fnname,datatype,convfunc) \
513+
datatype * \
514+
fnname(int numCols) \
515+
{ \
516+
datatype *vals; \
517+
READ_TEMP_LOCALS(); \
518+
token = pg_strtok(&length); \
519+
if (token == NULL) \
520+
elog(ERROR, "incomplete scalar array"); \
521+
if (length == 0) \
522+
return NULL;/* it was "<>", so return NULL pointer */ \
523+
if (length!=1||token[0]!='(') \
524+
elog(ERROR,"unrecognized token: \"%.*s\"",length,token); \
525+
vals= (datatype*)palloc(numCols*sizeof(datatype)); \
526+
for (inti=0;i<numCols;i++) \
527+
{ \
528+
token=pg_strtok(&length); \
529+
if (token==NULL||token[0]==')') \
530+
elog(ERROR,"incomplete scalar array"); \
531+
vals[i]=convfunc(token); \
532+
} \
533+
token=pg_strtok(&length); \
534+
if (token==NULL||length!=1||token[0]!=')') \
535+
elog(ERROR,"incomplete scalar array"); \
536+
returnvals; \
574537
}
575538

576539
/*
577-
* readBoolCols
540+
* Note: these functions are exported in nodes.h for possible use by
541+
* extensions, so don't mess too much with their names or API.
578542
*/
579-
bool*
580-
readBoolCols(intnumCols)
581-
{
582-
inttokenLength,
583-
i;
584-
constchar*token;
585-
bool*bool_vals;
586-
587-
if (numCols <=0)
588-
returnNULL;
589-
590-
bool_vals= (bool*)palloc(numCols*sizeof(bool));
591-
for (i=0;i<numCols;i++)
592-
{
593-
token=pg_strtok(&tokenLength);
594-
bool_vals[i]=strtobool(token);
595-
}
596-
597-
returnbool_vals;
598-
}
543+
READ_SCALAR_ARRAY(readAttrNumberCols,int16,atoi)
544+
READ_SCALAR_ARRAY(readOidCols,Oid,atooid)
545+
/* outfuncs.c has writeIndexCols, but we don't yet need that here */
546+
/* READ_SCALAR_ARRAY(readIndexCols, Index, atoui) */
547+
READ_SCALAR_ARRAY(readIntCols,int,atoi)
548+
READ_SCALAR_ARRAY(readBoolCols,bool,strtobool)

‎src/include/catalog/catversion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,6 @@
5757
*/
5858

5959
/*yyyymmddN */
60-
#defineCATALOG_VERSION_NO202207131
60+
#defineCATALOG_VERSION_NO202207201
6161

6262
#endif

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp