Remove Value node struct

The Value node struct is a weird construct.  It is its own node type,
but most of the time, it actually has a node type of Integer, Float,
String, or BitString.  As a consequence, the struct name and the node
type don't match most of the time, and so it has to be treated
specially a lot.  There doesn't seem to be any value in the special
construct.  There is very little code that wants to accept all Value
variants but nothing else (and even if it did, this doesn't provide
any convenient way to check it), and most code wants either just one
particular node type (usually String), or it accepts a broader set of
node types besides just Value.

This change removes the Value struct and node type and replaces them
by separate Integer, Float, String, and BitString node types that are
proper node types and structs of their own and behave mostly like
normal node types.

Also, this removes the T_Null node tag, which was previously also a
possible variant of Value but wasn't actually used outside of the
Value contained in A_Const.  Replace that by an isnull field in
A_Const.

Reviewed-by: Dagfinn Ilmari Mannsåker <ilmari@ilmari.org>
Reviewed-by: Kyotaro Horiguchi <horikyota.ntt@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/5ba6bc5b-3f95-04f2-2419-f8ddb4c046fb@enterprisedb.com
This commit is contained in:
Peter Eisentraut 2021-09-09 07:58:12 +02:00
parent cbdf75bf80
commit 639a86e36a
30 changed files with 371 additions and 335 deletions

View File

@ -101,9 +101,9 @@ enum FdwModifyPrivateIndex
FdwModifyPrivateUpdateSql,
/* Integer list of target attribute numbers for INSERT/UPDATE */
FdwModifyPrivateTargetAttnums,
/* Length till the end of VALUES clause (as an integer Value node) */
/* Length till the end of VALUES clause (as an Integer node) */
FdwModifyPrivateLen,
/* has-returning flag (as an integer Value node) */
/* has-returning flag (as an Integer node) */
FdwModifyPrivateHasReturning,
/* Integer list of attribute numbers retrieved by RETURNING */
FdwModifyPrivateRetrievedAttrs
@ -122,11 +122,11 @@ enum FdwDirectModifyPrivateIndex
{
/* SQL statement to execute remotely (as a String node) */
FdwDirectModifyPrivateUpdateSql,
/* has-returning flag (as an integer Value node) */
/* has-returning flag (as an Integer node) */
FdwDirectModifyPrivateHasReturning,
/* Integer list of attribute numbers retrieved by RETURNING */
FdwDirectModifyPrivateRetrievedAttrs,
/* set-processed flag (as an integer Value node) */
/* set-processed flag (as an Integer node) */
FdwDirectModifyPrivateSetProcessed
};
@ -280,9 +280,9 @@ typedef struct PgFdwAnalyzeState
*/
enum FdwPathPrivateIndex
{
/* has-final-sort flag (as an integer Value node) */
/* has-final-sort flag (as an Integer node) */
FdwPathPrivateHasFinalSort,
/* has-limit flag (as an integer Value node) */
/* has-limit flag (as an Integer node) */
FdwPathPrivateHasLimit
};

View File

@ -3026,7 +3026,7 @@ CheckSetNamespace(Oid oldNspOid, Oid nspOid)
/*
* QualifiedNameGetCreationNamespace
* Given a possibly-qualified name for an object (in List-of-Values
* Given a possibly-qualified name for an object (in List-of-Strings
* format), determine what namespace the object should be created in.
* Also extract and return the object name (last component of list).
*
@ -3140,7 +3140,7 @@ makeRangeVarFromNameList(List *names)
* This is used primarily to form error messages, and so we do not quote
* the list elements, for the sake of legibility.
*
* In most scenarios the list elements should always be Value strings,
* In most scenarios the list elements should always be String values,
* but we also allow A_Star for the convenience of ColumnRef processing.
*/
char *

View File

@ -851,7 +851,7 @@ const ObjectAddress InvalidObjectAddress =
};
static ObjectAddress get_object_address_unqualified(ObjectType objtype,
Value *strval, bool missing_ok);
String *strval, bool missing_ok);
static ObjectAddress get_relation_by_qualified_name(ObjectType objtype,
List *object, Relation *relp,
LOCKMODE lockmode, bool missing_ok);
@ -1011,7 +1011,7 @@ get_object_address(ObjectType objtype, Node *object,
case OBJECT_PUBLICATION:
case OBJECT_SUBSCRIPTION:
address = get_object_address_unqualified(objtype,
(Value *) object, missing_ok);
castNode(String, object), missing_ok);
break;
case OBJECT_TYPE:
case OBJECT_DOMAIN:
@ -1244,7 +1244,7 @@ get_object_address_rv(ObjectType objtype, RangeVar *rel, List *object,
*/
static ObjectAddress
get_object_address_unqualified(ObjectType objtype,
Value *strval, bool missing_ok)
String *strval, bool missing_ok)
{
const char *name;
ObjectAddress address;

View File

@ -55,7 +55,7 @@ static int sort_order_cmp(const void *p1, const void *p2);
* EnumValuesCreate
* Create an entry in pg_enum for each of the supplied enum values.
*
* vals is a list of Value strings.
* vals is a list of String values.
*/
void
EnumValuesCreate(Oid enumTypeOid, List *vals)

View File

@ -222,9 +222,8 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
{
/*
* Build the ColumnRef for each column. The ColumnRef
* 'fields' property is a String 'Value' node (see
* nodes/value.h) that corresponds to the column name
* respectively.
* 'fields' property is a String node that corresponds to
* the column name respectively.
*/
cr = makeNode(ColumnRef);
cr->fields = list_make1(lfirst(lc));

View File

@ -58,12 +58,7 @@ defGetString(DefElem *def)
case T_Integer:
return psprintf("%ld", (long) intVal(def->arg));
case T_Float:
/*
* T_Float values are kept in string form, so this type cheat
* works (and doesn't risk losing precision)
*/
return strVal(def->arg);
return castNode(Float, def->arg)->val;
case T_String:
return strVal(def->arg);
case T_TypeName:
@ -206,7 +201,7 @@ defGetInt64(DefElem *def)
* strings.
*/
return DatumGetInt64(DirectFunctionCall1(int8in,
CStringGetDatum(strVal(def->arg))));
CStringGetDatum(castNode(Float, def->arg)->val)));
default:
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),

View File

