Logo Search packages:      
Sourcecode: postgresql-8.4 version File versions  Download package

readfuncs.c

/*-------------------------------------------------------------------------
 *
 * readfuncs.c
 *      Reader functions for Postgres tree nodes.
 *
 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *      $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.222 2009/06/11 14:48:58 momjian Exp $
 *
 * NOTES
 *      Path and Plan nodes do not have any readfuncs support, because we
 *      never have occasion to read them in.    (There was once code here that
 *      claimed to read them, but it was broken as well as unused.)  We
 *      never read executor state trees, either.
 *
 *      Parse location fields are written out by outfuncs.c, but only for
 *      possible debugging use.  When reading a location field, we discard
 *      the stored value and set the location field to -1 (ie, "unknown").
 *      This is because nodes coming from a stored rule should not be thought
 *      to have a known location in the current query's text.
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include <math.h>

#include "nodes/parsenodes.h"
#include "nodes/readfuncs.h"


/*
 * Macros to simplify reading 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 a Read
 * routine.
 */

/* Macros for declaring appropriate local variables */

/* A few guys need only local_node */
#define READ_LOCALS_NO_FIELDS(nodeTypeName) \
      nodeTypeName *local_node = makeNode(nodeTypeName)

/* And a few guys need only the pg_strtok support fields */
#define READ_TEMP_LOCALS()    \
      char     *token;        \
      int               length

/* ... but most need both */
#define READ_LOCALS(nodeTypeName)               \
      READ_LOCALS_NO_FIELDS(nodeTypeName);      \
      READ_TEMP_LOCALS()

/* Read an integer field (anything written as ":fldname %d") */
#define READ_INT_FIELD(fldname) \
      token = pg_strtok(&length);         /* skip :fldname */ \
      token = pg_strtok(&length);         /* get field value */ \
      local_node->fldname = atoi(token)

/* Read an unsigned integer field (anything written as ":fldname %u") */
#define READ_UINT_FIELD(fldname) \
      token = pg_strtok(&length);         /* skip :fldname */ \
      token = pg_strtok(&length);         /* get field value */ \
      local_node->fldname = atoui(token)

/* Read an OID field (don't hard-wire assumption that OID is same as uint) */
#define READ_OID_FIELD(fldname) \
      token = pg_strtok(&length);         /* skip :fldname */ \
      token = pg_strtok(&length);         /* get field value */ \
      local_node->fldname = atooid(token)

/* Read a char field (ie, one ascii character) */
#define READ_CHAR_FIELD(fldname) \
      token = pg_strtok(&length);         /* skip :fldname */ \
      token = pg_strtok(&length);         /* get field value */ \
      local_node->fldname = token[0]

/* Read an enumerated-type field that was written as an integer code */
#define READ_ENUM_FIELD(fldname, enumtype) \
      token = pg_strtok(&length);         /* skip :fldname */ \
      token = pg_strtok(&length);         /* get field value */ \
      local_node->fldname = (enumtype) atoi(token)

/* Read a float field */
#define READ_FLOAT_FIELD(fldname) \
      token = pg_strtok(&length);         /* skip :fldname */ \
      token = pg_strtok(&length);         /* get field value */ \
      local_node->fldname = atof(token)

/* Read a boolean field */
#define READ_BOOL_FIELD(fldname) \
      token = pg_strtok(&length);         /* skip :fldname */ \
      token = pg_strtok(&length);         /* get field value */ \
      local_node->fldname = strtobool(token)

/* Read a character-string field */
#define READ_STRING_FIELD(fldname) \
      token = pg_strtok(&length);         /* skip :fldname */ \
      token = pg_strtok(&length);         /* get field value */ \
      local_node->fldname = nullable_string(token, length)

/* Read a parse location field (and throw away the value, per notes above) */
#define READ_LOCATION_FIELD(fldname) \
      token = pg_strtok(&length);         /* skip :fldname */ \
      token = pg_strtok(&length);         /* get field value */ \
      local_node->fldname = -1      /* set field to "unknown" */

/* Read a Node field */
#define READ_NODE_FIELD(fldname) \
      token = pg_strtok(&length);         /* skip :fldname */ \
      local_node->fldname = nodeRead(NULL, 0)

/* Read a bitmapset field */
#define READ_BITMAPSET_FIELD(fldname) \
      token = pg_strtok(&length);         /* skip :fldname */ \
      local_node->fldname = _readBitmapset()

/* Routine exit */
#define READ_DONE() \
      return local_node


