Re: Symbolic names for the values of typalign and typstorage - Mailing list pgsql-hackers

From Tom Lane
Subject Re: Symbolic names for the values of typalign and typstorage
Date
Msg-id 7709.1583271951@sss.pgh.pa.us
Whole thread Raw
In response to Re: Symbolic names for the values of typalign and typstorage  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: Symbolic names for the values of typalign and typstorage  (Michael Paquier <michael@paquier.xyz>)
List pgsql-hackers
I wrote:
> Alvaro Herrera <alvherre@2ndquadrant.com> writes:
>> On 2020-Mar-03, Tom Lane wrote:
>>> I realized that a possible compromise position is to have tupmacs.h
>>> include pg_type_d.h, not the whole pg_type.h header, thus dodging the
>>> indirect inclusions.  That still brings in the type-OID macros, but
>>> it's a lot less header scope creep than I was first fearing.

>> WFM.

> OK, I'll look harder at doing it that way.

Yeah, that works out very nicely: there's now only one place besides
tupmacs.h that needs a new #include.

I did a little more polishing, and consider the attached committable,
unless anyone has objections.

            regards, tom lane

diff --git a/contrib/hstore/hstore_gin.c b/contrib/hstore/hstore_gin.c
index 4c3a422..9085302 100644
--- a/contrib/hstore/hstore_gin.c
+++ b/contrib/hstore/hstore_gin.c
@@ -119,7 +119,7 @@ gin_extract_hstore_query(PG_FUNCTION_ARGS)
         text       *item;

         deconstruct_array(query,
-                          TEXTOID, -1, false, 'i',
+                          TEXTOID, -1, false, TYPALIGN_INT,
                           &key_datums, &key_nulls, &key_count);

         entries = (Datum *) palloc(sizeof(Datum) * key_count);
diff --git a/contrib/hstore/hstore_gist.c b/contrib/hstore/hstore_gist.c
index e860f1e..d198c4b 100644
--- a/contrib/hstore/hstore_gist.c
+++ b/contrib/hstore/hstore_gist.c
@@ -555,7 +555,7 @@ ghstore_consistent(PG_FUNCTION_ARGS)
         int            i;

         deconstruct_array(query,
-                          TEXTOID, -1, false, 'i',
+                          TEXTOID, -1, false, TYPALIGN_INT,
                           &key_datums, &key_nulls, &key_count);

         for (i = 0; res && i < key_count; ++i)
@@ -578,7 +578,7 @@ ghstore_consistent(PG_FUNCTION_ARGS)
         int            i;

         deconstruct_array(query,
-                          TEXTOID, -1, false, 'i',
+                          TEXTOID, -1, false, TYPALIGN_INT,
                           &key_datums, &key_nulls, &key_count);

         res = false;
diff --git a/contrib/hstore/hstore_io.c b/contrib/hstore/hstore_io.c
index f3174f2..60bdbea 100644
--- a/contrib/hstore/hstore_io.c
+++ b/contrib/hstore/hstore_io.c
@@ -560,7 +560,7 @@ hstore_from_arrays(PG_FUNCTION_ARGS)
                  errmsg("wrong number of array subscripts")));

     deconstruct_array(key_array,
-                      TEXTOID, -1, false, 'i',
+                      TEXTOID, -1, false, TYPALIGN_INT,
                       &key_datums, &key_nulls, &key_count);

     /* see discussion in hstoreArrayToPairs() */
@@ -599,7 +599,7 @@ hstore_from_arrays(PG_FUNCTION_ARGS)
                      errmsg("arrays must have same bounds")));

         deconstruct_array(value_array,
-                          TEXTOID, -1, false, 'i',
+                          TEXTOID, -1, false, TYPALIGN_INT,
                           &value_datums, &value_nulls, &value_count);

         Assert(key_count == value_count);
@@ -689,7 +689,7 @@ hstore_from_array(PG_FUNCTION_ARGS)
     }

     deconstruct_array(in_array,
-                      TEXTOID, -1, false, 'i',
+                      TEXTOID, -1, false, TYPALIGN_INT,
                       &in_datums, &in_nulls, &in_count);

     count = in_count / 2;
diff --git a/contrib/hstore/hstore_op.c b/contrib/hstore/hstore_op.c
index fb1bb06..dd79d01 100644
--- a/contrib/hstore/hstore_op.c
+++ b/contrib/hstore/hstore_op.c
@@ -81,7 +81,7 @@ hstoreArrayToPairs(ArrayType *a, int *npairs)
                 j;

     deconstruct_array(a,
-                      TEXTOID, -1, false, 'i',
+                      TEXTOID, -1, false, TYPALIGN_INT,
                       &key_datums, &key_nulls, &key_count);

     if (key_count == 0)
@@ -583,7 +583,7 @@ hstore_slice_to_array(PG_FUNCTION_ARGS)
     int            i;

     deconstruct_array(key_array,
-                      TEXTOID, -1, false, 'i',
+                      TEXTOID, -1, false, TYPALIGN_INT,
                       &key_datums, &key_nulls, &key_count);

     if (key_count == 0)
@@ -623,7 +623,7 @@ hstore_slice_to_array(PG_FUNCTION_ARGS)
                               ARR_NDIM(key_array),
                               ARR_DIMS(key_array),
                               ARR_LBOUND(key_array),
-                              TEXTOID, -1, false, 'i');
+                              TEXTOID, -1, false, TYPALIGN_INT);

     PG_RETURN_POINTER(aout);
 }
@@ -720,7 +720,7 @@ hstore_akeys(PG_FUNCTION_ARGS)
     }

     a = construct_array(d, count,
-                        TEXTOID, -1, false, 'i');
+                        TEXTOID, -1, false, TYPALIGN_INT);

     PG_RETURN_POINTER(a);
 }
@@ -767,7 +767,7 @@ hstore_avals(PG_FUNCTION_ARGS)
     }

     a = construct_md_array(d, nulls, 1, &count, &lb,
-                           TEXTOID, -1, false, 'i');
+                           TEXTOID, -1, false, TYPALIGN_INT);

     PG_RETURN_POINTER(a);
 }
@@ -819,7 +819,7 @@ hstore_to_array_internal(HStore *hs, int ndims)

     return construct_md_array(out_datums, out_nulls,
                               ndims, out_size, lb,
-                              TEXTOID, -1, false, 'i');
+                              TEXTOID, -1, false, TYPALIGN_INT);
 }

 PG_FUNCTION_INFO_V1(hstore_to_array);
diff --git a/contrib/pageinspect/btreefuncs.c b/contrib/pageinspect/btreefuncs.c
index 2ddedef..dffb3e1 100644
--- a/contrib/pageinspect/btreefuncs.c
+++ b/contrib/pageinspect/btreefuncs.c
@@ -385,7 +385,7 @@ bt_page_print_tuples(FuncCallContext *fctx, struct user_args *uargs)
                                                       nposting,
                                                       TIDOID,
                                                       sizeof(ItemPointerData),
-                                                      false, 's'));
+                                                      false, TYPALIGN_SHORT));
         pfree(tids_datum);
     }
     else
diff --git a/contrib/pageinspect/ginfuncs.c b/contrib/pageinspect/ginfuncs.c
index 9b1d41c..7e2cafa 100644
--- a/contrib/pageinspect/ginfuncs.c
+++ b/contrib/pageinspect/ginfuncs.c
@@ -144,7 +144,8 @@ gin_page_opaque_info(PG_FUNCTION_ARGS)
     values[0] = Int64GetDatum(opaq->rightlink);
     values[1] = Int32GetDatum(opaq->maxoff);
     values[2] = PointerGetDatum(construct_array(flags, nflags,
-                                                TEXTOID, -1, false, 'i'));
+                                                TEXTOID,
+                                                -1, false, TYPALIGN_INT));

     /* Build and return the result tuple. */
     resultTuple = heap_form_tuple(tupdesc, values, nulls);
@@ -247,7 +248,7 @@ gin_leafpage_items(PG_FUNCTION_ARGS)
                                                     ndecoded,
                                                     TIDOID,
                                                     sizeof(ItemPointerData),
-                                                    false, 's'));
+                                                    false, TYPALIGN_SHORT));
         pfree(tids_datum);
         pfree(tids);

diff --git a/contrib/pageinspect/hashfuncs.c b/contrib/pageinspect/hashfuncs.c
index effc80f..984ac33 100644
--- a/contrib/pageinspect/hashfuncs.c
+++ b/contrib/pageinspect/hashfuncs.c
@@ -560,14 +560,18 @@ hash_metapage_info(PG_FUNCTION_ARGS)
     values[j++] = PointerGetDatum(construct_array(spares,
                                                   HASH_MAX_SPLITPOINTS,
                                                   INT8OID,
-                                                  8, FLOAT8PASSBYVAL, 'd'));
+                                                  sizeof(int64),
+                                                  FLOAT8PASSBYVAL,
+                                                  TYPALIGN_DOUBLE));

     for (i = 0; i < HASH_MAX_BITMAPS; i++)
         mapp[i] = Int64GetDatum((int64) metad->hashm_mapp[i]);
     values[j++] = PointerGetDatum(construct_array(mapp,
                                                   HASH_MAX_BITMAPS,
                                                   INT8OID,
-                                                  8, FLOAT8PASSBYVAL, 'd'));
+                                                  sizeof(int64),
+                                                  FLOAT8PASSBYVAL,
+                                                  TYPALIGN_DOUBLE));

     tuple = heap_form_tuple(tupleDesc, values, nulls);

diff --git a/contrib/pageinspect/heapfuncs.c b/contrib/pageinspect/heapfuncs.c
index 20b4d32..11a9101 100644
--- a/contrib/pageinspect/heapfuncs.c
+++ b/contrib/pageinspect/heapfuncs.c
@@ -589,7 +589,7 @@ heap_tuple_infomask_flags(PG_FUNCTION_ARGS)

     /* build value */
     Assert(cnt <= bitcnt);
-    a = construct_array(flags, cnt, TEXTOID, -1, false, 'i');
+    a = construct_array(flags, cnt, TEXTOID, -1, false, TYPALIGN_INT);
     values[0] = PointerGetDatum(a);

     /*
@@ -611,7 +611,7 @@ heap_tuple_infomask_flags(PG_FUNCTION_ARGS)
     if (cnt == 0)
         a = construct_empty_array(TEXTOID);
     else
-        a = construct_array(flags, cnt, TEXTOID, -1, false, 'i');
+        a = construct_array(flags, cnt, TEXTOID, -1, false, TYPALIGN_INT);
     pfree(flags);
     values[1] = PointerGetDatum(a);

diff --git a/contrib/pg_trgm/trgm_op.c b/contrib/pg_trgm/trgm_op.c
index 0670095..fb38135 100644
--- a/contrib/pg_trgm/trgm_op.c
+++ b/contrib/pg_trgm/trgm_op.c
@@ -980,7 +980,7 @@ show_trgm(PG_FUNCTION_ARGS)
                         TEXTOID,
                         -1,
                         false,
-                        'i');
+                        TYPALIGN_INT);

     for (i = 0; i < ARRNELEM(trg); i++)
         pfree(DatumGetPointer(d[i]));
diff --git a/contrib/pgcrypto/pgp-pgsql.c b/contrib/pgcrypto/pgp-pgsql.c
index 8be895d..62a2f35 100644
--- a/contrib/pgcrypto/pgp-pgsql.c
+++ b/contrib/pgcrypto/pgp-pgsql.c
@@ -787,11 +787,11 @@ parse_key_value_arrays(ArrayType *key_array, ArrayType *val_array,
         return 0;

     deconstruct_array(key_array,
-                      TEXTOID, -1, false, 'i',
+                      TEXTOID, -1, false, TYPALIGN_INT,
                       &key_datums, &key_nulls, &key_count);

     deconstruct_array(val_array,
-                      TEXTOID, -1, false, 'i',
+                      TEXTOID, -1, false, TYPALIGN_INT,
                       &val_datums, &val_nulls, &val_count);

     if (key_count != val_count)
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index b7c864c..f89769f 100644
--- a/src/backend/access/common/heaptuple.c
+++ b/src/backend/access/common/heaptuple.c
@@ -24,7 +24,7 @@
  * that have been put into a tuple but never sent to disk.  Hopefully there
  * are few such places.
  *
- * Varlenas still have alignment 'i' (or 'd') in pg_type/pg_attribute, since
+ * Varlenas still have alignment INT (or DOUBLE) in pg_type/pg_attribute, since
  * that's the normal requirement for the untoasted format.  But we ignore that
  * for the 1-byte-header format.  This means that the actual start position
  * of a varlena datum may vary depending on which format it has.  To determine
@@ -39,7 +39,7 @@
  * catalog, this is now risky: it's only safe if the preceding field is
  * word-aligned, so that there will never be any padding.
  *
- * We don't pack varlenas whose attstorage is 'p', since the data type
+ * We don't pack varlenas whose attstorage is PLAIN, since the data type
  * isn't expecting to have to detoast values.  This is used in particular
  * by oidvector and int2vector, which are used in the system catalogs
  * and we'd like to still refer to them via C struct offsets.
@@ -66,10 +66,10 @@

 /* Does att's datatype allow packing into the 1-byte-header varlena format? */
 #define ATT_IS_PACKABLE(att) \
-    ((att)->attlen == -1 && (att)->attstorage != 'p')
+    ((att)->attlen == -1 && (att)->attstorage != TYPSTORAGE_PLAIN)
 /* Use this if it's already known varlena */
 #define VARLENA_ATT_IS_PACKABLE(att) \
-    ((att)->attstorage != 'p')
+    ((att)->attstorage != TYPSTORAGE_PLAIN)


 /* ----------------------------------------------------------------
@@ -274,7 +274,7 @@ fill_val(Form_pg_attribute att,
     {
         /* cstring ... never needs alignment */
         *infomask |= HEAP_HASVARWIDTH;
