On 27.12.21 10:02, Peter Eisentraut wrote:
This patch adds a new node type Boolean, to go alongside the "value" nodes Integer, Float, String, etc.  This seems appropriate given that Boolean values are a fundamental part of the system and are used a lot.

Before, SQL-level Boolean constants were represented by a string with
a cast, and internal Boolean values in DDL commands were usually represented by Integer nodes.  This takes the place of both of these uses, making the intent clearer and having some amount of type safety.

Here is an update of this patch set based on the feedback. First, I added a patch that makes some changes in AlterRole() that my original patch might have broken or at least made more confusing. Unlike in CreateRole(), we use three-valued logic here, so that a variable like issuper would have 0 = no, 1 = yes, -1 = not specified, keep previous value. I'm simplifying this, by instead using the dissuper etc. variables to track whether a setting was specified. This makes everything a bit simpler and makes the subsequent patch easier.

Second, I added the suggest by Tom Lane to rename to fields in the used-to-be-Value nodes to be different in each node type (ival, fval, etc.). I agree that this makes things a bit cleaner and reduces the changes of mixups.

And third, the original patch that introduces the Boolean node with some small changes based on the feedback.
From 8d5f7f330c0824c862a3c0d8ce5cd3d578e22d82 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Mon, 3 Jan 2022 09:37:12 +0100
Subject: [PATCH v2 1/3] Refactor AlterRole()

Get rid of the three-valued logic for the Boolean variables to track
whether the value was been specified and what the new value should be.
Instead, we can use the "dfoo" variables to determine whether the
value was specified and should be applied.  This was already done in
some cases, so this makes this more uniform and removes one layer of
indirection.
---
 src/backend/commands/user.c | 97 +++++++++++++------------------------
 1 file changed, 35 insertions(+), 62 deletions(-)

diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index aa69821be4..0aae87ff4a 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -501,20 +501,12 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
                                new_tuple;
        Form_pg_authid authform;
        ListCell   *option;
-       char       *rolename = NULL;
+       char       *rolename;
        char       *password = NULL;    /* user password */
-       int                     issuper = -1;   /* Make the user a superuser? */
-       int                     inherit = -1;   /* Auto inherit privileges? */
-       int                     createrole = -1;        /* Can this user create 
roles? */
-       int                     createdb = -1;  /* Can the user create 
databases? */
-       int                     canlogin = -1;  /* Can this user login? */
-       int                     isreplication = -1; /* Is this a replication 
role? */
        int                     connlimit = -1; /* maximum connections allowed 
*/
-       List       *rolemembers = NIL;  /* roles to be added/removed */
        char       *validUntil = NULL;  /* time the login is valid until */
        Datum           validUntil_datum;       /* same, as timestamptz Datum */
        bool            validUntil_null;
-       int                     bypassrls = -1;
        DefElem    *dpassword = NULL;
        DefElem    *dissuper = NULL;
        DefElem    *dinherit = NULL;
@@ -610,18 +602,6 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
 
        if (dpassword && dpassword->arg)
                password = strVal(dpassword->arg);
-       if (dissuper)
-               issuper = intVal(dissuper->arg);
-       if (dinherit)
-               inherit = intVal(dinherit->arg);
-       if (dcreaterole)
-               createrole = intVal(dcreaterole->arg);
-       if (dcreatedb)
-               createdb = intVal(dcreatedb->arg);
-       if (dcanlogin)
-               canlogin = intVal(dcanlogin->arg);
-       if (disreplication)
-               isreplication = intVal(disreplication->arg);
        if (dconnlimit)
        {
                connlimit = intVal(dconnlimit->arg);
@@ -630,12 +610,8 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
                                        
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                         errmsg("invalid connection limit: %d", 
connlimit)));
        }
-       if (drolemembers)
-               rolemembers = (List *) drolemembers->arg;
        if (dvalidUntil)
                validUntil = strVal(dvalidUntil->arg);
-       if (dbypassRLS)
-               bypassrls = intVal(dbypassRLS->arg);
 
        /*
         * Scan the pg_authid relation to be certain the user exists.
@@ -654,21 +630,21 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
         * property.  Otherwise, if you don't have createrole, you're only 
allowed
         * to change your own password.
         */