@ -1179,7 +1179,7 @@ getTokenTypes(Oid prsId, List *tokennames)
i = 0;
foreach(tn, tokennames)
{
Value *val = (Value *) lfirst(tn);
String *val = lfirst_node(String, tn);
bool found = false;
int j;
@ -1395,7 +1395,7 @@ DropConfigurationMapping(AlterTSConfigurationStmt *stmt,
i = 0;
foreach(c, stmt->tokentype)
{
Value *val = (Value *) lfirst(c);
String *val = lfirst_node(String, c);
bool found = false;
ScanKeyInit(&skey[0],

View File

@ -364,7 +364,7 @@ tfuncInitialize(TableFuncScanState *tstate, ExprContext *econtext, Datum doc)
forboth(lc1, tstate->ns_uris, lc2, tstate->ns_names)
{
ExprState *expr = (ExprState *) lfirst(lc1);
Value *ns_node = (Value *) lfirst(lc2);
String *ns_node = lfirst_node(String, lc2);
char *ns_uri;
char *ns_name;

View File

@ -28,7 +28,7 @@ FILES IN THIS DIRECTORY (src/backend/nodes/)
list.c - generic list support
params.c - Param support
tidbitmap.c - TIDBitmap support
value.c - support for Value nodes
value.c - support for value nodes
FILES IN src/include/nodes/

View File

@ -2729,25 +2729,30 @@ _copyA_Const(const A_Const *from)
{
A_Const *newnode = makeNode(A_Const);
/* This part must duplicate _copyValue */
COPY_SCALAR_FIELD(val.type);
switch (from->val.type)
COPY_SCALAR_FIELD(isnull);
if (!from->isnull)
{
case T_Integer:
COPY_SCALAR_FIELD(val.val.ival);
break;
case T_Float:
case T_String:
case T_BitString:
COPY_STRING_FIELD(val.val.str);
break;
case T_Null:
/* nothing to do */
break;
default:
elog(ERROR, "unrecognized node type: %d",
(int) from->val.type);
break;
/* This part must duplicate other _copy*() functions. */
COPY_SCALAR_FIELD(val.node.type);
switch (nodeTag(&from->val))
{
case T_Integer:
COPY_SCALAR_FIELD(val.ival.val);
break;
case T_Float:
COPY_STRING_FIELD(val.fval.val);
break;
case T_String:
COPY_STRING_FIELD(val.sval.val);
break;
case T_BitString:
COPY_STRING_FIELD(val.bsval.val);
break;
default:
elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(&from->val));
break;
}
}
COPY_LOCATION_FIELD(location);
@ -4892,32 +4897,43 @@ _copyExtensibleNode(const ExtensibleNode *from)
* value.h copy functions
* ****************************************************************
*/
static Value *
_copyValue(const Value *from)
static Integer *
_copyInteger(const Integer *from)
{
Value *newnode = makeNode(Value);
Integer *newnode = makeNode(Integer);
/* See also _copyAConst when changing this code! */
COPY_SCALAR_FIELD(val);
return newnode;
}
static Float *
_copyFloat(const Float *from)
{
Float *newnode = makeNode(Float);
COPY_STRING_FIELD(val);
return newnode;
}
static String *
_copyString(const String *from)
{
String *newnode = makeNode(String);
COPY_STRING_FIELD(val);
return newnode;
}
static BitString *
_copyBitString(const BitString *from)
{
BitString *newnode = makeNode(BitString);
COPY_STRING_FIELD(val);
COPY_SCALAR_FIELD(type);
switch (from->type)
{
case T_Integer:
COPY_SCALAR_FIELD(val.ival);
break;
case T_Float:
case T_String:
case T_BitString:
COPY_STRING_FIELD(val.str);
break;
case T_Null:
/* nothing to do */
break;
default:
elog(ERROR, "unrecognized node type: %d",
(int) from->type);
break;
}
return newnode;
}
@ -5314,11 +5330,16 @@ copyObjectImpl(const void *from)
* VALUE NODES
*/
case T_Integer:
retval = _copyInteger(from);
break;
case T_Float:
retval = _copyFloat(from);
break;
case T_String:
retval = _copyString(from);
break;
case T_BitString:
case T_Null:
retval = _copyValue(from);
retval = _copyBitString(from);
break;
/*

View File

@ -2409,7 +2409,7 @@ _equalParamRef(const ParamRef *a, const ParamRef *b)
static bool
_equalA_Const(const A_Const *a, const A_Const *b)
{
if (!equal(&a->val, &b->val)) /* hack for in-line Value field */
if (!equal(&a->val, &b->val)) /* hack for in-line val field */
return false;
COMPARE_LOCATION_FIELD(location);
@ -3089,27 +3089,33 @@ _equalList(const List *a, const List *b)
*/
static bool
_equalValue(const Value *a, const Value *b)
_equalInteger(const Integer *a, const Integer *b)
{
COMPARE_SCALAR_FIELD(type);
COMPARE_SCALAR_FIELD(val);
switch (a->type)
{
case T_Integer:
COMPARE_SCALAR_FIELD(val.ival);
break;
case T_Float:
case T_String:
case T_BitString:
COMPARE_STRING_FIELD(val.str);
break;
case T_Null:
/* nothing to do */
break;
default:
elog(ERROR, "unrecognized node type: %d", (int) a->type);
break;
}
return true;
}
static bool
_equalFloat(const Float *a, const Float *b)
{
COMPARE_STRING_FIELD(val);
return true;
}
static bool
_equalString(const String *a, const String *b)
{
COMPARE_STRING_FIELD(val);
return true;
}
static bool
_equalBitString(const BitString *a, const BitString *b)
{
COMPARE_STRING_FIELD(val);
return true;
}
@ -3337,11 +3343,16 @@ equal(const void *a, const void *b)
break;
case T_Integer:
retval = _equalInteger(a, b);
break;
case T_Float:
retval = _equalFloat(a, b);
break;
case T_String:
retval = _equalString(a, b);
break;
case T_BitString:
case T_Null:
retval = _equalValue(a, b);
retval = _equalBitString(a, b);
break;
/*

View File

@ -3537,7 +3537,6 @@ raw_expression_tree_walker(Node *node,
case T_Float:
case T_String:
case T_BitString:
case T_Null:
case T_ParamRef:
case T_A_Const:
case T_A_Star:

View File

@ -3414,44 +3414,39 @@ _outA_Expr(StringInfo str, const A_Expr *node)
}
static void
_outValue(StringInfo str, const Value *node)
_outInteger(StringInfo str, const Integer *node)
{
switch (node->type)
{
case T_Integer:
appendStringInfo(str, "%d", node->val.ival);
break;
case T_Float:
appendStringInfo(str, "%d", node->val);
}
/*
* We assume the value is a valid numeric literal and so does not
* need quoting.
*/
appendStringInfoString(str, node->val.str);
break;
case T_String:
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->val);
}
/*
* We use outToken to provide escaping of the string's content,
* but we don't want it to do anything with an empty string.
*/
appendStringInfoChar(str, '"');
if (node->val.str[0] != '\0')
outToken(str, node->val.str);
appendStringInfoChar(str, '"');
break;
case T_BitString:
/* internal representation already has leading 'b' */
appendStringInfoString(str, node->val.str);
break;
case T_Null:
/* this is seen only within A_Const, not in transformed trees */
appendStringInfoString(str, "NULL");
break;
default:
elog(ERROR, "unrecognized node type: %d", (int) node->type);
break;
}
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 do anything with an empty string.
*/
appendStringInfoChar(str, '"');
if (node->val[0] != '\0')
outToken(str, node->val);
appendStringInfoChar(str, '"');
}
static void
_outBitString(StringInfo str, const BitString *node)
{
/* internal representation already has leading 'b' */
appendStringInfoString(str, node->val);
}
static void
@ -3491,8 +3486,13 @@ _outA_Const(StringInfo str, const A_Const *node)
{
WRITE_NODE_TYPE("A_CONST");
appendStringInfoString(str, " :val ");
_outValue(str, &(node->val));
if (node->isnull)
appendStringInfoString(str, "NULL");
else
{
appendStringInfoString(str, " :val ");
outNode(str, &node->val);
}
WRITE_LOCATION_FIELD(location);
}
@ -3835,14 +3835,15 @@ outNode(StringInfo str, const void *obj)
appendStringInfoString(str, "<>");
else if (IsA(obj, List) || IsA(obj, IntList) || IsA(obj, OidList))
_outList(str, obj);
else if (IsA(obj, Integer) ||
IsA(obj, Float) ||
IsA(obj, String) ||
IsA(obj, BitString))
{
/* nodeRead does not want to see { } around these! */
_outValue(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, String))
_outString(str, (String *) obj);
else if (IsA(obj, BitString))
_outBitString(str, (BitString *) obj);
else
{
appendStringInfoChar(str, '{');

View File

@ -1,7 +1,7 @@
/*-------------------------------------------------------------------------
*
* value.c
* implementation of Value nodes
* implementation of value nodes
*
*
* Copyright (c) 2003-2021, PostgreSQL Global Development Group
@ -14,18 +14,17 @@
*/
#include "postgres.h"
#include "nodes/parsenodes.h"
#include "nodes/value.h"
/*
* makeInteger
*/
Value *
Integer *
makeInteger(int i)
{
Value *v = makeNode(Value);
Integer *v = makeNode(Integer);
v->type = T_Integer;
v->val.ival = i;
v->val = i;
return v;
}
@ -34,13 +33,12 @@ makeInteger(int i)
*
* Caller is responsible for passing a palloc'd string.
*/
Value *
Float *
makeFloat(char *numericStr)
{
Value *v = makeNode(Value);
Float *v = makeNode(Float);
v->type = T_Float;
v->val.str = numericStr;
v->val = numericStr;
return v;
}
@ -49,13 +47,12 @@ makeFloat(char *numericStr)
*
* Caller is responsible for passing a palloc'd string.
*/
Value *
String *
makeString(char *str)
{
Value *v = makeNode(Value);
String *v = makeNode(String);
v->type = T_String;
v->val.str = str;
v->val = str;
return v;
}
@ -64,12 +61,11 @@ makeString(char *str)
*
* Caller is responsible for passing a palloc'd string.
*/
Value *
BitString *
makeBitString(char *str)
{
Value *v = makeNode(Value);
BitString *v = makeNode(BitString);
v->type = T_BitString;
v->val.str = str;
v->val = str;
return v;
}

View File

@ -166,7 +166,7 @@ static Node *makeIntConst(int val, int location);
static Node *makeFloatConst(char *str, int location);
static Node *makeBitStringConst(char *str, int location);
static Node *makeNullAConst(int location);
static Node *makeAConst(Value *v, int location);
static Node *makeAConst(Node *v, int location);
static Node *makeBoolAConst(bool state, int location);
static RoleSpec *makeRoleSpec(RoleSpecType type, int location);
static void check_qualified_name(List *names, core_yyscan_t yyscanner);
@ -183,7 +183,7 @@ static void insertSelectOptions(SelectStmt *stmt,
core_yyscan_t yyscanner);
static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg);
static Node *doNegate(Node *n, int location);
static void doNegateFloat(Value *v);
static void doNegateFloat(Float *v);
static Node *makeAndExpr(Node *lexpr, Node *rexpr, int location);
static Node *makeOrExpr(Node *lexpr, Node *rexpr, int location);
static Node *makeNotExpr(Node *expr, int location);
@ -228,7 +228,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
OnCommitAction oncommit;
List *list;
Node *node;
Value *value;
ObjectType objtype;
TypeName *typnam;
FunctionParameter *fun_param;
@ -351,7 +350,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <boolean> TriggerForSpec TriggerForType
%type <ival> TriggerActionTime
%type <list> TriggerEvents TriggerOneEvent
%type <value> TriggerFuncArg
%type <node> TriggerFuncArg
%type <node> TriggerWhen
%type <str> TransitionRelName
%type <boolean> TransitionRowOrTable TransitionOldOrNew
@ -508,7 +507,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <list> when_clause_list
%type <node> opt_search_clause opt_cycle_clause
%type <ival> sub_type opt_materialized
%type <value> NumericOnly
%type <node> NumericOnly
%type <list> NumericOnly_list
%type <alias> alias_clause opt_alias_clause opt_alias_clause_for_join_using
%type <list> func_alias_clause
@ -1696,7 +1695,7 @@ zone_value:
if ($3 != NIL)
{
A_Const *n = (A_Const *) linitial($3);
if ((n->val.val.ival & ~(INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE))) != 0)
if ((n->val.ival.val & ~(INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE))) != 0)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("time zone interval must be HOUR or HOUR TO MINUTE"),
@ -4459,14 +4458,15 @@ opt_by: BY
;
NumericOnly:
FCONST { $$ = makeFloat($1); }
| '+' FCONST { $$ = makeFloat($2); }
FCONST { $$ = (Node *) makeFloat($1); }
| '+' FCONST { $$ = (Node *) makeFloat($2); }
| '-' FCONST
{
$$ = makeFloat($2);
doNegateFloat($$);
Float *f = makeFloat($2);
doNegateFloat(f);
$$ = (Node *) f;
}
| SignedIconst { $$ = makeInteger($1); }
| SignedIconst { $$ = (Node *) makeInteger($1); }
;
NumericOnly_list: NumericOnly { $$ = list_make1($1); }
@ -5535,11 +5535,11 @@ TriggerFuncArgs:
TriggerFuncArg:
Iconst
{
$$ = makeString(psprintf("%d", $1));
$$ = (Node *) makeString(psprintf("%d", $1));
}
| FCONST { $$ = makeString($1); }
| Sconst { $$ = makeString($1); }
| ColLabel { $$ = makeString($1); }
| FCONST { $$ = (Node *) makeString($1); }
| Sconst { $$ = (Node *) makeString($1); }
| ColLabel { $$ = (Node *) makeString($1); }
;
OptConstrFromTable:
@ -7773,8 +7773,8 @@ aggr_arg: func_arg
*
* The return value of this production is a two-element list, in which the
* first item is a sublist of FunctionParameter nodes (with any duplicate
* VARIADIC item already dropped, as per above) and the second is an integer
* Value node, containing -1 if there was no ORDER BY and otherwise the number
* VARIADIC item already dropped, as per above) and the second is an Integer
* node, containing -1 if there was no ORDER BY and otherwise the number
* of argument declarations before the ORDER BY. (If this number is equal
* to the first sublist's length, then we dropped a duplicate VARIADIC item.)
* This representation is passed as-is to CREATE AGGREGATE; for operations
@ -16520,11 +16520,11 @@ makeStringConst(char *str, int location)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_String;
n->val.val.str = str;
n->val.sval.type = T_String;
n->val.sval.val = str;
n->location = location;
return (Node *)n;
return (Node *)n;
}
static Node *
@ -16540,11 +16540,11 @@ makeIntConst(int val, int location)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_Integer;
n->val.val.ival = val;
n->val.ival.type = T_Integer;
n->val.ival.val = val;
n->location = location;
return (Node *)n;
return (Node *)n;
}
static Node *
@ -16552,11 +16552,11 @@ makeFloatConst(char *str, int location)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_Float;
n->val.val.str = str;
n->val.fval.type = T_Float;
n->val.fval.val = str;
n->location = location;
return (Node *)n;
return (Node *)n;
}
static Node *
@ -16564,11 +16564,11 @@ makeBitStringConst(char *str, int location)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_BitString;
n->val.val.str = str;
n->val.bsval.type = T_BitString;
n->val.bsval.val = str;
n->location = location;
return (Node *)n;
return (Node *)n;
}
static Node *
@ -16576,30 +16576,30 @@ makeNullAConst(int location)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_Null;
n->isnull = true;
n->location = location;
return (Node *)n;
}
static Node *
makeAConst(Value *v, int location)
makeAConst(Node *v, int location)
{
Node *n;
switch (v->type)
{
case T_Float:
n = makeFloatConst(v->val.str, location);
n = makeFloatConst(castNode(Float, v)->val, location);
break;
case T_Integer:
n = makeIntConst(v->val.ival, location);
n = makeIntConst(castNode(Integer, v)->val, location);
break;
case T_String:
default:
n = makeStringConst(v->val.str, location);
n = makeStringConst(castNode(String, v)->val, location);
break;
}
@ -16612,13 +16612,9 @@ makeAConst(Value *v, int location)
static Node *
makeBoolAConst(bool state, int location)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_String;
n->val.val.str = (state ? "t" : "f");
n->location = location;
return makeTypeCast((Node *)n, SystemTypeName("bool"), -1);
return makeStringConstCast((state ? "t" : "f"),
location,
SystemTypeName("bool"));
}
/* makeRoleSpec
@ -16733,7 +16729,7 @@ makeOrderedSetArgs(List *directargs, List *orderedargs,
core_yyscan_t yyscanner)
{
FunctionParameter *lastd = (FunctionParameter *) llast(directargs);
Value *ndirectargs;
Integer *ndirectargs;
/* No restriction unless last direct arg is VARIADIC */
if (lastd->mode == FUNC_PARAM_VARIADIC)
@ -16890,14 +16886,14 @@ doNegate(Node *n, int location)
/* report the constant's location as that of the '-' sign */
con->location = location;
if (con->val.type == T_Integer)
if (IsA(&con->val, Integer))
{
con->val.val.ival = -con->val.val.ival;
con->val.ival.val = -con->val.ival.val;
return n;
}
if (con->val.type == T_Float)
if (IsA(&con->val, Float))
{
doNegateFloat(&con->val);
doNegateFloat(&con->val.fval);
return n;
}
}
@ -16906,17 +16902,16 @@ doNegate(Node *n, int location)
}
static void
doNegateFloat(Value *v)
doNegateFloat(Float *v)
{
char *oldval = v->val.str;
char *oldval = v->val;
Assert(IsA(v, Float));
if (*oldval == '+')
oldval++;
if (*oldval == '-')
v->val.str = oldval+1; /* just strip the '-' */
v->val = oldval+1; /* just strip the '-' */
else
v->val.str = psprintf("-%s", oldval);
v->val = psprintf("-%s", oldval);
}
static Node *

