0001-Convert-pg_attribut.attnotnull-to-char-type.patch
application/octet-stream
Filename: 0001-Convert-pg_attribut.attnotnull-to-char-type.patch
Type: application/octet-stream
Part: 0
Patch
Format: format-patch
Series: patch 0001
Subject: Convert pg_attribut.attnotnull to char type.
| File | + | − |
|---|---|---|
| src/backend/access/common/tupdesc.c | 6 | 6 |
| src/backend/bootstrap/bootstrap.c | 8 | 5 |
| src/backend/catalog/heap.c | 8 | 8 |
| src/backend/catalog/index.c | 1 | 1 |
| src/backend/catalog/indexing.c | 2 | 1 |
| src/backend/catalog/information_schema.sql | 2 | 2 |
| src/backend/commands/tablecmds.c | 20 | 15 |
| src/backend/executor/execMain.c | 2 | 1 |
| src/backend/jit/llvm/llvmjit_deform.c | 6 | 4 |
| src/backend/optimizer/util/plancat.c | 3 | 2 |
| src/include/access/tupdesc.h | 1 | 1 |
| src/include/catalog/pg_attribute.h | 4 | 1 |
From 547d79773cd88a94810d7d4c2e005f63316d9601 Mon Sep 17 00:00:00 2001
From: Rushabh Lathia <rushabh.lathia@enterprisedb.com>
Date: Mon, 10 Feb 2025 15:39:16 +0530
Subject: [PATCH 1/3] Convert pg_attribut.attnotnull to char type.
This commit change the pg_attribut.attnotnull to char type. Now
attnotnull holds three values, where attnotnull can be either
TRUE, FALSE and INVALID. INVALID is when name not null constrint
is NOT VALIDATED.
---
src/backend/access/common/tupdesc.c | 12 ++++----
src/backend/bootstrap/bootstrap.c | 13 ++++----
src/backend/catalog/heap.c | 16 +++++-----
src/backend/catalog/index.c | 2 +-
src/backend/catalog/indexing.c | 3 +-
src/backend/catalog/information_schema.sql | 4 +--
src/backend/commands/tablecmds.c | 35 ++++++++++++----------
src/backend/executor/execMain.c | 3 +-
src/backend/jit/llvm/llvmjit_deform.c | 10 ++++---
src/backend/optimizer/util/plancat.c | 5 ++--
src/include/access/tupdesc.h | 2 +-
src/include/catalog/pg_attribute.h | 5 +++-
12 files changed, 63 insertions(+), 47 deletions(-)
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index ed2195f14b2..58698812c0b 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -251,7 +251,7 @@ CreateTupleDescCopy(TupleDesc tupdesc)
{
Form_pg_attribute att = TupleDescAttr(desc, i);
- att->attnotnull = false;
+ att->attnotnull = ATTRIBUTE_NOTNULL_FALSE;
att->atthasdef = false;
att->atthasmissing = false;
att->attidentity = '\0';
@@ -297,7 +297,7 @@ CreateTupleDescTruncatedCopy(TupleDesc tupdesc, int natts)
{
Form_pg_attribute att = TupleDescAttr(desc, i);
- att->attnotnull = false;
+ att->attnotnull = ATTRIBUTE_NOTNULL_FALSE;
att->atthasdef = false;
att->atthasmissing = false;
att->attidentity = '\0';
@@ -417,7 +417,7 @@ TupleDescCopy(TupleDesc dst, TupleDesc src)
{
Form_pg_attribute att = TupleDescAttr(dst, i);
- att->attnotnull = false;
+ att->attnotnull = ATTRIBUTE_NOTNULL_FALSE;
att->atthasdef = false;
att->atthasmissing = false;
att->attidentity = '\0';
@@ -463,7 +463,7 @@ TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno,
dstAtt->attnum = dstAttno;
/* since we're not copying constraints or defaults, clear these */
- dstAtt->attnotnull = false;
+ dstAtt->attnotnull = ATTRIBUTE_NOTNULL_FALSE;
dstAtt->atthasdef = false;
dstAtt->atthasmissing = false;
dstAtt->attidentity = '\0';
@@ -840,7 +840,7 @@ TupleDescInitEntry(TupleDesc desc,
att->attnum = attributeNumber;
att->attndims = attdim;
- att->attnotnull = false;
+ att->attnotnull = ATTRIBUTE_NOTNULL_FALSE;
att->atthasdef = false;
att->atthasmissing = false;
att->attidentity = '\0';
@@ -903,7 +903,7 @@ TupleDescInitBuiltinEntry(TupleDesc desc,
att->attnum = attributeNumber;
att->attndims = attdim;
- att->attnotnull = false;
+ att->attnotnull = ATTRIBUTE_NOTNULL_FALSE;
att->atthasdef = false;
att->atthasmissing = false;
att->attidentity = '\0';
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 6db864892d0..1e95dc32f46 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -582,14 +582,17 @@ DefineAttr(char *name, char *type, int attnum, int nullness)
attrtypes[attnum]->atttypmod = -1;
attrtypes[attnum]->attislocal = true;
+ /* set default to false */
+ attrtypes[attnum]->attnotnull = ATTRIBUTE_NOTNULL_FALSE;
+
if (nullness == BOOTCOL_NULL_FORCE_NOT_NULL)
{
- attrtypes[attnum]->attnotnull = true;
+ attrtypes[attnum]->attnotnull = ATTRIBUTE_NOTNULL_TRUE;
}
else if (nullness == BOOTCOL_NULL_FORCE_NULL)
{
- attrtypes[attnum]->attnotnull = false;
+ attrtypes[attnum]->attnotnull = ATTRIBUTE_NOTNULL_FALSE;
}
else
{
@@ -608,11 +611,11 @@ DefineAttr(char *name, char *type, int attnum, int nullness)
for (i = 0; i < attnum; i++)
{
if (attrtypes[i]->attlen <= 0 ||
- !attrtypes[i]->attnotnull)
+ attrtypes[i]->attnotnull == ATTRIBUTE_NOTNULL_FALSE)
break;
}
if (i == attnum)
- attrtypes[attnum]->attnotnull = true;
+ attrtypes[attnum]->attnotnull = ATTRIBUTE_NOTNULL_TRUE;
}
}
}
@@ -696,7 +699,7 @@ InsertOneNull(int i)
{
elog(DEBUG4, "inserting column %d NULL", i);
Assert(i >= 0 && i < MAXATTR);
- if (TupleDescAttr(boot_reldesc->rd_att, i)->attnotnull)
+ if (TupleDescAttr(boot_reldesc->rd_att, i)->attnotnull == ATTRIBUTE_NOTNULL_TRUE)
elog(ERROR,
"NULL value specified for not-null column \"%s\" of relation \"%s\"",
NameStr(TupleDescAttr(boot_reldesc->rd_att, i)->attname),
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index bd3554c0bfd..8c2d2cdcdfe 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -150,7 +150,7 @@ static const FormData_pg_attribute a1 = {
.attbyval = false,
.attalign = TYPALIGN_SHORT,
.attstorage = TYPSTORAGE_PLAIN,
- .attnotnull = true,
+ .attnotnull = ATTRIBUTE_NOTNULL_TRUE,
.attislocal = true,
};
@@ -163,7 +163,7 @@ static const FormData_pg_attribute a2 = {
.attbyval = true,
.attalign = TYPALIGN_INT,
.attstorage = TYPSTORAGE_PLAIN,
- .attnotnull = true,
+ .attnotnull = ATTRIBUTE_NOTNULL_TRUE,
.attislocal = true,
};
@@ -176,7 +176,7 @@ static const FormData_pg_attribute a3 = {
.attbyval = true,
.attalign = TYPALIGN_INT,
.attstorage = TYPSTORAGE_PLAIN,
- .attnotnull = true,
+ .attnotnull = ATTRIBUTE_NOTNULL_TRUE,
.attislocal = true,
};
@@ -189,7 +189,7 @@ static const FormData_pg_attribute a4 = {
.attbyval = true,
.attalign = TYPALIGN_INT,
.attstorage = TYPSTORAGE_PLAIN,
- .attnotnull = true,
+ .attnotnull = ATTRIBUTE_NOTNULL_TRUE,
.attislocal = true,
};
@@ -202,7 +202,7 @@ static const FormData_pg_attribute a5 = {
.attbyval = true,
.attalign = TYPALIGN_INT,
.attstorage = TYPSTORAGE_PLAIN,
- .attnotnull = true,
+ .attnotnull = ATTRIBUTE_NOTNULL_TRUE,
.attislocal = true,
};
@@ -221,7 +221,7 @@ static const FormData_pg_attribute a6 = {
.attbyval = true,
.attalign = TYPALIGN_INT,
.attstorage = TYPSTORAGE_PLAIN,
- .attnotnull = true,
+ .attnotnull = ATTRIBUTE_NOTNULL_TRUE,
.attislocal = true,
};
@@ -752,7 +752,7 @@ InsertPgAttributeTuples(Relation pg_attribute_rel,
slot[slotCount]->tts_values[Anum_pg_attribute_attalign - 1] = CharGetDatum(attrs->attalign);
slot[slotCount]->tts_values[Anum_pg_attribute_attstorage - 1] = CharGetDatum(attrs->attstorage);
slot[slotCount]->tts_values[Anum_pg_attribute_attcompression - 1] = CharGetDatum(attrs->attcompression);
- slot[slotCount]->tts_values[Anum_pg_attribute_attnotnull - 1] = BoolGetDatum(attrs->attnotnull);
+ slot[slotCount]->tts_values[Anum_pg_attribute_attnotnull - 1] = CharGetDatum(attrs->attnotnull);
slot[slotCount]->tts_values[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(attrs->atthasdef);
slot[slotCount]->tts_values[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(attrs->atthasmissing);
slot[slotCount]->tts_values[Anum_pg_attribute_attidentity - 1] = CharGetDatum(attrs->attidentity);
@@ -1713,7 +1713,7 @@ RemoveAttributeById(Oid relid, AttrNumber attnum)
attStruct->atttypid = InvalidOid;
/* Remove any not-null constraint the column may have */
- attStruct->attnotnull = false;
+ attStruct->attnotnull = ATTRIBUTE_NOTNULL_FALSE;
/* Unset this so no one tries to look up the generation expression */
attStruct->attgenerated = '\0';
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 739a92bdcc1..6b0c16bf59d 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -262,7 +262,7 @@ index_check_primary_key(Relation heapRel,
attnum, RelationGetRelid(heapRel));
attform = (Form_pg_attribute) GETSTRUCT(atttuple);
- if (!attform->attnotnull)
+ if (attform->attnotnull == ATTRIBUTE_NOTNULL_FALSE)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("primary key column \"%s\" is not marked NOT NULL",
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index 25c4b6bdc87..a2211d75566 100644
--- a/src/backend/catalog/indexing.c
+++ b/src/backend/catalog/indexing.c
@@ -207,7 +207,8 @@ CatalogTupleCheckConstraints(Relation heapRel, HeapTuple tup)
{
Form_pg_attribute thisatt = TupleDescAttr(tupdesc, attnum);
- Assert(!(thisatt->attnotnull && att_isnull(attnum, bp)));
+ Assert(!(thisatt->attnotnull == ATTRIBUTE_NOTNULL_TRUE &&
+ att_isnull(attnum, bp)));
}
}
}
diff --git a/src/backend/catalog/information_schema.sql b/src/backend/catalog/information_schema.sql
index a7bffca93d1..4f59bc46e74 100644
--- a/src/backend/catalog/information_schema.sql
+++ b/src/backend/catalog/information_schema.sql
@@ -292,7 +292,7 @@ CREATE VIEW attributes AS
CAST(a.attname AS sql_identifier) AS attribute_name,
CAST(a.attnum AS cardinal_number) AS ordinal_position,
CAST(pg_get_expr(ad.adbin, ad.adrelid) AS character_data) AS attribute_default,
- CAST(CASE WHEN a.attnotnull OR (t.typtype = 'd' AND t.typnotnull) THEN 'NO' ELSE 'YES' END
+ CAST(CASE WHEN a.attnotnull = 't' OR (t.typtype = 'd' AND t.typnotnull) THEN 'NO' ELSE 'YES' END
AS yes_or_no)
AS is_nullable, -- This column was apparently removed between SQL:2003 and SQL:2008.
@@ -671,7 +671,7 @@ CREATE VIEW columns AS
CAST(a.attname AS sql_identifier) AS column_name,
CAST(a.attnum AS cardinal_number) AS ordinal_position,
CAST(CASE WHEN a.attgenerated = '' THEN pg_get_expr(ad.adbin, ad.adrelid) END AS character_data) AS column_default,
- CAST(CASE WHEN a.attnotnull OR (t.typtype = 'd' AND t.typnotnull) THEN 'NO' ELSE 'YES' END
+ CAST(CASE WHEN a.attnotnull = 't' OR (t.typtype = 'd' AND t.typnotnull) THEN 'NO' ELSE 'YES' END
AS yes_or_no)
AS is_nullable,
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 18ff8956577..3c81e48cac1 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1399,7 +1399,10 @@ BuildDescForRelation(const List *columns)
TupleDescInitEntryCollation(desc, attnum, attcollation);
/* Fill in additional stuff not handled by TupleDescInitEntry */
- att->attnotnull = entry->is_not_null;
+ if (entry->is_not_null)
+ att->attnotnull = ATTRIBUTE_NOTNULL_TRUE;
+ else
+ att->attnotnull = ATTRIBUTE_NOTNULL_FALSE;
att->attislocal = entry->is_local;
att->attinhcount = entry->inhcount;
att->attidentity = entry->identity;
@@ -6188,7 +6191,8 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap)
{
Form_pg_attribute attr = TupleDescAttr(newTupDesc, i);
- if (attr->attnotnull && !attr->attisdropped)
+ if (attr->attnotnull == ATTRIBUTE_NOTNULL_TRUE &&
+ !attr->attisdropped)
notnull_attrs = lappend_int(notnull_attrs, i);
}
if (notnull_attrs)
@@ -7669,7 +7673,7 @@ ATExecDropNotNull(Relation rel, const char *colName, bool recurse,
RelationGetRelid(rel), attnum);
/* If the column is already nullable there's nothing to do. */
- if (!attTup->attnotnull)
+ if (attTup->attnotnull == ATTRIBUTE_NOTNULL_FALSE)
{
table_close(attr_rel, RowExclusiveLock);
return InvalidObjectAddress;
@@ -7699,7 +7703,7 @@ ATExecDropNotNull(Relation rel, const char *colName, bool recurse,
AttrNumber parent_attnum;
parent_attnum = get_attnum(parentId, colName);
- if (TupleDescAttr(tupDesc, parent_attnum - 1)->attnotnull)
+ if (TupleDescAttr(tupDesc, parent_attnum - 1)->attnotnull == ATTRIBUTE_NOTNULL_TRUE)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("column \"%s\" is marked NOT NULL in parent table",
@@ -7753,7 +7757,7 @@ set_attnotnull(List **wqueue, Relation rel, AttrNumber attnum,
if (attr->attisdropped)
return;
- if (!attr->attnotnull)
+ if (attr->attnotnull == ATTRIBUTE_NOTNULL_FALSE)
{
Relation attr_rel;
HeapTuple tuple;
@@ -7766,8 +7770,8 @@ set_attnotnull(List **wqueue, Relation rel, AttrNumber attnum,
attnum, RelationGetRelid(rel));
attr = (Form_pg_attribute) GETSTRUCT(tuple);
- Assert(!attr->attnotnull);
- attr->attnotnull = true;
+ Assert(attr->attnotnull == ATTRIBUTE_NOTNULL_FALSE);
+ attr->attnotnull = ATTRIBUTE_NOTNULL_TRUE;
CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
/*
@@ -8172,7 +8176,7 @@ ATExecAddIdentity(Relation rel, const char *colName,
* to an existing column that is not NOT NULL would create a state that
* cannot be reproduced without contortions.
*/
- if (!attTup->attnotnull)
+ if (attTup->attnotnull == ATTRIBUTE_NOTNULL_FALSE)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("column \"%s\" of relation \"%s\" must be declared NOT NULL before identity can be added",
@@ -9373,7 +9377,7 @@ ATPrepAddPrimaryKey(List **wqueue, Relation rel, AlterTableCmd *cmd,
elog(ERROR, "cache lookup failed for attribute %s of relation %u",
attname, childrelid);
attrForm = (Form_pg_attribute) GETSTRUCT(tup);
- if (!attrForm->attnotnull)
+ if (attrForm->attnotnull == ATTRIBUTE_NOTNULL_FALSE)
ereport(ERROR,
errmsg("column \"%s\" of table \"%s\" is not marked NOT NULL",
attname, get_rel_name(childrelid)));
@@ -13476,9 +13480,9 @@ dropconstraint_internal(Relation rel, HeapTuple constraintTup, DropBehavior beha
RelationGetRelationName(rel)));
/* All good -- reset attnotnull if needed */
- if (attForm->attnotnull)
+ if (attForm->attnotnull == ATTRIBUTE_NOTNULL_TRUE)
{
- attForm->attnotnull = false;
+ attForm->attnotnull = ATTRIBUTE_NOTNULL_FALSE;
CatalogTupleUpdate(attrel, &atttup->t_self, atttup);
}
@@ -16805,7 +16809,8 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel, bool ispart
*
* Other constraints are checked elsewhere.
*/
- if (parent_att->attnotnull && !child_att->attnotnull)
+ if (parent_att->attnotnull == ATTRIBUTE_NOTNULL_TRUE &&
+ child_att->attnotnull == ATTRIBUTE_NOTNULL_FALSE)
{
HeapTuple contup;
@@ -17848,7 +17853,7 @@ ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKMODE lockmode
RelationGetRelationName(indexRel), attno)));
attr = TupleDescAttr(rel->rd_att, attno - 1);
- if (!attr->attnotnull)
+ if (attr->attnotnull == ATTRIBUTE_NOTNULL_FALSE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("index \"%s\" cannot be used as replica identity because column \"%s\" is nullable",
@@ -19326,7 +19331,7 @@ PartConstraintImpliedByRelConstraint(Relation scanrel,
{
Form_pg_attribute att = TupleDescAttr(scanrel->rd_att, i - 1);
- if (att->attnotnull && !att->attisdropped)
+ if (att->attnotnull == ATTRIBUTE_NOTNULL_TRUE && !att->attisdropped)
{
NullTest *ntest = makeNode(NullTest);
@@ -21158,7 +21163,7 @@ verifyPartitionIndexNotNull(IndexInfo *iinfo, Relation partition)
Form_pg_attribute att = TupleDescAttr(RelationGetDescr(partition),
iinfo->ii_IndexAttrNumbers[i] - 1);
- if (!att->attnotnull)
+ if (att->attnotnull == ATTRIBUTE_NOTNULL_FALSE)
ereport(ERROR,
errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("invalid primary key definition"),
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 0493b7d5365..d582231ab60 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -2070,7 +2070,8 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
{
Form_pg_attribute att = TupleDescAttr(tupdesc, attrChk - 1);
- if (att->attnotnull && slot_attisnull(slot, attrChk))
+ if (att->attnotnull == ATTRIBUTE_NOTNULL_TRUE &&
+ slot_attisnull(slot, attrChk))
{
char *val_desc;
Relation orig_rel = rel;
diff --git a/src/backend/jit/llvm/llvmjit_deform.c b/src/backend/jit/llvm/llvmjit_deform.c
index 5d169c7a40b..e6444bc2c91 100644
--- a/src/backend/jit/llvm/llvmjit_deform.c
+++ b/src/backend/jit/llvm/llvmjit_deform.c
@@ -123,7 +123,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
* combination of attisdropped && attnotnull combination shouldn't
* exist.
*/
- if (att->attnotnull &&
+ if (att->attnotnull == ATTRIBUTE_NOTNULL_TRUE &&
!att->atthasmissing &&
!att->attisdropped)
guaranteed_column_number = attnum;
@@ -438,7 +438,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
* into account, because if they're present the heaptuple's natts
* would have indicated that a slot_getmissingattrs() is needed.
*/
- if (!att->attnotnull)
+ if (att->attnotnull == ATTRIBUTE_NOTNULL_FALSE)
{
LLVMBasicBlockRef b_ifnotnull;
LLVMBasicBlockRef b_ifnull;
@@ -604,7 +604,8 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
known_alignment = -1;
attguaranteedalign = false;
}
- else if (att->attnotnull && attguaranteedalign && known_alignment >= 0)
+ else if (att->attnotnull == ATTRIBUTE_NOTNULL_TRUE &&
+ attguaranteedalign && known_alignment >= 0)
{
/*
* If the offset to the column was previously known, a NOT NULL &
@@ -614,7 +615,8 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
Assert(att->attlen > 0);
known_alignment += att->attlen;
}
- else if (att->attnotnull && (att->attlen % alignto) == 0)
+ else if (att->attnotnull == ATTRIBUTE_NOTNULL_TRUE &&
+ (att->attlen % alignto) == 0)
{
/*
* After a NOT NULL fixed-width column with a length that is a
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 71abb01f655..e322098cfb2 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -177,7 +177,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
{
CompactAttribute *attr = TupleDescCompactAttr(relation->rd_att, i);
- if (attr->attnotnull)
+ if (attr->attnotnull == ATTRIBUTE_NOTNULL_TRUE)
{
rel->notnullattnums = bms_add_member(rel->notnullattnums,
i + 1);
@@ -1355,7 +1355,8 @@ get_relation_constraints(PlannerInfo *root,
{
Form_pg_attribute att = TupleDescAttr(relation->rd_att, i - 1);
- if (att->attnotnull && !att->attisdropped)
+ if (att->attnotnull == ATTRIBUTE_NOTNULL_TRUE &&
+ !att->attisdropped)
{
NullTest *ntest = makeNode(NullTest);
diff --git a/src/include/access/tupdesc.h b/src/include/access/tupdesc.h
index 396eeb7a0bb..1eba67ca8e9 100644
--- a/src/include/access/tupdesc.h
+++ b/src/include/access/tupdesc.h
@@ -76,7 +76,7 @@ typedef struct CompactAttribute
bool atthasmissing; /* as FormData_pg_attribute.atthasmissing */
bool attisdropped; /* as FormData_pg_attribute.attisdropped */
bool attgenerated; /* FormData_pg_attribute.attgenerated != '\0' */
- bool attnotnull; /* as FormData_pg_attribute.attnotnull */
+ char attnotnull; /* as FormData_pg_attribute.attnotnull */
uint8 attalignby; /* alignment requirement in bytes */
} CompactAttribute;
diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h
index deaa515fe53..b51a2670958 100644
--- a/src/include/catalog/pg_attribute.h
+++ b/src/include/catalog/pg_attribute.h
@@ -118,7 +118,7 @@ CATALOG(pg_attribute,1249,AttributeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(75,
char attcompression BKI_DEFAULT('\0');
/* This flag represents the "NOT NULL" constraint */
- bool attnotnull;
+ char attnotnull;
/* Has DEFAULT value or not */
bool atthasdef BKI_DEFAULT(f);
@@ -227,6 +227,9 @@ MAKE_SYSCACHE(ATTNUM, pg_attribute_relid_attnum_index, 128);
#define ATTRIBUTE_GENERATED_STORED 's'
#define ATTRIBUTE_GENERATED_VIRTUAL 'v'
+#define ATTRIBUTE_NOTNULL_TRUE 't'
+#define ATTRIBUTE_NOTNULL_FALSE 'f'
+
#endif /* EXPOSE_TO_CLIENT_CODE */
#endif /* PG_ATTRIBUTE_H */
--
2.43.0