/*
 * NOTE: use atoi() to read values written with %d, or atoui() to read
 * values written with %u in outfuncs.c.  An exception is OID values,
 * for which use atooid().    (As of 7.1, outfuncs.c writes OIDs as %u,
 * but this will probably change in the future.)
 */
#define atoui(x)  ((unsigned int) strtoul((x), NULL, 10))

#define atooid(x)  ((Oid) strtoul((x), NULL, 10))

#define strtobool(x)  ((*(x) == 't') ? true : false)

#define nullable_string(token,length)  \
      ((length) == 0 ? NULL : debackslash(token, length))


static Datum readDatum(bool typbyval);

/*
 * _readBitmapset
 */
static Bitmapset *
_readBitmapset(void)
{
      Bitmapset  *result = NULL;

      READ_TEMP_LOCALS();

      token = pg_strtok(&length);
      if (token == NULL)
            elog(ERROR, "incomplete Bitmapset structure");
      if (length != 1 || token[0] != '(')
            elog(ERROR, "unrecognized token: \"%.*s\"", length, token);

      token = pg_strtok(&length);
      if (token == NULL)
            elog(ERROR, "incomplete Bitmapset structure");
      if (length != 1 || token[0] != 'b')
            elog(ERROR, "unrecognized token: \"%.*s\"", length, token);

      for (;;)
      {
            int               val;
            char     *endptr;

            token = pg_strtok(&length);
            if (token == NULL)
                  elog(ERROR, "unterminated Bitmapset structure");
            if (length == 1 && token[0] == ')')
                  break;
            val = (int) strtol(token, &endptr, 10);
            if (endptr != token + length)
                  elog(ERROR, "unrecognized integer: \"%.*s\"", length, token);
            result = bms_add_member(result, val);
      }

      return result;
}


/*
 * _readQuery
 */
static Query *
_readQuery(void)
{
      READ_LOCALS(Query);

      READ_ENUM_FIELD(commandType, CmdType);
      READ_ENUM_FIELD(querySource, QuerySource);
      READ_BOOL_FIELD(canSetTag);
      READ_NODE_FIELD(utilityStmt);
      READ_INT_FIELD(resultRelation);
      READ_NODE_FIELD(intoClause);
      READ_BOOL_FIELD(hasAggs);
      READ_BOOL_FIELD(hasWindowFuncs);
      READ_BOOL_FIELD(hasSubLinks);
      READ_BOOL_FIELD(hasDistinctOn);
      READ_BOOL_FIELD(hasRecursive);
      READ_NODE_FIELD(cteList);
      READ_NODE_FIELD(rtable);
      READ_NODE_FIELD(jointree);
      READ_NODE_FIELD(targetList);
      READ_NODE_FIELD(returningList);
      READ_NODE_FIELD(groupClause);
      READ_NODE_FIELD(havingQual);
      READ_NODE_FIELD(windowClause);
      READ_NODE_FIELD(distinctClause);
      READ_NODE_FIELD(sortClause);
      READ_NODE_FIELD(limitOffset);
      READ_NODE_FIELD(limitCount);
      READ_NODE_FIELD(rowMarks);
      READ_NODE_FIELD(setOperations);

      READ_DONE();
}

/*
 * _readNotifyStmt
 */
static NotifyStmt *
_readNotifyStmt(void)
{
      READ_LOCALS(NotifyStmt);

      READ_STRING_FIELD(conditionname);

      READ_DONE();
}

/*
 * _readDeclareCursorStmt
 */
static DeclareCursorStmt *
_readDeclareCursorStmt(void)
{
      READ_LOCALS(DeclareCursorStmt);

      READ_STRING_FIELD(portalname);
      READ_INT_FIELD(options);
      READ_NODE_FIELD(query);

      READ_DONE();
}

/*
 * _readSortGroupClause
 */
static SortGroupClause *
_readSortGroupClause(void)
{
      READ_LOCALS(SortGroupClause);

      READ_UINT_FIELD(tleSortGroupRef);
      READ_OID_FIELD(eqop);
      READ_OID_FIELD(sortop);
      READ_BOOL_FIELD(nulls_first);

      READ_DONE();
}

/*
 * _readWindowClause
 */
static WindowClause *
_readWindowClause(void)
{
      READ_LOCALS(WindowClause);

      READ_STRING_FIELD(name);
      READ_STRING_FIELD(refname);
      READ_NODE_FIELD(partitionClause);
      READ_NODE_FIELD(orderClause);
      READ_INT_FIELD(frameOptions);
      READ_UINT_FIELD(winref);
      READ_BOOL_FIELD(copiedOrder);

      READ_DONE();
}