View File

@ -852,7 +852,7 @@ transformRangeTableFunc(ParseState *pstate, RangeTableFunc *rtf)
{
foreach(lc2, ns_names)
{
Value *ns_node = (Value *) lfirst(lc2);
String *ns_node = lfirst_node(String, lc2);
if (ns_node == NULL)
continue;
@ -1240,7 +1240,7 @@ transformFromClauseItem(ParseState *pstate, Node *n,
foreach(lx, l_colnames)
{
char *l_colname = strVal(lfirst(lx));
Value *m_name = NULL;
String *m_name = NULL;
if (l_colname[0] == '\0')
continue; /* ignore dropped columns */
@ -1785,7 +1785,7 @@ transformLimitClause(ParseState *pstate, Node *clause,
* unadorned NULL that's not accepted back by the grammar.
*/
if (exprKind == EXPR_KIND_LIMIT && limitOption == LIMIT_OPTION_WITH_TIES &&
IsA(clause, A_Const) && ((A_Const *) clause)->val.type == T_Null)
IsA(clause, A_Const) && castNode(A_Const, clause)->isnull)
ereport(ERROR,
(errcode(ERRCODE_INVALID_ROW_COUNT_IN_LIMIT_CLAUSE),
errmsg("row count cannot be null in FETCH FIRST ... WITH TIES clause")));
@ -1998,20 +1998,19 @@ findTargetlistEntrySQL92(ParseState *pstate, Node *node, List **tlist,
}
if (IsA(node, A_Const))
{
Value *val = &((A_Const *) node)->val;
int location = ((A_Const *) node)->location;
A_Const *aconst = castNode(A_Const, node);
int targetlist_pos = 0;
int target_pos;
if (!IsA(val, Integer))
if (!IsA(&aconst->val, Integer))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
/* translator: %s is name of a SQL construct, eg ORDER BY */
errmsg("non-integer constant in %s",
ParseExprKindName(exprKind)),
parser_errposition(pstate, location)));
parser_errposition(pstate, aconst->location)));
target_pos = intVal(val);
target_pos = intVal(&aconst->val);
foreach(tl, *tlist)
{
TargetEntry *tle = (TargetEntry *) lfirst(tl);
@ -2031,7 +2030,7 @@ findTargetlistEntrySQL92(ParseState *pstate, Node *node, List **tlist,
/* translator: %s is name of a SQL construct, eg ORDER BY */
errmsg("%s position %d is not in select list",
ParseExprKindName(exprKind), target_pos),
parser_errposition(pstate, location)));
parser_errposition(pstate, aconst->location)));
}
/*

View File

@ -393,7 +393,7 @@ analyzeCTE(ParseState *pstate, CommonTableExpr *cte)
foreach(lc, cte->search_clause->search_col_list)
{
Value *colname = lfirst(lc);
String *colname = lfirst_node(String, lc);
if (!list_member(cte->ctecolnames, colname))
ereport(ERROR,
@ -428,7 +428,7 @@ analyzeCTE(ParseState *pstate, CommonTableExpr *cte)
foreach(lc, cte->cycle_clause->cycle_col_list)
{
Value *colname = lfirst(lc);
String *colname = lfirst_node(String, lc);
if (!list_member(cte->ctecolnames, colname))
ereport(ERROR,

View File

@ -130,13 +130,8 @@ transformExprRecurse(ParseState *pstate, Node *expr)
break;
case T_A_Const:
{
A_Const *con = (A_Const *) expr;
Value *val = &con->val;
result = (Node *) make_const(pstate, val, con->location);
break;
}
result = (Node *) make_const(pstate, (A_Const *) expr);
break;
case T_A_Indirection:
result = transformIndirection(pstate, (A_Indirection *) expr);
@ -855,7 +850,7 @@ exprIsNullConstant(Node *arg)
{
A_Const *con = (A_Const *) arg;
if (con->val.type == T_Null)
if (con->isnull)
return true;
}
return false;
@ -1626,7 +1621,7 @@ transformCaseExpr(ParseState *pstate, CaseExpr *c)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_Null;
n->isnull = true;
n->location = -1;
defresult = (Node *) n;
}

View File

@ -333,7 +333,7 @@ transformContainerSubscripts(ParseState *pstate,
/*
* make_const
*
* Convert a Value node (as returned by the grammar) to a Const node
* Convert an A_Const node (as returned by the grammar) to a Const node
* of the "natural" type for the constant. Note that this routine is
* only used when there is no explicit cast for the constant, so we
* have to guess what type is wanted.
@ -349,7 +349,7 @@ transformContainerSubscripts(ParseState *pstate,
* too many examples that fail if we try.
*/
Const *
make_const(ParseState *pstate, Value *value, int location)
make_const(ParseState *pstate, A_Const *aconst)
{
Const *con;
Datum val;
@ -359,10 +359,24 @@ make_const(ParseState *pstate, Value *value, int location)
bool typebyval;
ParseCallbackState pcbstate;
switch (nodeTag(value))
if (aconst->isnull)
{
/* return a null const */
con = makeConst(UNKNOWNOID,
-1,
InvalidOid,
-2,
(Datum) 0,
true,
false);
con->location = aconst->location;
return con;
}
switch (nodeTag(&aconst->val))
{
case T_Integer:
val = Int32GetDatum(intVal(value));
val = Int32GetDatum(aconst->val.ival.val);
typeid = INT4OID;
typelen = sizeof(int32);
@ -371,7 +385,7 @@ make_const(ParseState *pstate, Value *value, int location)
case T_Float:
/* could be an oversize integer as well as a float ... */
if (scanint8(strVal(value), true, &val64))
if (scanint8(aconst->val.fval.val, true, &val64))
{
/*
* It might actually fit in int32. Probably only INT_MIN can
@ -399,9 +413,9 @@ make_const(ParseState *pstate, Value *value, int location)
else
{
/* arrange to report location if numeric_in() fails */
setup_parser_errposition_callback(&pcbstate, pstate, location);
setup_parser_errposition_callback(&pcbstate, pstate, aconst->location);
val = DirectFunctionCall3(numeric_in,
CStringGetDatum(strVal(value)),
CStringGetDatum(aconst->val.fval.val),
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(-1));
cancel_parser_errposition_callback(&pcbstate);
@ -418,7 +432,7 @@ make_const(ParseState *pstate, Value *value, int location)
* We assume here that UNKNOWN's internal representation is the
* same as CSTRING
*/
val = CStringGetDatum(strVal(value));
val = CStringGetDatum(aconst->val.sval.val);
typeid = UNKNOWNOID; /* will be coerced later */
typelen = -2; /* cstring-style varwidth type */
@ -427,9 +441,9 @@ make_const(ParseState *pstate, Value *value, int location)
case T_BitString:
/* arrange to report location if bit_in() fails */
setup_parser_errposition_callback(&pcbstate, pstate, location);
setup_parser_errposition_callback(&pcbstate, pstate, aconst->location);
val = DirectFunctionCall3(bit_in,
CStringGetDatum(strVal(value)),
CStringGetDatum(aconst->val.bsval.val),
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(-1));
cancel_parser_errposition_callback(&pcbstate);
@ -438,20 +452,8 @@ make_const(ParseState *pstate, Value *value, int location)
typebyval = false;
break;
case T_Null:
/* return a null const */
con = makeConst(UNKNOWNOID,
-1,
InvalidOid,
-2,
(Datum) 0,
true,
false);
con->location = location;
return con;
default:
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(value));
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(&aconst->val));
return NULL; /* keep compiler quiet */
}
@ -462,7 +464,7 @@ make_const(ParseState *pstate, Value *value, int location)
val,
false,
typebyval);
con->location = location;
con->location = aconst->location;
return con;
}

