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

View File

@ -3026,7 +3026,7 @@ CheckSetNamespace(Oid oldNspOid, Oid nspOid)
/* /*
* QualifiedNameGetCreationNamespace * 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. * format), determine what namespace the object should be created in.
* Also extract and return the object name (last component of list). * 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 * This is used primarily to form error messages, and so we do not quote
* the list elements, for the sake of legibility. * 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. * but we also allow A_Star for the convenience of ColumnRef processing.
*/ */
char * char *

View File

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

View File

@ -55,7 +55,7 @@ static int sort_order_cmp(const void *p1, const void *p2);
* EnumValuesCreate * EnumValuesCreate
* Create an entry in pg_enum for each of the supplied enum values. * 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 void
EnumValuesCreate(Oid enumTypeOid, List *vals) 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 * Build the ColumnRef for each column. The ColumnRef
* 'fields' property is a String 'Value' node (see * 'fields' property is a String node that corresponds to
* nodes/value.h) that corresponds to the column name * the column name respectively.
* respectively.
*/ */
cr = makeNode(ColumnRef); cr = makeNode(ColumnRef);
cr->fields = list_make1(lfirst(lc)); cr->fields = list_make1(lfirst(lc));

View File

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

View File

@ -1179,7 +1179,7 @@ getTokenTypes(Oid prsId, List *tokennames)
i = 0; i = 0;
foreach(tn, tokennames) foreach(tn, tokennames)
{ {
Value *val = (Value *) lfirst(tn); String *val = lfirst_node(String, tn);
bool found = false; bool found = false;
int j; int j;
@ -1395,7 +1395,7 @@ DropConfigurationMapping(AlterTSConfigurationStmt *stmt,
i = 0; i = 0;
foreach(c, stmt->tokentype) foreach(c, stmt->tokentype)
{ {
Value *val = (Value *) lfirst(c); String *val = lfirst_node(String, c);
bool found = false; bool found = false;
ScanKeyInit(&skey[0], 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) forboth(lc1, tstate->ns_uris, lc2, tstate->ns_names)
{ {
ExprState *expr = (ExprState *) lfirst(lc1); ExprState *expr = (ExprState *) lfirst(lc1);
Value *ns_node = (Value *) lfirst(lc2); String *ns_node = lfirst_node(String, lc2);
char *ns_uri; char *ns_uri;
char *ns_name; char *ns_name;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1140,7 +1140,7 @@ buildRelationAliases(TupleDesc tupdesc, Alias *alias, Alias *eref)
for (varattno = 0; varattno < maxattrs; varattno++) for (varattno = 0; varattno < maxattrs; varattno++)
{ {
Form_pg_attribute attr = TupleDescAttr(tupdesc, varattno); Form_pg_attribute attr = TupleDescAttr(tupdesc, varattno);
Value *attrname; String *attrname;
if (attr->attisdropped) if (attr->attisdropped)
{ {
@ -1153,7 +1153,7 @@ buildRelationAliases(TupleDesc tupdesc, Alias *alias, Alias *eref)
else if (aliaslc) else if (aliaslc)
{ {
/* Use the next user-supplied alias */ /* Use the next user-supplied alias */
attrname = (Value *) lfirst(aliaslc); attrname = lfirst_node(String, aliaslc);
aliaslc = lnext(aliaslist, aliaslc); aliaslc = lnext(aliaslist, aliaslc);
alias->colnames = lappend(alias->colnames, attrname); alias->colnames = lappend(alias->colnames, attrname);
} }
@ -3052,7 +3052,7 @@ expandNSItemVars(ParseNamespaceItem *nsitem,
colindex = 0; colindex = 0;
foreach(lc, nsitem->p_names->colnames) foreach(lc, nsitem->p_names->colnames)
{ {
Value *colnameval = (Value *) lfirst(lc); String *colnameval = lfirst(lc);
const char *colname = strVal(colnameval); const char *colname = strVal(colnameval);
ParseNamespaceColumn *nscol = nsitem->p_nscolumns + colindex; 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)) 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) || else if (IsA(&ac->val, Float))
IsA(&ac->val, String))
{ {
/* we can just use the str field directly. */ /* we can just use the string representation directly. */
cstr = ac->val.val.str; 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)) else if (IsA(tm, ColumnRef))

View File

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

View File

@ -324,7 +324,7 @@ oidparse(Node *node)
* constants by the lexer. Accept these if they are valid OID * constants by the lexer. Accept these if they are valid OID
* strings. * strings.
*/ */
return oidin_subr(strVal(node), NULL); return oidin_subr(castNode(Float, node)->val, NULL);
default: default:
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); 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) forboth(lc1, tf->ns_uris, lc2, tf->ns_names)
{ {
Node *expr = (Node *) lfirst(lc1); Node *expr = (Node *) lfirst(lc1);
Value *ns_node = (Value *) lfirst(lc2); String *ns_node = lfirst_node(String, lc2);
if (!first) if (!first)
appendStringInfoString(buf, ", "); appendStringInfoString(buf, ", ");

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* value.h * value.h
* interface for Value nodes * interface for value nodes
* *
* *
* Copyright (c) 2003-2021, PostgreSQL Global Development Group * Copyright (c) 2003-2021, PostgreSQL Global Development Group
@ -16,46 +16,57 @@
#include "nodes/nodes.h" #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, * (There used to be a Value node, which encompassed all these different node types. Hence the name of this file.)
* 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.
*----------------------
*/ */
typedef struct Value
typedef struct Integer
{ {
NodeTag type; /* tag appropriately (eg. T_String) */ NodeTag type;
union ValUnion int val;
{ } Integer;
int ival; /* machine integer */
char *str; /* string */
} val;
} Value;
#define intVal(v) (((Value *)(v))->val.ival) /*
#define floatVal(v) atof(((Value *)(v))->val.str) * Float is internally represented as string. Using T_Float as the node type
#define strVal(v) (((Value *)(v))->val.str) * 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); typedef struct String
extern Value *makeFloat(char *numericStr); {
extern Value *makeString(char *str); NodeTag type;
extern Value *makeBitString(char *str); 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 */ #endif /* VALUE_H */

View File

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