-       if (authform->rolsuper || issuper >= 0)
+       if (authform->rolsuper || dissuper)
        {
                if (!superuser())
                        ereport(ERROR,
                                        
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                         errmsg("must be superuser to alter 
superuser roles or change superuser attribute")));
        }
-       else if (authform->rolreplication || isreplication >= 0)
+       else if (authform->rolreplication || disreplication)
        {
                if (!superuser())
                        ereport(ERROR,
                                        
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                         errmsg("must be superuser to alter 
replication roles or change replication attribute")));
        }
-       else if (bypassrls >= 0)
+       else if (dbypassRLS)
        {
                if (!superuser())
                        ereport(ERROR,
@@ -677,23 +653,16 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
        }
        else if (!have_createrole_privilege())
        {
-               /* We already checked issuper, isreplication, and bypassrls */
-               if (!(inherit < 0 &&
-                         createrole < 0 &&
-                         createdb < 0 &&
-                         canlogin < 0 &&
-                         !dconnlimit &&
-                         !rolemembers &&
-                         !validUntil &&
-                         dpassword &&
-                         roleid == GetUserId()))
+               /* check the rest */
+               if (dinherit || dcreaterole || dcreatedb || dcanlogin || 
dconnlimit ||
+                       drolemembers || dvalidUntil || !dpassword || roleid != 
GetUserId())
                        ereport(ERROR,
                                        
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                         errmsg("permission denied")));
        }
 
        /* Convert validuntil to internal form */
-       if (validUntil)
+       if (dvalidUntil)
        {
                validUntil_datum = DirectFunctionCall3(timestamptz_in,
                                                                                
           CStringGetDatum(validUntil),
@@ -729,39 +698,39 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
        /*
         * issuper/createrole/etc
         */
-       if (issuper >= 0)
+       if (dissuper)
        {
-               new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(issuper 
> 0);
+               new_record[Anum_pg_authid_rolsuper - 1] = 
BoolGetDatum(intVal(dissuper->arg));
                new_record_repl[Anum_pg_authid_rolsuper - 1] = true;
        }
 
-       if (inherit >= 0)
+       if (dinherit)
        {
-               new_record[Anum_pg_authid_rolinherit - 1] = 
BoolGetDatum(inherit > 0);
+               new_record[Anum_pg_authid_rolinherit - 1] = 
BoolGetDatum(intVal(dinherit->arg));
                new_record_repl[Anum_pg_authid_rolinherit - 1] = true;
        }
 
-       if (createrole >= 0)
+       if (dcreaterole)
        {
-               new_record[Anum_pg_authid_rolcreaterole - 1] = 
BoolGetDatum(createrole > 0);
+               new_record[Anum_pg_authid_rolcreaterole - 1] = 
BoolGetDatum(intVal(dcreaterole->arg));
                new_record_repl[Anum_pg_authid_rolcreaterole - 1] = true;
        }
 
-       if (createdb >= 0)
+       if (dcreatedb)
        {
-               new_record[Anum_pg_authid_rolcreatedb - 1] = 
BoolGetDatum(createdb > 0);
+               new_record[Anum_pg_authid_rolcreatedb - 1] = 
BoolGetDatum(intVal(dcreatedb->arg));
                new_record_repl[Anum_pg_authid_rolcreatedb - 1] = true;
        }
 
-       if (canlogin >= 0)
+       if (dcanlogin)
        {
-               new_record[Anum_pg_authid_rolcanlogin - 1] = 
BoolGetDatum(canlogin > 0);
+               new_record[Anum_pg_authid_rolcanlogin - 1] = 
BoolGetDatum(intVal(dcanlogin->arg));
                new_record_repl[Anum_pg_authid_rolcanlogin - 1] = true;
        }
 
-       if (isreplication >= 0)
+       if (disreplication)
        {
-               new_record[Anum_pg_authid_rolreplication - 1] = 
BoolGetDatum(isreplication > 0);
+               new_record[Anum_pg_authid_rolreplication - 1] = 
BoolGetDatum(intVal(disreplication->arg));
                new_record_repl[Anum_pg_authid_rolreplication - 1] = true;
        }
 
@@ -808,9 +777,9 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
        new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null;
        new_record_repl[Anum_pg_authid_rolvaliduntil - 1] = true;
 
-       if (bypassrls >= 0)
+       if (dbypassRLS)
        {
-               new_record[Anum_pg_authid_rolbypassrls - 1] = 
BoolGetDatum(bypassrls > 0);
+               new_record[Anum_pg_authid_rolbypassrls - 1] = 
BoolGetDatum(intVal(dbypassRLS->arg));
                new_record_repl[Anum_pg_authid_rolbypassrls - 1] = true;
        }
 
@@ -827,17 +796,21 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
         * Advance command counter so we can see new record; else tests in
         * AddRoleMems may fail.
         */
-       if (rolemembers)
+       if (drolemembers)
+       {
+               List       *rolemembers = (List *) drolemembers->arg;
+
                CommandCounterIncrement();
 
-       if (stmt->action == +1)         /* add members to role */
-               AddRoleMems(rolename, roleid,
-                                       rolemembers, 
roleSpecsToIds(rolemembers),
-                                       GetUserId(), false);
-       else if (stmt->action == -1)    /* drop members from role */
-               DelRoleMems(rolename, roleid,
-                                       rolemembers, 
roleSpecsToIds(rolemembers),
-                                       false);
+               if (stmt->action == +1)         /* add members to role */
+                       AddRoleMems(rolename, roleid,
+                                               rolemembers, 
roleSpecsToIds(rolemembers),
+                                               GetUserId(), false);
+               else if (stmt->action == -1)    /* drop members from role */
+                       DelRoleMems(rolename, roleid,
+                                               rolemembers, 
roleSpecsToIds(rolemembers),
+                                               false);
+       }
 
        /*
         * Close pg_authid, but keep lock till commit.

base-commit: 69872d0bbe64fcd67c4fb4c61e5c7bf6a3443a47
-- 
2.34.1

From 08010ba3345fb8020587326304d6a6dafe0f098c Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Mon, 3 Jan 2022 09:59:44 +0100
Subject: [PATCH v2 2/3] Rename value node fields

For the formerly-Value node types, rename the "val" field to a name
specific to the node type, namely "ival", "fval", "sval", and "bsval".
This makes some code clearer and catches mixups better.
---
 src/backend/commands/define.c      |  4 ++--
 src/backend/nodes/copyfuncs.c      | 16 ++++++++--------
 src/backend/nodes/equalfuncs.c     |  8 ++++----
 src/backend/nodes/outfuncs.c       | 10 +++++-----
 src/backend/nodes/value.c          |  8 ++++----
 src/backend/parser/gram.y          | 24 ++++++++++++------------
 src/backend/parser/parse_node.c    | 10 +++++-----
 src/backend/parser/parse_type.c    |  6 +++---
 src/backend/parser/parse_utilcmd.c |  2 +-
 src/backend/utils/adt/oid.c        |  2 +-
 src/backend/utils/misc/guc.c       |  2 +-
 src/include/nodes/value.h          | 14 +++++++-------
 12 files changed, 53 insertions(+), 53 deletions(-)

diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c
index 19c317a472..0fe7e471d9 100644
--- a/src/backend/commands/define.c
+++ b/src/backend/commands/define.c
@@ -58,7 +58,7 @@ defGetString(DefElem *def)
                case T_Integer:
                        return psprintf("%ld", (long) intVal(def->arg));
                case T_Float:
-                       return castNode(Float, def->arg)->val;
+                       return castNode(Float, def->arg)->fval;
                case T_String:
                        return strVal(def->arg);
                case T_TypeName:
@@ -201,7 +201,7 @@ defGetInt64(DefElem *def)
                         * strings.
                         */
                        return DatumGetInt64(DirectFunctionCall1(int8in,
-                                                                               
                         CStringGetDatum(castNode(Float, def->arg)->val)));
+                                                                               
                         CStringGetDatum(castNode(Float, def->arg)->fval)));
                default:
                        ereport(ERROR,
                                        (errcode(ERRCODE_SYNTAX_ERROR),
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index df0b747883..439b903eb8 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -2744,16 +2744,16 @@ _copyA_Const(const A_Const *from)
                switch (nodeTag(&from->val))
                {
                        case T_Integer:
-                               COPY_SCALAR_FIELD(val.ival.val);
+                               COPY_SCALAR_FIELD(val.ival.ival);
                                break;
                        case T_Float:
-                               COPY_STRING_FIELD(val.fval.val);
+                               COPY_STRING_FIELD(val.fval.fval);
                                break;
                        case T_String:
-                               COPY_STRING_FIELD(val.sval.val);
+                               COPY_STRING_FIELD(val.sval.sval);
                                break;
                        case T_BitString:
-                               COPY_STRING_FIELD(val.bsval.val);
+                               COPY_STRING_FIELD(val.bsval.bsval);
                                break;
                        default:
                                elog(ERROR, "unrecognized node type: %d",
@@ -4933,7 +4933,7 @@ _copyInteger(const Integer *from)
 {
        Integer    *newnode = makeNode(Integer);
 
-       COPY_SCALAR_FIELD(val);
+       COPY_SCALAR_FIELD(ival);
 
        return newnode;
 }
@@ -4943,7 +4943,7 @@ _copyFloat(const Float *from)
 {
        Float      *newnode = makeNode(Float);
 
-       COPY_STRING_FIELD(val);
+       COPY_STRING_FIELD(fval);
 
        return newnode;
 }
@@ -4953,7 +4953,7 @@ _copyString(const String *from)
 {
        String     *newnode = makeNode(String);
 
-       COPY_STRING_FIELD(val);
+       COPY_STRING_FIELD(sval);
 
        return newnode;
 }
@@ -4963,7 +4963,7 @@ _copyBitString(const BitString *from)
 {
        BitString   *newnode = makeNode(BitString);
 
-       COPY_STRING_FIELD(val);
+       COPY_STRING_FIELD(bsval);
 
        return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index cb7ddd463c..be09f91ee2 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -3125,7 +3125,7 @@ _equalList(const List *a, const List *b)
 static bool
 _equalInteger(const Integer *a, const Integer *b)
 {
-       COMPARE_SCALAR_FIELD(val);
+       COMPARE_SCALAR_FIELD(ival);
 
        return true;
 }
@@ -3133,7 +3133,7 @@ _equalInteger(const Integer *a, const Integer *b)
 static bool
 _equalFloat(const Float *a, const Float *b)
 {
-       COMPARE_STRING_FIELD(val);
+       COMPARE_STRING_FIELD(fval);
 
        return true;
 }
@@ -3141,7 +3141,7 @@ _equalFloat(const Float *a, const Float *b)
 static bool
 _equalString(const String *a, const String *b)
 {
-       COMPARE_STRING_FIELD(val);
+       COMPARE_STRING_FIELD(sval);
 
        return true;
 }
@@ -3149,7 +3149,7 @@ _equalString(const String *a, const String *b)
 static bool
 _equalBitString(const BitString *a, const BitString *b)
 {
-       COMPARE_STRING_FIELD(val);
+       COMPARE_STRING_FIELD(bsval);
 
        return true;
 }
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 91a89b6d51..1accbc1e78 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -3420,7 +3420,7 @@ _outA_Expr(StringInfo str, const A_Expr *node)
 static void
 _outInteger(StringInfo str, const Integer *node)
 {
-       appendStringInfo(str, "%d", node->val);
+       appendStringInfo(str, "%d", node->ival);
 }
 
 static void
@@ -3430,7 +3430,7 @@ _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);
+       appendStringInfoString(str, node->fval);
 }
 
 static void
@@ -3441,8 +3441,8 @@ _outString(StringInfo str, const String *node)
         * but we don't want it to do anything with an empty string.
         */
        appendStringInfoChar(str, '"');
-       if (node->val[0] != '\0')
-               outToken(str, node->val);
+       if (node->sval[0] != '\0')
+               outToken(str, node->sval);
        appendStringInfoChar(str, '"');
 }
 
@@ -3450,7 +3450,7 @@ static void
 _outBitString(StringInfo str, const BitString *node)
 {
        /* internal representation already has leading 'b' */
-       appendStringInfoString(str, node->val);
+       appendStringInfoString(str, node->bsval);
 }
 
 static void
diff --git a/src/backend/nodes/value.c b/src/backend/nodes/value.c
index 515f93c223..ab2d6f74d3 100644
--- a/src/backend/nodes/value.c
+++ b/src/backend/nodes/value.c
@@ -24,7 +24,7 @@ makeInteger(int i)
 {
        Integer    *v = makeNode(Integer);
 
-       v->val = i;
+       v->ival = i;
        return v;
 }
 
@@ -38,7 +38,7 @@ makeFloat(char *numericStr)
 {
        Float      *v = makeNode(Float);
 
-       v->val = numericStr;
+       v->fval = numericStr;
        return v;
 }
 
@@ -52,7 +52,7 @@ makeString(char *str)
 {
        String     *v = makeNode(String);
 
-       v->val = str;
+       v->sval = str;
        return v;
 }
 
@@ -66,6 +66,6 @@ makeBitString(char *str)
 {
        BitString  *v = makeNode(BitString);
 
-       v->val = str;
+       v->bsval = str;
        return v;
 }
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index f3c232842d..adce748a69 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -1719,7 +1719,7 @@ zone_value:
                                        if ($3 != NIL)
                                        {
                                                A_Const *n = (A_Const *) 
linitial($3);
-                                               if ((n->val.ival.val & 
~(INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE))) != 0)
+                                               if ((n->val.ival.ival & 
~(INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE))) != 0)
                                                        ereport(ERROR,
                                                                        
(errcode(ERRCODE_SYNTAX_ERROR),
                                                                         
errmsg("time zone interval must be HOUR or HOUR TO MINUTE"),
@@ -16667,7 +16667,7 @@ makeStringConst(char *str, int location)
        A_Const *n = makeNode(A_Const);
 
        n->val.sval.type = T_String;
-       n->val.sval.val = str;
+       n->val.sval.sval = str;
        n->location = location;
 
    return (Node *)n;
@@ -16687,7 +16687,7 @@ makeIntConst(int val, int location)
        A_Const *n = makeNode(A_Const);
 
        n->val.ival.type = T_Integer;
-       n->val.ival.val = val;
+       n->val.ival.ival = val;
        n->location = location;
 
    return (Node *)n;
@@ -16699,7 +16699,7 @@ makeFloatConst(char *str, int location)
        A_Const *n = makeNode(A_Const);
 
        n->val.fval.type = T_Float;
-       n->val.fval.val = str;
+       n->val.fval.fval = str;
        n->location = location;
 
    return (Node *)n;
@@ -16711,7 +16711,7 @@ makeBitStringConst(char *str, int location)
        A_Const *n = makeNode(A_Const);
 
        n->val.bsval.type = T_BitString;
-       n->val.bsval.val = str;
+       n->val.bsval.bsval = str;
        n->location = location;
 
    return (Node *)n;
@@ -16736,16 +16736,16 @@ makeAConst(Node *v, int location)
        switch (v->type)
        {
                case T_Float:
-                       n = makeFloatConst(castNode(Float, v)->val, location);
+                       n = makeFloatConst(castNode(Float, v)->fval, location);
                        break;
 
                case T_Integer:
-                       n = makeIntConst(castNode(Integer, v)->val, location);
+                       n = makeIntConst(castNode(Integer, v)->ival, location);
                        break;
 
                case T_String:
                default:
-                       n = makeStringConst(castNode(String, v)->val, location);
+                       n = makeStringConst(castNode(String, v)->sval, 
location);
                        break;
        }
 
@@ -17049,7 +17049,7 @@ doNegate(Node *n, int location)
 
                if (IsA(&con->val, Integer))
                {
-                       con->val.ival.val = -con->val.ival.val;
+                       con->val.ival.ival = -con->val.ival.ival;
                        return n;
                }
                if (IsA(&con->val, Float))
@@ -17065,14 +17065,14 @@ doNegate(Node *n, int location)
 static void
 doNegateFloat(Float *v)
 {
-       char   *oldval = v->val;
+       char   *oldval = v->fval;
 
        if (*oldval == '+')
                oldval++;
        if (*oldval == '-')
-               v->val = oldval+1;      /* just strip the '-' */
+               v->fval = oldval+1;     /* just strip the '-' */
        else
-               v->val = psprintf("-%s", oldval);
+               v->fval = psprintf("-%s", oldval);
 }
 
 static Node *
diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c
index 8cfe6f67c0..bd92133b21 100644
--- a/src/backend/parser/parse_node.c
+++ b/src/backend/parser/parse_node.c
@@ -376,7 +376,7 @@ make_const(ParseState *pstate, A_Const *aconst)
        switch (nodeTag(&aconst->val))
        {
                case T_Integer:
-                       val = Int32GetDatum(aconst->val.ival.val);
+                       val = Int32GetDatum(intVal(&aconst->val));
 
                        typeid = INT4OID;
                        typelen = sizeof(int32);
@@ -385,7 +385,7 @@ make_const(ParseState *pstate, A_Const *aconst)
 
                case T_Float:
                        /* could be an oversize integer as well as a float ... 
*/
-                       if (scanint8(aconst->val.fval.val, true, &val64))
+                       if (scanint8(aconst->val.fval.fval, true, &val64))
                        {
                                /*
                                 * It might actually fit in int32. Probably 
only INT_MIN can
@@ -415,7 +415,7 @@ make_const(ParseState *pstate, A_Const *aconst)
                                /* arrange to report location if numeric_in() 
fails */
                                setup_parser_errposition_callback(&pcbstate, 
pstate, aconst->location);
                                val = DirectFunctionCall3(numeric_in,
-                                                                               
  CStringGetDatum(aconst->val.fval.val),
+                                                                               
  CStringGetDatum(aconst->val.fval.fval),
                                                                                
  ObjectIdGetDatum(InvalidOid),
                                                                                
  Int32GetDatum(-1));
                                cancel_parser_errposition_callback(&pcbstate);
@@ -432,7 +432,7 @@ make_const(ParseState *pstate, A_Const *aconst)
                         * We assume here that UNKNOWN's internal 
representation is the
                         * same as CSTRING
                         */
-                       val = CStringGetDatum(aconst->val.sval.val);
+                       val = CStringGetDatum(strVal(&aconst->val));
 
                        typeid = UNKNOWNOID;    /* will be coerced later */
                        typelen = -2;           /* cstring-style varwidth type 
*/
@@ -443,7 +443,7 @@ make_const(ParseState *pstate, A_Const *aconst)
                        /* arrange to report location if bit_in() fails */
                        setup_parser_errposition_callback(&pcbstate, pstate, 
aconst->location);
                        val = DirectFunctionCall3(bit_in,
-                                                                         
CStringGetDatum(aconst->val.bsval.val),
+                                                                         
CStringGetDatum(aconst->val.bsval.bsval),
                                                                          
ObjectIdGetDatum(InvalidOid),
                                                                          
Int32GetDatum(-1));
                        cancel_parser_errposition_callback(&pcbstate);
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
index 31b07ad5ae..f2d5e98127 100644
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -382,17 +382,17 @@ typenameTypeMod(ParseState *pstate, const TypeName 
*typeName, Type typ)
 
                        if (IsA(&ac->val, Integer))
                        {
-                               cstr = psprintf("%ld", (long) ac->val.ival.val);
+                               cstr = psprintf("%ld", (long) intVal(&ac->val));
                        }
                        else if (IsA(&ac->val, Float))
                        {
                                /* we can just use the string representation 
directly. */
-                               cstr = ac->val.fval.val;
+                               cstr = ac->val.fval.fval;
                        }
                        else if (IsA(&ac->val, String))
                        {
                                /* we can just use the string representation 
directly. */
-                               cstr = ac->val.sval.val;
+                               cstr = strVal(&ac->val);
                        }
                }
                else if (IsA(tm, ColumnRef))
diff --git a/src/backend/parser/parse_utilcmd.c 
b/src/backend/parser/parse_utilcmd.c
index 2d857a301b..2c64f12a78 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -603,7 +603,7 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef 
*column)
                qstring = quote_qualified_identifier(snamespace, sname);
                snamenode = makeNode(A_Const);
                snamenode->val.node.type = T_String;
-               snamenode->val.sval.val = qstring;
+               snamenode->val.sval.sval = qstring;
                snamenode->location = -1;
                castnode = makeNode(TypeCast);
                castnode->typeName = SystemTypeName("regclass");
diff --git a/src/backend/utils/adt/oid.c b/src/backend/utils/adt/oid.c
index 7be260663e..4e684fe91c 100644
--- a/src/backend/utils/adt/oid.c
+++ b/src/backend/utils/adt/oid.c
@@ -324,7 +324,7 @@ oidparse(Node *node)
                         * constants by the lexer.  Accept these if they are 
valid OID
                         * strings.
                         */
-                       return oidin_subr(castNode(Float, node)->val, NULL);
+                       return oidin_subr(castNode(Float, node)->fval, NULL);
                default:
                        elog(ERROR, "unrecognized node type: %d", (int) 
nodeTag(node));
        }
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index f9504d3aec..ff95c3631c 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -8332,7 +8332,7 @@ flatten_set_variable_args(const char *name, List *args)
                                break;
                        case T_Float:
                                /* represented as a string, so just copy it */
-                               appendStringInfoString(&buf, castNode(Float, 
&con->val)->val);
+                               appendStringInfoString(&buf, castNode(Float, 
&con->val)->fval);
                                break;
                        case T_String:
                                val = strVal(&con->val);
diff --git a/src/include/nodes/value.h b/src/include/nodes/value.h
index 8b71b510eb..cc3a4a639c 100644
--- a/src/include/nodes/value.h
+++ b/src/include/nodes/value.h
@@ -28,7 +28,7 @@
 typedef struct Integer
 {
        NodeTag         type;
-       int                     val;
+       int                     ival;
 } Integer;
 
 /*
@@ -45,24 +45,24 @@ typedef struct Integer
 typedef struct Float
 {
        NodeTag         type;
-       char       *val;
+       char       *fval;
 } Float;
 
 typedef struct String
 {
        NodeTag         type;
-       char       *val;
+       char       *sval;
 } String;
 
 typedef struct BitString
 {
        NodeTag         type;
-       char       *val;
+       char       *bsval;
 } BitString;
 
-#define intVal(v)              (castNode(Integer, v)->val)
-#define floatVal(v)            atof(castNode(Float, v)->val)
-#define strVal(v)              (castNode(String, v)->val)
+#define intVal(v)              (castNode(Integer, v)->ival)
+#define floatVal(v)            atof(castNode(Float, v)->fval)
+#define strVal(v)              (castNode(String, v)->sval)
 
 extern Integer *makeInteger(int i);
 extern Float *makeFloat(char *numericStr);
-- 
2.34.1

From eb4bdfc511f1c0f2e8f3971699c33fcfb8cf6105 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Mon, 3 Jan 2022 11:19:52 +0100
Subject: [PATCH v2 3/3] Add Boolean node

Before, SQL-level boolean constants were represented by a string with
a cast, and internal Boolean values in DDL commands were usually
represented by Integer nodes.  This takes the place of both of these
uses, making the intent clearer and having some amount of type safety.
---
 contrib/postgres_fdw/postgres_fdw.c           | 32 +++---
 src/backend/commands/define.c                 |  2 +
 src/backend/commands/functioncmds.c           | 14 +--
 src/backend/commands/sequence.c               |  4 +-
 src/backend/commands/tsearchcmds.c            |  9 ++
 src/backend/commands/user.c                   | 28 +++---
 src/backend/nodes/copyfuncs.c                 | 16 +++
 src/backend/nodes/equalfuncs.c                | 11 +++
 src/backend/nodes/nodeFuncs.c                 |  1 +
 src/backend/nodes/outfuncs.c                  |  8 ++
 src/backend/nodes/read.c                      |  9 +-
 src/backend/nodes/value.c                     | 12 +++
 src/backend/parser/gram.y                     | 98 +++++++++----------
 src/backend/parser/parse_node.c               |  8 ++
 src/backend/replication/repl_gram.y           | 14 +--
 src/include/nodes/nodes.h                     |  1 +
 src/include/nodes/parsenodes.h                |  1 +
 src/include/nodes/value.h                     |  8 ++
 src/test/isolation/expected/ri-trigger.out    | 60 ++++++------
 .../regress/expected/create_function_3.out    |  2 +-
 20 files changed, 210 insertions(+), 128 deletions(-)

diff --git a/contrib/postgres_fdw/postgres_fdw.c 
b/contrib/postgres_fdw/postgres_fdw.c
index fa9a099f13..4d61d88d7b 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -103,7 +103,7 @@ enum FdwModifyPrivateIndex
        FdwModifyPrivateTargetAttnums,
        /* Length till the end of VALUES clause (as an Integer node) */
        FdwModifyPrivateLen,
-       /* has-returning flag (as an Integer node) */
+       /* has-returning flag (as a Boolean 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 node) */
+       /* has-returning flag (as a Boolean node) */
        FdwDirectModifyPrivateHasReturning,
        /* Integer list of attribute numbers retrieved by RETURNING */
        FdwDirectModifyPrivateRetrievedAttrs,
-       /* set-processed flag (as an Integer node) */
+       /* set-processed flag (as a Boolean node) */
        FdwDirectModifyPrivateSetProcessed
 };
 
@@ -280,9 +280,9 @@ typedef struct PgFdwAnalyzeState
  */
 enum FdwPathPrivateIndex
 {
-       /* has-final-sort flag (as an Integer node) */
+       /* has-final-sort flag (as a Boolean node) */
        FdwPathPrivateHasFinalSort,
-       /* has-limit flag (as an Integer node) */
+       /* has-limit flag (as a Boolean node) */
        FdwPathPrivateHasLimit
 };
 
@@ -1245,9 +1245,9 @@ postgresGetForeignPlan(PlannerInfo *root,
         */
        if (best_path->fdw_private)
        {
-               has_final_sort = intVal(list_nth(best_path->fdw_private,
+               has_final_sort = boolVal(list_nth(best_path->fdw_private,
                                                                                
 FdwPathPrivateHasFinalSort));
-               has_limit = intVal(list_nth(best_path->fdw_private,
+               has_limit = boolVal(list_nth(best_path->fdw_private,
                                                                        
FdwPathPrivateHasLimit));
        }
 
@@ -1879,7 +1879,7 @@ postgresPlanForeignModify(PlannerInfo *root,
        return list_make5(makeString(sql.data),
                                          targetAttrs,
                                          makeInteger(values_end_len),
-                                         makeInteger((retrieved_attrs != NIL)),
+                                         makeBoolean((retrieved_attrs != NIL)),
                                          retrieved_attrs);
 }
 
@@ -1916,7 +1916,7 @@ postgresBeginForeignModify(ModifyTableState *mtstate,
                                                                         
FdwModifyPrivateTargetAttnums);
        values_end_len = intVal(list_nth(fdw_private,
                                                                         
FdwModifyPrivateLen));
-       has_returning = intVal(list_nth(fdw_private,
+       has_returning = boolVal(list_nth(fdw_private,
                                                                        
FdwModifyPrivateHasReturning));
        retrieved_attrs = (List *) list_nth(fdw_private,
                                                                                
FdwModifyPrivateRetrievedAttrs);
@@ -2567,9 +2567,9 @@ postgresPlanDirectModify(PlannerInfo *root,
         * Items in the list must match enum FdwDirectModifyPrivateIndex, above.
         */
        fscan->fdw_private = list_make4(makeString(sql.data),
-                                                                       
makeInteger((retrieved_attrs != NIL)),
+                                                                       
makeBoolean((retrieved_attrs != NIL)),
                                                                        
retrieved_attrs,
-                                                                       
makeInteger(plan->canSetTag));
+                                                                       
makeBoolean(plan->canSetTag));
 
        /*
         * Update the foreign-join-related fields.
@@ -2667,11 +2667,11 @@ postgresBeginDirectModify(ForeignScanState *node, int 
eflags)
        /* Get private info created by planner functions. */
        dmstate->query = strVal(list_nth(fsplan->fdw_private,
                                                                         
FdwDirectModifyPrivateUpdateSql));
-       dmstate->has_returning = intVal(list_nth(fsplan->fdw_private,
+       dmstate->has_returning = boolVal(list_nth(fsplan->fdw_private,
                                                                                
         FdwDirectModifyPrivateHasReturning));
        dmstate->retrieved_attrs = (List *) list_nth(fsplan->fdw_private,
                                                                                
                 FdwDirectModifyPrivateRetrievedAttrs);
-       dmstate->set_processed = intVal(list_nth(fsplan->fdw_private,
+       dmstate->set_processed = boolVal(list_nth(fsplan->fdw_private,
                                                                                
         FdwDirectModifyPrivateSetProcessed));
 
        /* Create context for per-tuple temp workspace. */
@@ -6566,7 +6566,7 @@ add_foreign_ordered_paths(PlannerInfo *root, RelOptInfo 
*input_rel,
         * Build the fdw_private list that will be used by 
postgresGetForeignPlan.
         * Items in the list must match order in enum FdwPathPrivateIndex.
         */
-       fdw_private = list_make2(makeInteger(true), makeInteger(false));
+       fdw_private = list_make2(makeBoolean(true), makeBoolean(false));
 
        /* Create foreign ordering path */
        ordered_path = create_foreign_upper_path(root,
@@ -6797,8 +6797,8 @@ add_foreign_final_paths(PlannerInfo *root, RelOptInfo 
*input_rel,
         * Build the fdw_private list that will be used by 
postgresGetForeignPlan.
         * Items in the list must match order in enum FdwPathPrivateIndex.
         */
-       fdw_private = list_make2(makeInteger(has_final_sort),
-                                                        
makeInteger(extra->limit_needed));
+       fdw_private = list_make2(makeBoolean(has_final_sort),
+                                                        
makeBoolean(extra->limit_needed));
 
        /*
         * Create foreign final path; this gets rid of a no-longer-needed outer
diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c
index 0fe7e471d9..f17cfb5ade 100644
--- a/src/backend/commands/define.c
+++ b/src/backend/commands/define.c
@@ -59,6 +59,8 @@ defGetString(DefElem *def)
                        return psprintf("%ld", (long) intVal(def->arg));
                case T_Float:
                        return castNode(Float, def->arg)->fval;
+               case T_Boolean:
+                       return boolVal(def->arg) ? "true" : "false";
                case T_String:
                        return strVal(def->arg);
                case T_TypeName:
diff --git a/src/backend/commands/functioncmds.c 
b/src/backend/commands/functioncmds.c
index 38e78f7102..ba5b23fb11 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -813,15 +813,15 @@ compute_function_attributes(ParseState *pstate,
        if (transform_item)
                *transform = transform_item->arg;
        if (windowfunc_item)
-               *windowfunc_p = intVal(windowfunc_item->arg);
+               *windowfunc_p = boolVal(windowfunc_item->arg);
        if (volatility_item)
                *volatility_p = interpret_func_volatility(volatility_item);
        if (strict_item)
-               *strict_p = intVal(strict_item->arg);
+               *strict_p = boolVal(strict_item->arg);
        if (security_item)
-               *security_definer = intVal(security_item->arg);
+               *security_definer = boolVal(security_item->arg);
        if (leakproof_item)
-               *leakproof_p = intVal(leakproof_item->arg);
+               *leakproof_p = boolVal(leakproof_item->arg);
        if (set_items)
                *proconfig = update_proconfig_value(NULL, set_items);
        if (cost_item)
@@ -1417,12 +1417,12 @@ AlterFunction(ParseState *pstate, AlterFunctionStmt 
*stmt)
        if (volatility_item)
                procForm->provolatile = 
interpret_func_volatility(volatility_item);
        if (strict_item)
-               procForm->proisstrict = intVal(strict_item->arg);
+               procForm->proisstrict = boolVal(strict_item->arg);
        if (security_def_item)
-               procForm->prosecdef = intVal(security_def_item->arg);
+               procForm->prosecdef = boolVal(security_def_item->arg);
        if (leakproof_item)
        {
-               procForm->proleakproof = intVal(leakproof_item->arg);
+               procForm->proleakproof = boolVal(leakproof_item->arg);
                if (procForm->proleakproof && !superuser())
                        ereport(ERROR,
                                        
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 72bfdc07a4..81368b8b2f 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1401,7 +1401,7 @@ init_params(ParseState *pstate, List *options, bool 
for_identity,
        /* CYCLE */
        if (is_cycled != NULL)
        {
-               seqform->seqcycle = intVal(is_cycled->arg);
+               seqform->seqcycle = boolVal(is_cycled->arg);
                Assert(BoolIsValid(seqform->seqcycle));
                seqdataform->log_cnt = 0;
        }
@@ -1739,7 +1739,7 @@ sequence_options(Oid relid)
        options = lappend(options,
                                          makeDefElem("cache", (Node *) 
makeFloat(psprintf(INT64_FORMAT, pgsform->seqcache)), -1));
        options = lappend(options,
-                                         makeDefElem("cycle", (Node *) 
makeInteger(pgsform->seqcycle), -1));
+                                         makeDefElem("cycle", (Node *) 
makeBoolean(pgsform->seqcycle), -1));
        options = lappend(options,
                                          makeDefElem("increment", (Node *) 
makeFloat(psprintf(INT64_FORMAT, pgsform->seqincrement)), -1));
        options = lappend(options,
diff --git a/src/backend/commands/tsearchcmds.c 
b/src/backend/commands/tsearchcmds.c
index c47a05d10d..b7261a88d4 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -1742,6 +1742,15 @@ buildDefItem(const char *name, const char *val, bool 
was_quoted)
                        return makeDefElem(pstrdup(name),
                                                           (Node *) 
makeFloat(pstrdup(val)),
                                                           -1);
+
+               if (strcmp(val, "true") == 0)
+                       return makeDefElem(pstrdup(name),
+                                                          (Node *) 
makeBoolean(true),
+                                                          -1);
+               if (strcmp(val, "false") == 0)
+                       return makeDefElem(pstrdup(name),
+                                                          (Node *) 
makeBoolean(false),
+                                                          -1);
        }
        /* Just make it a string */
        return makeDefElem(pstrdup(name),
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 0aae87ff4a..288805ba78 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -217,17 +217,17 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
        if (dpassword && dpassword->arg)
                password = strVal(dpassword->arg);
        if (dissuper)
-               issuper = intVal(dissuper->arg) != 0;
+               issuper = boolVal(dissuper->arg);
        if (dinherit)
-               inherit = intVal(dinherit->arg) != 0;
+               inherit = boolVal(dinherit->arg);
        if (dcreaterole)
-               createrole = intVal(dcreaterole->arg) != 0;
+               createrole = boolVal(dcreaterole->arg);
        if (dcreatedb)
-               createdb = intVal(dcreatedb->arg) != 0;
+               createdb = boolVal(dcreatedb->arg);
        if (dcanlogin)
-               canlogin = intVal(dcanlogin->arg) != 0;
+               canlogin = boolVal(dcanlogin->arg);
        if (disreplication)
-               isreplication = intVal(disreplication->arg) != 0;
+               isreplication = boolVal(disreplication->arg);
        if (dconnlimit)
        {
                connlimit = intVal(dconnlimit->arg);
@@ -245,7 +245,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
        if (dvalidUntil)
                validUntil = strVal(dvalidUntil->arg);
        if (dbypassRLS)
-               bypassrls = intVal(dbypassRLS->arg) != 0;
+               bypassrls = boolVal(dbypassRLS->arg);
 
        /* Check some permissions first */
        if (issuper)
@@ -700,37 +700,37 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
         */
        if (dissuper)
        {
-               new_record[Anum_pg_authid_rolsuper - 1] = 
BoolGetDatum(intVal(dissuper->arg));
+               new_record[Anum_pg_authid_rolsuper - 1] = 
BoolGetDatum(boolVal(dissuper->arg));
                new_record_repl[Anum_pg_authid_rolsuper - 1] = true;
        }
 
        if (dinherit)
        {
-               new_record[Anum_pg_authid_rolinherit - 1] = 
BoolGetDatum(intVal(dinherit->arg));
+               new_record[Anum_pg_authid_rolinherit - 1] = 
BoolGetDatum(boolVal(dinherit->arg));
                new_record_repl[Anum_pg_authid_rolinherit - 1] = true;
        }
 
        if (dcreaterole)
        {
-               new_record[Anum_pg_authid_rolcreaterole - 1] = 
BoolGetDatum(intVal(dcreaterole->arg));
+               new_record[Anum_pg_authid_rolcreaterole - 1] = 
BoolGetDatum(boolVal(dcreaterole->arg));
                new_record_repl[Anum_pg_authid_rolcreaterole - 1] = true;
        }
 
        if (dcreatedb)
        {
-               new_record[Anum_pg_authid_rolcreatedb - 1] = 
BoolGetDatum(intVal(dcreatedb->arg));
+               new_record[Anum_pg_authid_rolcreatedb - 1] = 
BoolGetDatum(boolVal(dcreatedb->arg));
                new_record_repl[Anum_pg_authid_rolcreatedb - 1] = true;
        }
 
        if (dcanlogin)
        {
-               new_record[Anum_pg_authid_rolcanlogin - 1] = 
BoolGetDatum(intVal(dcanlogin->arg));
+               new_record[Anum_pg_authid_rolcanlogin - 1] = 
BoolGetDatum(boolVal(dcanlogin->arg));
                new_record_repl[Anum_pg_authid_rolcanlogin - 1] = true;
        }
 
        if (disreplication)
        {
-               new_record[Anum_pg_authid_rolreplication - 1] = 
BoolGetDatum(intVal(disreplication->arg));
+               new_record[Anum_pg_authid_rolreplication - 1] = 
BoolGetDatum(boolVal(disreplication->arg));
                new_record_repl[Anum_pg_authid_rolreplication - 1] = true;
        }
 
@@ -779,7 +779,7 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
 
        if (dbypassRLS)
        {
-               new_record[Anum_pg_authid_rolbypassrls - 1] = 
BoolGetDatum(intVal(dbypassRLS->arg));
+               new_record[Anum_pg_authid_rolbypassrls - 1] = 
BoolGetDatum(boolVal(dbypassRLS->arg));
                new_record_repl[Anum_pg_authid_rolbypassrls - 1] = true;
        }
 
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 439b903eb8..e0b440b9f6 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -2749,6 +2749,9 @@ _copyA_Const(const A_Const *from)
                        case T_Float:
                                COPY_STRING_FIELD(val.fval.fval);
                                break;
+                       case T_Boolean:
+                               COPY_SCALAR_FIELD(val.boolval.boolval);
+                               break;
                        case T_String:
                                COPY_STRING_FIELD(val.sval.sval);
                                break;
@@ -4948,6 +4951,16 @@ _copyFloat(const Float *from)
        return newnode;
 }
 
+static Boolean *
+_copyBoolean(const Boolean *from)
+{
+       Boolean    *newnode = makeNode(Boolean);
+
+       COPY_SCALAR_FIELD(boolval);
+
+       return newnode;
+}
+
 static String *
 _copyString(const String *from)
 {
@@ -5355,6 +5368,9 @@ copyObjectImpl(const void *from)
                case T_Float:
                        retval = _copyFloat(from);
                        break;
+               case T_Boolean:
+                       retval = _copyBoolean(from);
+                       break;
                case T_String:
                        retval = _copyString(from);
                        break;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index be09f91ee2..64522e8db0 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -3138,6 +3138,14 @@ _equalFloat(const Float *a, const Float *b)
        return true;
 }
 
+static bool
+_equalBoolean(const Boolean *a, const Boolean *b)
+{
+       COMPARE_SCALAR_FIELD(boolval);
+
+       return true;
+}
+
 static bool
 _equalString(const String *a, const String *b)
 {
@@ -3374,6 +3382,9 @@ equal(const void *a, const void *b)
                case T_Float:
                        retval = _equalFloat(a, b);
                        break;
+               case T_Boolean:
+                       retval = _equalBoolean(a, b);
+                       break;
                case T_String:
                        retval = _equalString(a, b);
                        break;
diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c
index e276264882..397aa6de3c 100644
--- a/src/backend/nodes/nodeFuncs.c
+++ b/src/backend/nodes/nodeFuncs.c
@@ -3535,6 +3535,7 @@ raw_expression_tree_walker(Node *node,
                case T_SQLValueFunction:
                case T_Integer:
                case T_Float:
+               case T_Boolean:
                case T_String:
                case T_BitString:
                case T_ParamRef:
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 1accbc1e78..598adcd844 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -3433,6 +3433,12 @@ _outFloat(StringInfo str, const Float *node)
        appendStringInfoString(str, node->fval);
 }
 
+static void
+_outBoolean(StringInfo str, const Boolean *node)
+{
+       appendStringInfoString(str, node->boolval ? "true" : "false");
+}
+
 static void
 _outString(StringInfo str, const String *node)
 {
@@ -3845,6 +3851,8 @@ outNode(StringInfo str, const void *obj)
                _outInteger(str, (Integer *) obj);
        else if (IsA(obj, Float))
                _outFloat(str, (Float *) obj);
+       else if (IsA(obj, Boolean))
+               _outBoolean(str, (Boolean *) obj);
        else if (IsA(obj, String))
                _outString(str, (String *) obj);
        else if (IsA(obj, BitString))
diff --git a/src/backend/nodes/read.c b/src/backend/nodes/read.c
index d281f7db6c..b2330f2002 100644
--- a/src/backend/nodes/read.c
+++ b/src/backend/nodes/read.c
@@ -235,7 +235,7 @@ debackslash(const char *token, int length)
  * nodeTokenType -
  *       returns the type of the node token contained in token.
  *       It returns one of the following valid NodeTags:
- *             T_Integer, T_Float, T_String, T_BitString
+ *             T_Integer, T_Float, T_Boolean, T_String, T_BitString
  *       and some of its own:
  *             RIGHT_PAREN, LEFT_PAREN, LEFT_BRACE, OTHER_TOKEN
  *
@@ -283,6 +283,8 @@ nodeTokenType(const char *token, int length)
                retval = RIGHT_PAREN;
        else if (*token == '{')
                retval = LEFT_BRACE;
+       else if (strcmp(token, "true") == 0 || strcmp(token, "false") == 0)
+               retval = T_Boolean;
        else if (*token == '"' && length > 1 && token[length - 1] == '"')
                retval = T_String;
        else if (*token == 'b')
@@ -298,7 +300,7 @@ nodeTokenType(const char *token, int length)
  *
  * This routine applies some semantic knowledge on top of the purely
  * lexical tokenizer pg_strtok().   It can read
- *     * Value token nodes (integers, floats, or strings);
+ *     * Value token nodes (integers, floats, booleans, or strings);
  *     * General nodes (via parseNodeString() from readfuncs.c);
  *     * Lists of the above;
  *     * Lists of integers or OIDs.
@@ -438,6 +440,9 @@ nodeRead(const char *token, int tok_len)
                                result = (Node *) makeFloat(fval);
                        }
                        break;
+               case T_Boolean:
+                       result = (Node *) makeBoolean(token[0] == 't');
+                       break;
                case T_String:
                        /* need to remove leading and trailing quotes, and 
backslashes */
                        result = (Node *) makeString(debackslash(token + 1, 
tok_len - 2));
diff --git a/src/backend/nodes/value.c b/src/backend/nodes/value.c
index ab2d6f74d3..937bf90e83 100644
--- a/src/backend/nodes/value.c
+++ b/src/backend/nodes/value.c
@@ -42,6 +42,18 @@ makeFloat(char *numericStr)
        return v;
 }
 
+/*
+ *     makeBoolean
+ */
+Boolean *
+makeBoolean(bool val)
+{
+       Boolean    *v = makeNode(Boolean);
+
+       v->boolval = val;
+       return v;
+}
+
 /*
  *     makeString
  *
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index adce748a69..1f6498f0a9 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -177,10 +177,10 @@ static Node *makeStringConst(char *str, int location);
 static Node *makeStringConstCast(char *str, int location, TypeName *typename);
 static Node *makeIntConst(int val, int location);
 static Node *makeFloatConst(char *str, int location);
+static Node *makeBoolAConst(bool state, int location);
 static Node *makeBitStringConst(char *str, int location);
 static Node *makeNullAConst(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);
 static List *check_func_name(List *names, core_yyscan_t yyscanner);
@@ -1133,7 +1133,7 @@ AlterOptRoleElem:
                                }
                        | INHERIT
                                {
-                                       $$ = makeDefElem("inherit", (Node 
*)makeInteger(true), @1);
+                                       $$ = makeDefElem("inherit", (Node 
*)makeBoolean(true), @1);
                                }
                        | CONNECTION LIMIT SignedIconst
                                {
@@ -1156,36 +1156,36 @@ AlterOptRoleElem:
                                         * size of the main parser.
                                         */
                                        if (strcmp($1, "superuser") == 0)
-                                               $$ = makeDefElem("superuser", 
(Node *)makeInteger(true), @1);
+                                               $$ = makeDefElem("superuser", 
(Node *)makeBoolean(true), @1);
                                        else if (strcmp($1, "nosuperuser") == 0)
-                                               $$ = makeDefElem("superuser", 
(Node *)makeInteger(false), @1);
+                                               $$ = makeDefElem("superuser", 
(Node *)makeBoolean(false), @1);
                                        else if (strcmp($1, "createrole") == 0)
-                                               $$ = makeDefElem("createrole", 
(Node *)makeInteger(true), @1);
+                                               $$ = makeDefElem("createrole", 
(Node *)makeBoolean(true), @1);
                                        else if (strcmp($1, "nocreaterole") == 
0)
-                                               $$ = makeDefElem("createrole", 
(Node *)makeInteger(false), @1);
+                                               $$ = makeDefElem("createrole", 
(Node *)makeBoolean(false), @1);
                                        else if (strcmp($1, "replication") == 0)
-                                               $$ = 
makeDefElem("isreplication", (Node *)makeInteger(true), @1);
+                                               $$ = 
makeDefElem("isreplication", (Node *)makeBoolean(true), @1);
                                        else if (strcmp($1, "noreplication") == 
0)
-                                               $$ = 
makeDefElem("isreplication", (Node *)makeInteger(false), @1);
+                                               $$ = 
makeDefElem("isreplication", (Node *)makeBoolean(false), @1);
                                        else if (strcmp($1, "createdb") == 0)
-                                               $$ = makeDefElem("createdb", 
(Node *)makeInteger(true), @1);
+                                               $$ = makeDefElem("createdb", 
(Node *)makeBoolean(true), @1);
                                        else if (strcmp($1, "nocreatedb") == 0)
-                                               $$ = makeDefElem("createdb", 
(Node *)makeInteger(false), @1);
+                                               $$ = makeDefElem("createdb", 
(Node *)makeBoolean(false), @1);
                                        else if (strcmp($1, "login") == 0)
-                                               $$ = makeDefElem("canlogin", 
(Node *)makeInteger(true), @1);
+                                               $$ = makeDefElem("canlogin", 
(Node *)makeBoolean(true), @1);
                                        else if (strcmp($1, "nologin") == 0)
-                                               $$ = makeDefElem("canlogin", 
(Node *)makeInteger(false), @1);
+                                               $$ = makeDefElem("canlogin", 
(Node *)makeBoolean(false), @1);
                                        else if (strcmp($1, "bypassrls") == 0)
-                                               $$ = makeDefElem("bypassrls", 
(Node *)makeInteger(true), @1);
+                                               $$ = makeDefElem("bypassrls", 
(Node *)makeBoolean(true), @1);
                                        else if (strcmp($1, "nobypassrls") == 0)
-                                               $$ = makeDefElem("bypassrls", 
(Node *)makeInteger(false), @1);
+                                               $$ = makeDefElem("bypassrls", 
(Node *)makeBoolean(false), @1);
                                        else if (strcmp($1, "noinherit") == 0)
                                        {
                                                /*
                                                 * Note that INHERIT is a 
keyword, so it's handled by main parser, but
                                                 * NOINHERIT is handled here.
                                                 */
-                                               $$ = makeDefElem("inherit", 
(Node *)makeInteger(false), @1);
+                                               $$ = makeDefElem("inherit", 
(Node *)makeBoolean(false), @1);
                                        }
                                        else
                                                ereport(ERROR,
@@ -3175,7 +3175,7 @@ copy_opt_item:
                                }
                        | FREEZE
                                {
-                                       $$ = makeDefElem("freeze", (Node 
*)makeInteger(true), @1);
+                                       $$ = makeDefElem("freeze", (Node 
*)makeBoolean(true), @1);
                                }
                        | DELIMITER opt_as Sconst
                                {
@@ -3191,7 +3191,7 @@ copy_opt_item:
                                }
                        | HEADER_P
                                {
-                                       $$ = makeDefElem("header", (Node 
*)makeInteger(true), @1);
+                                       $$ = makeDefElem("header", (Node 
*)makeBoolean(true), @1);
                                }
                        | QUOTE opt_as Sconst
                                {
@@ -4499,11 +4499,11 @@ SeqOptElem: AS SimpleTypename
                                }
                        | CYCLE
                                {
-                                       $$ = makeDefElem("cycle", (Node 
*)makeInteger(true), @1);
+                                       $$ = makeDefElem("cycle", (Node 
*)makeBoolean(true), @1);
                                }
                        | NO CYCLE
                                {
-                                       $$ = makeDefElem("cycle", (Node 
*)makeInteger(false), @1);
+                                       $$ = makeDefElem("cycle", (Node 
*)makeBoolean(false), @1);
                                }
                        | INCREMENT opt_by NumericOnly
                                {
@@ -4739,7 +4739,7 @@ create_extension_opt_item:
                                }
                        | CASCADE
                                {
-                                       $$ = makeDefElem("cascade", (Node 
*)makeInteger(true), @1);
+                                       $$ = makeDefElem("cascade", (Node 
*)makeBoolean(true), @1);
                                }
                ;
 
@@ -7934,15 +7934,15 @@ createfunc_opt_list:
 common_func_opt_item:
                        CALLED ON NULL_P INPUT_P
                                {
-                                       $$ = makeDefElem("strict", (Node 
*)makeInteger(false), @1);
+                                       $$ = makeDefElem("strict", (Node 
*)makeBoolean(false), @1);
                                }
                        | RETURNS NULL_P ON NULL_P INPUT_P
                                {
-                                       $$ = makeDefElem("strict", (Node 
*)makeInteger(true), @1);
+                                       $$ = makeDefElem("strict", (Node 
*)makeBoolean(true), @1);
                                }
                        | STRICT_P
                                {
-                                       $$ = makeDefElem("strict", (Node 
*)makeInteger(true), @1);
+                                       $$ = makeDefElem("strict", (Node 
*)makeBoolean(true), @1);
                                }
                        | IMMUTABLE
                                {
@@ -7958,27 +7958,27 @@ common_func_opt_item:
                                }
                        | EXTERNAL SECURITY DEFINER
                                {
-                                       $$ = makeDefElem("security", (Node 
*)makeInteger(true), @1);
+                                       $$ = makeDefElem("security", (Node 
*)makeBoolean(true), @1);
                                }
                        | EXTERNAL SECURITY INVOKER
                                {
-                                       $$ = makeDefElem("security", (Node 
*)makeInteger(false), @1);
+                                       $$ = makeDefElem("security", (Node 
*)makeBoolean(false), @1);
                                }
                        | SECURITY DEFINER
                                {
-                                       $$ = makeDefElem("security", (Node 
*)makeInteger(true), @1);
+                                       $$ = makeDefElem("security", (Node 
*)makeBoolean(true), @1);
                                }
                        | SECURITY INVOKER
                                {
-                                       $$ = makeDefElem("security", (Node 
*)makeInteger(false), @1);
+                                       $$ = makeDefElem("security", (Node 
*)makeBoolean(false), @1);
                                }
                        | LEAKPROOF
                                {
-                                       $$ = makeDefElem("leakproof", (Node 
*)makeInteger(true), @1);
+                                       $$ = makeDefElem("leakproof", (Node 
*)makeBoolean(true), @1);
                                }
                        | NOT LEAKPROOF
                                {
-                                       $$ = makeDefElem("leakproof", (Node 
*)makeInteger(false), @1);
+                                       $$ = makeDefElem("leakproof", (Node 
*)makeBoolean(false), @1);
                                }
                        | COST NumericOnly
                                {
@@ -8018,7 +8018,7 @@ createfunc_opt_item:
                                }
                        | WINDOW
                                {
-                                       $$ = makeDefElem("window", (Node 
*)makeInteger(true), @1);
+                                       $$ = makeDefElem("window", (Node 
*)makeBoolean(true), @1);
                                }
                        | common_func_opt_item
                                {
@@ -9941,7 +9941,7 @@ AlterSubscriptionStmt:
                                        n->kind = ALTER_SUBSCRIPTION_ENABLED;
                                        n->subname = $3;
                                        n->options = 
list_make1(makeDefElem("enabled",
-                                                                               
        (Node *)makeInteger(true), @1));
+                                                                               
        (Node *)makeBoolean(true), @1));
                                        $$ = (Node *)n;
                                }
                        | ALTER SUBSCRIPTION name DISABLE_P
@@ -9951,7 +9951,7 @@ AlterSubscriptionStmt:
                                        n->kind = ALTER_SUBSCRIPTION_ENABLED;
                                        n->subname = $3;
                                        n->options = 
list_make1(makeDefElem("enabled",
-                                                                               
        (Node *)makeInteger(false), @1));
+                                                                               
        (Node *)makeBoolean(false), @1));
                                        $$ = (Node *)n;
                                }
                ;
@@ -12874,7 +12874,7 @@ xmltable_column_el:
                                                                                
(errcode(ERRCODE_SYNTAX_ERROR),
                                                                                
 errmsg("conflicting or redundant NULL / NOT NULL declarations for column 
\"%s\"", fc->colname),
                                                                                
 parser_errposition(defel->location)));
-                                                       fc->is_not_null = 
intVal(defel->arg);
+                                                       fc->is_not_null = 
boolVal(defel->arg);
                                                        nullability_seen = true;
                                                }
                                                else
@@ -12914,9 +12914,9 @@ xmltable_column_option_el:
                        | DEFAULT b_expr
                                { $$ = makeDefElem("default", $2, @1); }
                        | NOT NULL_P
-                               { $$ = makeDefElem("is_not_null", (Node *) 
makeInteger(true), @1); }
+                               { $$ = makeDefElem("is_not_null", (Node *) 
makeBoolean(true), @1); }
                        | NULL_P
-                               { $$ = makeDefElem("is_not_null", (Node *) 
makeInteger(false), @1); }
+                               { $$ = makeDefElem("is_not_null", (Node *) 
makeBoolean(false), @1); }
                ;
 
 xml_namespace_list:
@@ -16705,6 +16705,18 @@ makeFloatConst(char *str, int location)
    return (Node *)n;
 }
 
+static Node *
+makeBoolAConst(bool state, int location)
+{
+       A_Const *n = makeNode(A_Const);
+
+       n->val.boolval.type = T_Boolean;
+       n->val.boolval.boolval = state;
+       n->location = location;
+
+   return (Node *)n;
+}
+
 static Node *
 makeBitStringConst(char *str, int location)
 {
@@ -16743,26 +16755,14 @@ makeAConst(Node *v, int location)
                        n = makeIntConst(castNode(Integer, v)->ival, location);
                        break;
 
-               case T_String:
                default:
-                       n = makeStringConst(castNode(String, v)->sval, 
location);
-                       break;
+                       /* currently not used */
+                       Assert(false);
        }
 
        return n;
 }
 
-/* makeBoolAConst()
- * Create an A_Const string node and put it inside a boolean cast.
- */
-static Node *
-makeBoolAConst(bool state, int location)
-{
-       return makeStringConstCast((state ? "t" : "f"),
-                                                          location,
-                                                          
SystemTypeName("bool"));
-}
-
 /* makeRoleSpec
  * Create a RoleSpec with the given type
  */
diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c
index bd92133b21..533669e37e 100644
--- a/src/backend/parser/parse_node.c
+++ b/src/backend/parser/parse_node.c
@@ -426,6 +426,14 @@ make_const(ParseState *pstate, A_Const *aconst)
                        }
                        break;
 
+               case T_Boolean:
+                       val = BoolGetDatum(boolVal(&aconst->val));
+
+                       typeid = BOOLOID;
+                       typelen = 1;
+                       typebyval = true;
+                       break;
+
                case T_String:
 
                        /*
diff --git a/src/backend/replication/repl_gram.y 
b/src/backend/replication/repl_gram.y
index dcb1108579..dd23f98b44 100644
--- a/src/backend/replication/repl_gram.y
+++ b/src/backend/replication/repl_gram.y
@@ -212,7 +212,7 @@ base_backup_legacy_opt:
                        | K_PROGRESS
                                {
                                  $$ = makeDefElem("progress",
-                                                                  (Node 
*)makeInteger(true), -1);
+                                                                  (Node 
*)makeBoolean(true), -1);
                                }
                        | K_FAST
                                {
@@ -222,12 +222,12 @@ base_backup_legacy_opt:
                        | K_WAL
                                {
                                  $$ = makeDefElem("wal",
-                                                                  (Node 
*)makeInteger(true), -1);
+                                                                  (Node 
*)makeBoolean(true), -1);
                                }
                        | K_NOWAIT
                                {
                                  $$ = makeDefElem("wait",
-                                                                  (Node 
*)makeInteger(false), -1);
+                                                                  (Node 
*)makeBoolean(false), -1);
                                }
                        | K_MAX_RATE UCONST
                                {
@@ -237,12 +237,12 @@ base_backup_legacy_opt:
                        | K_TABLESPACE_MAP
                                {
                                  $$ = makeDefElem("tablespace_map",
-                                                                  (Node 
*)makeInteger(true), -1);
+                                                                  (Node 
*)makeBoolean(true), -1);
                                }
                        | K_NOVERIFY_CHECKSUMS
                                {
                                  $$ = makeDefElem("verify_checksums",
-                                                                  (Node 
*)makeInteger(false), -1);
+                                                                  (Node 
*)makeBoolean(false), -1);
                                }
                        | K_MANIFEST SCONST
                                {
@@ -313,12 +313,12 @@ create_slot_legacy_opt:
                        | K_RESERVE_WAL
                                {
                                  $$ = makeDefElem("reserve_wal",
-                                                                  (Node 
*)makeInteger(true), -1);
+                                                                  (Node 
*)makeBoolean(true), -1);
                                }
                        | K_TWO_PHASE
                                {
                                  $$ = makeDefElem("two_phase",
-                                                                  (Node 
*)makeInteger(true), -1);
+                                                                  (Node 
*)makeBoolean(true), -1);
                                }
                        ;
 
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 7c657c1241..15444c60b7 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -292,6 +292,7 @@ typedef enum NodeTag
         */
        T_Integer,
        T_Float,
+       T_Boolean,
        T_String,
        T_BitString,
 
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 784164b32a..ef12148b1f 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -304,6 +304,7 @@ typedef struct A_Const
                Node            node;
                Integer         ival;
                Float           fval;
+               Boolean         boolval;
                String          sval;
                BitString       bsval;
        }                       val;
diff --git a/src/include/nodes/value.h b/src/include/nodes/value.h
index cc3a4a639c..5f877ea9ea 100644
--- a/src/include/nodes/value.h
+++ b/src/include/nodes/value.h
@@ -48,6 +48,12 @@ typedef struct Float
        char       *fval;
 } Float;
 
+typedef struct Boolean
+{
+       NodeTag         type;
+       bool            boolval;
+} Boolean;
+
 typedef struct String
 {
        NodeTag         type;
@@ -62,10 +68,12 @@ typedef struct BitString
 
 #define intVal(v)              (castNode(Integer, v)->ival)
 #define floatVal(v)            atof(castNode(Float, v)->fval)
+#define boolVal(v)             (castNode(Boolean, v)->boolval)
 #define strVal(v)              (castNode(String, v)->sval)
 
 extern Integer *makeInteger(int i);
 extern Float *makeFloat(char *numericStr);
+extern Boolean *makeBoolean(bool var);
 extern String *makeString(char *str);
 extern BitString *makeBitString(char *str);
 
diff --git a/src/test/isolation/expected/ri-trigger.out 
b/src/test/isolation/expected/ri-trigger.out
index 842df80a90..db85618bef 100644
--- a/src/test/isolation/expected/ri-trigger.out
+++ b/src/test/isolation/expected/ri-trigger.out
@@ -4,9 +4,9 @@ starting permutation: wxry1 c1 r2 wyrx2 c2
 step wxry1: INSERT INTO child (parent_id) VALUES (0);
 step c1: COMMIT;
 step r2: SELECT TRUE;
-bool
-----
-t   
+?column?
+--------
+t       
 (1 row)
 
 step wyrx2: DELETE FROM parent WHERE parent_id = 0;
@@ -16,9 +16,9 @@ step c2: COMMIT;
 starting permutation: wxry1 r2 c1 wyrx2 c2
 step wxry1: INSERT INTO child (parent_id) VALUES (0);
 step r2: SELECT TRUE;
-bool
-----
-t   
+?column?
+--------
+t       
 (1 row)
 
 step c1: COMMIT;
@@ -29,9 +29,9 @@ step c2: COMMIT;
 starting permutation: wxry1 r2 wyrx2 c1 c2
 step wxry1: INSERT INTO child (parent_id) VALUES (0);
 step r2: SELECT TRUE;
-bool
-----
-t   
+?column?
+--------
+t       
 (1 row)
 
 step wyrx2: DELETE FROM parent WHERE parent_id = 0;
@@ -42,9 +42,9 @@ ERROR:  could not serialize access due to read/write 
dependencies among transact
 starting permutation: wxry1 r2 wyrx2 c2 c1
 step wxry1: INSERT INTO child (parent_id) VALUES (0);
 step r2: SELECT TRUE;
-bool
-----
-t   
+?column?
+--------
+t       
 (1 row)
 
 step wyrx2: DELETE FROM parent WHERE parent_id = 0;
@@ -54,9 +54,9 @@ ERROR:  could not serialize access due to read/write 
dependencies among transact
 
 starting permutation: r2 wxry1 c1 wyrx2 c2
 step r2: SELECT TRUE;
-bool
-----
-t   
+?column?
+--------
+t       
 (1 row)
 
 step wxry1: INSERT INTO child (parent_id) VALUES (0);
@@ -67,9 +67,9 @@ step c2: COMMIT;
 
 starting permutation: r2 wxry1 wyrx2 c1 c2
 step r2: SELECT TRUE;
-bool
-----
-t   
+?column?
+--------
+t       
 (1 row)
 
 step wxry1: INSERT INTO child (parent_id) VALUES (0);
@@ -80,9 +80,9 @@ ERROR:  could not serialize access due to read/write 
dependencies among transact
 
 starting permutation: r2 wxry1 wyrx2 c2 c1
 step r2: SELECT TRUE;
-bool
-----
-t   
+?column?
+--------
+t       
 (1 row)
 
 step wxry1: INSERT INTO child (parent_id) VALUES (0);
@@ -93,9 +93,9 @@ ERROR:  could not serialize access due to read/write 
dependencies among transact
 
 starting permutation: r2 wyrx2 wxry1 c1 c2
 step r2: SELECT TRUE;
-bool
-----
-t   
+?column?
+--------
+t       
 (1 row)
 
 step wyrx2: DELETE FROM parent WHERE parent_id = 0;
@@ -106,9 +106,9 @@ ERROR:  could not serialize access due to read/write 
dependencies among transact
 
 starting permutation: r2 wyrx2 wxry1 c2 c1
 step r2: SELECT TRUE;
-bool
-----
-t   
+?column?
+--------
+t       
 (1 row)
 
 step wyrx2: DELETE FROM parent WHERE parent_id = 0;
@@ -119,9 +119,9 @@ ERROR:  could not serialize access due to read/write 
dependencies among transact
 
 starting permutation: r2 wyrx2 c2 wxry1 c1
 step r2: SELECT TRUE;
-bool
-----
-t   
+?column?
+--------
+t       
 (1 row)
 
 step wyrx2: DELETE FROM parent WHERE parent_id = 0;
diff --git a/src/test/regress/expected/create_function_3.out 
b/src/test/regress/expected/create_function_3.out
index 3a4fd45147..e0c4bee893 100644
--- a/src/test/regress/expected/create_function_3.out
+++ b/src/test/regress/expected/create_function_3.out
@@ -403,7 +403,7 @@ SELECT pg_get_functiondef('functest_S_13'::regproc);
   LANGUAGE sql                                            +
  BEGIN ATOMIC                                             +
   SELECT 1;                                               +
-  SELECT false AS bool;                                   +
+  SELECT false;                                           +
  END                                                      +
  
 (1 row)
-- 
2.34.1

Reply via email to