View File

@ -1140,7 +1140,7 @@ buildRelationAliases(TupleDesc tupdesc, Alias *alias, Alias *eref)
for (varattno = 0; varattno < maxattrs; varattno++)
{
Form_pg_attribute attr = TupleDescAttr(tupdesc, varattno);
Value *attrname;
String *attrname;
if (attr->attisdropped)
{
@ -1153,7 +1153,7 @@ buildRelationAliases(TupleDesc tupdesc, Alias *alias, Alias *eref)
else if (aliaslc)
{
/* Use the next user-supplied alias */
attrname = (Value *) lfirst(aliaslc);
attrname = lfirst_node(String, aliaslc);
aliaslc = lnext(aliaslist, aliaslc);
alias->colnames = lappend(alias->colnames, attrname);
}
@ -3052,7 +3052,7 @@ expandNSItemVars(ParseNamespaceItem *nsitem,
colindex = 0;
foreach(lc, nsitem->p_names->colnames)
{
Value *colnameval = (Value *) lfirst(lc);
String *colnameval = lfirst(lc);
const char *colname = strVal(colnameval);
ParseNamespaceColumn *nscol = nsitem->p_nscolumns + colindex;

View File

@ -382,13 +382,17 @@ typenameTypeMod(ParseState *pstate, const TypeName *typeName, Type typ)
if (IsA(&ac->val, Integer))
{
cstr = psprintf("%ld", (long) ac->val.val.ival);
cstr = psprintf("%ld", (long) ac->val.ival.val);
}
else if (IsA(&ac->val, Float) ||
IsA(&ac->val, String))
else if (IsA(&ac->val, Float))
{
/* we can just use the str field directly. */
cstr = ac->val.val.str;
/* we can just use the string representation directly. */
cstr = ac->val.fval.val;
}
else if (IsA(&ac->val, String))
{
/* we can just use the string representation directly. */
cstr = ac->val.sval.val;
}
}
else if (IsA(tm, ColumnRef))

View File

@ -602,8 +602,8 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
*/
qstring = quote_qualified_identifier(snamespace, sname);
snamenode = makeNode(A_Const);
snamenode->val.type = T_String;
snamenode->val.val.str = qstring;
snamenode->val.node.type = T_String;
snamenode->val.sval.val = qstring;
snamenode->location = -1;
castnode = makeNode(TypeCast);
castnode->typeName = SystemTypeName("regclass");

View File

@ -324,7 +324,7 @@ oidparse(Node *node)
* constants by the lexer. Accept these if they are valid OID
* strings.
*/
return oidin_subr(strVal(node), NULL);
return oidin_subr(castNode(Float, node)->val, NULL);
default:
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
}

View File

@ -10514,7 +10514,7 @@ get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
forboth(lc1, tf->ns_uris, lc2, tf->ns_names)
{
Node *expr = (Node *) lfirst(lc1);
Value *ns_node = (Value *) lfirst(lc2);
String *ns_node = lfirst_node(String, lc2);
if (!first)
appendStringInfoString(buf, ", ");

View File

@ -8301,7 +8301,7 @@ flatten_set_variable_args(const char *name, List *args)
break;
case T_Float:
/* represented as a string, so just copy it */
appendStringInfoString(&buf, strVal(&con->val));
appendStringInfoString(&buf, castNode(Float, &con->val)->val);
break;
case T_String:
val = strVal(&con->val);
@ -8797,7 +8797,6 @@ ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
errmsg("SET LOCAL TRANSACTION SNAPSHOT is not implemented")));
WarnNoTransactionBlock(isTopLevel, "SET TRANSACTION");
Assert(nodeTag(&con->val) == T_String);
ImportSnapshot(strVal(&con->val));
}
else