-        Assert(att->attalign == 'c');
+        Assert(att->attalign == TYPALIGN_CHAR);
         data_length = strlen(DatumGetCString(datum)) + 1;
         memcpy(data, DatumGetPointer(datum), data_length);
     }
diff --git a/src/backend/access/common/indextuple.c b/src/backend/access/common/indextuple.c
index bfc8b15..634016b 100644
--- a/src/backend/access/common/indextuple.c
+++ b/src/backend/access/common/indextuple.c
@@ -100,7 +100,8 @@ index_form_tuple(TupleDesc tupleDescriptor,
          */
         if (!VARATT_IS_EXTENDED(DatumGetPointer(untoasted_values[i])) &&
             VARSIZE(DatumGetPointer(untoasted_values[i])) > TOAST_INDEX_TARGET &&
-            (att->attstorage == 'x' || att->attstorage == 'm'))
+            (att->attstorage == TYPSTORAGE_EXTENDED ||
+             att->attstorage == TYPSTORAGE_MAIN))
         {
             Datum        cvalue = toast_compress_datum(untoasted_values[i]);

diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 5325dd3..c3d45c7 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -892,7 +892,7 @@ transformRelOptions(Datum oldOptions, List *defList, const char *namspace,
         int            noldoptions;
         int            i;

-        deconstruct_array(array, TEXTOID, -1, false, 'i',
+        deconstruct_array(array, TEXTOID, -1, false, TYPALIGN_INT,
                           &oldoptions, NULL, &noldoptions);

         for (i = 0; i < noldoptions; i++)
@@ -1060,7 +1060,7 @@ untransformRelOptions(Datum options)

     array = DatumGetArrayTypeP(options);

-    deconstruct_array(array, TEXTOID, -1, false, 'i',
+    deconstruct_array(array, TEXTOID, -1, false, TYPALIGN_INT,
                       &optiondatums, NULL, &noptions);

     for (i = 0; i < noptions; i++)
@@ -1201,7 +1201,7 @@ parseRelOptions(Datum options, bool validate, relopt_kind kind,
         Datum       *optiondatums;
         int            noptions;

-        deconstruct_array(array, TEXTOID, -1, false, 'i',
+        deconstruct_array(array, TEXTOID, -1, false, TYPALIGN_INT,
                           &optiondatums, NULL, &noptions);

         for (i = 0; i < noptions; i++)
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index 2883551..1e743d7 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -725,32 +725,32 @@ TupleDescInitBuiltinEntry(TupleDesc desc,
         case TEXTARRAYOID:
             att->attlen = -1;
             att->attbyval = false;
-            att->attalign = 'i';
-            att->attstorage = 'x';
+            att->attalign = TYPALIGN_INT;
+            att->attstorage = TYPSTORAGE_EXTENDED;
             att->attcollation = DEFAULT_COLLATION_OID;
             break;

         case BOOLOID:
             att->attlen = 1;
             att->attbyval = true;
-            att->attalign = 'c';
-            att->attstorage = 'p';
+            att->attalign = TYPALIGN_CHAR;
+            att->attstorage = TYPSTORAGE_PLAIN;
             att->attcollation = InvalidOid;
             break;

         case INT4OID:
             att->attlen = 4;
             att->attbyval = true;
-            att->attalign = 'i';
-            att->attstorage = 'p';
+            att->attalign = TYPALIGN_INT;
+            att->attstorage = TYPSTORAGE_PLAIN;
             att->attcollation = InvalidOid;
             break;

         case INT8OID:
             att->attlen = 8;
             att->attbyval = FLOAT8PASSBYVAL;
-            att->attalign = 'd';
-            att->attstorage = 'p';
+            att->attalign = TYPALIGN_DOUBLE;
+            att->attstorage = TYPSTORAGE_PLAIN;
             att->attcollation = InvalidOid;
             break;

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 3fa4b76..ca52846 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2023,7 +2023,7 @@ heapam_relation_needs_toast_table(Relation rel)
                 maxlength_unknown = true;
             else
                 data_length += maxlen;
-            if (att->attstorage != 'p')
+            if (att->attstorage != TYPSTORAGE_PLAIN)
                 has_toastable_attrs = true;
         }
     }
diff --git a/src/backend/access/heap/heaptoast.c b/src/backend/access/heap/heaptoast.c
index a6631f9..584f101 100644
--- a/src/backend/access/heap/heaptoast.c
+++ b/src/backend/access/heap/heaptoast.c
@@ -159,11 +159,12 @@ heap_toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
     /* ----------
      * Compress and/or save external until data fits into target length
      *
-     *    1: Inline compress attributes with attstorage 'x', and store very
-     *       large attributes with attstorage 'x' or 'e' external immediately
-     *    2: Store attributes with attstorage 'x' or 'e' external
-     *    3: Inline compress attributes with attstorage 'm'
-     *    4: Store attributes with attstorage 'm' external
+     *    1: Inline compress attributes with attstorage EXTENDED, and store very
+     *       large attributes with attstorage EXTENDED or EXTERNAL external
+     *       immediately
+     *    2: Store attributes with attstorage EXTENDED or EXTERNAL external
+     *    3: Inline compress attributes with attstorage MAIN
+     *    4: Store attributes with attstorage MAIN external
      * ----------
      */

@@ -176,8 +177,9 @@ heap_toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
     maxDataLen = RelationGetToastTupleTarget(rel, TOAST_TUPLE_TARGET) - hoff;

     /*
-     * Look for attributes with attstorage 'x' to compress.  Also find large
-     * attributes with attstorage 'x' or 'e', and store them external.
+     * Look for attributes with attstorage EXTENDED to compress.  Also find
+     * large attributes with attstorage EXTENDED or EXTERNAL, and store them
+     * external.
      */
     while (heap_compute_data_size(tupleDesc,
                                   toast_values, toast_isnull) > maxDataLen)
@@ -189,13 +191,16 @@ heap_toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
             break;

         /*
-         * Attempt to compress it inline, if it has attstorage 'x'
+         * Attempt to compress it inline, if it has attstorage EXTENDED
          */
-        if (TupleDescAttr(tupleDesc, biggest_attno)->attstorage == 'x')
+        if (TupleDescAttr(tupleDesc, biggest_attno)->attstorage == TYPSTORAGE_EXTENDED)
             toast_tuple_try_compression(&ttc, biggest_attno);
         else
         {
-            /* has attstorage 'e', ignore on subsequent compression passes */
+            /*
+             * has attstorage EXTERNAL, ignore on subsequent compression
+             * passes
+             */
             toast_attr[biggest_attno].tai_colflags |= TOASTCOL_INCOMPRESSIBLE;
         }

@@ -213,9 +218,9 @@ heap_toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
     }

     /*
-     * Second we look for attributes of attstorage 'x' or 'e' that are still
-     * inline, and make them external.  But skip this if there's no toast
-     * table to push them to.
+     * Second we look for attributes of attstorage EXTENDED or EXTERNAL that
+     * are still inline, and make them external.  But skip this if there's no
+     * toast table to push them to.
      */
     while (heap_compute_data_size(tupleDesc,
                                   toast_values, toast_isnull) > maxDataLen &&
@@ -230,7 +235,7 @@ heap_toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
     }

     /*
-     * Round 3 - this time we take attributes with storage 'm' into
+     * Round 3 - this time we take attributes with storage MAIN into
      * compression
      */
     while (heap_compute_data_size(tupleDesc,
@@ -246,8 +251,8 @@ heap_toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
     }

     /*
-     * Finally we store attributes of type 'm' externally.  At this point we
-     * increase the target tuple size, so that 'm' attributes aren't stored
+     * Finally we store attributes of type MAIN externally.  At this point we
+     * increase the target tuple size, so that MAIN attributes aren't stored
      * externally unless really necessary.
      */
     maxDataLen = TOAST_TUPLE_TARGET_MAIN - hoff;
diff --git a/src/backend/access/table/toast_helper.c b/src/backend/access/table/toast_helper.c
index a324865..739b6ae 100644
--- a/src/backend/access/table/toast_helper.c
+++ b/src/backend/access/table/toast_helper.c
@@ -7,7 +7,7 @@
  * Copyright (c) 2000-2020, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *      src/backend/access/common/toast_helper.c
+ *      src/backend/access/table/toast_helper.c
  *
  *-------------------------------------------------------------------------
  */
@@ -18,6 +18,8 @@
 #include "access/table.h"
 #include "access/toast_helper.h"
 #include "access/toast_internals.h"
+#include "catalog/pg_type_d.h"
+

 /*
  * Prepare to TOAST a tuple.
@@ -120,7 +122,7 @@ toast_tuple_init(ToastTupleContext *ttc)
             /*
              * If the table's attribute says PLAIN always, force it so.
              */
-            if (att->attstorage == 'p')
+            if (att->attstorage == TYPSTORAGE_PLAIN)
                 ttc->ttc_attr[i].tai_colflags |= TOASTCOL_IGNORE;

             /*
@@ -134,7 +136,7 @@ toast_tuple_init(ToastTupleContext *ttc)
             if (VARATT_IS_EXTERNAL(new_value))
             {
                 ttc->ttc_attr[i].tai_oldexternal = new_value;
-                if (att->attstorage == 'p')
+                if (att->attstorage == TYPSTORAGE_PLAIN)
                     new_value = detoast_attr(new_value);
                 else
                     new_value = detoast_external_attr(new_value);
@@ -165,8 +167,8 @@ toast_tuple_init(ToastTupleContext *ttc)
  * for_compression flag is passed as true, it must also not be marked
  * TOASTCOL_INCOMPRESSIBLE.
  *
- * The column must have attstorage 'e' or 'x' if check_main is false, and
- * must have attstorage 'm' if check_main is true.
+ * The column must have attstorage EXTERNAL or EXTENDED if check_main is
+ * false, and must have attstorage MAIN if check_main is true.
  *
  * The column must have a minimum size of MAXALIGN(TOAST_POINTER_SIZE);
  * if not, no benefit is to be expected by compressing it.
@@ -195,13 +197,14 @@ toast_tuple_find_biggest_attribute(ToastTupleContext *ttc,
         if ((ttc->ttc_attr[i].tai_colflags & skip_colflags) != 0)
             continue;
         if (VARATT_IS_EXTERNAL(DatumGetPointer(ttc->ttc_values[i])))
-            continue;            /* can't happen, toast_action would be 'p' */
+            continue;            /* can't happen, toast_action would be PLAIN */
         if (for_compression &&
             VARATT_IS_COMPRESSED(DatumGetPointer(ttc->ttc_values[i])))
             continue;
-        if (check_main && att->attstorage != 'm')
+        if (check_main && att->attstorage != TYPSTORAGE_MAIN)
             continue;
-        if (!check_main && att->attstorage != 'x' && att->attstorage != 'e')
+        if (!check_main && att->attstorage != TYPSTORAGE_EXTENDED &&
+            att->attstorage != TYPSTORAGE_EXTERNAL)
             continue;

         if (ttc->ttc_attr[i].tai_size > biggest_size)
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index bfc629c..657b18e 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -101,55 +101,55 @@ struct typinfo
 };

 static const struct typinfo TypInfo[] = {
-    {"bool", BOOLOID, 0, 1, true, 'c', 'p', InvalidOid,
+    {"bool", BOOLOID, 0, 1, true, TYPALIGN_CHAR, TYPSTORAGE_PLAIN, InvalidOid,
     F_BOOLIN, F_BOOLOUT},
-    {"bytea", BYTEAOID, 0, -1, false, 'i', 'x', InvalidOid,
+    {"bytea", BYTEAOID, 0, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, InvalidOid,
     F_BYTEAIN, F_BYTEAOUT},
-    {"char", CHAROID, 0, 1, true, 'c', 'p', InvalidOid,
+    {"char", CHAROID, 0, 1, true, TYPALIGN_CHAR, TYPSTORAGE_PLAIN, InvalidOid,
     F_CHARIN, F_CHAROUT},
-    {"int2", INT2OID, 0, 2, true, 's', 'p', InvalidOid,
+    {"int2", INT2OID, 0, 2, true, TYPALIGN_SHORT, TYPSTORAGE_PLAIN, InvalidOid,
     F_INT2IN, F_INT2OUT},
-    {"int4", INT4OID, 0, 4, true, 'i', 'p', InvalidOid,
+    {"int4", INT4OID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     F_INT4IN, F_INT4OUT},
-    {"float4", FLOAT4OID, 0, 4, true, 'i', 'p', InvalidOid,
+    {"float4", FLOAT4OID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     F_FLOAT4IN, F_FLOAT4OUT},
-    {"name", NAMEOID, CHAROID, NAMEDATALEN, false, 'c', 'p', C_COLLATION_OID,
+    {"name", NAMEOID, CHAROID, NAMEDATALEN, false, TYPALIGN_CHAR, TYPSTORAGE_PLAIN, C_COLLATION_OID,
     F_NAMEIN, F_NAMEOUT},
-    {"regclass", REGCLASSOID, 0, 4, true, 'i', 'p', InvalidOid,
+    {"regclass", REGCLASSOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     F_REGCLASSIN, F_REGCLASSOUT},
-    {"regproc", REGPROCOID, 0, 4, true, 'i', 'p', InvalidOid,
+    {"regproc", REGPROCOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     F_REGPROCIN, F_REGPROCOUT},
-    {"regtype", REGTYPEOID, 0, 4, true, 'i', 'p', InvalidOid,
+    {"regtype", REGTYPEOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     F_REGTYPEIN, F_REGTYPEOUT},
-    {"regrole", REGROLEOID, 0, 4, true, 'i', 'p', InvalidOid,
+    {"regrole", REGROLEOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     F_REGROLEIN, F_REGROLEOUT},
-    {"regnamespace", REGNAMESPACEOID, 0, 4, true, 'i', 'p', InvalidOid,
+    {"regnamespace", REGNAMESPACEOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     F_REGNAMESPACEIN, F_REGNAMESPACEOUT},
-    {"text", TEXTOID, 0, -1, false, 'i', 'x', DEFAULT_COLLATION_OID,
+    {"text", TEXTOID, 0, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, DEFAULT_COLLATION_OID,
     F_TEXTIN, F_TEXTOUT},
-    {"oid", OIDOID, 0, 4, true, 'i', 'p', InvalidOid,
+    {"oid", OIDOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     F_OIDIN, F_OIDOUT},
-    {"tid", TIDOID, 0, 6, false, 's', 'p', InvalidOid,
+    {"tid", TIDOID, 0, 6, false, TYPALIGN_SHORT, TYPSTORAGE_PLAIN, InvalidOid,
     F_TIDIN, F_TIDOUT},
-    {"xid", XIDOID, 0, 4, true, 'i', 'p', InvalidOid,
+    {"xid", XIDOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     F_XIDIN, F_XIDOUT},
-    {"cid", CIDOID, 0, 4, true, 'i', 'p', InvalidOid,
+    {"cid", CIDOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     F_CIDIN, F_CIDOUT},
-    {"pg_node_tree", PGNODETREEOID, 0, -1, false, 'i', 'x', DEFAULT_COLLATION_OID,
+    {"pg_node_tree", PGNODETREEOID, 0, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, DEFAULT_COLLATION_OID,
     F_PG_NODE_TREE_IN, F_PG_NODE_TREE_OUT},
-    {"int2vector", INT2VECTOROID, INT2OID, -1, false, 'i', 'p', InvalidOid,
+    {"int2vector", INT2VECTOROID, INT2OID, -1, false, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     F_INT2VECTORIN, F_INT2VECTOROUT},
-    {"oidvector", OIDVECTOROID, OIDOID, -1, false, 'i', 'p', InvalidOid,
+    {"oidvector", OIDVECTOROID, OIDOID, -1, false, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     F_OIDVECTORIN, F_OIDVECTOROUT},
-    {"_int4", INT4ARRAYOID, INT4OID, -1, false, 'i', 'x', InvalidOid,
+    {"_int4", INT4ARRAYOID, INT4OID, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, InvalidOid,
     F_ARRAY_IN, F_ARRAY_OUT},
-    {"_text", 1009, TEXTOID, -1, false, 'i', 'x', DEFAULT_COLLATION_OID,
+    {"_text", 1009, TEXTOID, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, DEFAULT_COLLATION_OID,
     F_ARRAY_IN, F_ARRAY_OUT},
-    {"_oid", 1028, OIDOID, -1, false, 'i', 'x', InvalidOid,
+    {"_oid", 1028, OIDOID, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, InvalidOid,
     F_ARRAY_IN, F_ARRAY_OUT},
-    {"_char", 1002, CHAROID, -1, false, 'i', 'x', InvalidOid,
+    {"_char", 1002, CHAROID, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, InvalidOid,
     F_ARRAY_IN, F_ARRAY_OUT},
-    {"_aclitem", 1034, ACLITEMOID, -1, false, 'i', 'x', InvalidOid,
+    {"_aclitem", 1034, ACLITEMOID, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, InvalidOid,
     F_ARRAY_IN, F_ARRAY_OUT}
 };

diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index e31478b..9d9e915 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -156,8 +156,8 @@ static const FormData_pg_attribute a1 = {
     .attcacheoff = -1,
     .atttypmod = -1,
     .attbyval = false,
-    .attstorage = 'p',
-    .attalign = 's',
+    .attstorage = TYPSTORAGE_PLAIN,
+    .attalign = TYPALIGN_SHORT,
     .attnotnull = true,
     .attislocal = true,
 };
@@ -170,8 +170,8 @@ static const FormData_pg_attribute a2 = {
     .attcacheoff = -1,
     .atttypmod = -1,
     .attbyval = true,
-    .attstorage = 'p',
-    .attalign = 'i',
+    .attstorage = TYPSTORAGE_PLAIN,
+    .attalign = TYPALIGN_INT,
     .attnotnull = true,
     .attislocal = true,
 };
@@ -184,8 +184,8 @@ static const FormData_pg_attribute a3 = {
     .attcacheoff = -1,
     .atttypmod = -1,
     .attbyval = true,
-    .attstorage = 'p',
-    .attalign = 'i',
+    .attstorage = TYPSTORAGE_PLAIN,
+    .attalign = TYPALIGN_INT,
     .attnotnull = true,
     .attislocal = true,
 };
@@ -198,8 +198,8 @@ static const FormData_pg_attribute a4 = {
     .attcacheoff = -1,
     .atttypmod = -1,
     .attbyval = true,
-    .attstorage = 'p',
-    .attalign = 'i',
+    .attstorage = TYPSTORAGE_PLAIN,
+    .attalign = TYPALIGN_INT,
     .attnotnull = true,
     .attislocal = true,
 };
@@ -212,8 +212,8 @@ static const FormData_pg_attribute a5 = {
     .attcacheoff = -1,
     .atttypmod = -1,
     .attbyval = true,
-    .attstorage = 'p',
-    .attalign = 'i',
+    .attstorage = TYPSTORAGE_PLAIN,
+    .attalign = TYPALIGN_INT,
     .attnotnull = true,
     .attislocal = true,
 };
@@ -232,8 +232,8 @@ static const FormData_pg_attribute a6 = {
     .attcacheoff = -1,
     .atttypmod = -1,
     .attbyval = true,
-    .attstorage = 'p',
-    .attalign = 'i',
+    .attstorage = TYPSTORAGE_PLAIN,
+    .attalign = TYPALIGN_INT,
     .attnotnull = true,
     .attislocal = true,
 };
@@ -1053,8 +1053,8 @@ AddNewRelationType(const char *typeName,
                    NULL,        /* default value - none */
                    NULL,        /* default binary representation */
                    false,        /* passed by reference */
-                   'd',            /* alignment - must be the largest! */
-                   'x',            /* fully TOASTable */
+                   TYPALIGN_DOUBLE, /* alignment - must be the largest! */
+                   TYPSTORAGE_EXTENDED, /* fully TOASTable */
                    -1,            /* typmod */
                    0,            /* array dimensions for typBaseType */
                    false,        /* Type NOT NULL */
@@ -1334,8 +1334,8 @@ heap_create_with_catalog(const char *relname,
                    NULL,        /* default value - none */
                    NULL,        /* default binary representation */
                    false,        /* passed by reference */
-                   'd',            /* alignment - must be the largest! */
-                   'x',            /* fully TOASTable */
+                   TYPALIGN_DOUBLE, /* alignment - must be the largest! */
+                   TYPSTORAGE_EXTENDED, /* fully TOASTable */
                    -1,            /* typmod */
                    0,            /* array dimensions for typBaseType */
                    false,        /* Type NOT NULL */
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 93b9043..d0b5de4 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -1967,7 +1967,7 @@ textarray_to_strvaluelist(ArrayType *arr)
     List       *list = NIL;
     int            i;

-    deconstruct_array(arr, TEXTOID, -1, false, 'i',
+    deconstruct_array(arr, TEXTOID, -1, false, TYPALIGN_INT,
                       &elems, &nulls, &nelems);

     for (i = 0; i < nelems; i++)
@@ -2024,7 +2024,7 @@ pg_get_object_address(PG_FUNCTION_ARGS)
         bool       *nulls;
         int            nelems;

-        deconstruct_array(namearr, TEXTOID, -1, false, 'i',
+        deconstruct_array(namearr, TEXTOID, -1, false, TYPALIGN_INT,
                           &elems, &nulls, &nelems);
         if (nelems != 1)
             ereport(ERROR,
@@ -2042,7 +2042,7 @@ pg_get_object_address(PG_FUNCTION_ARGS)
         bool       *nulls;
         int            nelems;

-        deconstruct_array(namearr, TEXTOID, -1, false, 'i',
+        deconstruct_array(namearr, TEXTOID, -1, false, TYPALIGN_INT,
                           &elems, &nulls, &nelems);
         if (nelems != 1)
             ereport(ERROR,
@@ -2081,7 +2081,7 @@ pg_get_object_address(PG_FUNCTION_ARGS)
         int            nelems;
         int            i;

-        deconstruct_array(argsarr, TEXTOID, -1, false, 'i',
+        deconstruct_array(argsarr, TEXTOID, -1, false, TYPALIGN_INT,
                           &elems, &nulls, &nelems);

         args = NIL;
@@ -5333,7 +5333,7 @@ strlist_to_textarray(List *list)

     lb[0] = 1;
     arr = construct_md_array(datums, nulls, 1, &j,
-                             lb, TEXTOID, -1, false, 'i');
+                             lb, TEXTOID, -1, false, TYPALIGN_INT);

     MemoryContextDelete(memcxt);

diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index 3d2b1cc..90932be 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -108,7 +108,7 @@ CreateConstraintEntry(const char *constraintName,
         for (i = 0; i < constraintNKeys; i++)
             conkey[i] = Int16GetDatum(constraintKey[i]);
         conkeyArray = construct_array(conkey, constraintNKeys,
-                                      INT2OID, 2, true, 's');
+                                      INT2OID, 2, true, TYPALIGN_SHORT);
     }
     else
         conkeyArray = NULL;
@@ -121,19 +121,19 @@ CreateConstraintEntry(const char *constraintName,
         for (i = 0; i < foreignNKeys; i++)
             fkdatums[i] = Int16GetDatum(foreignKey[i]);
         confkeyArray = construct_array(fkdatums, foreignNKeys,
-                                       INT2OID, 2, true, 's');
+                                       INT2OID, 2, true, TYPALIGN_SHORT);
         for (i = 0; i < foreignNKeys; i++)
             fkdatums[i] = ObjectIdGetDatum(pfEqOp[i]);
         conpfeqopArray = construct_array(fkdatums, foreignNKeys,
-                                         OIDOID, sizeof(Oid), true, 'i');
+                                         OIDOID, sizeof(Oid), true, TYPALIGN_INT);
         for (i = 0; i < foreignNKeys; i++)
             fkdatums[i] = ObjectIdGetDatum(ppEqOp[i]);
         conppeqopArray = construct_array(fkdatums, foreignNKeys,
-                                         OIDOID, sizeof(Oid), true, 'i');
+                                         OIDOID, sizeof(Oid), true, TYPALIGN_INT);
         for (i = 0; i < foreignNKeys; i++)
             fkdatums[i] = ObjectIdGetDatum(ffEqOp[i]);
         conffeqopArray = construct_array(fkdatums, foreignNKeys,
-                                         OIDOID, sizeof(Oid), true, 'i');
+                                         OIDOID, sizeof(Oid), true, TYPALIGN_INT);
     }
     else
     {
@@ -151,7 +151,7 @@ CreateConstraintEntry(const char *constraintName,
         for (i = 0; i < constraintNKeys; i++)
             opdatums[i] = ObjectIdGetDatum(exclOp[i]);
         conexclopArray = construct_array(opdatums, constraintNKeys,
-                                         OIDOID, sizeof(Oid), true, 'i');
+                                         OIDOID, sizeof(Oid), true, TYPALIGN_INT);
     }
     else
         conexclopArray = NULL;
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 5194dca..423fd79 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -1171,7 +1171,7 @@ oid_array_to_list(Datum datum)

     deconstruct_array(array,
                       OIDOID,
-                      sizeof(Oid), true, 'i',
+                      sizeof(Oid), true, TYPALIGN_INT,
                       &values, NULL, &nelems);
     for (i = 0; i < nelems; i++)
         result = lappend_oid(result, values[i]);
diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c
index f77a83b..cb15731 100644
--- a/src/backend/catalog/pg_subscription.c
+++ b/src/backend/catalog/pg_subscription.c
@@ -216,7 +216,7 @@ textarray_to_stringlist(ArrayType *textarray)
     List       *res = NIL;

     deconstruct_array(textarray,
-                      TEXTOID, -1, false, 'i',
+                      TEXTOID, -1, false, TYPALIGN_INT,
                       &elems, NULL, &nelems);

     if (nelems == 0)
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index 8d7572d..56e0bcf 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -111,8 +111,8 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
     values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(InvalidOid);
     values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(InvalidOid);
     values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(InvalidOid);
-    values[Anum_pg_type_typalign - 1] = CharGetDatum('i');
-    values[Anum_pg_type_typstorage - 1] = CharGetDatum('p');
+    values[Anum_pg_type_typalign - 1] = CharGetDatum(TYPALIGN_INT);
+    values[Anum_pg_type_typstorage - 1] = CharGetDatum(TYPSTORAGE_PLAIN);
     values[Anum_pg_type_typnotnull - 1] = BoolGetDatum(false);
     values[Anum_pg_type_typbasetype - 1] = ObjectIdGetDatum(InvalidOid);
     values[Anum_pg_type_typtypmod - 1] = Int32GetDatum(-1);
@@ -259,7 +259,7 @@ TypeCreate(Oid newTypeOid,
          */
         if (internalSize == (int16) sizeof(char))
         {
-            if (alignment != 'c')
+            if (alignment != TYPALIGN_CHAR)
                 ereport(ERROR,
                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                          errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
@@ -267,7 +267,7 @@ TypeCreate(Oid newTypeOid,
         }
         else if (internalSize == (int16) sizeof(int16))
         {
-            if (alignment != 's')
+            if (alignment != TYPALIGN_SHORT)
                 ereport(ERROR,
                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                          errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
@@ -275,7 +275,7 @@ TypeCreate(Oid newTypeOid,
         }
         else if (internalSize == (int16) sizeof(int32))
         {
-            if (alignment != 'i')
+            if (alignment != TYPALIGN_INT)
                 ereport(ERROR,
                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                          errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
@@ -284,7 +284,7 @@ TypeCreate(Oid newTypeOid,
 #if SIZEOF_DATUM == 8
         else if (internalSize == (int16) sizeof(Datum))
         {
-            if (alignment != 'd')
+            if (alignment != TYPALIGN_DOUBLE)
                 ereport(ERROR,
                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                          errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
@@ -300,13 +300,14 @@ TypeCreate(Oid newTypeOid,
     else
     {
         /* varlena types must have int align or better */
-        if (internalSize == -1 && !(alignment == 'i' || alignment == 'd'))
+        if (internalSize == -1 &&
+            !(alignment == TYPALIGN_INT || alignment == TYPALIGN_DOUBLE))
             ereport(ERROR,
                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                      errmsg("alignment \"%c\" is invalid for variable-length type",
                             alignment)));
         /* cstring must have char alignment */
-        if (internalSize == -2 && !(alignment == 'c'))
+        if (internalSize == -2 && !(alignment == TYPALIGN_CHAR))
             ereport(ERROR,
                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                      errmsg("alignment \"%c\" is invalid for variable-length type",
@@ -314,7 +315,7 @@ TypeCreate(Oid newTypeOid,
     }

     /* Only varlena types can be toasted */
-    if (storage != 'p' && internalSize != -1)
+    if (storage != TYPSTORAGE_PLAIN && internalSize != -1)
         ereport(ERROR,
                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                  errmsg("fixed-size types must have storage PLAIN")));
diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
index 3334447..3239185 100644
--- a/src/backend/catalog/toasting.c
+++ b/src/backend/catalog/toasting.c
@@ -221,9 +221,9 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
      * toast :-(.  This is essential for chunk_data because type bytea is
      * toastable; hit the other two just to be sure.
      */
-    TupleDescAttr(tupdesc, 0)->attstorage = 'p';
-    TupleDescAttr(tupdesc, 1)->attstorage = 'p';
-    TupleDescAttr(tupdesc, 2)->attstorage = 'p';
+    TupleDescAttr(tupdesc, 0)->attstorage = TYPSTORAGE_PLAIN;
+    TupleDescAttr(tupdesc, 1)->attstorage = TYPSTORAGE_PLAIN;
+    TupleDescAttr(tupdesc, 2)->attstorage = TYPSTORAGE_PLAIN;

     /*
      * Toast tables for regular relations go in pg_toast; those for temp
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index c4420dd..924ef37 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -1527,7 +1527,7 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
                 /* XXX knows more than it should about type float4: */
                 arry = construct_array(numdatums, nnum,
                                        FLOAT4OID,
-                                       sizeof(float4), true, 'i');
+                                       sizeof(float4), true, TYPALIGN_INT);
                 values[i++] = PointerGetDatum(arry);    /* stanumbersN */
             }
             else
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index a366869..91800d1 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -357,7 +357,8 @@ filter_list_to_array(List *filterlist)
         pfree(result);
     }

-    return PointerGetDatum(construct_array(data, l, TEXTOID, -1, false, 'i'));
+    return PointerGetDatum(construct_array(data, l, TEXTOID,
+                                           -1, false, TYPALIGN_INT));
 }

 /*
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index a0db7db..00cf4ef 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -2293,7 +2293,7 @@ convert_requires_to_datum(List *requires)
     }
     a = construct_array(datums, ndatums,
                         NAMEOID,
-                        NAMEDATALEN, false, 'c');
+                        NAMEDATALEN, false, TYPALIGN_CHAR);
     return PointerGetDatum(a);
 }

@@ -2503,7 +2503,7 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)

         a = construct_array(&elementDatum, 1,
                             OIDOID,
-                            sizeof(Oid), true, 'i');
+                            sizeof(Oid), true, TYPALIGN_INT);
     }
     else
     {
@@ -2539,7 +2539,7 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
                       -1 /* varlena array */ ,
                       sizeof(Oid) /* OID's typlen */ ,
                       true /* OID's typbyval */ ,
-                      'i' /* OID's typalign */ );
+                      TYPALIGN_INT /* OID's typalign */ );
     }
     repl_val[Anum_pg_extension_extconfig - 1] = PointerGetDatum(a);
     repl_repl[Anum_pg_extension_extconfig - 1] = true;
@@ -2556,7 +2556,7 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)

         a = construct_array(&elementDatum, 1,
                             TEXTOID,
-                            -1, false, 'i');
+                            -1, false, TYPALIGN_INT);
     }
     else
     {
@@ -2577,7 +2577,7 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
                       -1 /* varlena array */ ,
                       -1 /* TEXT's typlen */ ,
                       false /* TEXT's typbyval */ ,
-                      'i' /* TEXT's typalign */ );
+                      TYPALIGN_INT /* TEXT's typalign */ );
     }
     repl_val[Anum_pg_extension_extcondition - 1] = PointerGetDatum(a);
     repl_repl[Anum_pg_extension_extcondition - 1] = true;
@@ -2698,14 +2698,14 @@ extension_config_remove(Oid extensionoid, Oid tableoid)
         int            i;

         /* We already checked there are no nulls */
-        deconstruct_array(a, OIDOID, sizeof(Oid), true, 'i',
+        deconstruct_array(a, OIDOID, sizeof(Oid), true, TYPALIGN_INT,
                           &dvalues, NULL, &nelems);

         for (i = arrayIndex; i < arrayLength - 1; i++)
             dvalues[i] = dvalues[i + 1];

         a = construct_array(dvalues, arrayLength - 1,
-                            OIDOID, sizeof(Oid), true, 'i');
+                            OIDOID, sizeof(Oid), true, TYPALIGN_INT);

         repl_val[Anum_pg_extension_extconfig - 1] = PointerGetDatum(a);
     }
@@ -2744,14 +2744,14 @@ extension_config_remove(Oid extensionoid, Oid tableoid)
         int            i;

         /* We already checked there are no nulls */
-        deconstruct_array(a, TEXTOID, -1, false, 'i',
+        deconstruct_array(a, TEXTOID, -1, false, TYPALIGN_INT,
                           &dvalues, NULL, &nelems);

         for (i = arrayIndex; i < arrayLength - 1; i++)
             dvalues[i] = dvalues[i + 1];

         a = construct_array(dvalues, arrayLength - 1,
-                            TEXTOID, -1, false, 'i');
+                            TEXTOID, -1, false, TYPALIGN_INT);

         repl_val[Anum_pg_extension_extcondition - 1] = PointerGetDatum(a);
     }
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 540044b..6d824a5 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -433,9 +433,9 @@ interpret_function_parameter_list(ParseState *pstate,
     if (outCount > 0 || varCount > 0)
     {
         *allParameterTypes = construct_array(allTypes, parameterCount, OIDOID,
-                                             sizeof(Oid), true, 'i');
+                                             sizeof(Oid), true, TYPALIGN_INT);
         *parameterModes = construct_array(paramModes, parameterCount, CHAROID,
-                                          1, true, 'c');
+                                          1, true, TYPALIGN_CHAR);
         if (outCount > 1)
             *requiredResultType = RECORDOID;
         /* otherwise we set requiredResultType correctly above */
@@ -454,7 +454,7 @@ interpret_function_parameter_list(ParseState *pstate,
                 paramNames[i] = CStringGetTextDatum("");
         }
         *parameterNames = construct_array(paramNames, parameterCount, TEXTOID,
-                                          -1, false, 'i');
+                                          -1, false, TYPALIGN_INT);
     }
     else
         *parameterNames = NULL;
@@ -1107,7 +1107,7 @@ CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt)
         foreach(lc, trftypes_list)
             arr[i++] = ObjectIdGetDatum(lfirst_oid(lc));
         trftypes = construct_array(arr, list_length(trftypes_list),
-                                   OIDOID, sizeof(Oid), true, 'i');
+                                   OIDOID, sizeof(Oid), true, TYPALIGN_INT);
     }
     else
     {
diff --git a/src/backend/commands/policy.c b/src/backend/commands/policy.c
index 6e990a3..4b4e469 100644
--- a/src/backend/commands/policy.c
+++ b/src/backend/commands/policy.c
@@ -614,7 +614,7 @@ RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid policy_id)

         /* This is the array for the new tuple */
         role_ids = construct_array(role_oids, num_roles, OIDOID,
-                                   sizeof(Oid), true, 'i');
+                                   sizeof(Oid), true, TYPALIGN_INT);

         replaces[Anum_pg_policy_polroles - 1] = true;
         values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids);
@@ -735,7 +735,7 @@ CreatePolicy(CreatePolicyStmt *stmt)
     /* Collect role ids */
     role_oids = policy_role_list_to_array(stmt->roles, &nitems);
     role_ids = construct_array(role_oids, nitems, OIDOID,
-                               sizeof(Oid), true, 'i');
+                               sizeof(Oid), true, TYPALIGN_INT);

     /* Parse the supplied clause */
     qual_pstate = make_parsestate(NULL);
@@ -919,7 +919,7 @@ AlterPolicy(AlterPolicyStmt *stmt)
     {
         role_oids = policy_role_list_to_array(stmt->roles, &nitems);
         role_ids = construct_array(role_oids, nitems, OIDOID,
-                                   sizeof(Oid), true, 'i');
+                                   sizeof(Oid), true, TYPALIGN_INT);
     }

     /* Get id of table.  Also handles permissions checks. */
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index f917fc9..284a5bf 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -788,6 +788,7 @@ build_regtype_array(Oid *param_types, int num_params)
         tmp_ary[i] = ObjectIdGetDatum(param_types[i]);

     /* XXX: this hardcodes assumptions about the regtype type */
-    result = construct_array(tmp_ary, num_params, REGTYPEOID, 4, true, 'i');
+    result = construct_array(tmp_ary, num_params, REGTYPEOID,
+                             4, true, TYPALIGN_INT);
     return PointerGetDatum(result);
 }
diff --git a/src/backend/commands/statscmds.c b/src/backend/commands/statscmds.c
index fb608cf..988cdba 100644
--- a/src/backend/commands/statscmds.c
+++ b/src/backend/commands/statscmds.c
@@ -323,7 +323,7 @@ CreateStatistics(CreateStatsStmt *stmt)
     if (build_mcv)
         types[ntypes++] = CharGetDatum(STATS_EXT_MCV);
     Assert(ntypes > 0 && ntypes <= lengthof(types));
-    stxkind = construct_array(types, ntypes, CHAROID, 1, true, 'c');
+    stxkind = construct_array(types, ntypes, CHAROID, 1, true, TYPALIGN_CHAR);

     statrel = table_open(StatisticExtRelationId, RowExclusiveLock);

diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 119a9ce..f3ec012 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -293,7 +293,7 @@ publicationListToArray(List *publist)
     MemoryContextSwitchTo(oldcxt);

     arr = construct_array(datums, list_length(publist),
-                          TEXTOID, -1, false, 'i');
+                          TEXTOID, -1, false, TYPALIGN_INT);

     MemoryContextDelete(memcxt);

diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 02a7c04..7a13b97 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -2030,14 +2030,14 @@ storage_name(char c)
 {
     switch (c)
     {
-        case 'p':
+        case TYPSTORAGE_PLAIN:
             return "PLAIN";
-        case 'm':
-            return "MAIN";
-        case 'x':
-            return "EXTENDED";
-        case 'e':
+        case TYPSTORAGE_EXTERNAL:
             return "EXTERNAL";
+        case TYPSTORAGE_EXTENDED:
+            return "EXTENDED";
+        case TYPSTORAGE_MAIN:
+            return "MAIN";
         default:
             return "???";
     }
@@ -7388,13 +7388,13 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc
     storagemode = strVal(newValue);

     if (pg_strcasecmp(storagemode, "plain") == 0)
-        newstorage = 'p';
+        newstorage = TYPSTORAGE_PLAIN;
     else if (pg_strcasecmp(storagemode, "external") == 0)
-        newstorage = 'e';
+        newstorage = TYPSTORAGE_EXTERNAL;
     else if (pg_strcasecmp(storagemode, "extended") == 0)
-        newstorage = 'x';
+        newstorage = TYPSTORAGE_EXTENDED;
     else if (pg_strcasecmp(storagemode, "main") == 0)
-        newstorage = 'm';
+        newstorage = TYPSTORAGE_MAIN;
     else
     {
         ereport(ERROR,
@@ -7426,7 +7426,7 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc
      * safety check: do not allow toasted storage modes unless column datatype
      * is TOAST-aware.
      */
-    if (newstorage == 'p' || TypeIsToastable(attrtuple->atttypid))
+    if (newstorage == TYPSTORAGE_PLAIN || TypeIsToastable(attrtuple->atttypid))
         attrtuple->attstorage = newstorage;
     else
         ereport(ERROR,
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 5209736..99528bf 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -132,8 +132,8 @@ DefineType(ParseState *pstate, List *names, List *parameters)
     Oid            elemType = InvalidOid;
     char       *defaultValue = NULL;
     bool        byValue = false;
-    char        alignment = 'i';    /* default alignment */
-    char        storage = 'p';    /* default TOAST storage method */
+    char        alignment = TYPALIGN_INT;    /* default alignment */
+    char        storage = TYPSTORAGE_PLAIN; /* default TOAST storage method */
     Oid            collation = InvalidOid;
     DefElem    *likeTypeEl = NULL;
     DefElem    *internalLengthEl = NULL;
@@ -382,16 +382,16 @@ DefineType(ParseState *pstate, List *names, List *parameters)
         if (pg_strcasecmp(a, "double") == 0 ||
             pg_strcasecmp(a, "float8") == 0 ||
             pg_strcasecmp(a, "pg_catalog.float8") == 0)
-            alignment = 'd';
+            alignment = TYPALIGN_DOUBLE;
         else if (pg_strcasecmp(a, "int4") == 0 ||
                  pg_strcasecmp(a, "pg_catalog.int4") == 0)
-            alignment = 'i';
+            alignment = TYPALIGN_INT;
         else if (pg_strcasecmp(a, "int2") == 0 ||
                  pg_strcasecmp(a, "pg_catalog.int2") == 0)
-            alignment = 's';
+            alignment = TYPALIGN_SHORT;
         else if (pg_strcasecmp(a, "char") == 0 ||
                  pg_strcasecmp(a, "pg_catalog.bpchar") == 0)
-            alignment = 'c';
+            alignment = TYPALIGN_CHAR;
         else
             ereport(ERROR,
                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -402,13 +402,13 @@ DefineType(ParseState *pstate, List *names, List *parameters)
         char       *a = defGetString(storageEl);

         if (pg_strcasecmp(a, "plain") == 0)
-            storage = 'p';
+            storage = TYPSTORAGE_PLAIN;
         else if (pg_strcasecmp(a, "external") == 0)
-            storage = 'e';
+            storage = TYPSTORAGE_EXTERNAL;
         else if (pg_strcasecmp(a, "extended") == 0)
-            storage = 'x';
+            storage = TYPSTORAGE_EXTENDED;
         else if (pg_strcasecmp(a, "main") == 0)
-            storage = 'm';
+            storage = TYPSTORAGE_MAIN;
         else
             ereport(ERROR,
                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -643,8 +643,8 @@ DefineType(ParseState *pstate, List *names, List *parameters)
      */
     array_type = makeArrayTypeName(typeName, typeNamespace);

-    /* alignment must be 'i' or 'd' for arrays */
-    alignment = (alignment == 'd') ? 'd' : 'i';
+    /* alignment must be TYPALIGN_INT or TYPALIGN_DOUBLE for arrays */
+    alignment = (alignment == TYPALIGN_DOUBLE) ? TYPALIGN_DOUBLE : TYPALIGN_INT;

     TypeCreate(array_oid,        /* force assignment of this type OID */
                array_type,        /* type name */
@@ -672,7 +672,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
                NULL,            /* binary default isn't sent either */
                false,            /* never passed by value */
                alignment,        /* see above */
-               'x',                /* ARRAY is always toastable */
+               TYPSTORAGE_EXTENDED, /* ARRAY is always toastable */
                -1,                /* typMod (Domains only) */
                0,                /* Array dimensions of typbasetype */
                false,            /* Type NOT NULL */
@@ -1078,8 +1078,8 @@ DefineDomain(CreateDomainStmt *stmt)
      */
     domainArrayName = makeArrayTypeName(domainName, domainNamespace);

-    /* alignment must be 'i' or 'd' for arrays */
-    alignment = (alignment == 'd') ? 'd' : 'i';
+    /* alignment must be TYPALIGN_INT or TYPALIGN_DOUBLE for arrays */
+    alignment = (alignment == TYPALIGN_DOUBLE) ? TYPALIGN_DOUBLE : TYPALIGN_INT;

     TypeCreate(domainArrayOid,    /* force assignment of this type OID */
                domainArrayName, /* type name */
@@ -1107,7 +1107,7 @@ DefineDomain(CreateDomainStmt *stmt)
                NULL,            /* binary default isn't sent either */
                false,            /* never passed by value */
                alignment,        /* see above */
-               'x',                /* ARRAY is always toastable */
+               TYPSTORAGE_EXTENDED, /* ARRAY is always toastable */
                -1,                /* typMod (Domains only) */
                0,                /* Array dimensions of typbasetype */
                false,            /* Type NOT NULL */
@@ -1221,8 +1221,8 @@ DefineEnum(CreateEnumStmt *stmt)
                    NULL,        /* never a default type value */
                    NULL,        /* binary default isn't sent either */
                    true,        /* always passed by value */
-                   'i',            /* int alignment */
-                   'p',            /* TOAST strategy always plain */
+                   TYPALIGN_INT,    /* int alignment */
+                   TYPSTORAGE_PLAIN,    /* TOAST strategy always plain */
                    -1,            /* typMod (Domains only) */
                    0,            /* Array dimensions of typbasetype */
                    false,        /* Type NOT NULL */
@@ -1261,8 +1261,8 @@ DefineEnum(CreateEnumStmt *stmt)
                NULL,            /* never a default type value */
                NULL,            /* binary default isn't sent either */
                false,            /* never passed by value */
-               'i',                /* enums have align i, so do their arrays */
-               'x',                /* ARRAY is always toastable */
+               TYPALIGN_INT,    /* enums have int align, so do their arrays */
+               TYPSTORAGE_EXTENDED, /* ARRAY is always toastable */
                -1,                /* typMod (Domains only) */
                0,                /* Array dimensions of typbasetype */
                false,            /* Type NOT NULL */
@@ -1516,8 +1516,8 @@ DefineRange(CreateRangeStmt *stmt)
     get_typlenbyvalalign(rangeSubtype,
                          &subtyplen, &subtypbyval, &subtypalign);

-    /* alignment must be 'i' or 'd' for ranges */
-    alignment = (subtypalign == 'd') ? 'd' : 'i';
+    /* alignment must be TYPALIGN_INT or TYPALIGN_DOUBLE for ranges */
+    alignment = (subtypalign == TYPALIGN_DOUBLE) ? TYPALIGN_DOUBLE : TYPALIGN_INT;

     /* Allocate OID for array type */
     rangeArrayOid = AssignTypeArrayOid();
@@ -1550,7 +1550,7 @@ DefineRange(CreateRangeStmt *stmt)
                    NULL,        /* no binary form available either */
                    false,        /* never passed by value */
                    alignment,    /* alignment */
-                   'x',            /* TOAST strategy (always extended) */
+                   TYPSTORAGE_EXTENDED, /* TOAST strategy (always extended) */
                    -1,            /* typMod (Domains only) */
                    0,            /* Array dimensions of typbasetype */
                    false,        /* Type NOT NULL */
@@ -1592,7 +1592,7 @@ DefineRange(CreateRangeStmt *stmt)
                NULL,            /* binary default isn't sent either */
                false,            /* never passed by value */
                alignment,        /* alignment - same as range's */
-               'x',                /* ARRAY is always toastable */
+               TYPSTORAGE_EXTENDED, /* ARRAY is always toastable */
                -1,                /* typMod (Domains only) */
                0,                /* Array dimensions of typbasetype */
                false,            /* Type NOT NULL */
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index f0d4883..b53a6bb 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -207,7 +207,7 @@ TidListEval(TidScanState *tidstate)
                 continue;
             itemarray = DatumGetArrayTypeP(arraydatum);
             deconstruct_array(itemarray,
-                              TIDOID, sizeof(ItemPointerData), false, 's',
+                              TIDOID, sizeof(ItemPointerData), false, TYPALIGN_SHORT,
                               &ipdatums, &ipnulls, &ndatums);
             if (numTids + ndatums > numAllocTids)
             {
diff --git a/src/backend/jit/llvm/llvmjit_deform.c b/src/backend/jit/llvm/llvmjit_deform.c
index d7a7b32..8a3064e 100644
--- a/src/backend/jit/llvm/llvmjit_deform.c
+++ b/src/backend/jit/llvm/llvmjit_deform.c
@@ -476,13 +476,13 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
         LLVMPositionBuilderAtEnd(b, attcheckalignblocks[attnum]);

         /* determine required alignment */
-        if (att->attalign == 'i')
+        if (att->attalign == TYPALIGN_INT)
             alignto = ALIGNOF_INT;
-        else if (att->attalign == 'c')
+        else if (att->attalign == TYPALIGN_CHAR)
             alignto = 1;
-        else if (att->attalign == 'd')
+        else if (att->attalign == TYPALIGN_DOUBLE)
             alignto = ALIGNOF_DOUBLE;
-        else if (att->attalign == 's')
+        else if (att->attalign == TYPALIGN_SHORT)
             alignto = ALIGNOF_SHORT;
         else
         {
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index d2a63e9..da5189a 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -2390,7 +2390,7 @@ gethba_options(HbaLine *hba)
     Assert(noptions <= MAX_HBA_OPTIONS);

     if (noptions > 0)
-        return construct_array(options, noptions, TEXTOID, -1, false, 'i');
+        return construct_array(options, noptions, TEXTOID, -1, false, TYPALIGN_INT);
     else
         return NULL;
 }
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
index 2c237cd..2709f6f 100644
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -409,7 +409,7 @@ typenameTypeMod(ParseState *pstate, const TypeName *typeName, Type typ)

     /* hardwired knowledge about cstring's representation details here */
     arrtypmod = construct_array(datums, n, CSTRINGOID,
-                                -2, false, 'c');
+                                -2, false, TYPALIGN_CHAR);

     /* arrange to report location if type's typmodin function fails */
     setup_parser_errposition_callback(&pcbstate, pstate, typeName->location);
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 973eab6..af77f18 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -1473,7 +1473,7 @@ generateClonedIndexStmt(RangeVar *heapRel, Relation source_idx,
                          constraintId);

                 deconstruct_array(DatumGetArrayTypeP(datum),
-                                  OIDOID, sizeof(Oid), true, 'i',
+                                  OIDOID, sizeof(Oid), true, TYPALIGN_INT,
                                   &elems, NULL, &nElems);

                 for (i = 0; i < nElems; i++)
diff --git a/src/backend/replication/logical/logicalfuncs.c b/src/backend/replication/logical/logicalfuncs.c
index 2bba2b4..a3a83a9 100644
--- a/src/backend/replication/logical/logicalfuncs.c
+++ b/src/backend/replication/logical/logicalfuncs.c
@@ -203,7 +203,7 @@ pg_logical_slot_get_changes_guts(FunctionCallInfo fcinfo, bool confirm, bool bin

         Assert(ARR_ELEMTYPE(arr) == TEXTOID);

-        deconstruct_array(arr, TEXTOID, -1, false, 'i',
+        deconstruct_array(arr, TEXTOID, -1, false, TYPALIGN_INT,
                           &datum_opts, NULL, &nelems);

         if (nelems % 2 != 0)
diff --git a/src/backend/tsearch/dict.c b/src/backend/tsearch/dict.c
index e1d9e90..835b672 100644
--- a/src/backend/tsearch/dict.c
+++ b/src/backend/tsearch/dict.c
@@ -73,7 +73,7 @@ ts_lexize(PG_FUNCTION_ARGS)
                         TEXTOID,
                         -1,
                         false,
-                        'i');
+                        TYPALIGN_INT);

     ptr = res;
     while (ptr->lexeme)
diff --git a/src/backend/utils/adt/arrayutils.c b/src/backend/utils/adt/arrayutils.c
index d972be1..bc4360a 100644
--- a/src/backend/utils/adt/arrayutils.c
+++ b/src/backend/utils/adt/arrayutils.c
@@ -220,7 +220,7 @@ ArrayGetIntegerTypmods(ArrayType *arr, int *n)

     /* hardwired knowledge about cstring's representation details here */
     deconstruct_array(arr, CSTRINGOID,
-                      -2, false, 'c',
+                      -2, false, TYPALIGN_CHAR,
                       &elem_values, NULL, n);

     result = (int32 *) palloc(*n * sizeof(int32));
diff --git a/src/backend/utils/adt/enum.c b/src/backend/utils/adt/enum.c
index 3ea0d5d..5ead794 100644
--- a/src/backend/utils/adt/enum.c
+++ b/src/backend/utils/adt/enum.c
@@ -602,7 +602,8 @@ enum_range_internal(Oid enumtypoid, Oid lower, Oid upper)

     /* and build the result array */
     /* note this hardwires some details about the representation of Oid */
-    result = construct_array(elems, cnt, enumtypoid, sizeof(Oid), true, 'i');
+    result = construct_array(elems, cnt, enumtypoid,
+                             sizeof(Oid), true, TYPALIGN_INT);

     pfree(elems);

diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index 34af0eb..2101d58 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -2878,7 +2878,7 @@ float8_combine(PG_FUNCTION_ARGS)

         result = construct_array(transdatums, 3,
                                  FLOAT8OID,
-                                 sizeof(float8), FLOAT8PASSBYVAL, 'd');
+                                 sizeof(float8), FLOAT8PASSBYVAL, TYPALIGN_DOUBLE);

         PG_RETURN_ARRAYTYPE_P(result);
     }
@@ -2950,7 +2950,7 @@ float8_accum(PG_FUNCTION_ARGS)

         result = construct_array(transdatums, 3,
                                  FLOAT8OID,
-                                 sizeof(float8), FLOAT8PASSBYVAL, 'd');
+                                 sizeof(float8), FLOAT8PASSBYVAL, TYPALIGN_DOUBLE);

         PG_RETURN_ARRAYTYPE_P(result);
     }
@@ -3024,7 +3024,7 @@ float4_accum(PG_FUNCTION_ARGS)

         result = construct_array(transdatums, 3,
                                  FLOAT8OID,
-                                 sizeof(float8), FLOAT8PASSBYVAL, 'd');
+                                 sizeof(float8), FLOAT8PASSBYVAL, TYPALIGN_DOUBLE);

         PG_RETURN_ARRAYTYPE_P(result);
     }
@@ -3256,7 +3256,7 @@ float8_regr_accum(PG_FUNCTION_ARGS)

         result = construct_array(transdatums, 6,
                                  FLOAT8OID,
-                                 sizeof(float8), FLOAT8PASSBYVAL, 'd');
+                                 sizeof(float8), FLOAT8PASSBYVAL, TYPALIGN_DOUBLE);

         PG_RETURN_ARRAYTYPE_P(result);
     }
@@ -3397,7 +3397,7 @@ float8_regr_combine(PG_FUNCTION_ARGS)

         result = construct_array(transdatums, 6,
                                  FLOAT8OID,
-                                 sizeof(float8), FLOAT8PASSBYVAL, 'd');
+                                 sizeof(float8), FLOAT8PASSBYVAL, TYPALIGN_DOUBLE);

         PG_RETURN_ARRAYTYPE_P(result);
     }
diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c
index 92ee77a..df0bdeb 100644
--- a/src/backend/utils/adt/format_type.c
+++ b/src/backend/utils/adt/format_type.c
@@ -136,7 +136,8 @@ format_type_extended(Oid type_oid, int32 typemod, bits16 flags)
      */
     array_base_type = typeform->typelem;

-    if (array_base_type != InvalidOid && typeform->typstorage != 'p')
+    if (array_base_type != InvalidOid &&
+        typeform->typstorage != TYPSTORAGE_PLAIN)
     {
         /* Switch our attention to the array element type */
         ReleaseSysCache(tuple);
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index 567eab1..f78420e 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -1142,7 +1142,7 @@ json_object(PG_FUNCTION_ARGS)
     }

     deconstruct_array(in_array,
-                      TEXTOID, -1, false, 'i',
+                      TEXTOID, -1, false, TYPALIGN_INT,
                       &in_datums, &in_nulls, &in_count);

     count = in_count / 2;
@@ -1219,11 +1219,11 @@ json_object_two_arg(PG_FUNCTION_ARGS)
         PG_RETURN_DATUM(CStringGetTextDatum("{}"));

     deconstruct_array(key_array,
-                      TEXTOID, -1, false, 'i',
+                      TEXTOID, -1, false, TYPALIGN_INT,
                       &key_datums, &key_nulls, &key_count);

     deconstruct_array(val_array,
-                      TEXTOID, -1, false, 'i',
+                      TEXTOID, -1, false, TYPALIGN_INT,
                       &val_datums, &val_nulls, &val_count);

     if (key_count != val_count)
diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c
index fea4335..b961d29 100644
--- a/src/backend/utils/adt/jsonb.c
+++ b/src/backend/utils/adt/jsonb.c
@@ -1317,7 +1317,7 @@ jsonb_object(PG_FUNCTION_ARGS)
     }

     deconstruct_array(in_array,
-                      TEXTOID, -1, false, 'i',
+                      TEXTOID, -1, false, TYPALIGN_INT,
                       &in_datums, &in_nulls, &in_count);

     count = in_count / 2;
@@ -1405,11 +1405,11 @@ jsonb_object_two_arg(PG_FUNCTION_ARGS)
         goto close_object;

     deconstruct_array(key_array,
-                      TEXTOID, -1, false, 'i',
+                      TEXTOID, -1, false, TYPALIGN_INT,
                       &key_datums, &key_nulls, &key_count);

     deconstruct_array(val_array,
-                      TEXTOID, -1, false, 'i',
+                      TEXTOID, -1, false, TYPALIGN_INT,
                       &val_datums, &val_nulls, &val_count);

     if (key_count != val_count)
diff --git a/src/backend/utils/adt/jsonb_gin.c b/src/backend/utils/adt/jsonb_gin.c
index 63122ed..aee3d9d 100644
--- a/src/backend/utils/adt/jsonb_gin.c
+++ b/src/backend/utils/adt/jsonb_gin.c
@@ -886,7 +886,7 @@ gin_extract_jsonb_query(PG_FUNCTION_ARGS)
                     j;

         deconstruct_array(query,
-                          TEXTOID, -1, false, 'i',
+                          TEXTOID, -1, false, TYPALIGN_INT,
                           &key_datums, &key_nulls, &key_count);

         entries = (Datum *) palloc(sizeof(Datum) * key_count);
diff --git a/src/backend/utils/adt/jsonb_op.c b/src/backend/utils/adt/jsonb_op.c
index 443ea24..dc17e17 100644
--- a/src/backend/utils/adt/jsonb_op.c
+++ b/src/backend/utils/adt/jsonb_op.c
@@ -53,8 +53,8 @@ jsonb_exists_any(PG_FUNCTION_ARGS)
     bool       *key_nulls;
     int            elem_count;

-    deconstruct_array(keys, TEXTOID, -1, false, 'i', &key_datums, &key_nulls,
-                      &elem_count);
+    deconstruct_array(keys, TEXTOID, -1, false, TYPALIGN_INT,
+                      &key_datums, &key_nulls, &elem_count);

     for (i = 0; i < elem_count; i++)
     {
@@ -86,8 +86,8 @@ jsonb_exists_all(PG_FUNCTION_ARGS)
     bool       *key_nulls;
     int            elem_count;

-    deconstruct_array(keys, TEXTOID, -1, false, 'i', &key_datums, &key_nulls,
-                      &elem_count);
+    deconstruct_array(keys, TEXTOID, -1, false, TYPALIGN_INT,
+                      &key_datums, &key_nulls, &elem_count);

     for (i = 0; i < elem_count; i++)
     {
diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c
index 6e33dfb..f92861d 100644
--- a/src/backend/utils/adt/jsonfuncs.c
+++ b/src/backend/utils/adt/jsonfuncs.c
@@ -1019,7 +1019,7 @@ get_path_all(FunctionCallInfo fcinfo, bool as_text)
     if (array_contains_nulls(path))
         PG_RETURN_NULL();

-    deconstruct_array(path, TEXTOID, -1, false, 'i',
+    deconstruct_array(path, TEXTOID, -1, false, TYPALIGN_INT,
                       &pathtext, &pathnulls, &npath);

     tpath = palloc(npath * sizeof(char *));
@@ -1479,7 +1479,7 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
     if (array_contains_nulls(path))
         PG_RETURN_NULL();

-    deconstruct_array(path, TEXTOID, -1, false, 'i',
+    deconstruct_array(path, TEXTOID, -1, false, TYPALIGN_INT,
                       &pathtext, &pathnulls, &npath);

     /* Identify whether we have object, array, or scalar at top-level */
@@ -4361,7 +4361,7 @@ jsonb_delete_array(PG_FUNCTION_ARGS)
     if (JB_ROOT_COUNT(in) == 0)
         PG_RETURN_JSONB_P(in);

-    deconstruct_array(keys, TEXTOID, -1, false, 'i',
+    deconstruct_array(keys, TEXTOID, -1, false, TYPALIGN_INT,
                       &keys_elems, &keys_nulls, &keys_len);

     if (keys_len == 0)
@@ -4511,7 +4511,7 @@ jsonb_set(PG_FUNCTION_ARGS)
     if (JB_ROOT_COUNT(in) == 0 && !create)
         PG_RETURN_JSONB_P(in);

-    deconstruct_array(path, TEXTOID, -1, false, 'i',
+    deconstruct_array(path, TEXTOID, -1, false, TYPALIGN_INT,
                       &path_elems, &path_nulls, &path_len);

     if (path_len == 0)
@@ -4622,7 +4622,7 @@ jsonb_delete_path(PG_FUNCTION_ARGS)
     if (JB_ROOT_COUNT(in) == 0)
         PG_RETURN_JSONB_P(in);

-    deconstruct_array(path, TEXTOID, -1, false, 'i',
+    deconstruct_array(path, TEXTOID, -1, false, TYPALIGN_INT,
                       &path_elems, &path_nulls, &path_len);

     if (path_len == 0)
@@ -4665,7 +4665,7 @@ jsonb_insert(PG_FUNCTION_ARGS)
                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                  errmsg("cannot set path in scalar")));

-    deconstruct_array(path, TEXTOID, -1, false, 'i',
+    deconstruct_array(path, TEXTOID, -1, false, TYPALIGN_INT,
                       &path_elems, &path_nulls, &path_len);

     if (path_len == 0)
diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c
index 7e47ebe..ecb1bf9 100644
--- a/src/backend/utils/adt/lockfuncs.c
+++ b/src/backend/utils/adt/lockfuncs.c
@@ -519,7 +519,7 @@ pg_blocking_pids(PG_FUNCTION_ARGS)
     /* Construct array, using hardwired knowledge about int4 type */
     PG_RETURN_ARRAYTYPE_P(construct_array(arrayelems, narrayelems,
                                           INT4OID,
-                                          sizeof(int32), true, 'i'));
+                                          sizeof(int32), true, TYPALIGN_INT));
 }


@@ -560,7 +560,7 @@ pg_safe_snapshot_blocking_pids(PG_FUNCTION_ARGS)
     /* Construct array, using hardwired knowledge about int4 type */
     PG_RETURN_ARRAYTYPE_P(construct_array(blocker_datums, num_blockers,
                                           INT4OID,
-                                          sizeof(int32), true, 'i'));
+                                          sizeof(int32), true, TYPALIGN_INT));
 }


diff --git a/src/backend/utils/adt/name.c b/src/backend/utils/adt/name.c
index 6749e75..64877f6 100644
--- a/src/backend/utils/adt/name.c
+++ b/src/backend/utils/adt/name.c
@@ -358,7 +358,7 @@ current_schemas(PG_FUNCTION_ARGS)
                             NAMEOID,
                             NAMEDATALEN,    /* sizeof(Name) */
                             false,    /* Name is not by-val */
-                            'c');    /* alignment of Name */
+                            TYPALIGN_CHAR); /* alignment of Name */

     PG_RETURN_POINTER(array);
 }
diff --git a/src/backend/utils/adt/orderedsetaggs.c b/src/backend/utils/adt/orderedsetaggs.c
index d169045..f9b5d70 100644
--- a/src/backend/utils/adt/orderedsetaggs.c
+++ b/src/backend/utils/adt/orderedsetaggs.c
@@ -755,7 +755,7 @@ percentile_disc_multi_final(PG_FUNCTION_ARGS)

     deconstruct_array(param, FLOAT8OID,
     /* hard-wired info on type float8 */
-                      8, FLOAT8PASSBYVAL, 'd',
+                      sizeof(float8), FLOAT8PASSBYVAL, TYPALIGN_DOUBLE,
                       &percentiles_datum,
                       &percentiles_null,
                       &num_percentiles);
@@ -879,7 +879,7 @@ percentile_cont_multi_final_common(FunctionCallInfo fcinfo,

     deconstruct_array(param, FLOAT8OID,
     /* hard-wired info on type float8 */
-                      8, FLOAT8PASSBYVAL, 'd',
+                      sizeof(float8), FLOAT8PASSBYVAL, TYPALIGN_DOUBLE,
                       &percentiles_datum,
                       &percentiles_null,
                       &num_percentiles);
@@ -1002,7 +1002,9 @@ percentile_cont_float8_multi_final(PG_FUNCTION_ARGS)
     return percentile_cont_multi_final_common(fcinfo,
                                               FLOAT8OID,
     /* hard-wired info on type float8 */
-                                              8, FLOAT8PASSBYVAL, 'd',
+                                              sizeof(float8),
+                                              FLOAT8PASSBYVAL,
+                                              TYPALIGN_DOUBLE,
                                               float8_lerp);
 }

@@ -1015,7 +1017,7 @@ percentile_cont_interval_multi_final(PG_FUNCTION_ARGS)
     return percentile_cont_multi_final_common(fcinfo,
                                               INTERVALOID,
     /* hard-wired info on type interval */
-                                              16, false, 'd',
+                                              16, false, TYPALIGN_DOUBLE,
                                               interval_lerp);
 }

diff --git a/src/backend/utils/adt/pg_upgrade_support.c b/src/backend/utils/adt/pg_upgrade_support.c
index 0d9e55c..18f2ee8 100644
--- a/src/backend/utils/adt/pg_upgrade_support.c
+++ b/src/backend/utils/adt/pg_upgrade_support.c
@@ -160,7 +160,7 @@ binary_upgrade_create_empty_extension(PG_FUNCTION_ARGS)
         int            i;

         deconstruct_array(textArray,
-                          TEXTOID, -1, false, 'i',
+                          TEXTOID, -1, false, TYPALIGN_INT,
                           &textDatums, NULL, &ndatums);
         for (i = 0; i < ndatums; i++)
         {
diff --git a/src/backend/utils/adt/rangetypes.c b/src/backend/utils/adt/rangetypes.c
index b95132b..490bc2a 100644
--- a/src/backend/utils/adt/rangetypes.c
+++ b/src/backend/utils/adt/rangetypes.c
@@ -2389,7 +2389,7 @@ range_contains_elem_internal(TypeCacheEntry *typcache, const RangeType *r, Datum

 /* Does datatype allow packing into the 1-byte-header varlena format? */
 #define TYPE_IS_PACKABLE(typlen, typstorage) \
-    ((typlen) == -1 && (typstorage) != 'p')
+    ((typlen) == -1 && (typstorage) != TYPSTORAGE_PLAIN)

 /*
  * Increment data_length by the space needed by the datum, including any
@@ -2473,7 +2473,7 @@ datum_write(Pointer ptr, Datum datum, bool typbyval, char typalign,
     else if (typlen == -2)
     {
         /* cstring ... never needs alignment */
-        Assert(typalign == 'c');
+        Assert(typalign == TYPALIGN_CHAR);
         data_length = strlen(DatumGetCString(datum)) + 1;
         memcpy(ptr, DatumGetPointer(datum), data_length);
     }
diff --git a/src/backend/utils/adt/regexp.c b/src/backend/utils/adt/regexp.c
index 6c76e89..06f8086 100644
--- a/src/backend/utils/adt/regexp.c
+++ b/src/backend/utils/adt/regexp.c
@@ -1329,7 +1329,7 @@ build_regexp_match_result(regexp_matches_ctx *matchctx)
     lbs[0] = 1;
     /* XXX: this hardcodes assumptions about the text type */
     return construct_md_array(elems, nulls, 1, dims, lbs,
-                              TEXTOID, -1, false, 'i');
+                              TEXTOID, -1, false, TYPALIGN_INT);
 }

 /*
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 1587844..5e63238 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -2154,7 +2154,7 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
                         elog(ERROR, "null indkey for index %u", indexId);

                     deconstruct_array(DatumGetArrayTypeP(cols),
-                                      INT2OID, 2, true, 's',
+                                      INT2OID, 2, true, TYPALIGN_SHORT,
                                       &keys, NULL, &nKeys);

                     for (j = keyatts; j < nKeys; j++)
@@ -2279,7 +2279,7 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
                          constraintId);

                 deconstruct_array(DatumGetArrayTypeP(val),
-                                  OIDOID, sizeof(Oid), true, 'i',
+                                  OIDOID, sizeof(Oid), true, TYPALIGN_INT,
                                   &elems, NULL, &nElems);

                 operators = (Oid *) palloc(nElems * sizeof(Oid));
@@ -2335,7 +2335,7 @@ decompile_column_index_array(Datum column_index_array, Oid relId,

     /* Extract data from array of int16 */
     deconstruct_array(DatumGetArrayTypeP(column_index_array),
-                      INT2OID, 2, true, 's',
+                      INT2OID, 2, true, TYPALIGN_SHORT,
                       &keys, NULL, &nKeys);

     for (j = 0; j < nKeys; j++)
@@ -2730,7 +2730,7 @@ pg_get_functiondef(PG_FUNCTION_ARGS)
                           -1 /* varlenarray */ ,
                           -1 /* TEXT's typlen */ ,
                           false /* TEXT's typbyval */ ,
-                          'i' /* TEXT's typalign */ ,
+                          TYPALIGN_INT /* TEXT's typalign */ ,
                           &isnull);
             if (!isnull)
             {
@@ -11277,7 +11277,7 @@ flatten_reloptions(Oid relid)
         initStringInfo(&buf);

         deconstruct_array(DatumGetArrayTypeP(reloptions),
-                          TEXTOID, -1, false, 'i',
+                          TEXTOID, -1, false, TYPALIGN_INT,
                           &options, NULL, &noptions);

         for (i = 0; i < noptions; i++)
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 0b6c9d5..4caffb5 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -3421,7 +3421,7 @@ interval_accum(PG_FUNCTION_ARGS)
     ArrayType  *result;

     deconstruct_array(transarray,
-                      INTERVALOID, sizeof(Interval), false, 'd',
+                      INTERVALOID, sizeof(Interval), false, TYPALIGN_DOUBLE,
                       &transdatums, NULL, &ndatums);
     if (ndatums != 2)
         elog(ERROR, "expected 2-element interval array");
@@ -3438,7 +3438,7 @@ interval_accum(PG_FUNCTION_ARGS)
     transdatums[1] = IntervalPGetDatum(&N);

     result = construct_array(transdatums, 2,
-                             INTERVALOID, sizeof(Interval), false, 'd');
+                             INTERVALOID, sizeof(Interval), false, TYPALIGN_DOUBLE);

     PG_RETURN_ARRAYTYPE_P(result);
 }
@@ -3461,7 +3461,7 @@ interval_combine(PG_FUNCTION_ARGS)
     ArrayType  *result;

     deconstruct_array(transarray1,
-                      INTERVALOID, sizeof(Interval), false, 'd',
+                      INTERVALOID, sizeof(Interval), false, TYPALIGN_DOUBLE,
                       &transdatums1, NULL, &ndatums1);
     if (ndatums1 != 2)
         elog(ERROR, "expected 2-element interval array");
@@ -3470,7 +3470,7 @@ interval_combine(PG_FUNCTION_ARGS)
     N1 = *(DatumGetIntervalP(transdatums1[1]));

     deconstruct_array(transarray2,
-                      INTERVALOID, sizeof(Interval), false, 'd',
+                      INTERVALOID, sizeof(Interval), false, TYPALIGN_DOUBLE,
                       &transdatums2, NULL, &ndatums2);
     if (ndatums2 != 2)
         elog(ERROR, "expected 2-element interval array");
@@ -3487,7 +3487,7 @@ interval_combine(PG_FUNCTION_ARGS)
     transdatums1[1] = IntervalPGetDatum(&N1);

     result = construct_array(transdatums1, 2,
-                             INTERVALOID, sizeof(Interval), false, 'd');
+                             INTERVALOID, sizeof(Interval), false, TYPALIGN_DOUBLE);

     PG_RETURN_ARRAYTYPE_P(result);
 }
@@ -3505,7 +3505,7 @@ interval_accum_inv(PG_FUNCTION_ARGS)
     ArrayType  *result;

     deconstruct_array(transarray,
-                      INTERVALOID, sizeof(Interval), false, 'd',
+                      INTERVALOID, sizeof(Interval), false, TYPALIGN_DOUBLE,
                       &transdatums, NULL, &ndatums);
     if (ndatums != 2)
         elog(ERROR, "expected 2-element interval array");
@@ -3522,7 +3522,7 @@ interval_accum_inv(PG_FUNCTION_ARGS)
     transdatums[1] = IntervalPGetDatum(&N);

     result = construct_array(transdatums, 2,
-                             INTERVALOID, sizeof(Interval), false, 'd');
+                             INTERVALOID, sizeof(Interval), false, TYPALIGN_DOUBLE);

     PG_RETURN_ARRAYTYPE_P(result);
 }
@@ -3537,7 +3537,7 @@ interval_avg(PG_FUNCTION_ARGS)
                 N;

     deconstruct_array(transarray,
-                      INTERVALOID, sizeof(Interval), false, 'd',
+                      INTERVALOID, sizeof(Interval), false, TYPALIGN_DOUBLE,
                       &transdatums, NULL, &ndatums);
     if (ndatums != 2)
         elog(ERROR, "expected 2-element interval array");
diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c
index cab6874..7903550 100644
--- a/src/backend/utils/adt/tsvector_op.c
+++ b/src/backend/utils/adt/tsvector_op.c
@@ -303,7 +303,7 @@ tsvector_setweight_by_filter(PG_FUNCTION_ARGS)
     memcpy(tsout, tsin, VARSIZE(tsin));
     entry = ARRPTR(tsout);

-    deconstruct_array(lexemes, TEXTOID, -1, false, 'i',
+    deconstruct_array(lexemes, TEXTOID, -1, false, TYPALIGN_INT,
                       &dlexemes, &nulls, &nlexemes);

     /*
@@ -582,7 +582,7 @@ tsvector_delete_arr(PG_FUNCTION_ARGS)
     Datum       *dlexemes;
     bool       *nulls;

-    deconstruct_array(lexemes, TEXTOID, -1, false, 'i',
+    deconstruct_array(lexemes, TEXTOID, -1, false, TYPALIGN_INT,
                       &dlexemes, &nulls, &nlex);

     /*
@@ -692,9 +692,9 @@ tsvector_unnest(PG_FUNCTION_ARGS)
             }

             values[1] = PointerGetDatum(construct_array(positions, posv->npos,
-                                                        INT2OID, 2, true, 's'));
+                                                        INT2OID, 2, true, TYPALIGN_SHORT));
             values[2] = PointerGetDatum(construct_array(weights, posv->npos,
-                                                        TEXTOID, -1, false, 'i'));
+                                                        TEXTOID, -1, false, TYPALIGN_INT));
         }
         else
         {
@@ -731,7 +731,7 @@ tsvector_to_array(PG_FUNCTION_ARGS)
                                                                arrin[i].len));
     }

-    array = construct_array(elements, tsin->size, TEXTOID, -1, false, 'i');
+    array = construct_array(elements, tsin->size, TEXTOID, -1, false, TYPALIGN_INT);

     pfree(elements);
     PG_FREE_IF_COPY(tsin, 0);
@@ -755,7 +755,7 @@ array_to_tsvector(PG_FUNCTION_ARGS)
                 datalen = 0;
     char       *cur;

-    deconstruct_array(v, TEXTOID, -1, false, 'i', &dlexemes, &nulls, &nitems);
+    deconstruct_array(v, TEXTOID, -1, false, TYPALIGN_INT, &dlexemes, &nulls, &nitems);

     /* Reject nulls (maybe we should just ignore them, instead?) */
     for (i = 0; i < nitems; i++)
@@ -823,7 +823,7 @@ tsvector_filter(PG_FUNCTION_ARGS)
     int            cur_pos = 0;
     char        mask = 0;

-    deconstruct_array(weights, CHAROID, 1, true, 'c',
+    deconstruct_array(weights, CHAROID, 1, true, TYPALIGN_CHAR,
                       &dweights, &nulls, &nweights);

     for (i = 0; i < nweights; i++)
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index 18900e0..907b5ab 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -4754,7 +4754,7 @@ text_to_array_internal(PG_FUNCTION_ARGS)
             /* XXX: this hardcodes assumptions about the text type */
             PG_RETURN_ARRAYTYPE_P(construct_md_array(elems, nulls,
                                                      1, dims, lbs,
-                                                     TEXTOID, -1, false, 'i'));
+                                                     TEXTOID, -1, false, TYPALIGN_INT));
         }

         text_position_setup(inputstring, fldsep, PG_GET_COLLATION(), &state);
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index 3808c30..c7ae1ed 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -4036,7 +4036,7 @@ xpath_internal(text *xpath_expr_text, xmltype *data, ArrayType *namespaces,

         Assert(ARR_ELEMTYPE(namespaces) == TEXTOID);

-        deconstruct_array(namespaces, TEXTOID, -1, false, 'i',
+        deconstruct_array(namespaces, TEXTOID, -1, false, TYPALIGN_INT,
                           &ns_names_uris, &ns_names_uris_nulls,
                           &ns_count);

diff --git a/src/backend/utils/cache/evtcache.c b/src/backend/utils/cache/evtcache.c
index b9c1a0a..73d091d 100644
--- a/src/backend/utils/cache/evtcache.c
+++ b/src/backend/utils/cache/evtcache.c
@@ -230,7 +230,8 @@ DecodeTextArrayToBitmapset(Datum array)

     if (ARR_NDIM(arr) != 1 || ARR_HASNULL(arr) || ARR_ELEMTYPE(arr) != TEXTOID)
         elog(ERROR, "expected 1-D text array");
-    deconstruct_array(arr, TEXTOID, -1, false, 'i', &elems, NULL, &nelems);
+    deconstruct_array(arr, TEXTOID, -1, false, TYPALIGN_INT,
+                      &elems, NULL, &nelems);

     for (bms = NULL, i = 0; i < nelems; ++i)
     {
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index fb0599f..3da90cb 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -2189,7 +2189,7 @@ get_typalign(Oid typid)
         return result;
     }
     else
-        return 'i';
+        return TYPALIGN_INT;
 }
 #endif

@@ -2209,7 +2209,7 @@ get_typstorage(Oid typid)
         return result;
     }
     else
-        return 'p';
+        return TYPSTORAGE_PLAIN;
 }

 /*
diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c
index b7eee3d..0201e4f 100644
--- a/src/backend/utils/fmgr/funcapi.c
+++ b/src/backend/utils/fmgr/funcapi.c
@@ -917,7 +917,7 @@ get_func_arg_info(HeapTuple procTup,
     else
     {
         deconstruct_array(DatumGetArrayTypeP(proargnames),
-                          TEXTOID, -1, false, 'i',
+                          TEXTOID, -1, false, TYPALIGN_INT,
                           &elems, NULL, &nelems);
         if (nelems != numargs)    /* should not happen */
             elog(ERROR, "proargnames must have the same number of elements as the function has arguments");
@@ -1030,7 +1030,7 @@ get_func_input_arg_names(Datum proargnames, Datum proargmodes,
         ARR_HASNULL(arr) ||
         ARR_ELEMTYPE(arr) != TEXTOID)
         elog(ERROR, "proargnames is not a 1-D text array");
-    deconstruct_array(arr, TEXTOID, -1, false, 'i',
+    deconstruct_array(arr, TEXTOID, -1, false, TYPALIGN_INT,
                       &argnames, NULL, &numargs);
     if (proargmodes != PointerGetDatum(NULL))
     {
@@ -1143,7 +1143,7 @@ get_func_result_name(Oid functionId)
             ARR_HASNULL(arr) ||
             ARR_ELEMTYPE(arr) != TEXTOID)
             elog(ERROR, "proargnames is not a 1-D text array");
-        deconstruct_array(arr, TEXTOID, -1, false, 'i',
+        deconstruct_array(arr, TEXTOID, -1, false, TYPALIGN_INT,
                           &argnames, NULL, &nargnames);
         Assert(nargnames == numargs);

@@ -1290,7 +1290,7 @@ build_function_result_tupdesc_d(char prokind,
             ARR_HASNULL(arr) ||
             ARR_ELEMTYPE(arr) != TEXTOID)
             elog(ERROR, "proargnames is not a 1-D text array");
-        deconstruct_array(arr, TEXTOID, -1, false, 'i',
+        deconstruct_array(arr, TEXTOID, -1, false, TYPALIGN_INT,
                           &argnames, NULL, &nargnames);
         Assert(nargnames == numargs);
     }
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 464f264..dbecc00 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -10470,7 +10470,7 @@ ProcessGUCArray(ArrayType *array,
                       -1 /* varlenarray */ ,
                       -1 /* TEXT's typlen */ ,
                       false /* TEXT's typbyval */ ,
-                      'i' /* TEXT's typalign */ ,
+                      TYPALIGN_INT /* TEXT's typalign */ ,
                       &isnull);

         if (isnull)
@@ -10549,7 +10549,7 @@ GUCArrayAdd(ArrayType *array, const char *name, const char *value)
                           -1 /* varlenarray */ ,
                           -1 /* TEXT's typlen */ ,
                           false /* TEXT's typbyval */ ,
-                          'i' /* TEXT's typalign */ ,
+                          TYPALIGN_INT /* TEXT's typalign */ ,
                           &isnull);
             if (isnull)
                 continue;
@@ -10569,12 +10569,12 @@ GUCArrayAdd(ArrayType *array, const char *name, const char *value)
                       -1 /* varlena array */ ,
                       -1 /* TEXT's typlen */ ,
                       false /* TEXT's typbyval */ ,
-                      'i' /* TEXT's typalign */ );
+                      TYPALIGN_INT /* TEXT's typalign */ );
     }
     else
         a = construct_array(&datum, 1,
                             TEXTOID,
-                            -1, false, 'i');
+                            -1, false, TYPALIGN_INT);

     return a;
 }