/*
 * _readRowMarkClause
 */
static RowMarkClause *
_readRowMarkClause(void)
{
      READ_LOCALS(RowMarkClause);

      READ_UINT_FIELD(rti);
      READ_UINT_FIELD(prti);
      READ_BOOL_FIELD(forUpdate);
      READ_BOOL_FIELD(noWait);
      READ_BOOL_FIELD(isParent);

      READ_DONE();
}

/*
 * _readCommonTableExpr
 */
static CommonTableExpr *
_readCommonTableExpr(void)
{
      READ_LOCALS(CommonTableExpr);

      READ_STRING_FIELD(ctename);
      READ_NODE_FIELD(aliascolnames);
      READ_NODE_FIELD(ctequery);
      READ_LOCATION_FIELD(location);
      READ_BOOL_FIELD(cterecursive);
      READ_INT_FIELD(cterefcount);
      READ_NODE_FIELD(ctecolnames);
      READ_NODE_FIELD(ctecoltypes);
      READ_NODE_FIELD(ctecoltypmods);

      READ_DONE();
}

/*
 * _readSetOperationStmt
 */
static SetOperationStmt *
_readSetOperationStmt(void)
{
      READ_LOCALS(SetOperationStmt);

      READ_ENUM_FIELD(op, SetOperation);
      READ_BOOL_FIELD(all);
      READ_NODE_FIELD(larg);
      READ_NODE_FIELD(rarg);
      READ_NODE_FIELD(colTypes);
      READ_NODE_FIELD(colTypmods);
      READ_NODE_FIELD(groupClauses);

      READ_DONE();
}


/*
 *    Stuff from primnodes.h.
 */

static Alias *
_readAlias(void)
{
      READ_LOCALS(Alias);

      READ_STRING_FIELD(aliasname);
      READ_NODE_FIELD(colnames);

      READ_DONE();
}

