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 1w5C9z-002zmP-1E for pgsql-hackers@arkaria.postgresql.org; Wed, 25 Mar 2026 00:31:47 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1w5C9x-009shK-0B for pgsql-hackers@arkaria.postgresql.org; Wed, 25 Mar 2026 00:31:45 +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 1w5C9w-009shA-2U for pgsql-hackers@lists.postgresql.org; Wed, 25 Mar 2026 00:31:45 +0000 Received: from mail-wm1-x32b.google.com ([2a00:1450:4864:20::32b]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1w5C9v-00000000sSC-1GvT for pgsql-hackers@lists.postgresql.org; Wed, 25 Mar 2026 00:31:44 +0000 Received: by mail-wm1-x32b.google.com with SMTP id 5b1f17b1804b1-486fd5360d4so20707615e9.1 for ; Tue, 24 Mar 2026 17:31:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1774398702; cv=none; d=google.com; s=arc-20240605; b=GYgvqzYtIi9maBffbcv5YM6AeKSQXoEaMJyzf2iP13+MWUhp2juvhGqLeOlM2QY8GJ hXkVzge/TdAOHKewhGrqhSCQB516rP7ugQsu0lnlQTD6atAax0phaabmJybMx6puUP2C 49PlvHGY9KjRXOIaLB4BWuOptLvxLqXb23w1AgCQDx08swDxbRk/9norSCWPq7JpdWFo xm0dXfgaX3BoDnrGIFYeOoJta3v9HTtlSvKsY8kYyMgU9v2nLprjDzoknzKtYkq5TIqN LYuIQNVh08SA7YQtJ99suFZILABoAP3m7tAm0j85L8isfHfNgYSvvywNVKfzpbXxe15W ivxA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=sMpDmDZFtDJCnHI10Vk//JcxT2oidjtKGlRz2U05FN0=; fh=gWEIeDmQKdd45XEEz4u6Oa1DmedM0UlgJ92BAKEBfqE=; b=Q0muTpafXLJu3V7DlXTvZAM2+2q0tixAM7r7MLxBXEY0Tm75Wqem8FhDxUKnN+xfcJ G19uRMTF8LJNAgP5RyBjJ0PamonMrZZ43pj7I2/Zh0Tw1he4bPNGwWbua6oQ/rFvIAg/ 5I6qhQ9unWu4Yhmj3X9XJpwY7aGa9xq8ehlMOnRAAqAy/bx6qJ7b41Buiz8LFK7h2USY 5U/J8Vwl9IkuQuaSMWQYh3HW46eqdWm7CRslrJwjZF/meXiaicRA9EPwN7rBGDQyYDjq FqIgOxw9DCNGukcAAV4hO9QtqxeijUXBMZoJLoe8X716pFXZsUeP79f6RWlkYhS11c3f 15Xw==; darn=lists.postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1774398702; x=1775003502; darn=lists.postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=sMpDmDZFtDJCnHI10Vk//JcxT2oidjtKGlRz2U05FN0=; b=puv/RRIq4Yp/yvq+mgqCm3X+rrLMN4VBjOIeXnfA9nqHivnJvTtYtxmNzMBEEhg+Tl z9X+z3vKw7ufyueKGjwhxmZSrl1MgW/EV/0xrSZ8jfkVM/F92NgylOBXwK/iScpyGC/I 1QEoGh0cq0Rob5OKSiynAeXNmK6S49H8vZEpW5TfvZ2jSOkihYe0iAneNtEwsjY2TJM0 FjtUsrqV1UFapvhKIx2ziFaRnnbwcBHs1SY+YRhJOdzRHJ2Z2opqYsL6D5FJv8k6F7i7 IIS8+MPLc+KxAcejyGreC55y3c2j76cKXZogQY+EDTQkWdK7+xvqhF87McqL6Fi6ZQBG Y6ww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774398702; x=1775003502; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=sMpDmDZFtDJCnHI10Vk//JcxT2oidjtKGlRz2U05FN0=; b=PrBUTKwyFvN9J+IUoliqeDjSPveqpBLK1uCAZAGuR/B3s9gFnhq9h9+amtF/Mitlfx iDUcD/ToazH2dDMt94rYAnX6QEtcY0u/yDvGdtvNtrPCYiJbuhMdUhAjglB3CxkbQIrr LNs9HLvczdw/Tlxa7/kzwbz2tsDNK+oF62SlG0KGxodv7uT9RCJszKgxK76yfSyVQQJr QE394ba154MieD4drSpeK+H6VGdDKb23VzjCoU4WHc/zES3n6AcGTUGle09WUuY+Nr6z G11GvXkX55/K7CmrmhEXX0iEx4MAJTMWxOagBKK7d8JyE6N2gLCMBOZLPFbJeKYv06dU kNUw== X-Gm-Message-State: AOJu0YxWCeRw3o+KhbtmL5sVRDAbEF6p6lV6P+YdNkypabubIjFS/yTp 7WlEo5Si6CSXVi29uFA2fBV59ONtWZtqzBw7qqF640av7PJr9IOtR0kH659Me5bzjk5i9A9bTQW DAdSDGlfUmQWHuUkBZPWJpydtk1Tl4Ue1fNor X-Gm-Gg: ATEYQzwqIa9kMnnDcDnB/m7Cxg04tZIK253tgmMGxEA1EEK0VzTme9K2IFE2m7UZJmb FmJitmGnvKGk4eUzLXC2v7BrFKcYqRrj/cc3oegPMT+LZQISmYwzuCbaE8LWtQK957dvgvevrzb zH4SBRtIudU0b59jTRP9BF5c9Nbgg/EPXkj/Tvz9fHmn9C+N3TkxCa6Y1zDie7qBpd/kr9m5T22 oum9D4O/+pps8kHVlyR61NF6bU3qTw71gr0AZ758555ysZQhq1BFj9jkrD6DyVrQAThGLjVqRe4 l92d2eolFbl2iVr7FuGXmEDllPnmfagO7RIoBEUPrD6d9IJ/u3C2TOqd9wdrUxd1ROLwIHc= X-Received: by 2002:a05:600c:4e87:b0:477:6d96:b3e5 with SMTP id 5b1f17b1804b1-48715fd463emr22829955e9.7.1774398701615; Tue, 24 Mar 2026 17:31:41 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: David Rowley Date: Wed, 25 Mar 2026 13:31:30 +1300 X-Gm-Features: AQROBzA7SwJzxd6BzbG5yp3l-UcRlkDQr1-grkwDUB5sj2PmBMYt6Y_Ye54ND5A Message-ID: Subject: Re: Fix "could not find memoization table entry" To: Tender Wang Cc: PostgreSQL Hackers Content-Type: text/plain; charset="UTF-8" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Tue, 24 Mar 2026 at 13:12, David Rowley wrote: > It looks to me like the bug is in hash_numeric(). Seems like it has no > idea what type it's meant to return. hash_numeric_extended() doesn't > seem to be much better. I recreated this locally and spent some time debugging to understand the issue more clearly. Because hash_numeric() isn't being careful to convert the Datum return value into int32, in cases where the Datum is a number above 2^31, (which would cause an int32 to wrap to negative), that isn't happening when the expression evaluation code is run and the Memoize hash table is populated. During the eviction code, when we re-lookup the hash table with the stored key later, we deform the MinimalTuple for the Memoize key, because the Datum has been formed into a MinimalTuple, it's been forced into the correct 32-bit representation via store_att_byval()'s DatumGetInt32() call. The values below are examples of what we're dealing with: 1) 3041168208 (0xB5448B50) 2) 18446744072455752528 (0xFFFFFFFFB5448B50) #1 is the number that the expression evaluation code gets from hash_numeric(). This is the value that's used to choose the hashtable bucket. #2 is what we probe the hash table for after reading the Memoize key from the MinimalTuple, which has wrapped to negative correctly from being stored in the MinimalTuple via store_att_byval(). If we fix hash_numeric() so it casts its value to int32, it will return #2, the sign-extended representation. Obviously, we don't want to back-patch anything that would cause a user-visible change in the return value of hash_numeric(), so I've been experimenting to see if there's any way to get PostgreSQL to output any value from hash_numeric() larger than 2^31 and I've been unable to. I tried: Experiment a: create table bigint (a bigint); insert into bigint select hash_numeric(n) from (values('1234.124'::numeric),('1234.124'::numeric)) n(n); In this case, the hash_numeric() value goes through int48() to cast it to the bigint before storing it in the table. int48() does PG_GETARG_INT32(0), which fixes the issue. Experiment b: I tried just getting PostgreSQL to output the data: select hash_numeric(n) from (values('1234.124'::numeric),('1234.124'::numeric)) n(n); The larger than 2^31 makes it all the way to int4out() in this case, but it gets fixed by int4out's PG_GETARG_INT32(0) call. My 2 experiments aren't exactly exhaustive, so they've only slightly reduced my concern level. Does anyone else have any opinions on this one? I'm also wondering about other places where we're using the wrong return macro in functions. Maybe there's something we can do in debug builds and put the return type in the fcinfo and add some Asserts to the PG_RETURN_* macros. David