Expand AclMode to 64 bits
authorAndrew Dunstan <[email protected]>
Wed, 23 Nov 2022 19:41:30 +0000 (14:41 -0500)
committerAndrew Dunstan <[email protected]>
Wed, 23 Nov 2022 19:43:16 +0000 (14:43 -0500)
We're running out of bits for new permissions. This change doubles the
number of permissions we can accomodate from 16 to 32, so the
forthcoming new ones for vacuum/analyze don't exhaust the pool.

Nathan Bossart

Reviewed by: Bharath Rupireddy, Kyotaro Horiguchi, Stephen Frost, Robert
Haas, Mark Dilger, Tom Lane, Corey Huinker, David G. Johnston, Michael
Paquier.

Discussion: https://postgr.es/m/20220722203735.GB3996698@nathanxps13

src/backend/nodes/outfuncs.c
src/bin/pg_upgrade/check.c
src/include/catalog/catversion.h
src/include/catalog/pg_type.dat
src/include/nodes/parsenodes.h
src/include/utils/acl.h

index f05e72f0dc3d0956f707fd2a7bf6b89f8deb64ba..8f150e9a2e89f0132a9f53e001b111fda57a6a04 100644 (file)
@@ -560,7 +560,7 @@ _outRangeTblEntry(StringInfo str, const RangeTblEntry *node)
    WRITE_BOOL_FIELD(lateral);
    WRITE_BOOL_FIELD(inh);
    WRITE_BOOL_FIELD(inFromCl);
-   WRITE_UINT_FIELD(requiredPerms);
+   WRITE_UINT64_FIELD(requiredPerms);
    WRITE_OID_FIELD(checkAsUser);
    WRITE_BITMAPSET_FIELD(selectedCols);
    WRITE_BITMAPSET_FIELD(insertedCols);
index f1bc1e688680ea42b15c7936bf9d657e82c84953..615a53a86488dcf351e4f1e834d02735ab374232 100644 (file)
@@ -28,6 +28,7 @@ static void check_for_incompatible_polymorphics(ClusterInfo *cluster);
 static void check_for_tables_with_oids(ClusterInfo *cluster);
 static void check_for_composite_data_type_usage(ClusterInfo *cluster);
 static void check_for_reg_data_type_usage(ClusterInfo *cluster);
+static void check_for_aclitem_data_type_usage(ClusterInfo *cluster);
 static void check_for_jsonb_9_4_usage(ClusterInfo *cluster);
 static void check_for_pg_role_prefix(ClusterInfo *cluster);
 static void check_for_new_tablespace_dir(ClusterInfo *new_cluster);
@@ -107,6 +108,13 @@ check_and_dump_old_cluster(bool live_check)
    check_for_reg_data_type_usage(&old_cluster);
    check_for_isn_and_int8_passing_mismatch(&old_cluster);
 
+   /*
+    * PG 16 increased the size of the 'aclitem' type, which breaks the on-disk
+    * format for existing data.
+    */
+   if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1500)
+       check_for_aclitem_data_type_usage(&old_cluster);
+
    /*
     * PG 14 changed the function signature of encoding conversion functions.
     * Conversions from older versions cannot be upgraded automatically
@@ -1319,6 +1327,33 @@ check_for_reg_data_type_usage(ClusterInfo *cluster)
        check_ok();
 }
 
+/*
+ * check_for_aclitem_data_type_usage
+ *
+ * aclitem changed its storage format in 16, so check for it.
+ */
+static void
+check_for_aclitem_data_type_usage(ClusterInfo *cluster)
+{
+   char        output_path[MAXPGPATH];
+
+   prep_status("Checking for incompatible aclitem data type in user tables");
+
+   snprintf(output_path, sizeof(output_path), "tables_using_aclitem.txt");
+
+   if (check_for_data_type_usage(cluster, "pg_catalog.aclitem", output_path))
+   {
+       pg_log(PG_REPORT, "fatal");
+       pg_fatal("Your installation contains the \"aclitem\" data type in user tables.\n"
+                "The internal format of \"aclitem\" changed in PostgreSQL version 16\n"
+                "so this cluster cannot currently be upgraded.  You can drop the\n"
+                "problem columns and restart the upgrade.  A list of the problem\n"
+                "columns is in the file:\n"
+                "    %s", output_path);
+   }
+   else
+       check_ok();
+}
 
 /*
  * check_for_jsonb_9_4_usage()
index 49e9dc4a94b03ed5a8c80eaadc6cb5902183da4a..94da0ee1d744579e15e11db9264c02ad272f64bf 100644 (file)
@@ -57,6 +57,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 202211211
+#define CATALOG_VERSION_NO 202211221
 
 #endif
index df458794635700c2d78d52d1366f31e2b2b5f54a..0763dfde3942e5e9e6309289e5f8006fa709bd83 100644 (file)
 # OIDS 1000 - 1099
 
 { oid => '1033', array_type_oid => '1034', descr => 'access control list',
-  typname => 'aclitem', typlen => '12', typbyval => 'f', typcategory => 'U',
+  typname => 'aclitem', typlen => '16', typbyval => 'f', typcategory => 'U',
   typinput => 'aclitemin', typoutput => 'aclitemout', typreceive => '-',
-  typsend => '-', typalign => 'i' },
+  typsend => '-', typalign => 'd' },
 { oid => '1042', array_type_oid => '1014',
   descr => 'char(length), blank-padded string, fixed storage length',
   typname => 'bpchar', typlen => '-1', typbyval => 'f', typcategory => 'S',
index 7caff62af7f348f790ea2a6050393b64e2306608..f4ed9bbff912fa6c286079b10660397304fe4854 100644 (file)
@@ -73,12 +73,12 @@ typedef enum SetQuantifier
 
 /*
  * Grantable rights are encoded so that we can OR them together in a bitmask.
- * The present representation of AclItem limits us to 16 distinct rights,
- * even though AclMode is defined as uint32.  See utils/acl.h.
+ * The present representation of AclItem limits us to 32 distinct rights,
+ * even though AclMode is defined as uint64.  See utils/acl.h.
  *
  * Caution: changing these codes breaks stored ACLs, hence forces initdb.
  */