@@ -10620,7 +10620,7 @@ GUCArrayDelete(ArrayType *array, const char *name)
                       -1 /* varlenarray */ ,
                       -1 /* TEXT's typlen */ ,
                       false /* TEXT's typbyval */ ,
-                      'i' /* TEXT's typalign */ ,
+                      TYPALIGN_INT /* TEXT's typalign */ ,
                       &isnull);
         if (isnull)
             continue;
@@ -10639,11 +10639,11 @@ GUCArrayDelete(ArrayType *array, const char *name)
                                  -1 /* varlenarray */ ,
                                  -1 /* TEXT's typlen */ ,
                                  false /* TEXT's typbyval */ ,
-                                 'i' /* TEXT's typalign */ );
+                                 TYPALIGN_INT /* TEXT's typalign */ );
         else
             newarray = construct_array(&d, 1,
                                        TEXTOID,
-                                       -1, false, 'i');
+                                       -1, false, TYPALIGN_INT);

         index++;
     }
@@ -10686,7 +10686,7 @@ GUCArrayReset(ArrayType *array)
                       -1 /* varlenarray */ ,
                       -1 /* TEXT's typlen */ ,
                       false /* TEXT's typbyval */ ,
-                      'i' /* TEXT's typalign */ ,
+                      TYPALIGN_INT /* TEXT's typalign */ ,
                       &isnull);
         if (isnull)
             continue;
