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 1vQ4DD-008Qmd-0H for pgsql-hackers@arkaria.postgresql.org; Mon, 01 Dec 2025 13:45:07 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vQ4DB-002wFZ-2G for pgsql-hackers@arkaria.postgresql.org; Mon, 01 Dec 2025 13:45:06 +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 1vQ4DB-002wFQ-1J for pgsql-hackers@lists.postgresql.org; Mon, 01 Dec 2025 13:45:05 +0000 Received: from mail-wm1-x331.google.com ([2a00:1450:4864:20::331]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1vQ4D9-002a2H-0E for pgsql-hackers@lists.postgresql.org; Mon, 01 Dec 2025 13:45:04 +0000 Received: by mail-wm1-x331.google.com with SMTP id 5b1f17b1804b1-4779cb0a33fso43483125e9.0 for ; Mon, 01 Dec 2025 05:45:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1764596702; x=1765201502; 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=st48QHgV2xjIoikV8uIt6OAQi3pzqeNpq1v89pSQpsM=; b=Y6VMihdkGDO2NWVBHxOyVE4X3rFDBqfPc9kDbyar86ywqWJLINTT0q9t1PVmw+gm2n 53PC/QxBaUpaj2Q3kVHkFJuLDjCgN99D9BQNrNKH1mdc0i2Ijiz4Io08nHCxrjOJ5mRa 3RyXBuk1+x3ggIR8lJFyUcD3OoOZ/K0weGMjNfaG+Utkj2tp/BACCa/wGLTl0CuTQ4Hb xXfLMCyFi5xBN6h/d1q8jcIoQeYU8Of5doAeSOeL92k78qUqZ0AQIRCnyBk2qqYCaWCm oIZYR7/xTs98ay8YhEQ1ZwVZXmjAnRm7VAEk6Pbf/Z8WpQ/K00NTZpWiT4HVPVPyotM9 OPag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764596702; x=1765201502; 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=st48QHgV2xjIoikV8uIt6OAQi3pzqeNpq1v89pSQpsM=; b=LK4Kn4h3uZsXfQfPRD4/PRpWsFkPrVDORGAU7QipgLjphLMdsIhPkxdPwU4ZnYezXe AoTlhEnhMD1teQFEPdPXTbuH8GGgOiPsQ9RFMrb1f1wANnwZ1vp8edi5C5IhPdtBFsV4 TPXbmEBDwvOYxF7sfbOq/P7791KjHqSvo9TxXDjTSrpR/11562vNeAY+jYQlxW9LoM+s Gof4Q6XL/5N1vAxe+TbAgtqYTrMRutihEaE66WiAapM+0rEPAhA5UqDCW0KdpFTJMClD ZC2Yk6+0Fgf0TDXtYt9b4d4Svb2lM6QaEJBihQQpGPhNjVVzULH+FjAXh2Mhp4dSQZP4 HLsg== X-Gm-Message-State: AOJu0YzPgzNi32tWe1Cf/Q3FrdkgC0qBnkwXXAgprSAwxg12h+QUND9B MZczmDoSJyXc7RItTpBvQrplTJNzJzajkrtFQJuiqHY7VnTW4xz8EJU/ZSx7lw== X-Gm-Gg: ASbGnctibj6R/amas3IPkLcYX0QAHb/8whjHyjwCVWYjZ39294dxqGOnhMjjnPI5BYP rfFs0p7nA/QoVRK4qeh6ukVSBc/24txUlmYmKxWG4nkt9LPzTwOSqL9PEjhJgrdQufUNJ5M/KAB OLz6cC9qyxQCbBba28NjWQ4Ua3ZDJ1ICg0oDXB/Ye4f8ldORCBIDK+VIRx1uyg7ANfJ5EfCRZH+ DCSWtBFv5ONws4HfznnL0fJY1LrxHuAdj3P3kL2dM6qeOnPtyE3lk/j5h8CRKh1zs9KyFdOxfC2 DkqUwr2CxEapamasvZtpLVIQhLZYd4Oy6F21uAyZgtRgOXLyzs6/RT5wdmPYMcg1MA2fvq/xGKh c8VGumEZ/wmMUxVktRKMC60Ou8+dsFHtKTBP3TYL7ojGL28xTljFACUDVQhBDIpiqJZbedlwtrd dD7DEAiy/YfDb9rKGNjMqmseHryzoXqrOuHIgOq0rG6oQwYEXMQHT6xd/KVjNrsG97Cr84hunzC Y5LpZa8f9HfJGSKcjRqIl1stnwHJkKua9npPFrNpPzL4A== X-Google-Smtp-Source: AGHT+IFTUwAgJYYWdZSQnfkh8UcW3gZQcSlJWNHDmNQuGKt+FCOTDR+GROh00npyqNE0Uyk3WQDBPA== X-Received: by 2002:a05:600c:3110:b0:477:b734:8c52 with SMTP id 5b1f17b1804b1-477c0185bebmr404038055e9.14.1764596702218; Mon, 01 Dec 2025 05:45:02 -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-479111565a1sm239200975e9.5.2025.12.01.05.45.01 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 01 Dec 2025 05:45:01 -0800 (PST) Date: Mon, 1 Dec 2025 13:45:00 +0000 From: Bertrand Drouvot To: pgsql-hackers@lists.postgresql.org Subject: Safer hash table initialization macro Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Hi hackers, Currently to create a hash table we do things like: A) create a struct, say: typedef struct SeenRelsEntry { Oid rel_id; int list_index; } SeenRelsEntry; where the first member is the hash key, and then later: B) ctl.keysize = sizeof(Oid); ctl.entrysize = sizeof(SeenRelsEntry); ctl.hcxt = CurrentMemoryContext; seen_rels = hash_create("find_all_inheritors temporary table", 32, /* start small and extend */ &ctl, I can see 2 possible issues: 1) We manually specify the type for keysize, which could become incorrect (from the start) or if the key member's type changes. 2) It may be possible to remove the key member without the compiler noticing it. Take this example and remove: diff --git a/src/backend/catalog/pg_inherits.c b/src/backend/catalog/pg_inherits.c index 929bb53b620..eb11976afef 100644 --- a/src/backend/catalog/pg_inherits.c +++ b/src/backend/catalog/pg_inherits.c @@ -36,7 +36,6 @@ */ typedef struct SeenRelsEntry { - Oid rel_id; /* relation oid */ int list_index; /* its position in output list(s) */ } SeenRelsEntry; That would compile without any issues because this rel_id member is not referenced in the code (for this particular example). That's rare but possible. But then, on my machine, during make check: TRAP: failed Assert("!found"), File: "nodeModifyTable.c", Line: 5157, PID: 140430 The reason is that the struct member access is done only for bytes level operations (within the hash related macros). So it's easy to think that this member is unused (because it is not referenced in the code). I'm thinking about what kind of safety we could put in place to better deal with 1) and 2). What about adding a macro that: - requests the key member name - ensures that it is at offset 0 - computes the key size based on the member Something like: " #define HASH_ELEM_INIT(ctl, entrytype, keymember) \ do { \ StaticAssertStmt(offsetof(entrytype, keymember) == 0, \ #keymember " must be first member in " #entrytype); \ (ctl).keysize = sizeof(((entrytype *)0)->keymember); \ (ctl).entrysize = sizeof(entrytype); \ } while (0) " That way: - The key member is explicitly referenced in the code (preventing "unused" false positives) - The key size is automatically computed from the actual member type (preventing type mismatches) - We enforce that the key is at offset 0 An additional benefit: it avoids repeating the "keysize =" followed by "entrysize =" in a lot of places in the code (currently about 100 times). If that sounds like a good idea, I could work on a patch doing so. Thoughts? Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com