Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vWETf-00Fdwf-0b for pgsql-hackers@arkaria.postgresql.org; Thu, 18 Dec 2025 13:55:36 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vWETc-002Osl-3C for pgsql-hackers@arkaria.postgresql.org; Thu, 18 Dec 2025 13:55:33 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vWETc-002Osb-1R for pgsql-hackers@lists.postgresql.org; Thu, 18 Dec 2025 13:55:33 +0000 Received: from mail-wm1-x32f.google.com ([2a00:1450:4864:20::32f]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1vWETa-001L4Q-06 for pgsql-hackers@lists.postgresql.org; Thu, 18 Dec 2025 13:55:32 +0000 Received: by mail-wm1-x32f.google.com with SMTP id 5b1f17b1804b1-47775fb6cb4so4586085e9.0 for ; Thu, 18 Dec 2025 05:55:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1766066126; x=1766670926; darn=lists.postgresql.org; h=content-disposition:mime-version:message-id:subject:to:from:date :from:to:cc:subject:date:message-id:reply-to; bh=MBSoDMwc0QSC4WB+KmvElWDeJGi0doURdHAOxg+MkC0=; b=PPCo989wmvKENrTlB15faEXaV61paTPm/YPrrzGavLpu4VDw4y0c1O2dswtmjEWlB/ c0aqE+q7gHNLKnbRpERcQRIo/itP2kQJZhsvB+CPG6+p9NJDtOowVu0A4O2Hu2JVY3df sIKcXbOieze9RFMix+AcTELrsMQG/kk6ircmjVKAOpf4qt/qFGnVW8ZYeVX0xz4VX/LP OwR5BqeuNyU627UFu+eCMPHP/RQP737qU/vfPBeEsqLNB0MIKecp5F+mH9JlXaEXuocG 2K+xNXsFOxA+e9U9vW9qH5iIbaJBQg8SfA50bt6AqK6/wKcU++RaxrIsJF9YzOdRqYye BX/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1766066126; x=1766670926; h=content-disposition:mime-version:message-id:subject:to:from:date :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=MBSoDMwc0QSC4WB+KmvElWDeJGi0doURdHAOxg+MkC0=; b=imAyEpwnt4SrDi+nlT+2RsjndWIgdOu8tf9YCs1qiw67UjP9K4gFG4cxzeNSKH13rQ o37dvRsHuxRZQ/uEYLjmWmjemB5tbuAxUK/cBk2uEMFVLQMk3kGE4i3tMQU+Hnz15zHT zUGb5EyVeeEBED1SqqHsvFiZlDn8NJS0pf2dV2orqwMYoHUt75gHjfO08j7KcyK1TWHw E7ZBBOHEIUXcXd8wNiVlUgzN1GVMaJuwX82R0pfdSaBJb67bDkJ6dl2WXW22VMeGQ2tv cZTNpbo6Pur3L3czIm1k/5QbaHJgtjNeM90lLVyumHiWmCBVsv2ecxh2wMdkLQ8+Sqzq 6U+g== X-Gm-Message-State: AOJu0YxJUUermkxDKr4IvfU2jVj3E+/zrvJu2dVF/H4492CHFf4Ftpug wp/RFem0lOo33gl3PJnmHM+yZGzNd8yXu7hrnSIOIm1l1xc4yEgc5rq/aNWKXw== X-Gm-Gg: AY/fxX52Zf0D2khRZkKE/eOt8OenDl4rZECfrAfhXNKXpg4D8S3DUqF7OmQ1nXOrIqF sdYFeLp408A2ZEaLni1m2emaq3KB7e4RyIQORg9hEr7IXTjkd5pjtbPdNFqVYCwhC9VhcbN3sK6 vtwOliO2EWtDuL2pdBylKgEDoILO69c/a6aNVYq/1cachzQBBIJIZbszH7nnkAPh2Tn0eh+3Di+ 1njsqAF6AOTWn8IVrZXXfYLxAWunvExymeEeIKvQvBg8sRAmptYw2TDmpadhARr9Fqi4rhPlODQ J8QRSB0sErNHtVF8LhbKWD+Ex2oDH2b2d8QiszGPvRTjStx2hkv/p0WTlpjXZzJtY+ZDOcCVq1+ MArAGOIT7+0lUJwEiqtw+qHmWBllUtk5b1SkL29JrC/1iM4fBL0ERB2O4MvY/eXKqxap92Xhz04 2j7f7QlJUkZDDwSgLDCF211Ck41OHAqELvWxK4NkvxIYIz7rUaJGt1IZBGTyWtWw97BKT+pJfOD A6DT2RNl8VfRMxPOM8LzsAKb2nwv/8eR0LWCfF8jUDoY6dZAY+rSMLO X-Google-Smtp-Source: AGHT+IHuLXPJr7wdE0vZ0QeVEBQig5OJB/aUGqAfw64HQodlKrIzGMLVOinnGvsakKKwgp6UOztq8g== X-Received: by 2002:a05:600c:4f56:b0:475:de14:db1e with SMTP id 5b1f17b1804b1-47a8f9055edmr240927355e9.24.1766066125658; Thu, 18 Dec 2025 05:55:25 -0800 (PST) Received: from ip-10-97-1-34.eu-west-3.compute.internal (ec2-15-237-197-144.eu-west-3.compute.amazonaws.com. [15.237.197.144]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-47be3017fa3sm38826795e9.2.2025.12.18.05.55.24 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Dec 2025 05:55:25 -0800 (PST) Date: Thu, 18 Dec 2025 13:55:23 +0000 From: Bertrand Drouvot To: pgsql-hackers@lists.postgresql.org Subject: Don't cast away const where possible Message-ID: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="jEYXENy/7KdvfqDm" Content-Disposition: inline List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --jEYXENy/7KdvfqDm Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi hackers, Some functions are casting away the const qualifiers from their signatures in local variables. These 3 patches add const to read only local variables, preserving the const qualifiers from the function signatures. 0001: those are simple changes in 6 files (16 changes in total) 0002: Add const to read only TableInfo pointers in pg_dump Functions that dump table data receive their parameters through const void * but were casting away const. Add const qualifiers to functions that only read the table information. Also change getRootTableInfo to return const TableInfo *, since it only traverses the parent chain without modifying any TableInfo structures. This allows the dump functions to maintain const correctness when calling it. 0003: Separate read and write pointers in pg_saslprep Use separate pointers for reading const input ('p') and writing to mutable output ('outp'), avoiding the need to cast away const on the input parameter. It has been done with the help of [1], but not all the changes proposed by it have been implemented. Indeed, I did some filtering and decided not to change the ones that: - are just thin wrappers - would require public API changes - rely on external functions (such as LZ4F_compressUpdate()) - would require changes beyond the scope of this cleanup [1]: https://github.com/bdrouvot/coccinelle_on_pg/blob/main/misc/search_const_away.cocci Thoughts? Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com --jEYXENy/7KdvfqDm Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v1-0001-Don-t-cast-away-const-where-possible.patch" From f65cb5dfdf8208282ae3a924f33a9df7677ba8ca Mon Sep 17 00:00:00 2001 From: Bertrand Drouvot Date: Thu, 18 Dec 2025 09:51:01 +0000 Subject: [PATCH v1 1/3] Don't cast away const where possible Add const to read only local variables, preserving the const qualifiers from the function signatures. This does not change all such instances, but only those hand-picked by the author. The ones that are not changed: - are just thin wrappers - would require public API changes - rely on external functions (such as LZ4F_compressUpdate()) - would require complex subsystem changes --- src/backend/access/brin/brin_minmax_multi.c | 4 ++-- src/backend/access/heap/pruneheap.c | 4 ++-- src/backend/access/spgist/spgkdtreeproc.c | 8 ++++---- src/backend/statistics/mcv.c | 4 ++-- src/backend/tsearch/spell.c | 4 ++-- src/test/modules/injection_points/injection_points.c | 8 ++++---- 6 files changed, 16 insertions(+), 16 deletions(-) 10.8% src/backend/access/brin/ 12.8% src/backend/access/heap/ 19.8% src/backend/access/spgist/ 8.8% src/backend/statistics/ 11.2% src/backend/tsearch/ 36.2% src/test/modules/injection_points/ diff --git a/src/backend/access/brin/brin_minmax_multi.c b/src/backend/access/brin/brin_minmax_multi.c index 0298a9da8ba..a2d72aa1791 100644 --- a/src/backend/access/brin/brin_minmax_multi.c +++ b/src/backend/access/brin/brin_minmax_multi.c @@ -1304,8 +1304,8 @@ merge_overlapping_ranges(FmgrInfo *cmp, Oid colloid, static int compare_distances(const void *a, const void *b) { - DistanceValue *da = (DistanceValue *) a; - DistanceValue *db = (DistanceValue *) b; + const DistanceValue *da = (const DistanceValue *) a; + const DistanceValue *db = (const DistanceValue *) b; if (da->value < db->value) return 1; diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c index 07aa08cfe14..dbb417217f1 100644 --- a/src/backend/access/heap/pruneheap.c +++ b/src/backend/access/heap/pruneheap.c @@ -2021,8 +2021,8 @@ heap_log_freeze_eq(xlhp_freeze_plan *plan, HeapTupleFreeze *frz) static int heap_log_freeze_cmp(const void *arg1, const void *arg2) { - HeapTupleFreeze *frz1 = (HeapTupleFreeze *) arg1; - HeapTupleFreeze *frz2 = (HeapTupleFreeze *) arg2; + const HeapTupleFreeze *frz1 = (const HeapTupleFreeze *) arg1; + const HeapTupleFreeze *frz2 = (const HeapTupleFreeze *) arg2; if (frz1->xmax < frz2->xmax) return -1; diff --git a/src/backend/access/spgist/spgkdtreeproc.c b/src/backend/access/spgist/spgkdtreeproc.c index f0167d6ffa6..dc29d6898c5 100644 --- a/src/backend/access/spgist/spgkdtreeproc.c +++ b/src/backend/access/spgist/spgkdtreeproc.c @@ -84,8 +84,8 @@ typedef struct SortedPoint static int x_cmp(const void *a, const void *b) { - SortedPoint *pa = (SortedPoint *) a; - SortedPoint *pb = (SortedPoint *) b; + const SortedPoint *pa = (const SortedPoint *) a; + const SortedPoint *pb = (const SortedPoint *) b; if (pa->p->x == pb->p->x) return 0; @@ -95,8 +95,8 @@ x_cmp(const void *a, const void *b) static int y_cmp(const void *a, const void *b) { - SortedPoint *pa = (SortedPoint *) a; - SortedPoint *pb = (SortedPoint *) b; + const SortedPoint *pa = (const SortedPoint *) a; + const SortedPoint *pb = (const SortedPoint *) b; if (pa->p->y == pb->p->y) return 0; diff --git a/src/backend/statistics/mcv.c b/src/backend/statistics/mcv.c index ec650ba029f..1d210cdba3c 100644 --- a/src/backend/statistics/mcv.c +++ b/src/backend/statistics/mcv.c @@ -402,8 +402,8 @@ count_distinct_groups(int numrows, SortItem *items, MultiSortSupport mss) static int compare_sort_item_count(const void *a, const void *b, void *arg) { - SortItem *ia = (SortItem *) a; - SortItem *ib = (SortItem *) b; + const SortItem *ia = (const SortItem *) a; + const SortItem *ib = (const SortItem *) b; if (ia->count == ib->count) return 0; diff --git a/src/backend/tsearch/spell.c b/src/backend/tsearch/spell.c index e5badb6b43f..1af6b212245 100644 --- a/src/backend/tsearch/spell.c +++ b/src/backend/tsearch/spell.c @@ -210,8 +210,8 @@ cmpspellaffix(const void *s1, const void *s2) static int cmpcmdflag(const void *f1, const void *f2) { - CompoundAffixFlag *fv1 = (CompoundAffixFlag *) f1, - *fv2 = (CompoundAffixFlag *) f2; + const CompoundAffixFlag *fv1 = (const CompoundAffixFlag *) f1, + *fv2 = (const CompoundAffixFlag *) f2; Assert(fv1->flagMode == fv2->flagMode); diff --git a/src/test/modules/injection_points/injection_points.c b/src/test/modules/injection_points/injection_points.c index 25340e8d81b..df8f4cf1717 100644 --- a/src/test/modules/injection_points/injection_points.c +++ b/src/test/modules/injection_points/injection_points.c @@ -189,7 +189,7 @@ injection_init_shmem(void) * otherwise. */ static bool -injection_point_allowed(InjectionPointCondition *condition) +injection_point_allowed(const InjectionPointCondition *condition) { bool result = true; @@ -232,7 +232,7 @@ injection_points_cleanup(int code, Datum arg) void injection_error(const char *name, const void *private_data, void *arg) { - InjectionPointCondition *condition = (InjectionPointCondition *) private_data; + const InjectionPointCondition *condition = (const InjectionPointCondition *) private_data; char *argstr = (char *) arg; if (!injection_point_allowed(condition)) @@ -248,7 +248,7 @@ injection_error(const char *name, const void *private_data, void *arg) void injection_notice(const char *name, const void *private_data, void *arg) { - InjectionPointCondition *condition = (InjectionPointCondition *) private_data; + const InjectionPointCondition *condition = (const InjectionPointCondition *) private_data; char *argstr = (char *) arg; if (!injection_point_allowed(condition)) @@ -268,7 +268,7 @@ injection_wait(const char *name, const void *private_data, void *arg) uint32 old_wait_counts = 0; int index = -1; uint32 injection_wait_event = 0; - InjectionPointCondition *condition = (InjectionPointCondition *) private_data; + const InjectionPointCondition *condition = (const InjectionPointCondition *) private_data; if (inj_state == NULL) injection_init_shmem(); -- 2.34.1 --jEYXENy/7KdvfqDm Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v1-0002-Add-const-to-read-only-TableInfo-pointers-in-pg_d.patch" From a3d493f1f8430949a1bae1d5718baae9caea61cb Mon Sep 17 00:00:00 2001 From: Bertrand Drouvot Date: Thu, 18 Dec 2025 12:47:07 +0000 Subject: [PATCH v1 2/3] Add const to read only TableInfo pointers in pg_dump Functions that dump table data receive their parameters through const void * but were casting away const. Add const qualifiers to functions that only read the table information. Also change getRootTableInfo to return const TableInfo *, since it only traverses the parent chain without modifying any TableInfo structures. This allows the dump functions to maintain const correctness when calling it. --- src/bin/pg_dump/pg_dump.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) 100.0% src/bin/pg_dump/ diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 24ad201af2f..6aecc8b32fd 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -412,7 +412,7 @@ static void appendReloptionsArrayAH(PQExpBuffer buffer, const char *reloptions, static char *get_synchronized_snapshot(Archive *fout); static void set_restrict_relation_kind(Archive *AH, const char *value); static void setupDumpWorker(Archive *AH); -static TableInfo *getRootTableInfo(const TableInfo *tbinfo); +static const TableInfo *getRootTableInfo(const TableInfo *tbinfo); static bool forcePartitionRootLoad(const TableInfo *tbinfo); static void read_dump_filters(const char *filename, DumpOptions *dopt); @@ -2379,8 +2379,8 @@ selectDumpableObject(DumpableObject *dobj, Archive *fout) static int dumpTableData_copy(Archive *fout, const void *dcontext) { - TableDataInfo *tdinfo = (TableDataInfo *) dcontext; - TableInfo *tbinfo = tdinfo->tdtable; + const TableDataInfo *tdinfo = (const TableDataInfo *) dcontext; + const TableInfo *tbinfo = tdinfo->tdtable; const char *classname = tbinfo->dobj.name; PQExpBuffer q = createPQExpBuffer(); @@ -2547,8 +2547,8 @@ dumpTableData_copy(Archive *fout, const void *dcontext) static int dumpTableData_insert(Archive *fout, const void *dcontext) { - TableDataInfo *tdinfo = (TableDataInfo *) dcontext; - TableInfo *tbinfo = tdinfo->tdtable; + const TableDataInfo *tdinfo = (const TableDataInfo *) dcontext; + const TableInfo *tbinfo = tdinfo->tdtable; DumpOptions *dopt = fout->dopt; PQExpBuffer q = createPQExpBuffer(); PQExpBuffer insertStmt = NULL; @@ -2618,7 +2618,7 @@ dumpTableData_insert(Archive *fout, const void *dcontext) */ if (insertStmt == NULL) { - TableInfo *targettab; + const TableInfo *targettab; insertStmt = createPQExpBuffer(); @@ -2813,10 +2813,10 @@ dumpTableData_insert(Archive *fout, const void *dcontext) * getRootTableInfo: * get the root TableInfo for the given partition table. */ -static TableInfo * +static const TableInfo * getRootTableInfo(const TableInfo *tbinfo) { - TableInfo *parentTbinfo; + const TableInfo *parentTbinfo; Assert(tbinfo->ispartition); Assert(tbinfo->numParents == 1); @@ -2870,7 +2870,7 @@ static void dumpTableData(Archive *fout, const TableDataInfo *tdinfo) { DumpOptions *dopt = fout->dopt; - TableInfo *tbinfo = tdinfo->tdtable; + const TableInfo *tbinfo = tdinfo->tdtable; PQExpBuffer copyBuf = createPQExpBuffer(); PQExpBuffer clistBuf = createPQExpBuffer(); DataDumperPtr dumpFn; @@ -2891,7 +2891,7 @@ dumpTableData(Archive *fout, const TableDataInfo *tdinfo) (dopt->load_via_partition_root || forcePartitionRootLoad(tbinfo))) { - TableInfo *parentTbinfo; + const TableInfo *parentTbinfo; char *sanitized; parentTbinfo = getRootTableInfo(tbinfo); -- 2.34.1 --jEYXENy/7KdvfqDm Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v1-0003-Separate-read-and-write-pointers-in-pg_saslprep.patch" From f32dd7b645090b85e1297f312c73353d93c83383 Mon Sep 17 00:00:00 2001 From: Bertrand Drouvot Date: Thu, 18 Dec 2025 12:17:21 +0000 Subject: [PATCH v1 3/3] Separate read and write pointers in pg_saslprep Use separate pointers for reading const input ('p') and writing to mutable output ('outp'), avoiding the need to cast away const on the input parameter. --- src/common/saslprep.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) 100.0% src/common/ diff --git a/src/common/saslprep.c b/src/common/saslprep.c index 101e8d65a4d..b215ab0bf8e 100644 --- a/src/common/saslprep.c +++ b/src/common/saslprep.c @@ -1054,7 +1054,8 @@ pg_saslprep(const char *input, char **output) int count; int i; bool contains_RandALCat; - unsigned char *p; + const unsigned char *p; + unsigned char *outp; char32_t *wp; /* Ensure we return *output as NULL on failure */ @@ -1087,7 +1088,7 @@ pg_saslprep(const char *input, char **output) if (!input_chars) goto oom; - p = (unsigned char *) input; + p = (const unsigned char *) input; for (i = 0; i < input_size; i++) { input_chars[i] = utf8_to_unicode(p); @@ -1217,14 +1218,14 @@ pg_saslprep(const char *input, char **output) * There are no error exits below here, so the error exit paths don't need * to worry about possibly freeing "result". */ - p = (unsigned char *) result; + outp = (unsigned char *) result; for (wp = output_chars; *wp; wp++) { - unicode_to_utf8(*wp, p); - p += pg_utf_mblen(p); + unicode_to_utf8(*wp, outp); + outp += pg_utf_mblen(outp); } - Assert((char *) p == result + result_size); - *p = '\0'; + Assert((char *) outp == result + result_size); + *outp = '\0'; FREE(input_chars); FREE(output_chars); -- 2.34.1 --jEYXENy/7KdvfqDm--