@@ -10707,11 +10707,11 @@ GUCArrayReset(ArrayType *array)
                                  -1 /* varlenarray */ ,
                                  -1 /* TEXT's typlen */ ,
                                  false /* TEXT's typbyval */ ,
-                                 'i' /* TEXT's typalign */ );
+                                 TYPALIGN_INT /* TEXT's typalign */ );
         else
             newarray = construct_array(&d, 1,
                                        TEXTOID,
-                                       -1, false, 'i');
+                                       -1, false, TYPALIGN_INT);

         index++;
         pfree(val);
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index ef15390..caa25e3 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -10756,22 +10756,22 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo)
         appendStringLiteralAH(q, typdelim, fout);
     }

-    if (strcmp(typalign, "c") == 0)
+    if (*typalign == TYPALIGN_CHAR)
         appendPQExpBufferStr(q, ",\n    ALIGNMENT = char");
-    else if (strcmp(typalign, "s") == 0)
+    else if (*typalign == TYPALIGN_SHORT)
         appendPQExpBufferStr(q, ",\n    ALIGNMENT = int2");
-    else if (strcmp(typalign, "i") == 0)
+    else if (*typalign == TYPALIGN_INT)
         appendPQExpBufferStr(q, ",\n    ALIGNMENT = int4");
-    else if (strcmp(typalign, "d") == 0)
+    else if (*typalign == TYPALIGN_DOUBLE)
         appendPQExpBufferStr(q, ",\n    ALIGNMENT = double");