-typedef uint32 AclMode;            /* a bitmask of privilege bits */
+typedef uint64 AclMode;            /* a bitmask of privilege bits */
 
 #define ACL_INSERT     (1<<0)  /* for relations */
 #define ACL_SELECT     (1<<1)
index afbfdccf53c71ed61c129a79b4626fc640f4ddbf..406071037e26696aaac6f0a533086bdb48adc2fb 100644 (file)
@@ -59,33 +59,33 @@ typedef struct AclItem
 } AclItem;
 
 /*
- * The upper 16 bits of the ai_privs field of an AclItem are the grant option
- * bits, and the lower 16 bits are the actual privileges.  We use "rights"
+ * The upper 32 bits of the ai_privs field of an AclItem are the grant option
+ * bits, and the lower 32 bits are the actual privileges.  We use "rights"
  * to mean the combined grant option and privilege bits fields.
  */
-#define ACLITEM_GET_PRIVS(item)    ((item).ai_privs & 0xFFFF)
-#define ACLITEM_GET_GOPTIONS(item) (((item).ai_privs >> 16) & 0xFFFF)
+#define ACLITEM_GET_PRIVS(item)    ((item).ai_privs & 0xFFFFFFFF)
+#define ACLITEM_GET_GOPTIONS(item) (((item).ai_privs >> 32) & 0xFFFFFFFF)
 #define ACLITEM_GET_RIGHTS(item)   ((item).ai_privs)
 
-#define ACL_GRANT_OPTION_FOR(privs) (((AclMode) (privs) & 0xFFFF) << 16)
-#define ACL_OPTION_TO_PRIVS(privs) (((AclMode) (privs) >> 16) & 0xFFFF)
+#define ACL_GRANT_OPTION_FOR(privs) (((AclMode) (privs) & 0xFFFFFFFF) << 32)
+#define ACL_OPTION_TO_PRIVS(privs) (((AclMode) (privs) >> 32) & 0xFFFFFFFF)
 
 #define ACLITEM_SET_PRIVS(item,privs) \
-  ((item).ai_privs = ((item).ai_privs & ~((AclMode) 0xFFFF)) | \
-                    ((AclMode) (privs) & 0xFFFF))
+  ((item).ai_privs = ((item).ai_privs & ~((AclMode) 0xFFFFFFFF)) | \
+                    ((AclMode) (privs) & 0xFFFFFFFF))
 #define ACLITEM_SET_GOPTIONS(item,goptions) \
-  ((item).ai_privs = ((item).ai_privs & ~(((AclMode) 0xFFFF) << 16)) | \
-                    (((AclMode) (goptions) & 0xFFFF) << 16))
+  ((item).ai_privs = ((item).ai_privs & ~(((AclMode) 0xFFFFFFFF) << 32)) | \
+                    (((AclMode) (goptions) & 0xFFFFFFFF) << 32))
 #define ACLITEM_SET_RIGHTS(item,rights) \
   ((item).ai_privs = (AclMode) (rights))
 
 #define ACLITEM_SET_PRIVS_GOPTIONS(item,privs,goptions) \
-  ((item).ai_privs = ((AclMode) (privs) & 0xFFFF) | \
-                    (((AclMode) (goptions) & 0xFFFF) << 16))
+  ((item).ai_privs = ((AclMode) (privs) & 0xFFFFFFFF) | \
+                    (((AclMode) (goptions) & 0xFFFFFFFF) << 32))
 
 
-#define ACLITEM_ALL_PRIV_BITS      ((AclMode) 0xFFFF)
-#define ACLITEM_ALL_GOPTION_BITS   ((AclMode) 0xFFFF << 16)
+#define ACLITEM_ALL_PRIV_BITS      ((AclMode) 0xFFFFFFFF)
+#define ACLITEM_ALL_GOPTION_BITS   ((AclMode) 0xFFFFFFFF << 32)
 
 /*
  * Definitions for convenient access to Acl (array of AclItem).