static RangeVar *
_readRangeVar(void)
{
      READ_LOCALS(RangeVar);

      local_node->catalogname = NULL;           /* not currently saved in output
                                                             * format */

      READ_STRING_FIELD(schemaname);
      READ_STRING_FIELD(relname);
      READ_ENUM_FIELD(inhOpt, InhOption);
      READ_BOOL_FIELD(istemp);
      READ_NODE_FIELD(alias);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

static IntoClause *
_readIntoClause(void)
{
      READ_LOCALS(IntoClause);

      READ_NODE_FIELD(rel);
      READ_NODE_FIELD(colNames);
      READ_NODE_FIELD(options);
      READ_ENUM_FIELD(onCommit, OnCommitAction);
      READ_STRING_FIELD(tableSpaceName);

      READ_DONE();
}

/*
 * _readVar
 */
static Var *
_readVar(void)
{
      READ_LOCALS(Var);

      READ_UINT_FIELD(varno);
      READ_INT_FIELD(varattno);
      READ_OID_FIELD(vartype);
      READ_INT_FIELD(vartypmod);
      READ_UINT_FIELD(varlevelsup);
      READ_UINT_FIELD(varnoold);
      READ_INT_FIELD(varoattno);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readConst
 */
static Const *
_readConst(void)
{
      READ_LOCALS(Const);

      READ_OID_FIELD(consttype);
      READ_INT_FIELD(consttypmod);
      READ_INT_FIELD(constlen);
      READ_BOOL_FIELD(constbyval);
      READ_BOOL_FIELD(constisnull);
      READ_LOCATION_FIELD(location);

      token = pg_strtok(&length); /* skip :constvalue */
      if (local_node->constisnull)
            token = pg_strtok(&length);         /* skip "<>" */
      else
            local_node->constvalue = readDatum(local_node->constbyval);

      READ_DONE();
}

/*
 * _readParam
 */
static Param *
_readParam(void)
{
      READ_LOCALS(Param);

      READ_ENUM_FIELD(paramkind, ParamKind);
      READ_INT_FIELD(paramid);
      READ_OID_FIELD(paramtype);
      READ_INT_FIELD(paramtypmod);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readAggref
 */
static Aggref *
_readAggref(void)
{
      READ_LOCALS(Aggref);

      READ_OID_FIELD(aggfnoid);
      READ_OID_FIELD(aggtype);
      READ_NODE_FIELD(args);
      READ_UINT_FIELD(agglevelsup);
      READ_BOOL_FIELD(aggstar);
      READ_BOOL_FIELD(aggdistinct);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readWindowFunc
 */
static WindowFunc *
_readWindowFunc(void)
{
      READ_LOCALS(WindowFunc);

      READ_OID_FIELD(winfnoid);
      READ_OID_FIELD(wintype);
      READ_NODE_FIELD(args);
      READ_UINT_FIELD(winref);
      READ_BOOL_FIELD(winstar);
      READ_BOOL_FIELD(winagg);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readArrayRef
 */
static ArrayRef *
_readArrayRef(void)
{
      READ_LOCALS(ArrayRef);

      READ_OID_FIELD(refarraytype);
      READ_OID_FIELD(refelemtype);
      READ_INT_FIELD(reftypmod);
      READ_NODE_FIELD(refupperindexpr);
      READ_NODE_FIELD(reflowerindexpr);
      READ_NODE_FIELD(refexpr);
      READ_NODE_FIELD(refassgnexpr);

      READ_DONE();
}

/*
 * _readFuncExpr
 */
static FuncExpr *
_readFuncExpr(void)
{
      READ_LOCALS(FuncExpr);

      READ_OID_FIELD(funcid);
      READ_OID_FIELD(funcresulttype);
      READ_BOOL_FIELD(funcretset);
      READ_ENUM_FIELD(funcformat, CoercionForm);
      READ_NODE_FIELD(args);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readOpExpr
 */
static OpExpr *
_readOpExpr(void)
{
      READ_LOCALS(OpExpr);

      READ_OID_FIELD(opno);
      READ_OID_FIELD(opfuncid);

      /*
       * The opfuncid is stored in the textual format primarily for debugging
       * and documentation reasons.  We want to always read it as zero to force
       * it to be re-looked-up in the pg_operator entry.    This ensures that
       * stored rules don't have hidden dependencies on operators' functions.
       * (We don't currently support an ALTER OPERATOR command, but might
       * someday.)
       */
      local_node->opfuncid = InvalidOid;

      READ_OID_FIELD(opresulttype);
      READ_BOOL_FIELD(opretset);
      READ_NODE_FIELD(args);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readDistinctExpr
 */
static DistinctExpr *
_readDistinctExpr(void)
{
      READ_LOCALS(DistinctExpr);

      READ_OID_FIELD(opno);
      READ_OID_FIELD(opfuncid);

      /*
       * The opfuncid is stored in the textual format primarily for debugging
       * and documentation reasons.  We want to always read it as zero to force
       * it to be re-looked-up in the pg_operator entry.    This ensures that
       * stored rules don't have hidden dependencies on operators' functions.
       * (We don't currently support an ALTER OPERATOR command, but might
       * someday.)
       */
      local_node->opfuncid = InvalidOid;

      READ_OID_FIELD(opresulttype);
      READ_BOOL_FIELD(opretset);
      READ_NODE_FIELD(args);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readScalarArrayOpExpr
 */
static ScalarArrayOpExpr *
_readScalarArrayOpExpr(void)
{
      READ_LOCALS(ScalarArrayOpExpr);

      READ_OID_FIELD(opno);
      READ_OID_FIELD(opfuncid);

      /*
       * The opfuncid is stored in the textual format primarily for debugging
       * and documentation reasons.  We want to always read it as zero to force
       * it to be re-looked-up in the pg_operator entry.    This ensures that
       * stored rules don't have hidden dependencies on operators' functions.
       * (We don't currently support an ALTER OPERATOR command, but might
       * someday.)
       */
      local_node->opfuncid = InvalidOid;

      READ_BOOL_FIELD(useOr);
      READ_NODE_FIELD(args);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readBoolExpr
 */
static BoolExpr *
_readBoolExpr(void)
{
      READ_LOCALS(BoolExpr);

      /* do-it-yourself enum representation */
      token = pg_strtok(&length); /* skip :boolop */
      token = pg_strtok(&length); /* get field value */
      if (strncmp(token, "and", 3) == 0)
            local_node->boolop = AND_EXPR;
      else if (strncmp(token, "or", 2) == 0)
            local_node->boolop = OR_EXPR;
      else if (strncmp(token, "not", 3) == 0)
            local_node->boolop = NOT_EXPR;
      else
            elog(ERROR, "unrecognized boolop \"%.*s\"", length, token);

      READ_NODE_FIELD(args);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readSubLink
 */
static SubLink *
_readSubLink(void)
{
      READ_LOCALS(SubLink);

      READ_ENUM_FIELD(subLinkType, SubLinkType);
      READ_NODE_FIELD(testexpr);
      READ_NODE_FIELD(operName);
      READ_NODE_FIELD(subselect);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readSubPlan is not needed since it doesn't appear in stored rules.
 */

/*
 * _readFieldSelect
 */
static FieldSelect *
_readFieldSelect(void)
{
      READ_LOCALS(FieldSelect);

      READ_NODE_FIELD(arg);
      READ_INT_FIELD(fieldnum);
      READ_OID_FIELD(resulttype);
      READ_INT_FIELD(resulttypmod);

      READ_DONE();
}

/*
 * _readFieldStore
 */
static FieldStore *
_readFieldStore(void)
{
      READ_LOCALS(FieldStore);

      READ_NODE_FIELD(arg);
      READ_NODE_FIELD(newvals);
      READ_NODE_FIELD(fieldnums);
      READ_OID_FIELD(resulttype);

      READ_DONE();
}

/*
 * _readRelabelType
 */
static RelabelType *
_readRelabelType(void)
{
      READ_LOCALS(RelabelType);

      READ_NODE_FIELD(arg);
      READ_OID_FIELD(resulttype);
      READ_INT_FIELD(resulttypmod);
      READ_ENUM_FIELD(relabelformat, CoercionForm);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readCoerceViaIO
 */
static CoerceViaIO *
_readCoerceViaIO(void)
{
      READ_LOCALS(CoerceViaIO);

      READ_NODE_FIELD(arg);
      READ_OID_FIELD(resulttype);
      READ_ENUM_FIELD(coerceformat, CoercionForm);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readArrayCoerceExpr
 */
static ArrayCoerceExpr *
_readArrayCoerceExpr(void)
{
      READ_LOCALS(ArrayCoerceExpr);

      READ_NODE_FIELD(arg);
      READ_OID_FIELD(elemfuncid);
      READ_OID_FIELD(resulttype);
      READ_INT_FIELD(resulttypmod);
      READ_BOOL_FIELD(isExplicit);
      READ_ENUM_FIELD(coerceformat, CoercionForm);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readConvertRowtypeExpr
 */
static ConvertRowtypeExpr *
_readConvertRowtypeExpr(void)
{
      READ_LOCALS(ConvertRowtypeExpr);

      READ_NODE_FIELD(arg);
      READ_OID_FIELD(resulttype);
      READ_ENUM_FIELD(convertformat, CoercionForm);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readCaseExpr
 */
static CaseExpr *
_readCaseExpr(void)
{
      READ_LOCALS(CaseExpr);

      READ_OID_FIELD(casetype);
      READ_NODE_FIELD(arg);
      READ_NODE_FIELD(args);
      READ_NODE_FIELD(defresult);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readCaseWhen
 */
static CaseWhen *
_readCaseWhen(void)
{
      READ_LOCALS(CaseWhen);

      READ_NODE_FIELD(expr);
      READ_NODE_FIELD(result);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readCaseTestExpr
 */
static CaseTestExpr *
_readCaseTestExpr(void)
{
      READ_LOCALS(CaseTestExpr);

      READ_OID_FIELD(typeId);
      READ_INT_FIELD(typeMod);

      READ_DONE();
}

/*
 * _readArrayExpr
 */
static ArrayExpr *
_readArrayExpr(void)
{
      READ_LOCALS(ArrayExpr);

      READ_OID_FIELD(array_typeid);
      READ_OID_FIELD(element_typeid);
      READ_NODE_FIELD(elements);
      READ_BOOL_FIELD(multidims);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readRowExpr
 */
static RowExpr *
_readRowExpr(void)
{
      READ_LOCALS(RowExpr);

      READ_NODE_FIELD(args);
      READ_OID_FIELD(row_typeid);
      READ_ENUM_FIELD(row_format, CoercionForm);
      READ_NODE_FIELD(colnames);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readRowCompareExpr
 */
static RowCompareExpr *
_readRowCompareExpr(void)
{
      READ_LOCALS(RowCompareExpr);

      READ_ENUM_FIELD(rctype, RowCompareType);
      READ_NODE_FIELD(opnos);
      READ_NODE_FIELD(opfamilies);
      READ_NODE_FIELD(largs);
      READ_NODE_FIELD(rargs);

      READ_DONE();
}

/*
 * _readCoalesceExpr
 */
static CoalesceExpr *
_readCoalesceExpr(void)
{
      READ_LOCALS(CoalesceExpr);

      READ_OID_FIELD(coalescetype);
      READ_NODE_FIELD(args);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readMinMaxExpr
 */
static MinMaxExpr *
_readMinMaxExpr(void)
{
      READ_LOCALS(MinMaxExpr);

      READ_OID_FIELD(minmaxtype);
      READ_ENUM_FIELD(op, MinMaxOp);
      READ_NODE_FIELD(args);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readXmlExpr
 */
static XmlExpr *
_readXmlExpr(void)
{
      READ_LOCALS(XmlExpr);

      READ_ENUM_FIELD(op, XmlExprOp);
      READ_STRING_FIELD(name);
      READ_NODE_FIELD(named_args);
      READ_NODE_FIELD(arg_names);
      READ_NODE_FIELD(args);
      READ_ENUM_FIELD(xmloption, XmlOptionType);
      READ_OID_FIELD(type);
      READ_INT_FIELD(typmod);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readNullIfExpr
 */
static NullIfExpr *
_readNullIfExpr(void)
{
      READ_LOCALS(NullIfExpr);

      READ_OID_FIELD(opno);
      READ_OID_FIELD(opfuncid);

      /*
       * The opfuncid is stored in the textual format primarily for debugging
       * and documentation reasons.  We want to always read it as zero to force
       * it to be re-looked-up in the pg_operator entry.    This ensures that
       * stored rules don't have hidden dependencies on operators' functions.
       * (We don't currently support an ALTER OPERATOR command, but might
       * someday.)
       */
      local_node->opfuncid = InvalidOid;

      READ_OID_FIELD(opresulttype);
      READ_BOOL_FIELD(opretset);
      READ_NODE_FIELD(args);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readNullTest
 */
static NullTest *
_readNullTest(void)
{
      READ_LOCALS(NullTest);

      READ_NODE_FIELD(arg);
      READ_ENUM_FIELD(nulltesttype, NullTestType);

      READ_DONE();
}

/*
 * _readBooleanTest
 */
static BooleanTest *
_readBooleanTest(void)
{
      READ_LOCALS(BooleanTest);

      READ_NODE_FIELD(arg);
      READ_ENUM_FIELD(booltesttype, BoolTestType);

      READ_DONE();
}

/*
 * _readCoerceToDomain
 */
static CoerceToDomain *
_readCoerceToDomain(void)
{
      READ_LOCALS(CoerceToDomain);

      READ_NODE_FIELD(arg);
      READ_OID_FIELD(resulttype);
      READ_INT_FIELD(resulttypmod);
      READ_ENUM_FIELD(coercionformat, CoercionForm);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readCoerceToDomainValue
 */
static CoerceToDomainValue *
_readCoerceToDomainValue(void)
{
      READ_LOCALS(CoerceToDomainValue);

      READ_OID_FIELD(typeId);
      READ_INT_FIELD(typeMod);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readSetToDefault
 */
static SetToDefault *
_readSetToDefault(void)
{
      READ_LOCALS(SetToDefault);

      READ_OID_FIELD(typeId);
      READ_INT_FIELD(typeMod);
      READ_LOCATION_FIELD(location);

      READ_DONE();
}

/*
 * _readCurrentOfExpr
 */
static CurrentOfExpr *
_readCurrentOfExpr(void)
{
      READ_LOCALS(CurrentOfExpr);

      READ_UINT_FIELD(cvarno);
      READ_STRING_FIELD(cursor_name);
      READ_INT_FIELD(cursor_param);

      READ_DONE();
}

/*
 * _readTargetEntry
 */
static TargetEntry *
_readTargetEntry(void)
{
      READ_LOCALS(TargetEntry);

      READ_NODE_FIELD(expr);
      READ_INT_FIELD(resno);
      READ_STRING_FIELD(resname);
      READ_UINT_FIELD(ressortgroupref);
      READ_OID_FIELD(resorigtbl);
      READ_INT_FIELD(resorigcol);
      READ_BOOL_FIELD(resjunk);

      READ_DONE();
}

/*
 * _readRangeTblRef
 */
static RangeTblRef *
_readRangeTblRef(void)
{
      READ_LOCALS(RangeTblRef);

      READ_INT_FIELD(rtindex);

      READ_DONE();
}

/*
 * _readJoinExpr
 */
static JoinExpr *
_readJoinExpr(void)
{
      READ_LOCALS(JoinExpr);

      READ_ENUM_FIELD(jointype, JoinType);
      READ_BOOL_FIELD(isNatural);
      READ_NODE_FIELD(larg);
      READ_NODE_FIELD(rarg);
      READ_NODE_FIELD(using);
      READ_NODE_FIELD(quals);
      READ_NODE_FIELD(alias);
      READ_INT_FIELD(rtindex);

      READ_DONE();
}

/*
 * _readFromExpr
 */
static FromExpr *
_readFromExpr(void)
{
      READ_LOCALS(FromExpr);

      READ_NODE_FIELD(fromlist);
      READ_NODE_FIELD(quals);

      READ_DONE();
}


/*
 *    Stuff from parsenodes.h.
 */

/*
 * _readRangeTblEntry
 */
static RangeTblEntry *
_readRangeTblEntry(void)
{
      READ_LOCALS(RangeTblEntry);

      /* put alias + eref first to make dump more legible */
      READ_NODE_FIELD(alias);
      READ_NODE_FIELD(eref);
      READ_ENUM_FIELD(rtekind, RTEKind);

      switch (local_node->rtekind)
      {
            case RTE_RELATION:
            case RTE_SPECIAL:
                  READ_OID_FIELD(relid);
                  break;
            case RTE_SUBQUERY:
                  READ_NODE_FIELD(subquery);
                  break;
            case RTE_JOIN:
                  READ_ENUM_FIELD(jointype, JoinType);
                  READ_NODE_FIELD(joinaliasvars);
                  break;
            case RTE_FUNCTION:
                  READ_NODE_FIELD(funcexpr);
                  READ_NODE_FIELD(funccoltypes);
                  READ_NODE_FIELD(funccoltypmods);
                  break;
            case RTE_VALUES:
                  READ_NODE_FIELD(values_lists);
                  break;
            case RTE_CTE:
                  READ_STRING_FIELD(ctename);
                  READ_UINT_FIELD(ctelevelsup);
                  READ_BOOL_FIELD(self_reference);
                  READ_NODE_FIELD(ctecoltypes);
                  READ_NODE_FIELD(ctecoltypmods);
                  break;
            default:
                  elog(ERROR, "unrecognized RTE kind: %d",
                         (int) local_node->rtekind);
                  break;
      }

      READ_BOOL_FIELD(inh);
      READ_BOOL_FIELD(inFromCl);
      READ_UINT_FIELD(requiredPerms);
      READ_OID_FIELD(checkAsUser);
      READ_BITMAPSET_FIELD(selectedCols);
      READ_BITMAPSET_FIELD(modifiedCols);

      READ_DONE();
}


/*
 * parseNodeString
 *
 * Given a character string representing a node tree, parseNodeString creates
 * the internal node structure.
 *
 * The string to be read must already have been loaded into pg_strtok().
 */
Node *
parseNodeString(void)
{
      void     *return_value;

      READ_TEMP_LOCALS();

      token = pg_strtok(&length);

#define MATCH(tokname, namelen) \
      (length == namelen && strncmp(token, tokname, namelen) == 0)

      if (MATCH("QUERY", 5))
            return_value = _readQuery();
      else if (MATCH("SORTGROUPCLAUSE", 15))
            return_value = _readSortGroupClause();
      else if (MATCH("WINDOWCLAUSE", 12))
            return_value = _readWindowClause();
      else if (MATCH("ROWMARKCLAUSE", 13))
            return_value = _readRowMarkClause();
      else if (MATCH("COMMONTABLEEXPR", 15))
            return_value = _readCommonTableExpr();
      else if (MATCH("SETOPERATIONSTMT", 16))
            return_value = _readSetOperationStmt();
      else if (MATCH("ALIAS", 5))
            return_value = _readAlias();
      else if (MATCH("RANGEVAR", 8))
            return_value = _readRangeVar();
      else if (MATCH("INTOCLAUSE", 10))
            return_value = _readIntoClause();
      else if (MATCH("VAR", 3))
            return_value = _readVar();
      else if (MATCH("CONST", 5))
            return_value = _readConst();
      else if (MATCH("PARAM", 5))
            return_value = _readParam();
      else if (MATCH("AGGREF", 6))
            return_value = _readAggref();
      else if (MATCH("WINDOWFUNC", 10))
            return_value = _readWindowFunc();
      else if (MATCH("ARRAYREF", 8))
            return_value = _readArrayRef();
      else if (MATCH("FUNCEXPR", 8))
            return_value = _readFuncExpr();
      else if (MATCH("OPEXPR", 6))
            return_value = _readOpExpr();
      else if (MATCH("DISTINCTEXPR", 12))
            return_value = _readDistinctExpr();
      else if (MATCH("SCALARARRAYOPEXPR", 17))
            return_value = _readScalarArrayOpExpr();
      else if (MATCH("BOOLEXPR", 8))
            return_value = _readBoolExpr();
      else if (MATCH("SUBLINK", 7))
            return_value = _readSubLink();
      else if (MATCH("FIELDSELECT", 11))
            return_value = _readFieldSelect();
      else if (MATCH("FIELDSTORE", 10))
            return_value = _readFieldStore();
      else if (MATCH("RELABELTYPE", 11))
            return_value = _readRelabelType();
      else if (MATCH("COERCEVIAIO", 11))
            return_value = _readCoerceViaIO();
      else if (MATCH("ARRAYCOERCEEXPR", 15))
            return_value = _readArrayCoerceExpr();
      else if (MATCH("CONVERTROWTYPEEXPR", 18))
            return_value = _readConvertRowtypeExpr();
      else if (MATCH("CASE", 4))
            return_value = _readCaseExpr();
      else if (MATCH("WHEN", 4))
            return_value = _readCaseWhen();
      else if (MATCH("CASETESTEXPR", 12))
            return_value = _readCaseTestExpr();
      else if (MATCH("ARRAY", 5))
            return_value = _readArrayExpr();
      else if (MATCH("ROW", 3))
            return_value = _readRowExpr();
      else if (MATCH("ROWCOMPARE", 10))
            return_value = _readRowCompareExpr();
      else if (MATCH("COALESCE", 8))
            return_value = _readCoalesceExpr();
      else if (MATCH("MINMAX", 6))
            return_value = _readMinMaxExpr();
      else if (MATCH("XMLEXPR", 7))
            return_value = _readXmlExpr();
      else if (MATCH("NULLIFEXPR", 10))
            return_value = _readNullIfExpr();
      else if (MATCH("NULLTEST", 8))
            return_value = _readNullTest();
      else if (MATCH("BOOLEANTEST", 11))
            return_value = _readBooleanTest();
      else if (MATCH("COERCETODOMAIN", 14))
            return_value = _readCoerceToDomain();
      else if (MATCH("COERCETODOMAINVALUE", 19))
            return_value = _readCoerceToDomainValue();
      else if (MATCH("SETTODEFAULT", 12))
            return_value = _readSetToDefault();
      else if (MATCH("CURRENTOFEXPR", 13))
            return_value = _readCurrentOfExpr();
      else if (MATCH("TARGETENTRY", 11))
            return_value = _readTargetEntry();
      else if (MATCH("RANGETBLREF", 11))
            return_value = _readRangeTblRef();
      else if (MATCH("JOINEXPR", 8))
            return_value = _readJoinExpr();
      else if (MATCH("FROMEXPR", 8))
            return_value = _readFromExpr();
      else if (MATCH("RTE", 3))
            return_value = _readRangeTblEntry();
      else if (MATCH("NOTIFY", 6))
            return_value = _readNotifyStmt();
      else if (MATCH("DECLARECURSOR", 13))
            return_value = _readDeclareCursorStmt();
      else
      {
            elog(ERROR, "badly formatted node string \"%.32s\"...", token);
            return_value = NULL;    /* keep compiler quiet */
      }

      return (Node *) return_value;
}


/*
 * readDatum
 *
 * Given a string representation of a constant, recreate the appropriate
 * Datum.  The string representation embeds length info, but not byValue,
 * so we must be told that.
 */
static Datum
readDatum(bool typbyval)
{
      Size        length,
                        i;
      int               tokenLength;
      char     *token;
      Datum       res;
      char     *s;

      /*
       * read the actual length of the value
       */
      token = pg_strtok(&tokenLength);
      length = atoui(token);

      token = pg_strtok(&tokenLength);    /* read the '[' */
      if (token == NULL || token[0] != '[')
            elog(ERROR, "expected \"[\" to start datum, but got \"%s\"; length = %lu",
                   token ? (const char *) token : "[NULL]",
                   (unsigned long) length);

      if (typbyval)
      {
            if (length > (Size) sizeof(Datum))
                  elog(ERROR, "byval datum but length = %lu",
                         (unsigned long) length);
            res = (Datum) 0;
            s = (char *) (&res);
            for (i = 0; i < (Size) sizeof(Datum); i++)
            {
                  token = pg_strtok(&tokenLength);
                  s[i] = (char) atoi(token);
            }
      }
      else if (length <= 0)
            res = (Datum) NULL;
      else
      {
            s = (char *) palloc(length);
            for (i = 0; i < length; i++)
            {
                  token = pg_strtok(&tokenLength);
                  s[i] = (char) atoi(token);
            }
            res = PointerGetDatum(s);
      }

      token = pg_strtok(&tokenLength);    /* read the ']' */
      if (token == NULL || token[0] != ']')
            elog(ERROR, "expected \"]\" to end datum, but got \"%s\"; length = %lu",
                   token ? (const char *) token : "[NULL]",
                   (unsigned long) length);

      return res;
}

Generated by  Doxygen 1.6.0   Back to index