From c00b309932b83e7c256a806223078f98d54f6cde Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sat, 8 May 2004 21:21:18 +0000 Subject: [PATCH] Alter string format used for integer and OID lists in stored rules. This simplifies and speeds up the reader by letting it get the representation right the first time, rather than correcting it after-the-fact. Also, after int and OID lists become separate node types per Neil's pending patch, this will let us treat these lists as just plain Nodes instead of requiring separate read/write macros the way we have now. --- src/backend/nodes/outfuncs.c | 10 +++-- src/backend/nodes/print.c | 18 +++++--- src/backend/nodes/read.c | 73 ++++++++++++++++++++++++++++---- src/backend/nodes/readfuncs.c | 60 +++----------------------- src/include/catalog/catversion.h | 4 +- 5 files changed, 91 insertions(+), 74 deletions(-) diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 788e7dc5af..9139a9bec5 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.234 2004/05/06 14:01:33 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.235 2004/05/08 21:21:18 tgl Exp $ * * NOTES * Every node type that can appear in stored rules' parsetrees *must* @@ -155,6 +155,7 @@ _outIntList(StringInfo str, List *list) List *l; appendStringInfoChar(str, '('); + appendStringInfoChar(str, 'i'); foreach(l, list) appendStringInfo(str, " %d", lfirsti(l)); appendStringInfoChar(str, ')'); @@ -170,6 +171,7 @@ _outOidList(StringInfo str, List *list) List *l; appendStringInfoChar(str, '('); + appendStringInfoChar(str, 'o'); foreach(l, list) appendStringInfo(str, " %u", lfirsto(l)); appendStringInfoChar(str, ')'); @@ -179,8 +181,9 @@ _outOidList(StringInfo str, List *list) * _outBitmapset - * converts a bitmap set of integers * - * Note: for historical reasons, the output is formatted exactly like - * an integer List would be. + * Note: the output format is "(b int int ...)", similar to an integer List. + * Currently bitmapsets do not appear in any node type that is stored in + * rules, so there is no support in readfuncs.c for reading this format. */ static void _outBitmapset(StringInfo str, Bitmapset *bms) @@ -189,6 +192,7 @@ _outBitmapset(StringInfo str, Bitmapset *bms) int x; appendStringInfoChar(str, '('); + appendStringInfoChar(str, 'b'); tmpset = bms_copy(bms); while ((x = bms_first_member(tmpset)) >= 0) appendStringInfo(str, " %d", x); diff --git a/src/backend/nodes/print.c b/src/backend/nodes/print.c index 074a838902..14f73b1860 100644 --- a/src/backend/nodes/print.c +++ b/src/backend/nodes/print.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/print.c,v 1.65 2003/11/29 19:51:49 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/print.c,v 1.66 2004/05/08 21:21:18 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -194,12 +194,20 @@ pretty_format_node_dump(const char *dump) } j = indentDist - 1; /* j will equal indentDist on next loop iteration */ + /* suppress whitespace just after } */ + while (dump[i+1] == ' ') + i++; break; case ')': - /* force line break after ')' */ - line[j + 1] = '\0'; - appendStringInfo(&str, "%s\n", line); - j = indentDist - 1; + /* force line break after ), unless another ) follows */ + if (dump[i+1] != ')') + { + line[j + 1] = '\0'; + appendStringInfo(&str, "%s\n", line); + j = indentDist - 1; + while (dump[i+1] == ' ') + i++; + } break; case '{': /* force line break before { */ diff --git a/src/backend/nodes/read.c b/src/backend/nodes/read.c index 402c999113..e90b413591 100644 --- a/src/backend/nodes/read.c +++ b/src/backend/nodes/read.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/read.c,v 1.40 2004/05/06 14:01:33 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/read.c,v 1.41 2004/05/08 21:21:18 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -261,7 +261,8 @@ nodeTokenType(char *token, int length) * lexical tokenizer pg_strtok(). It can read * * Value token nodes (integers, floats, or strings); * * General nodes (via parseNodeString() from readfuncs.c); - * * Lists of the above. + * * Lists of the above; + * * Lists of integers or OIDs. * The return value is declared void *, not Node *, to avoid having to * cast it explicitly in callers that assign to fields of different types. * @@ -300,14 +301,68 @@ nodeRead(char *token, int tok_len) { List *l = NIL; - for (;;) + /*---------- + * Could be an integer list: (i int int ...) + * or an OID list: (o int int ...) + * or a list of nodes/values: (node node ...) + *---------- + */ + token = pg_strtok(&tok_len); + if (token == NULL) + elog(ERROR, "unterminated List structure"); + if (tok_len == 1 && token[0] == 'i') { - token = pg_strtok(&tok_len); - if (token == NULL) - elog(ERROR, "unterminated List structure"); - if (token[0] == ')') - break; - l = lappend(l, nodeRead(token, tok_len)); + /* List of integers */ + for (;;) + { + int val; + char *endptr; + + token = pg_strtok(&tok_len); + if (token == NULL) + elog(ERROR, "unterminated List structure"); + if (token[0] == ')') + break; + val = (int) strtol(token, &endptr, 10); + if (endptr != token + tok_len) + elog(ERROR, "unrecognized integer: \"%.*s\"", + tok_len, token); + l = lappendi(l, val); + } + } + else if (tok_len == 1 && token[0] == 'o') + { + /* List of OIDs */ + for (;;) + { + Oid val; + char *endptr; + + token = pg_strtok(&tok_len); + if (token == NULL) + elog(ERROR, "unterminated List structure"); + if (token[0] == ')') + break; + val = (Oid) strtoul(token, &endptr, 10); + if (endptr != token + tok_len) + elog(ERROR, "unrecognized OID: \"%.*s\"", + tok_len, token); + l = lappendo(l, val); + } + } + else + { + /* List of other node types */ + for (;;) + { + /* We have already scanned next token... */ + if (token[0] == ')') + break; + l = lappend(l, nodeRead(token, tok_len)); + token = pg_strtok(&tok_len); + if (token == NULL) + elog(ERROR, "unterminated List structure"); + } } result = (Node *) l; break; diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 0e37459970..ebd3c636c2 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.167 2004/05/06 14:01:33 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.168 2004/05/08 21:21:18 tgl Exp $ * * NOTES * Path and Plan nodes do not have any readfuncs support, because we @@ -101,15 +101,15 @@ token = pg_strtok(&length); /* skip :fldname */ \ local_node->fldname = nodeRead(NULL, 0) -/* Read an integer-list field */ +/* Read an integer-list field (XXX combine me with READ_NODE_FIELD) */ #define READ_INTLIST_FIELD(fldname) \ token = pg_strtok(&length); /* skip :fldname */ \ - local_node->fldname = toIntList(nodeRead(NULL, 0)) + local_node->fldname = nodeRead(NULL, 0) -/* Read an OID-list field */ +/* Read an OID-list field (XXX combine me with READ_NODE_FIELD) */ #define READ_OIDLIST_FIELD(fldname) \ token = pg_strtok(&length); /* skip :fldname */ \ - local_node->fldname = toOidList(nodeRead(NULL, 0)) + local_node->fldname = nodeRead(NULL, 0) /* Routine exit */ #define READ_DONE() \ @@ -135,56 +135,6 @@ static Datum readDatum(bool typbyval); -/* Convert Value list returned by nodeRead into list of integers */ -static List * -toIntList(List *list) -{ - List *l; - - foreach(l, list) - { - Value *v = (Value *) lfirst(l); - - if (!IsA(v, Integer)) - elog(ERROR, "unexpected node type: %d", (int) nodeTag(v)); - lfirsti(l) = intVal(v); - pfree(v); - } - return list; -} - -/* Convert Value list returned by nodeRead into list of OIDs */ -static List * -toOidList(List *list) -{ - List *l; - - foreach(l, list) - { - Value *v = (Value *) lfirst(l); - - /* - * This is a bit tricky because OID is unsigned, and so nodeRead - * might have concluded the value doesn't fit in an integer. Must - * cope with T_Float as well. - */ - if (IsA(v, Integer)) - { - lfirsto(l) = (Oid) intVal(v); - pfree(v); - } - else if (IsA(v, Float)) - { - lfirsto(l) = atooid(strVal(v)); - pfree(strVal(v)); - pfree(v); - } - else - elog(ERROR, "unexpected node type: %d", (int) nodeTag(v)); - } - return list; -} - /* * _readQuery */ diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 3380178a0d..46a8a2d06f 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.227 2004/05/02 13:39:51 momjian Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.228 2004/05/08 21:21:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200405020 +#define CATALOG_VERSION_NO 200405081 #endif