View File

@ -291,12 +291,10 @@ typedef enum NodeTag
/*
* TAGS FOR VALUE NODES (value.h)
*/
T_Value,
T_Integer,
T_Float,
T_String,
T_BitString,
T_Null,
/*
* TAGS FOR LIST NODES (pg_list.h)

View File

@ -218,7 +218,7 @@ typedef struct Query
typedef struct TypeName
{
NodeTag type;
List *names; /* qualified name (list of Value strings) */
List *names; /* qualified name (list of String nodes) */
Oid typeOid; /* type identified by OID */
bool setof; /* is a set? */
bool pct_type; /* %TYPE specified? */
@ -231,7 +231,7 @@ typedef struct TypeName
/*
* ColumnRef - specifies a reference to a column, or possibly a whole tuple
*
* The "fields" list must be nonempty. It can contain string Value nodes
* The "fields" list must be nonempty. It can contain String nodes
* (representing names) and A_Star nodes (representing occurrence of a '*').
* Currently, A_Star must appear only as the last list element --- the grammar
* is responsible for enforcing this!
@ -244,7 +244,7 @@ typedef struct TypeName
typedef struct ColumnRef
{
NodeTag type;
List *fields; /* field names (Value strings) or A_Star */
List *fields; /* field names (String nodes) or A_Star */
int location; /* token location, or -1 if unknown */
} ColumnRef;
@ -295,7 +295,19 @@ typedef struct A_Expr
typedef struct A_Const
{
NodeTag type;
Value val; /* value (includes type info, see value.h) */
/*
* Value nodes are inline for performance. You can treat 'val' as a node,
* as in IsA(&val, Integer). 'val' is not valid if isnull is true.
*/
union ValUnion
{
Node node;
Integer ival;
Float fval;
String sval;
BitString bsval;
} val;
bool isnull; /* SQL NULL constant */
int location; /* token location, or -1 if unknown */
} A_Const;
@ -400,7 +412,7 @@ typedef struct A_Indices
* A_Indirection - select a field and/or array element from an expression
*
* The indirection list can contain A_Indices nodes (representing
* subscripting), string Value nodes (representing field selection --- the
* subscripting), String nodes (representing field selection --- the
* string value is the name of the field to select), and A_Star nodes
* (representing selection of all fields of a composite type).
* For example, a complex selection operation like
@ -744,7 +756,7 @@ typedef struct DefElem
NodeTag type;
char *defnamespace; /* NULL if unqualified name */
char *defname;
Node *arg; /* a (Value *) or a (TypeName *) */
Node *arg; /* typically Integer, Float, String, or TypeName */
DefElemAction defaction; /* unspecified action, or SET/ADD/DROP */
int location; /* token location, or -1 if unknown */
} DefElem;
@ -2015,7 +2027,7 @@ typedef struct GrantStmt
GrantTargetType targtype; /* type of the grant target */
ObjectType objtype; /* kind of object being operated on */
List *objects; /* list of RangeVar nodes, ObjectWithArgs
* nodes, or plain names (as Value strings) */
* nodes, or plain names (as String values) */
List *privileges; /* list of AccessPriv nodes */
/* privileges == NIL denotes ALL PRIVILEGES */
List *grantees; /* list of RoleSpec nodes */
@ -2061,7 +2073,7 @@ typedef struct AccessPriv
{
NodeTag type;
char *priv_name; /* string name of privilege */
List *cols; /* list of Value strings */
List *cols; /* list of String */
} AccessPriv;
/* ----------------------
@ -2070,7 +2082,7 @@ typedef struct AccessPriv
* Note: because of the parsing ambiguity with the GRANT <privileges>
* statement, granted_roles is a list of AccessPriv; the execution code
* should complain if any column lists appear. grantee_roles is a list
* of role names, as Value strings.
* of role names, as String values.
* ----------------------
*/
typedef struct GrantRoleStmt
@ -2531,7 +2543,7 @@ typedef struct CreateTrigStmt
char *trigname; /* TRIGGER's name */
RangeVar *relation; /* relation trigger is on */
List *funcname; /* qual. name of function to call */
List *args; /* list of (T_String) Values or NIL */
List *args; /* list of String or NIL */
bool row; /* ROW/STATEMENT */
/* timing uses the TRIGGER_TYPE bits defined in catalog/pg_trigger.h */
int16 timing; /* BEFORE, AFTER, or INSTEAD */
@ -2667,7 +2679,7 @@ typedef struct DefineStmt
NodeTag type;
ObjectType kind; /* aggregate, operator, type */
bool oldstyle; /* hack to signal old CREATE AGG syntax */
List *defnames; /* qualified name (list of Value strings) */
List *defnames; /* qualified name (list of String) */
List *args; /* a list of TypeName (if needed) */
List *definition; /* a list of DefElem */
bool if_not_exists; /* just do nothing if it already exists? */
@ -2681,7 +2693,7 @@ typedef struct DefineStmt
typedef struct CreateDomainStmt
{
NodeTag type;
List *domainname; /* qualified name (list of Value strings) */
List *domainname; /* qualified name (list of String) */
TypeName *typeName; /* the base type */
CollateClause *collClause; /* untransformed COLLATE spec, if any */
List *constraints; /* constraints (list of Constraint nodes) */
@ -2694,7 +2706,7 @@ typedef struct CreateDomainStmt
typedef struct CreateOpClassStmt
{
NodeTag type;
List *opclassname; /* qualified name (list of Value strings) */
List *opclassname; /* qualified name (list of String) */
List *opfamilyname; /* qualified name (ditto); NIL if omitted */
char *amname; /* name of index AM opclass is for */
TypeName *datatype; /* datatype of indexed column */
@ -2726,7 +2738,7 @@ typedef struct CreateOpClassItem
typedef struct CreateOpFamilyStmt
{
NodeTag type;
List *opfamilyname; /* qualified name (list of Value strings) */
List *opfamilyname; /* qualified name (list of String) */
char *amname; /* name of index AM opfamily is for */
} CreateOpFamilyStmt;
@ -2737,7 +2749,7 @@ typedef struct CreateOpFamilyStmt
typedef struct AlterOpFamilyStmt
{
NodeTag type;
List *opfamilyname; /* qualified name (list of Value strings) */
List *opfamilyname; /* qualified name (list of String) */
char *amname; /* name of index AM opfamily is for */
bool isDrop; /* ADD or DROP the items? */
List *items; /* List of CreateOpClassItem nodes */
@ -2908,8 +2920,8 @@ typedef struct IndexStmt
typedef struct CreateStatsStmt
{
NodeTag type;
List *defnames; /* qualified name (list of Value strings) */
List *stat_types; /* stat types (list of Value strings) */
List *defnames; /* qualified name (list of String) */
List *stat_types; /* stat types (list of String) */
List *exprs; /* expressions to build statistics on */
List *relations; /* rels to build stats on (list of RangeVar) */
char *stxcomment; /* comment to apply to stats, or NULL */
@ -2939,7 +2951,7 @@ typedef struct StatsElem
typedef struct AlterStatsStmt
{
NodeTag type;
List *defnames; /* qualified name (list of Value strings) */
List *defnames; /* qualified name (list of String) */
int stxstattarget; /* statistics target */
bool missing_ok; /* skip error if statistics object is missing */
} AlterStatsStmt;
@ -3061,7 +3073,7 @@ typedef struct AlterObjectDependsStmt
ObjectType objectType; /* OBJECT_FUNCTION, OBJECT_TRIGGER, etc */
RangeVar *relation; /* in case a table is involved */
Node *object; /* name of the object */
Value *extname; /* extension name */
String *extname; /* extension name */
bool remove; /* set true to remove dep rather than add */
} AlterObjectDependsStmt;
@ -3207,8 +3219,8 @@ typedef struct CompositeTypeStmt
typedef struct CreateEnumStmt
{
NodeTag type;
List *typeName; /* qualified name (list of Value strings) */
List *vals; /* enum values (list of Value strings) */
List *typeName; /* qualified name (list of String) */
List *vals; /* enum values (list of String) */
} CreateEnumStmt;
/* ----------------------
@ -3218,7 +3230,7 @@ typedef struct CreateEnumStmt
typedef struct CreateRangeStmt
{
NodeTag type;
List *typeName; /* qualified name (list of Value strings) */
List *typeName; /* qualified name (list of String) */
List *params; /* range parameters (list of DefElem) */
} CreateRangeStmt;
@ -3229,7 +3241,7 @@ typedef struct CreateRangeStmt
typedef struct AlterEnumStmt
{
NodeTag type;
List *typeName; /* qualified name (list of Value strings) */
List *typeName; /* qualified name (list of String) */
char *oldVal; /* old enum value's name, if renaming */
char *newVal; /* new enum value's name */
char *newValNeighbor; /* neighboring enum value, if specified */
@ -3591,7 +3603,7 @@ typedef struct ReassignOwnedStmt
typedef struct AlterTSDictionaryStmt
{
NodeTag type;
List *dictname; /* qualified name (list of Value strings) */
List *dictname; /* qualified name (list of String) */
List *options; /* List of DefElem nodes */
} AlterTSDictionaryStmt;
@ -3611,14 +3623,14 @@ typedef struct AlterTSConfigurationStmt
{
NodeTag type;
AlterTSConfigType kind; /* ALTER_TSCONFIG_ADD_MAPPING, etc */
List *cfgname; /* qualified name (list of Value strings) */
List *cfgname; /* qualified name (list of String) */
/*
* dicts will be non-NIL if ADD/ALTER MAPPING was specified. If dicts is
* NIL, but tokentype isn't, DROP MAPPING was specified.
*/
List *tokentype; /* list of Value strings */
List *dicts; /* list of list of Value strings */
List *tokentype; /* list of String */
List *dicts; /* list of list of String */
bool override; /* if true - remove old variant */
bool replace; /* if true - replace dictionary by another */
bool missing_ok; /* for DROP - skip error if missing? */

View File

@ -32,7 +32,7 @@
* specifies an alias for a range variable; the alias might also
* specify renaming of columns within the table.
*
* Note: colnames is a list of Value nodes (always strings). In Alias structs
* Note: colnames is a list of String nodes. In Alias structs
* associated with RTEs, there may be entries corresponding to dropped
* columns; these are normally empty strings (""). See parsenodes.h for info.
*/
@ -76,7 +76,7 @@ typedef struct RangeVar
/*
* TableFunc - node for a table function, such as XMLTABLE.
*
* Entries in the ns_names list are either string Value nodes containing
* Entries in the ns_names list are either String nodes containing
* literal namespace names, or NULL pointers to represent DEFAULT.
*/
typedef struct TableFunc
@ -1227,7 +1227,7 @@ typedef struct XmlExpr
XmlExprOp op; /* xml function ID */
char *name; /* name in xml(NAME foo ...) syntaxes */
List *named_args; /* non-XML expressions for xml_attributes */
List *arg_names; /* parallel list of Value strings */
List *arg_names; /* parallel list of String values */
List *args; /* list of expressions */
XmlOptionType xmloption; /* DOCUMENT or CONTENT */
Oid type; /* target type/typmod for XMLSERIALIZE */

View File

@ -1,7 +1,7 @@
/*-------------------------------------------------------------------------
*
* value.h
* interface for Value nodes
* interface for value nodes
*
*
* Copyright (c) 2003-2021, PostgreSQL Global Development Group
@ -16,46 +16,57 @@
#include "nodes/nodes.h"
/*----------------------
* Value node
/*
* The node types Integer, Float, String, and BitString are used to represent
* literals in the lexer and are also used to pass constants around in the
* parser. One difference between these node types and, say, a plain int or
* char * is that the nodes can be put into a List.
*
* The same Value struct is used for five node types: T_Integer,
* T_Float, T_String, T_BitString, T_Null.
*
* Integral values are actually represented by a machine integer,
* but both floats and strings are represented as strings.
* Using T_Float as the node type simply indicates that
* the contents of the string look like a valid numeric literal.
*
* (Before Postgres 7.0, we used a double to represent T_Float,
* but that creates loss-of-precision problems when the value is
* ultimately destined to be converted to NUMERIC. Since Value nodes
* are only used in the parsing process, not for runtime data, it's
* better to use the more general representation.)
*
* Note that an integer-looking string will get lexed as T_Float if
* the value is too large to fit in an 'int'.
*
* Nulls, of course, don't need the value part at all.
*----------------------
* (There used to be a Value node, which encompassed all these different node types. Hence the name of this file.)
*/
typedef struct Value
typedef struct Integer
{
NodeTag type; /* tag appropriately (eg. T_String) */
union ValUnion
{
int ival; /* machine integer */
char *str; /* string */
} val;
} Value;
NodeTag type;
int val;
} Integer;
#define intVal(v) (((Value *)(v))->val.ival)
#define floatVal(v) atof(((Value *)(v))->val.str)
#define strVal(v) (((Value *)(v))->val.str)
/*
* Float is internally represented as string. Using T_Float as the node type
* simply indicates that the contents of the string look like a valid numeric
* literal. The value might end up being converted to NUMERIC, so we can't
* store it internally as a C double, since that could lose precision. Since
* these nodes are generally only used in the parsing process, not for runtime
* data, it's better to use the more general representation.
*
* Note that an integer-looking string will get lexed as T_Float if the value
* is too large to fit in an 'int'.
*/
typedef struct Float
{
NodeTag type;
char *val;
} Float;
extern Value *makeInteger(int i);
extern Value *makeFloat(char *numericStr);
extern Value *makeString(char *str);
extern Value *makeBitString(char *str);
typedef struct String
{
NodeTag type;
char *val;
} String;
typedef struct BitString
{
NodeTag type;
char *val;
} BitString;
#define intVal(v) (castNode(Integer, v)->val)
#define floatVal(v) atof(castNode(Float, v)->val)
#define strVal(v) (castNode(String, v)->val)
extern Integer *makeInteger(int i);
extern Float *makeFloat(char *numericStr);
extern String *makeString(char *str);
extern BitString *makeBitString(char *str);
#endif /* VALUE_H */

View File

@ -333,7 +333,6 @@ extern SubscriptingRef *transformContainerSubscripts(ParseState *pstate,
int32 containerTypMod,
List *indirection,
bool isAssignment);
extern Const *make_const(ParseState *pstate, Value *value, int location);
extern Const *make_const(ParseState *pstate, A_Const *aconst);
#endif /* PARSE_NODE_H */