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.

Reviewed-by: Pavel Stehule <pavel.stehule@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/8c1a2e37-c68d-703c-5a83-7a6077f4f997@enterprisedb.com
This commit is contained in:
Peter Eisentraut 2022-01-14 10:46:49 +01:00
parent ca86a63d20
commit 941460fcf7
20 changed files with 211 additions and 128 deletions

View File

@ -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

View File

@ -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:

View File

@ -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),

View File

@ -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,

View File

@ -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),

View File

@ -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;
}

View File

@ -2750,6 +2750,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;
@ -4949,6 +4952,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)
{
@ -5356,6 +5369,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;

View File

@ -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;

View File

@ -3577,6 +3577,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:

View File

@ -3434,6 +3434,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)
{
@ -3846,6 +3852,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))

View File

@ -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));

View File

@ -42,6 +42,18 @@ makeFloat(char *numericStr)
return v;
}
/*
* makeBoolean
*/
Boolean *
makeBoolean(bool val)
{
Boolean *v = makeNode(Boolean);
v->boolval = val;
return v;
}
/*
* makeString
*

View File

@ -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,15 @@ 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);
n = NULL;
}
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
*/

View File

@ -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:
/*

View File

@ -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);
}
;

View File

@ -292,6 +292,7 @@ typedef enum NodeTag
*/
T_Integer,
T_Float,
T_Boolean,
T_String,
T_BitString,

View File

@ -304,6 +304,7 @@ typedef struct A_Const
Node node;
Integer ival;
Float fval;
Boolean boolval;
String sval;
BitString bsval;
} val;

View File

@ -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);

View File

@ -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;

View File

@ -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)