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 1wKNbr-000uOz-10 for pgsql-hackers@arkaria.postgresql.org; Tue, 05 May 2026 21:47:19 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wKNbo-00E8WS-1x for pgsql-hackers@arkaria.postgresql.org; Tue, 05 May 2026 21:47:16 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wKNbo-00E8WK-0u for pgsql-hackers@lists.postgresql.org; Tue, 05 May 2026 21:47:16 +0000 Received: from mail-qv1-xf29.google.com ([2607:f8b0:4864:20::f29]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wKNbm-00000000ijk-0Hqv for pgsql-hackers@lists.postgresql.org; Tue, 05 May 2026 21:47:16 +0000 Received: by mail-qv1-xf29.google.com with SMTP id 6a1803df08f44-8b5232009a6so46619016d6.1 for ; Tue, 05 May 2026 14:47:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778017632; x=1778622432; darn=lists.postgresql.org; h=in-reply-to:content-transfer-encoding:content-disposition :mime-version:references:message-id:subject:cc:to:from:date:from:to :cc:subject:date:message-id:reply-to; bh=PQrr/Y0UtfYkUy4dMiSFEJpa0/vGNCuZyU4n4UTfRZk=; b=p6seg7qbABZ59Ylp7ZDmONwIy4Y0/hZhRDv6ucqqTh8bv0nU4vGN463RCGDiCggLdZ kUGGgdPv9U3pS3SKbRuB/HyYkiWJTT+pHxyMd/9iFxPw+59S3sAWZcqRp2A56zYO/yE2 MDrQLbPR9wryJCLx6p6gRczCQu5HnnREcuy/FRbl583af0FThhixiClXJ/HJrXIGijvw p02beJUtc7XA1F6L73zTqxWdBvjpnjqhGwHmjhaZGjoGqGXM2jXKpX4zI7HSbH9HBAhe ftTNApdeB2VxD5B961Cqt/h9NjiwB9npnt85hgyZ2eK2PbnAnH5hV8nzfFdviHgZFHQN 90tQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778017632; x=1778622432; h=in-reply-to:content-transfer-encoding:content-disposition :mime-version:references:message-id:subject:cc:to:from:date:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=PQrr/Y0UtfYkUy4dMiSFEJpa0/vGNCuZyU4n4UTfRZk=; b=QhZMwe3f3mbLcf0FoZOJlOEEHVQqF1e8y6RQ+CGhMww6+mIcji+rFFzwMlZHuwR2oH SYX499y1VFUo1fnBDHR6AjlKRjNJLiNzJ9hqGrtN7w/Ujv0TJbwWTwOLtwIvEMHkGjJo xH8lVItu4fb93apzpQbp4sPzYUPvujH6o1JsqL8YZgdpLesRVYfeiR/LOd2x4oknvhhS UZ5TDua6StC4IEaal5icQG02nhrxErNQ5bUV3bJbOuaVBkVKYiexH6sniNGED8OTX87r RQYYDNBMN9Aa/wGmOl+uws/NqbQZ+z8GhlgHyCIWcRHPiJEEDsSVvaZtsZXQi1a5qIAf 1xbQ== X-Forwarded-Encrypted: i=1; AFNElJ/VA3+JcBbOOosoiKJCPqE5DC3GiROqriXFJb6SX++VWEF7L91rqrhP8hqDBiQaV3GVbwd3j9iSOlse8lwM@lists.postgresql.org X-Gm-Message-State: AOJu0Yz/sS9Ya39kPxIiTwApBEh41e23pXMrpj6ek7bal7BDCz2OR5oj 6fOvwvjLPVJwve5UAqh6LYUWqhA+rcWBpCsTnwrZIq5TPf3hrc9XMwxk X-Gm-Gg: AeBDietxN7z9ERXpg2mwJVHejPw/mzPmJzBYVft0a8xpvJDD0J1EnHjkBRtpYZYmJd0 4zJD5CZRbwusrIzWxziBVoFhm8JwWpd5mMCszdVN0ZoguL5mZ2KdOXsCEsJmLAs/2STO5jU0mix SNURuKWaVIjdHcpQhKDIptm6t2NFiB5nJx8fIEZEhVtfAYcaHXMggzO76kUm6yLeP6bRKTaYFAw g6eImZ0fa5ejPYhA30C0xO4M2wuL1MFtqMVoq8ydd35OcDY7X2PmcZ9Cr2kxOZBRZWvhS/6DlOl eFkj5j2aRH4fJEkY/lIPvIRVxylPlhHIHKH2BU043MuImpd1lQloYyP8yqsl9UXVoZu/MkxsEoQ YKDGySjwrOuE4emnKS9O6pnK+tKZYFnr5jRXHCW2MLInqMZz0wMVNDGvNJMg+4b+dUtsSBeQAAC /YdvOIN4ZAag95i/5MTPL1GORKytHB3J7aFVTWLJUgfoqXXwGhtw9N/j5NvmKhWEkB2/C83gVj/ 6speURqFoDahvvl1kq8q8M7RPLW0vuO X-Received: by 2002:a05:6214:46a0:b0:8ac:b5e0:bf92 with SMTP id 6a1803df08f44-8bc422a61f2mr9431776d6.9.1778017631876; Tue, 05 May 2026 14:47:11 -0700 (PDT) Received: from nathan (162-195-168-172.lightspeed.stlsmo.sbcglobal.net. [162.195.168.172]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-8b5397bdc7bsm166157406d6.20.2026.05.05.14.47.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 May 2026 14:47:09 -0700 (PDT) Date: Tue, 5 May 2026 16:47:07 -0500 From: Nathan Bossart To: Tom Lane Cc: Chao Li , Rahila Syed , Robert Haas , PostgreSQL Hackers Subject: Re: pgindent versus struct members and typedefs Message-ID: References: <347EA055-D626-414C-B10D-7E70041B9B55@gmail.com> <509793.1764715875@sss.pgh.pa.us> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="k2Vi/uo5iFea1Gni" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <509793.1764715875@sss.pgh.pa.us> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --k2Vi/uo5iFea1Gni Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit On Tue, Dec 02, 2025 at 05:51:15PM -0500, Tom Lane wrote: > Chao Li writes: >> On Dec 3, 2025, at 06:00, Nathan Bossart wrote: >>> I tried to fix pgindent for a few, but the code is basically impenetrable. >>> I didn't find any fixes upstream [0], either. As noted above, we could >>> also fix it by avoiding the naming conflicts. However, I can't imagine >>> that's worth the churn, and I've already spent way too much time on this, >>> so IMHO the best thing to do here is nothing. > >> I think that’s fine. > > Agreed, not worth the trouble to fool with. For fun, I spent some time with an AI tool to develop the attached fix for this problem. The explanation seems reasonable to me, although I am by no means a pgindent expert. When I looked at this in December, I did find this similar commit from upstream [0], but I failed to make the connection with last_u_d. 0002 is the result of a pgindent run after applying 0001. You'll notice that it fixes the exact set of cases I found with grep upthread. [0] https://github.com/pstef/freebsd_indent/commit/afa2239 -- nathan --k2Vi/uo5iFea1Gni Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v1-0001-pgindent-Fix-spacing-after-when-member-name-match.patch From 804bb1097a44cc35178f3e1de46d17422ce7b67f Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Tue, 5 May 2026 16:03:13 -0500 Subject: [PATCH v1 1/2] pgindent: Fix spacing after != when member name matches typedef. When a struct member name matches a registered typedef, pgindent removes the space after "!=" (and some other operators): entry->dsh.dsa_handle !=DSA_HANDLE_INVALID In lexi.c, when an identifier matches the typedef list, the code sets last_u_d = true before jumping to found_typename. This flag tells the lexer that the next operator should be treated as unary, which is correct for type names (e.g., "Datum *x" needs * to be unary, not multiplication). However, found_typename has a guard that recognizes when a typedef name appears after "." or "->": in that case, the name is a struct member, not a type, so it's returned as a plain identifier. The problem is that last_u_d has already been set to true and is never corrected. This causes the next operator (e.g., "!=") to be misclassified as unary, which suppresses the space after it. To fix, only set last_u_d when the token won't be caught by the guard, i.e., when it will actually be treated as a type name. This also explains why "==" was not affected: the "==" case always returns binary_op regardless of last_u_d, while "!=" checks last_u_d to decide. --- src/tools/pg_bsd_indent/lexi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tools/pg_bsd_indent/lexi.c b/src/tools/pg_bsd_indent/lexi.c index 943bf7ce6b0..e846188d6f4 100644 --- a/src/tools/pg_bsd_indent/lexi.c +++ b/src/tools/pg_bsd_indent/lexi.c @@ -363,7 +363,8 @@ lexi(struct parser_state *state) bsearch(s_token, typenames, typename_top + 1, sizeof(typenames[0]), strcmp_type))) { state->keyword = 4; /* a type name */ - state->last_u_d = true; + if (state->last_token != period && state->last_token != unary_op) + state->last_u_d = true; goto found_typename; } } else { /* we have a keyword */ -- 2.50.1 (Apple Git-155) --k2Vi/uo5iFea1Gni Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v1-0002-run-pgindent.patch From ccdde305aad8277bf91cf02577c723a008919288 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Tue, 5 May 2026 16:04:14 -0500 Subject: [PATCH v1 2/2] run pgindent --- src/backend/replication/logical/logicalfuncs.c | 2 +- src/backend/storage/ipc/dsm_registry.c | 2 +- src/bin/pg_basebackup/pg_basebackup.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/backend/replication/logical/logicalfuncs.c b/src/backend/replication/logical/logicalfuncs.c index 512013b0ef0..71fbaf72269 100644 --- a/src/backend/replication/logical/logicalfuncs.c +++ b/src/backend/replication/logical/logicalfuncs.c @@ -218,7 +218,7 @@ pg_logical_slot_get_changes_guts(FunctionCallInfo fcinfo, bool confirm, bool bin * what we need. */ if (!binary && - ctx->options.output_type !=OUTPUT_PLUGIN_TEXTUAL_OUTPUT) + ctx->options.output_type != OUTPUT_PLUGIN_TEXTUAL_OUTPUT) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("logical decoding output plugin \"%s\" produces binary output, but function \"%s\" expects textual data", diff --git a/src/backend/storage/ipc/dsm_registry.c b/src/backend/storage/ipc/dsm_registry.c index 2b56977659b..b9961c26019 100644 --- a/src/backend/storage/ipc/dsm_registry.c +++ b/src/backend/storage/ipc/dsm_registry.c @@ -479,7 +479,7 @@ pg_get_dsm_registry_allocations(PG_FUNCTION_ARGS) entry->dsa.handle != DSA_HANDLE_INVALID) vals[2] = Int64GetDatum(dsa_get_total_size_from_handle(entry->dsa.handle)); else if (entry->type == DSMR_ENTRY_TYPE_DSH && - entry->dsh.dsa_handle !=DSA_HANDLE_INVALID) + entry->dsh.dsa_handle != DSA_HANDLE_INVALID) vals[2] = Int64GetDatum(dsa_get_total_size_from_handle(entry->dsh.dsa_handle)); else nulls[2] = true; diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c index c1a4672aa6f..80dc3bbc8da 100644 --- a/src/bin/pg_basebackup/pg_basebackup.c +++ b/src/bin/pg_basebackup/pg_basebackup.c @@ -1282,7 +1282,7 @@ ReceiveArchiveStream(PGconn *conn, pg_compress_specification *compress) ReceiveCopyData(conn, ReceiveArchiveStreamChunk, &state); /* If we wrote the backup manifest to a file, close the file. */ - if (state.manifest_file !=NULL) + if (state.manifest_file != NULL) { fclose(state.manifest_file); state.manifest_file = NULL; @@ -1341,7 +1341,7 @@ ReceiveArchiveStreamChunk(size_t r, char *copybuf, void *callback_data) /* Sanity check. */ if (state->manifest_buffer != NULL || - state->manifest_file !=NULL) + state->manifest_file != NULL) pg_fatal("archives must precede manifest"); /* Parse the rest of the CopyData message. */ @@ -1406,7 +1406,7 @@ ReceiveArchiveStreamChunk(size_t r, char *copybuf, void *callback_data) appendPQExpBuffer(state->manifest_buffer, copybuf + 1, r - 1); } - else if (state->manifest_file !=NULL) + else if (state->manifest_file != NULL) { /* Manifest data, write to disk. */ if (fwrite(copybuf + 1, r - 1, 1, -- 2.50.1 (Apple Git-155) --k2Vi/uo5iFea1Gni--