diff options
author | vvvv <vvvv@yandex-team.com> | 2024-11-07 12:29:36 +0300 |
---|---|---|
committer | vvvv <vvvv@yandex-team.com> | 2024-11-07 13:49:47 +0300 |
commit | d4c258e9431675bab6745c8638df6e3dfd4dca6b (patch) | |
tree | b5efcfa11351152a4c872fccaea35749141c0b11 /yql/essentials/parser/pg_wrapper/postgresql/src/backend/nodes/outfuncs.c | |
parent | 13a4f274caef5cfdaf0263b24e4d6bdd5521472b (diff) | |
download | ydb-d4c258e9431675bab6745c8638df6e3dfd4dca6b.tar.gz |
Moved other yql/essentials libs YQL-19206
init
commit_hash:7d4c435602078407bbf20dd3c32f9c90d2bbcbc0
Diffstat (limited to 'yql/essentials/parser/pg_wrapper/postgresql/src/backend/nodes/outfuncs.c')
-rw-r--r-- | yql/essentials/parser/pg_wrapper/postgresql/src/backend/nodes/outfuncs.c | 906 |
1 files changed, 906 insertions, 0 deletions
diff --git a/yql/essentials/parser/pg_wrapper/postgresql/src/backend/nodes/outfuncs.c b/yql/essentials/parser/pg_wrapper/postgresql/src/backend/nodes/outfuncs.c new file mode 100644 index 00000000000..e56392e6f9d --- /dev/null +++ b/yql/essentials/parser/pg_wrapper/postgresql/src/backend/nodes/outfuncs.c @@ -0,0 +1,906 @@ +/*------------------------------------------------------------------------- + * + * outfuncs.c + * Output functions for Postgres tree nodes. + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/backend/nodes/outfuncs.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include <ctype.h> + +#include "access/attnum.h" +#include "common/shortest_dec.h" +#include "lib/stringinfo.h" +#include "miscadmin.h" +#include "nodes/bitmapset.h" +#include "nodes/nodes.h" +#include "nodes/pg_list.h" +#include "utils/datum.h" + +static void outChar(StringInfo str, char c); +static void outDouble(StringInfo str, double d); + + +/* + * Macros to simplify output of different kinds of fields. Use these + * wherever possible to reduce the chance for silly typos. Note that these + * hard-wire conventions about the names of the local variables in an Out + * routine. + */ + +/* Write the label for the node type */ +#define WRITE_NODE_TYPE(nodelabel) \ + appendStringInfoString(str, nodelabel) + +/* Write an integer field (anything written as ":fldname %d") */ +#define WRITE_INT_FIELD(fldname) \ + appendStringInfo(str, " :" CppAsString(fldname) " %d", node->fldname) + +/* Write an unsigned integer field (anything written as ":fldname %u") */ +#define WRITE_UINT_FIELD(fldname) \ + appendStringInfo(str, " :" CppAsString(fldname) " %u", node->fldname) + +/* Write an unsigned integer field (anything written with UINT64_FORMAT) */ +#define WRITE_UINT64_FIELD(fldname) \ + appendStringInfo(str, " :" CppAsString(fldname) " " UINT64_FORMAT, \ + node->fldname) + +/* Write an OID field (don't hard-wire assumption that OID is same as uint) */ +#define WRITE_OID_FIELD(fldname) \ + appendStringInfo(str, " :" CppAsString(fldname) " %u", node->fldname) + +/* Write a long-integer field */ +#define WRITE_LONG_FIELD(fldname) \ + appendStringInfo(str, " :" CppAsString(fldname) " %ld", node->fldname) + +/* Write a char field (ie, one ascii character) */ +#define WRITE_CHAR_FIELD(fldname) \ + (appendStringInfo(str, " :" CppAsString(fldname) " "), \ + outChar(str, node->fldname)) + +/* Write an enumerated-type field as an integer code */ +#define WRITE_ENUM_FIELD(fldname, enumtype) \ + appendStringInfo(str, " :" CppAsString(fldname) " %d", \ + (int) node->fldname) + +/* Write a float field (actually, they're double) */ +#define WRITE_FLOAT_FIELD(fldname) \ + (appendStringInfo(str, " :" CppAsString(fldname) " "), \ + outDouble(str, node->fldname)) + +/* Write a boolean field */ +#define WRITE_BOOL_FIELD(fldname) \ + appendStringInfo(str, " :" CppAsString(fldname) " %s", \ + booltostr(node->fldname)) + +/* Write a character-string (possibly NULL) field */ +#define WRITE_STRING_FIELD(fldname) \ + (appendStringInfoString(str, " :" CppAsString(fldname) " "), \ + outToken(str, node->fldname)) + +/* Write a parse location field (actually same as INT case) */ +#define WRITE_LOCATION_FIELD(fldname) \ + appendStringInfo(str, " :" CppAsString(fldname) " %d", node->fldname) + +/* Write a Node field */ +#define WRITE_NODE_FIELD(fldname) \ + (appendStringInfoString(str, " :" CppAsString(fldname) " "), \ + outNode(str, node->fldname)) + +/* Write a bitmapset field */ +#define WRITE_BITMAPSET_FIELD(fldname) \ + (appendStringInfoString(str, " :" CppAsString(fldname) " "), \ + outBitmapset(str, node->fldname)) + +/* Write a variable-length array (not a List) of Node pointers */ +#define WRITE_NODE_ARRAY(fldname, len) \ + (appendStringInfoString(str, " :" CppAsString(fldname) " "), \ + writeNodeArray(str, (const Node * const *) node->fldname, len)) + +/* Write a variable-length array of AttrNumber */ +#define WRITE_ATTRNUMBER_ARRAY(fldname, len) \ + (appendStringInfoString(str, " :" CppAsString(fldname) " "), \ + writeAttrNumberCols(str, node->fldname, len)) + +/* Write a variable-length array of Oid */ +#define WRITE_OID_ARRAY(fldname, len) \ + (appendStringInfoString(str, " :" CppAsString(fldname) " "), \ + writeOidCols(str, node->fldname, len)) + +/* Write a variable-length array of Index */ +#define WRITE_INDEX_ARRAY(fldname, len) \ + (appendStringInfoString(str, " :" CppAsString(fldname) " "), \ + writeIndexCols(str, node->fldname, len)) + +/* Write a variable-length array of int */ +#define WRITE_INT_ARRAY(fldname, len) \ + (appendStringInfoString(str, " :" CppAsString(fldname) " "), \ + writeIntCols(str, node->fldname, len)) + +/* Write a variable-length array of bool */ +#define WRITE_BOOL_ARRAY(fldname, len) \ + (appendStringInfoString(str, " :" CppAsString(fldname) " "), \ + writeBoolCols(str, node->fldname, len)) + +#define booltostr(x) ((x) ? "true" : "false") + + +/* + * outToken + * Convert an ordinary string (eg, an identifier) into a form that + * will be decoded back to a plain token by read.c's functions. + * + * If a null string pointer is given, it is encoded as '<>'. + * An empty string is encoded as '""'. To avoid ambiguity, input + * strings beginning with '<' or '"' receive a leading backslash. + */ +void +outToken(StringInfo str, const char *s) +{ + if (s == NULL) + { + appendStringInfoString(str, "<>"); + return; + } + if (*s == '\0') + { + appendStringInfoString(str, "\"\""); + return; + } + + /* + * Look for characters or patterns that are treated specially by read.c + * (either in pg_strtok() or in nodeRead()), and therefore need a + * protective backslash. + */ + /* These characters only need to be quoted at the start of the string */ + if (*s == '<' || + *s == '"' || + isdigit((unsigned char) *s) || + ((*s == '+' || *s == '-') && + (isdigit((unsigned char) s[1]) || s[1] == '.'))) + appendStringInfoChar(str, '\\'); + while (*s) + { + /* These chars must be backslashed anywhere in the string */ + if (*s == ' ' || *s == '\n' || *s == '\t' || + *s == '(' || *s == ')' || *s == '{' || *s == '}' || + *s == '\\') + appendStringInfoChar(str, '\\'); + appendStringInfoChar(str, *s++); + } +} + +/* + * Convert one char. Goes through outToken() so that special characters are + * escaped. + */ +static void +outChar(StringInfo str, char c) +{ + char in[2]; + + /* Traditionally, we've represented \0 as <>, so keep doing that */ + if (c == '\0') + { + appendStringInfoString(str, "<>"); + return; + } + + in[0] = c; + in[1] = '\0'; + + outToken(str, in); +} + +/* + * Convert a double value, attempting to ensure the value is preserved exactly. + */ +static void +outDouble(StringInfo str, double d) +{ + char buf[DOUBLE_SHORTEST_DECIMAL_LEN]; + + double_to_shortest_decimal_buf(d, buf); + appendStringInfoString(str, buf); +} + +/* + * common implementation for scalar-array-writing functions + * + * The data format is either "<>" for a NULL pointer or "(item item item)". + * fmtstr must include a leading space, and the rest of it must produce + * something that will be seen as a single simple token by pg_strtok(). + * convfunc can be empty, or the name of a conversion macro or function. + */ +#define WRITE_SCALAR_ARRAY(fnname, datatype, fmtstr, convfunc) \ +static void \ +fnname(StringInfo str, const datatype *arr, int len) \ +{ \ + if (arr != NULL) \ + { \ + appendStringInfoChar(str, '('); \ + for (int i = 0; i < len; i++) \ + appendStringInfo(str, fmtstr, convfunc(arr[i])); \ + appendStringInfoChar(str, ')'); \ + } \ + else \ + appendStringInfoString(str, "<>"); \ +} + +WRITE_SCALAR_ARRAY(writeAttrNumberCols, AttrNumber, " %d",) +WRITE_SCALAR_ARRAY(writeOidCols, Oid, " %u",) +WRITE_SCALAR_ARRAY(writeIndexCols, Index, " %u",) +WRITE_SCALAR_ARRAY(writeIntCols, int, " %d",) +WRITE_SCALAR_ARRAY(writeBoolCols, bool, " %s", booltostr) + +/* + * Print an array (not a List) of Node pointers. + * + * The decoration is identical to that of scalar arrays, but we can't + * quite use appendStringInfo() in the loop. + */ +static void +writeNodeArray(StringInfo str, const Node *const *arr, int len) +{ + if (arr != NULL) + { + appendStringInfoChar(str, '('); + for (int i = 0; i < len; i++) + { + appendStringInfoChar(str, ' '); + outNode(str, arr[i]); + } + appendStringInfoChar(str, ')'); + } + else + appendStringInfoString(str, "<>"); +} + +/* + * Print a List. + */ +static void +_outList(StringInfo str, const List *node) +{ + const ListCell *lc; + + appendStringInfoChar(str, '('); + + if (IsA(node, IntList)) + appendStringInfoChar(str, 'i'); + else if (IsA(node, OidList)) + appendStringInfoChar(str, 'o'); + else if (IsA(node, XidList)) + appendStringInfoChar(str, 'x'); + + foreach(lc, node) + { + /* + * For the sake of backward compatibility, we emit a slightly + * different whitespace format for lists of nodes vs. other types of + * lists. XXX: is this necessary? + */ + if (IsA(node, List)) + { + outNode(str, lfirst(lc)); + if (lnext(node, lc)) + appendStringInfoChar(str, ' '); + } + else if (IsA(node, IntList)) + appendStringInfo(str, " %d", lfirst_int(lc)); + else if (IsA(node, OidList)) + appendStringInfo(str, " %u", lfirst_oid(lc)); + else if (IsA(node, XidList)) + appendStringInfo(str, " %u", lfirst_xid(lc)); + else + elog(ERROR, "unrecognized list node type: %d", + (int) node->type); + } + + appendStringInfoChar(str, ')'); +} + +/* + * outBitmapset - + * converts a bitmap set of integers + * + * Note: the output format is "(b int int ...)", similar to an integer List. + * + * We export this function for use by extensions that define extensible nodes. + * That's somewhat historical, though, because calling outNode() will work. + */ +void +outBitmapset(StringInfo str, const Bitmapset *bms) +{ + int x; + + appendStringInfoChar(str, '('); + appendStringInfoChar(str, 'b'); + x = -1; + while ((x = bms_next_member(bms, x)) >= 0) + appendStringInfo(str, " %d", x); + appendStringInfoChar(str, ')'); +} + +/* + * Print the value of a Datum given its type. + */ +void +outDatum(StringInfo str, Datum value, int typlen, bool typbyval) +{ + Size length, + i; + char *s; + + length = datumGetSize(value, typbyval, typlen); + + if (typbyval) + { + s = (char *) (&value); + appendStringInfo(str, "%u [ ", (unsigned int) length); + for (i = 0; i < (Size) sizeof(Datum); i++) + appendStringInfo(str, "%d ", (int) (s[i])); + appendStringInfoChar(str, ']'); + } + else + { + s = (char *) DatumGetPointer(value); + if (!PointerIsValid(s)) + appendStringInfoString(str, "0 [ ]"); + else + { + appendStringInfo(str, "%u [ ", (unsigned int) length); + for (i = 0; i < length; i++) + appendStringInfo(str, "%d ", (int) (s[i])); + appendStringInfoChar(str, ']'); + } + } +} + + +#include "outfuncs.funcs.c" + + +/* + * Support functions for nodes with custom_read_write attribute or + * special_read_write attribute + */ + +static void +_outConst(StringInfo str, const Const *node) +{ + WRITE_NODE_TYPE("CONST"); + + WRITE_OID_FIELD(consttype); + WRITE_INT_FIELD(consttypmod); + WRITE_OID_FIELD(constcollid); + WRITE_INT_FIELD(constlen); + WRITE_BOOL_FIELD(constbyval); + WRITE_BOOL_FIELD(constisnull); + WRITE_LOCATION_FIELD(location); + + appendStringInfoString(str, " :constvalue "); + if (node->constisnull) + appendStringInfoString(str, "<>"); + else + outDatum(str, node->constvalue, node->constlen, node->constbyval); +} + +static void +_outBoolExpr(StringInfo str, const BoolExpr *node) +{ + char *opstr = NULL; + + WRITE_NODE_TYPE("BOOLEXPR"); + + /* do-it-yourself enum representation */ + switch (node->boolop) + { + case AND_EXPR: + opstr = "and"; + break; + case OR_EXPR: + opstr = "or"; + break; + case NOT_EXPR: + opstr = "not"; + break; + } + appendStringInfoString(str, " :boolop "); + outToken(str, opstr); + + WRITE_NODE_FIELD(args); + WRITE_LOCATION_FIELD(location); +} + +static void +_outForeignKeyOptInfo(StringInfo str, const ForeignKeyOptInfo *node) +{ + int i; + + WRITE_NODE_TYPE("FOREIGNKEYOPTINFO"); + + WRITE_UINT_FIELD(con_relid); + WRITE_UINT_FIELD(ref_relid); + WRITE_INT_FIELD(nkeys); + WRITE_ATTRNUMBER_ARRAY(conkey, node->nkeys); + WRITE_ATTRNUMBER_ARRAY(confkey, node->nkeys); + WRITE_OID_ARRAY(conpfeqop, node->nkeys); + WRITE_INT_FIELD(nmatched_ec); + WRITE_INT_FIELD(nconst_ec); + WRITE_INT_FIELD(nmatched_rcols); + WRITE_INT_FIELD(nmatched_ri); + /* for compactness, just print the number of matches per column: */ + appendStringInfoString(str, " :eclass"); + for (i = 0; i < node->nkeys; i++) + appendStringInfo(str, " %d", (node->eclass[i] != NULL)); + appendStringInfoString(str, " :rinfos"); + for (i = 0; i < node->nkeys; i++) + appendStringInfo(str, " %d", list_length(node->rinfos[i])); +} + +static void +_outEquivalenceClass(StringInfo str, const EquivalenceClass *node) +{ + /* + * To simplify reading, we just chase up to the topmost merged EC and + * print that, without bothering to show the merge-ees separately. + */ + while (node->ec_merged) + node = node->ec_merged; + + WRITE_NODE_TYPE("EQUIVALENCECLASS"); + + WRITE_NODE_FIELD(ec_opfamilies); + WRITE_OID_FIELD(ec_collation); + WRITE_NODE_FIELD(ec_members); + WRITE_NODE_FIELD(ec_sources); + WRITE_NODE_FIELD(ec_derives); + WRITE_BITMAPSET_FIELD(ec_relids); + WRITE_BOOL_FIELD(ec_has_const); + WRITE_BOOL_FIELD(ec_has_volatile); + WRITE_BOOL_FIELD(ec_broken); + WRITE_UINT_FIELD(ec_sortref); + WRITE_UINT_FIELD(ec_min_security); + WRITE_UINT_FIELD(ec_max_security); +} + +static void +_outExtensibleNode(StringInfo str, const ExtensibleNode *node) +{ + const ExtensibleNodeMethods *methods; + + methods = GetExtensibleNodeMethods(node->extnodename, false); + + WRITE_NODE_TYPE("EXTENSIBLENODE"); + + WRITE_STRING_FIELD(extnodename); + + /* serialize the private fields */ + methods->nodeOut(str, node); +} + +static void +_outRangeTblEntry(StringInfo str, const RangeTblEntry *node) +{ + WRITE_NODE_TYPE("RANGETBLENTRY"); + + /* put alias + eref first to make dump more legible */ + WRITE_NODE_FIELD(alias); + WRITE_NODE_FIELD(eref); + WRITE_ENUM_FIELD(rtekind, RTEKind); + + switch (node->rtekind) + { + case RTE_RELATION: + WRITE_OID_FIELD(relid); + WRITE_CHAR_FIELD(relkind); + WRITE_INT_FIELD(rellockmode); + WRITE_NODE_FIELD(tablesample); + WRITE_UINT_FIELD(perminfoindex); + break; + case RTE_SUBQUERY: + WRITE_NODE_FIELD(subquery); + WRITE_BOOL_FIELD(security_barrier); + /* we re-use these RELATION fields, too: */ + WRITE_OID_FIELD(relid); + WRITE_CHAR_FIELD(relkind); + WRITE_INT_FIELD(rellockmode); + WRITE_UINT_FIELD(perminfoindex); + break; + case RTE_JOIN: + WRITE_ENUM_FIELD(jointype, JoinType); + WRITE_INT_FIELD(joinmergedcols); + WRITE_NODE_FIELD(joinaliasvars); + WRITE_NODE_FIELD(joinleftcols); + WRITE_NODE_FIELD(joinrightcols); + WRITE_NODE_FIELD(join_using_alias); + break; + case RTE_FUNCTION: + WRITE_NODE_FIELD(functions); + WRITE_BOOL_FIELD(funcordinality); + break; + case RTE_TABLEFUNC: + WRITE_NODE_FIELD(tablefunc); + break; + case RTE_VALUES: + WRITE_NODE_FIELD(values_lists); + WRITE_NODE_FIELD(coltypes); + WRITE_NODE_FIELD(coltypmods); + WRITE_NODE_FIELD(colcollations); + break; + case RTE_CTE: + WRITE_STRING_FIELD(ctename); + WRITE_UINT_FIELD(ctelevelsup); + WRITE_BOOL_FIELD(self_reference); + WRITE_NODE_FIELD(coltypes); + WRITE_NODE_FIELD(coltypmods); + WRITE_NODE_FIELD(colcollations); + break; + case RTE_NAMEDTUPLESTORE: + WRITE_STRING_FIELD(enrname); + WRITE_FLOAT_FIELD(enrtuples); + WRITE_NODE_FIELD(coltypes); + WRITE_NODE_FIELD(coltypmods); + WRITE_NODE_FIELD(colcollations); + /* we re-use these RELATION fields, too: */ + WRITE_OID_FIELD(relid); + break; + case RTE_RESULT: + /* no extra fields */ + break; + default: + elog(ERROR, "unrecognized RTE kind: %d", (int) node->rtekind); + break; + } + + WRITE_BOOL_FIELD(lateral); + WRITE_BOOL_FIELD(inh); + WRITE_BOOL_FIELD(inFromCl); + WRITE_NODE_FIELD(securityQuals); +} + +static void +_outA_Expr(StringInfo str, const A_Expr *node) +{ + WRITE_NODE_TYPE("A_EXPR"); + + switch (node->kind) + { + case AEXPR_OP: + WRITE_NODE_FIELD(name); + break; + case AEXPR_OP_ANY: + appendStringInfoString(str, " ANY"); + WRITE_NODE_FIELD(name); + break; + case AEXPR_OP_ALL: + appendStringInfoString(str, " ALL"); + WRITE_NODE_FIELD(name); + break; + case AEXPR_DISTINCT: + appendStringInfoString(str, " DISTINCT"); + WRITE_NODE_FIELD(name); + break; + case AEXPR_NOT_DISTINCT: + appendStringInfoString(str, " NOT_DISTINCT"); + WRITE_NODE_FIELD(name); + break; + case AEXPR_NULLIF: + appendStringInfoString(str, " NULLIF"); + WRITE_NODE_FIELD(name); + break; + case AEXPR_IN: + appendStringInfoString(str, " IN"); + WRITE_NODE_FIELD(name); + break; + case AEXPR_LIKE: + appendStringInfoString(str, " LIKE"); + WRITE_NODE_FIELD(name); + break; + case AEXPR_ILIKE: + appendStringInfoString(str, " ILIKE"); + WRITE_NODE_FIELD(name); + break; + case AEXPR_SIMILAR: + appendStringInfoString(str, " SIMILAR"); + WRITE_NODE_FIELD(name); + break; + case AEXPR_BETWEEN: + appendStringInfoString(str, " BETWEEN"); + WRITE_NODE_FIELD(name); + break; + case AEXPR_NOT_BETWEEN: + appendStringInfoString(str, " NOT_BETWEEN"); + WRITE_NODE_FIELD(name); + break; + case AEXPR_BETWEEN_SYM: + appendStringInfoString(str, " BETWEEN_SYM"); + WRITE_NODE_FIELD(name); + break; + case AEXPR_NOT_BETWEEN_SYM: + appendStringInfoString(str, " NOT_BETWEEN_SYM"); + WRITE_NODE_FIELD(name); + break; + default: + elog(ERROR, "unrecognized A_Expr_Kind: %d", (int) node->kind); + break; + } + + WRITE_NODE_FIELD(lexpr); + WRITE_NODE_FIELD(rexpr); + WRITE_LOCATION_FIELD(location); +} + +static void +_outInteger(StringInfo str, const Integer *node) +{ + appendStringInfo(str, "%d", node->ival); +} + +static void +_outFloat(StringInfo str, const Float *node) +{ + /* + * We assume the value is a valid numeric literal and so does not need + * quoting. + */ + appendStringInfoString(str, node->fval); +} + +static void +_outBoolean(StringInfo str, const Boolean *node) +{ + appendStringInfoString(str, node->boolval ? "true" : "false"); +} + +static void +_outString(StringInfo str, const String *node) +{ + /* + * We use outToken to provide escaping of the string's content, but we + * don't want it to convert an empty string to '""', because we're putting + * double quotes around the string already. + */ + appendStringInfoChar(str, '"'); + if (node->sval[0] != '\0') + outToken(str, node->sval); + appendStringInfoChar(str, '"'); +} + +static void +_outBitString(StringInfo str, const BitString *node) +{ + /* + * The lexer will always produce a string starting with 'b' or 'x'. There + * might be characters following that that need escaping, but outToken + * won't escape the 'b' or 'x'. This is relied on by nodeTokenType. + */ + Assert(node->bsval[0] == 'b' || node->bsval[0] == 'x'); + outToken(str, node->bsval); +} + +static void +_outA_Const(StringInfo str, const A_Const *node) +{ + WRITE_NODE_TYPE("A_CONST"); + + if (node->isnull) + appendStringInfoString(str, " NULL"); + else + { + appendStringInfoString(str, " :val "); + outNode(str, &node->val); + } + WRITE_LOCATION_FIELD(location); +} + +static void +_outConstraint(StringInfo str, const Constraint *node) +{ + WRITE_NODE_TYPE("CONSTRAINT"); + + WRITE_STRING_FIELD(conname); + WRITE_BOOL_FIELD(deferrable); + WRITE_BOOL_FIELD(initdeferred); + WRITE_LOCATION_FIELD(location); + + appendStringInfoString(str, " :contype "); + switch (node->contype) + { + case CONSTR_NULL: + appendStringInfoString(str, "NULL"); + break; + + case CONSTR_NOTNULL: + appendStringInfoString(str, "NOT_NULL"); + break; + + case CONSTR_DEFAULT: + appendStringInfoString(str, "DEFAULT"); + WRITE_NODE_FIELD(raw_expr); + WRITE_STRING_FIELD(cooked_expr); + break; + + case CONSTR_IDENTITY: + appendStringInfoString(str, "IDENTITY"); + WRITE_NODE_FIELD(options); + WRITE_CHAR_FIELD(generated_when); + break; + + case CONSTR_GENERATED: + appendStringInfoString(str, "GENERATED"); + WRITE_NODE_FIELD(raw_expr); + WRITE_STRING_FIELD(cooked_expr); + WRITE_CHAR_FIELD(generated_when); + break; + + case CONSTR_CHECK: + appendStringInfoString(str, "CHECK"); + WRITE_BOOL_FIELD(is_no_inherit); + WRITE_NODE_FIELD(raw_expr); + WRITE_STRING_FIELD(cooked_expr); + WRITE_BOOL_FIELD(skip_validation); + WRITE_BOOL_FIELD(initially_valid); + break; + + case CONSTR_PRIMARY: + appendStringInfoString(str, "PRIMARY_KEY"); + WRITE_NODE_FIELD(keys); + WRITE_NODE_FIELD(including); + WRITE_NODE_FIELD(options); + WRITE_STRING_FIELD(indexname); + WRITE_STRING_FIELD(indexspace); + WRITE_BOOL_FIELD(reset_default_tblspc); + /* access_method and where_clause not currently used */ + break; + + case CONSTR_UNIQUE: + appendStringInfoString(str, "UNIQUE"); + WRITE_BOOL_FIELD(nulls_not_distinct); + WRITE_NODE_FIELD(keys); + WRITE_NODE_FIELD(including); + WRITE_NODE_FIELD(options); + WRITE_STRING_FIELD(indexname); + WRITE_STRING_FIELD(indexspace); + WRITE_BOOL_FIELD(reset_default_tblspc); + /* access_method and where_clause not currently used */ + break; + + case CONSTR_EXCLUSION: + appendStringInfoString(str, "EXCLUSION"); + WRITE_NODE_FIELD(exclusions); + WRITE_NODE_FIELD(including); + WRITE_NODE_FIELD(options); + WRITE_STRING_FIELD(indexname); + WRITE_STRING_FIELD(indexspace); + WRITE_BOOL_FIELD(reset_default_tblspc); + WRITE_STRING_FIELD(access_method); + WRITE_NODE_FIELD(where_clause); + break; + + case CONSTR_FOREIGN: + appendStringInfoString(str, "FOREIGN_KEY"); + WRITE_NODE_FIELD(pktable); + WRITE_NODE_FIELD(fk_attrs); + WRITE_NODE_FIELD(pk_attrs); + WRITE_CHAR_FIELD(fk_matchtype); + WRITE_CHAR_FIELD(fk_upd_action); + WRITE_CHAR_FIELD(fk_del_action); + WRITE_NODE_FIELD(fk_del_set_cols); + WRITE_NODE_FIELD(old_conpfeqop); + WRITE_OID_FIELD(old_pktable_oid); + WRITE_BOOL_FIELD(skip_validation); + WRITE_BOOL_FIELD(initially_valid); + break; + + case CONSTR_ATTR_DEFERRABLE: + appendStringInfoString(str, "ATTR_DEFERRABLE"); + break; + + case CONSTR_ATTR_NOT_DEFERRABLE: + appendStringInfoString(str, "ATTR_NOT_DEFERRABLE"); + break; + + case CONSTR_ATTR_DEFERRED: + appendStringInfoString(str, "ATTR_DEFERRED"); + break; + + case CONSTR_ATTR_IMMEDIATE: + appendStringInfoString(str, "ATTR_IMMEDIATE"); + break; + + default: + elog(ERROR, "unrecognized ConstrType: %d", (int) node->contype); + break; + } +} + + +/* + * outNode - + * converts a Node into ascii string and append it to 'str' + */ +void +outNode(StringInfo str, const void *obj) +{ + /* Guard against stack overflow due to overly complex expressions */ + check_stack_depth(); + + if (obj == NULL) + appendStringInfoString(str, "<>"); + else if (IsA(obj, List) || IsA(obj, IntList) || IsA(obj, OidList) || + IsA(obj, XidList)) + _outList(str, obj); + /* nodeRead does not want to see { } around these! */ + else if (IsA(obj, Integer)) + _outInteger(str, (Integer *) obj); + else if (IsA(obj, Float)) + _outFloat(str, (Float *) obj); + else if (IsA(obj, Boolean)) + _outBoolean(str, (Boolean *) obj); + else if (IsA(obj, String)) + _outString(str, (String *) obj); + else if (IsA(obj, BitString)) + _outBitString(str, (BitString *) obj); + else if (IsA(obj, Bitmapset)) + outBitmapset(str, (Bitmapset *) obj); + else + { + appendStringInfoChar(str, '{'); + switch (nodeTag(obj)) + { +#include "outfuncs.switch.c" + + default: + + /* + * This should be an ERROR, but it's too useful to be able to + * dump structures that outNode only understands part of. + */ + elog(WARNING, "could not dump unrecognized node type: %d", + (int) nodeTag(obj)); + break; + } + appendStringInfoChar(str, '}'); + } +} + +/* + * nodeToString - + * returns the ascii representation of the Node as a palloc'd string + */ +char * +nodeToString(const void *obj) +{ + StringInfoData str; + + /* see stringinfo.h for an explanation of this maneuver */ + initStringInfo(&str); + outNode(&str, obj); + return str.data; +} + +/* + * bmsToString - + * returns the ascii representation of the Bitmapset as a palloc'd string + */ +char * +bmsToString(const Bitmapset *bms) +{ + StringInfoData str; + + /* see stringinfo.h for an explanation of this maneuver */ + initStringInfo(&str); + outBitmapset(&str, bms); + return str.data; +} |