-    if (strcmp(typstorage, "p") == 0)
+    if (*typstorage == TYPSTORAGE_PLAIN)
         appendPQExpBufferStr(q, ",\n    STORAGE = plain");
-    else if (strcmp(typstorage, "e") == 0)
+    else if (*typstorage == TYPSTORAGE_EXTERNAL)
         appendPQExpBufferStr(q, ",\n    STORAGE = external");
-    else if (strcmp(typstorage, "x") == 0)
+    else if (*typstorage == TYPSTORAGE_EXTENDED)
         appendPQExpBufferStr(q, ",\n    STORAGE = extended");
-    else if (strcmp(typstorage, "m") == 0)
+    else if (*typstorage == TYPSTORAGE_MAIN)
         appendPQExpBufferStr(q, ",\n    STORAGE = main");

     if (strcmp(typbyval, "t") == 0)
@@ -16129,18 +16129,18 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
             {
                 switch (tbinfo->attstorage[j])
                 {
-                    case 'p':
+                    case TYPSTORAGE_PLAIN:
                         storage = "PLAIN";
                         break;
-                    case 'e':
+                    case TYPSTORAGE_EXTERNAL:
                         storage = "EXTERNAL";
                         break;
-                    case 'm':
-                        storage = "MAIN";
-                        break;
-                    case 'x':
+                    case TYPSTORAGE_EXTENDED:
                         storage = "EXTENDED";
                         break;
+                    case TYPSTORAGE_MAIN:
+                        storage = "MAIN";
+                        break;
                     default:
                         storage = NULL;
                 }
diff --git a/src/include/access/toast_helper.h b/src/include/access/toast_helper.h
index e59138d..0e92acc 100644
--- a/src/include/access/toast_helper.h
+++ b/src/include/access/toast_helper.h
@@ -20,12 +20,12 @@
  * Information about one column of a tuple being toasted.
  *
  * NOTE: toast_action[i] can have these values:
- *        ' '        default handling
- *        'p'        already processed --- don't touch it
- *        'x'        incompressible, but OK to move off
+ *        ' '                        default handling
+ *        TYPSTORAGE_PLAIN        already processed --- don't touch it
+ *        TYPSTORAGE_EXTENDED        incompressible, but OK to move off
  *
  * NOTE: toast_attr[i].tai_size is only made valid for varlena attributes with
- * toast_action[i] different from 'p'.
+ * toast_action[i] different from TYPSTORAGE_PLAIN.
  */
 typedef struct
 {
diff --git a/src/include/access/tupmacs.h b/src/include/access/tupmacs.h
index 0b205a0..70157cf 100644
--- a/src/include/access/tupmacs.h
+++ b/src/include/access/tupmacs.h
@@ -14,6 +14,8 @@
 #ifndef TUPMACS_H
 #define TUPMACS_H

+#include "catalog/pg_type_d.h"    /* for TYPALIGN macros */
+

 /*
  * Check a tuple's null bitmap to determine whether the attribute is null.
@@ -145,11 +147,11 @@
  */
 #define att_align_nominal(cur_offset, attalign) \
 ( \
-    ((attalign) == 'i') ? INTALIGN(cur_offset) : \
-     (((attalign) == 'c') ? (uintptr_t) (cur_offset) : \
-      (((attalign) == 'd') ? DOUBLEALIGN(cur_offset) : \
+    ((attalign) == TYPALIGN_INT) ? INTALIGN(cur_offset) : \
+     (((attalign) == TYPALIGN_CHAR) ? (uintptr_t) (cur_offset) : \
+      (((attalign) == TYPALIGN_DOUBLE) ? DOUBLEALIGN(cur_offset) : \
        ( \
-            AssertMacro((attalign) == 's'), \
+            AssertMacro((attalign) == TYPALIGN_SHORT), \
             SHORTALIGN(cur_offset) \
        ))) \
 )
diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h
index 591e0d6..a4cc80a 100644
--- a/src/include/catalog/pg_attribute.h
+++ b/src/include/catalog/pg_attribute.h
@@ -110,14 +110,7 @@ CATALOG(pg_attribute,1249,AttributeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(75,
     /*----------
      * attstorage tells for VARLENA attributes, what the heap access
      * methods can do to it if a given tuple doesn't fit into a page.
-     * Possible values are
-     *        'p': Value must be stored plain always
-     *        'e': Value can be stored in "secondary" relation (if relation
-     *             has one, see pg_class.reltoastrelid)
-     *        'm': Value can be stored compressed inline
-     *        'x': Value can be stored compressed inline or in "secondary"
-     * Note that 'm' fields can also be moved out to secondary storage,
-     * but only as a last resort ('e' and 'x' fields are moved first).
+     * Possible values are as for pg_type.typstorage (see TYPSTORAGE macros).
      *----------
      */
     char        attstorage;
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index e1a5ab3..f972f94 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -155,6 +155,7 @@ CATALOG(pg_type,1247,TypeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71,TypeRelati
      * 's' = SHORT alignment (2 bytes on most machines).
      * 'i' = INT alignment (4 bytes on most machines).
      * 'd' = DOUBLE alignment (8 bytes on many machines, but by no means all).
+     * (Use the TYPALIGN macros below for these.)
      *
      * See include/access/tupmacs.h for the macros that compute these
      * alignment requirements.  Note also that we allow the nominal alignment
@@ -176,6 +177,10 @@ CATALOG(pg_type,1247,TypeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71,TypeRelati
      * 'e' EXTERNAL   external storage possible, don't try to compress
      * 'x' EXTENDED   try to compress and store external if required
      * 'm' MAIN          like 'x' but try to keep in main tuple
+     * (Use the TYPSTORAGE macros below for these.)
+     *
+     * Note that 'm' fields can also be moved out to secondary storage,
+     * but only as a last resort ('e' and 'x' fields are moved first).
      * ----------------
      */
     char        typstorage BKI_DEFAULT(p) BKI_ARRAY_DEFAULT(x);
@@ -278,6 +283,16 @@ typedef FormData_pg_type *Form_pg_type;
 #define  TYPCATEGORY_BITSTRING    'V' /* er ... "varbit"? */
 #define  TYPCATEGORY_UNKNOWN    'X'

+#define  TYPALIGN_CHAR            'c' /* char alignment (i.e. unaligned) */
+#define  TYPALIGN_SHORT            's' /* short alignment (typically 2 bytes) */
+#define  TYPALIGN_INT            'i' /* int alignment (typically 4 bytes) */
+#define  TYPALIGN_DOUBLE        'd' /* double alignment (often 8 bytes) */
+
+#define  TYPSTORAGE_PLAIN        'p' /* type not prepared for toasting */
+#define  TYPSTORAGE_EXTERNAL    'e' /* toastable, don't try to compress */
+#define  TYPSTORAGE_EXTENDED    'x' /* fully toastable */
+#define  TYPSTORAGE_MAIN        'm' /* like 'x' but try to store inline */
+
 /* Is a type OID a polymorphic pseudotype?    (Beware of multiple evaluation) */
 #define IsPolymorphicType(typid)  \
     ((typid) == ANYELEMENTOID || \
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index 370f62a..f132d39 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -186,6 +186,6 @@ extern Oid    get_index_column_opclass(Oid index_oid, int attno);
 /* type_is_array_domain accepts both plain arrays and domains over arrays */
 #define type_is_array_domain(typid)  (get_base_element_type(typid) != InvalidOid)

-#define TypeIsToastable(typid)    (get_typstorage(typid) != 'p')
+#define TypeIsToastable(typid)    (get_typstorage(typid) != TYPSTORAGE_PLAIN)

 #endif                            /* LSYSCACHE_H */
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 4f6b36b..c8e43e6 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -2125,13 +2125,13 @@ build_datatype(HeapTuple typeTup, int32 typmod,
          */
         typ->typisarray = (typeStruct->typlen == -1 &&
                            OidIsValid(typeStruct->typelem) &&
-                           typeStruct->typstorage != 'p');
+                           typeStruct->typstorage != TYPSTORAGE_PLAIN);
     }
     else if (typeStruct->typtype == TYPTYPE_DOMAIN)
     {
         /* we can short-circuit looking up base types if it's not varlena */
         typ->typisarray = (typeStruct->typlen == -1 &&
-                           typeStruct->typstorage != 'p' &&
+                           typeStruct->typstorage != TYPSTORAGE_PLAIN &&
                            OidIsValid(get_base_element_type(typeStruct->typbasetype)));
     }
     else
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index a867c2c..d3ad4fa 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -1456,7 +1456,7 @@ plpgsql_fulfill_promise(PLpgSQL_execstate *estate,
                                   PointerGetDatum(construct_md_array(elems, NULL,
                                                                      1, dims, lbs,
                                                                      TEXTOID,
-                                                                     -1, false, 'i')),
+                                                                     -1, false, TYPALIGN_INT)),
                                   false, true);
             }
             else
diff --git a/src/pl/plpython/plpy_typeio.c b/src/pl/plpython/plpy_typeio.c
index e734b0d..7c844c2 100644
--- a/src/pl/plpython/plpy_typeio.c
+++ b/src/pl/plpython/plpy_typeio.c
@@ -328,7 +328,7 @@ PLy_output_setup_func(PLyObToDatum *arg, MemoryContext arg_mcxt,
         /* hard-wired knowledge about type RECORD: */
         arg->typbyval = false;
         arg->typlen = -1;
-        arg->typalign = 'd';
+        arg->typalign = TYPALIGN_DOUBLE;
     }

     /*
@@ -451,7 +451,7 @@ PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt,
         /* hard-wired knowledge about type RECORD: */
         arg->typbyval = false;
         arg->typlen = -1;
-        arg->typalign = 'd';
+        arg->typalign = TYPALIGN_DOUBLE;
     }

     /*
diff --git a/src/test/modules/test_rls_hooks/test_rls_hooks.c b/src/test/modules/test_rls_hooks/test_rls_hooks.c
index d1b7075..0bfa878 100644
--- a/src/test/modules/test_rls_hooks/test_rls_hooks.c
+++ b/src/test/modules/test_rls_hooks/test_rls_hooks.c
@@ -87,7 +87,7 @@ test_rls_hooks_permissive(CmdType cmdtype, Relation relation)

     policy->policy_name = pstrdup("extension policy");
     policy->polcmd = '*';
-    policy->roles = construct_array(&role, 1, OIDOID, sizeof(Oid), true, 'i');
+    policy->roles = construct_array(&role, 1, OIDOID, sizeof(Oid), true, TYPALIGN_INT);

     /*
      * policy->qual = (Expr *) makeConst(BOOLOID, -1, InvalidOid,
@@ -152,7 +152,7 @@ test_rls_hooks_restrictive(CmdType cmdtype, Relation relation)

     policy->policy_name = pstrdup("extension policy");
     policy->polcmd = '*';
-    policy->roles = construct_array(&role, 1, OIDOID, sizeof(Oid), true, 'i');
+    policy->roles = construct_array(&role, 1, OIDOID, sizeof(Oid), true, TYPALIGN_INT);

     n = makeFuncCall(list_make2(makeString("pg_catalog"),
                                 makeString("current_user")), NIL, 0);

pgsql-hackers by date:

Previous
From: David Zhang
Date:
Subject: Re: Fastpath while arranging the changes in LSN order in logicaldecoding
Next
From: Tomas Vondra
Date:
Subject: Re: PATCH: logical_work_mem and logical streaming of largein-progress transactions