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.94.2) (envelope-from ) id 1qq89c-008HSS-1X for pgsql-hackers@arkaria.postgresql.org; Tue, 10 Oct 2023 08:31:48 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1qq89Y-005vfn-61 for pgsql-hackers@arkaria.postgresql.org; Tue, 10 Oct 2023 08: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.94.2) (envelope-from ) id 1qq89X-005vdi-M5 for pgsql-hackers@lists.postgresql.org; Tue, 10 Oct 2023 08:31:44 +0000 Received: from mail.postgrespro.ru ([93.174.131.139]) by makus.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1qq89Q-000vDO-P0 for pgsql-hackers@lists.postgresql.org; Tue, 10 Oct 2023 08:31:43 +0000 Received: from [192.168.1.3] (a0.sub235.net78.udm.net [78.85.235.0]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client did not present a certificate) (Authenticated sender: s.glukhov@postgrespro.ru) by mail.postgrespro.ru (Postfix/587) with ESMTPSA id 9E66BE203C9; Tue, 10 Oct 2023 11:31:33 +0300 (MSK) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=postgrespro.ru; s=mx2023; t=1696926693; bh=CZaeDZMYN1WL25PXD/RnQUgNDwBr32kjoAepLfcp3hQ=; h=Message-ID:Date:User-Agent:Subject:To:Cc:References:From: In-Reply-To:From; b=dNdojSFOdksVFzOTaWCmFKm+kDS/XI4mcgquqbOmrQ245C2+lW/Ldj/yC7yqnzOS2 azU8nJOUXimMXC9veoKm5Ulo1oJuhJIc/6qzWlwgqApPYjgzoB0lezk0DYO4dzyvxT q7VWZADb9fwqq+iGNLyaqeh+yQGaiysN9e7UMTM6ODhYF+06L7ybU17UQrzjn64nV/ PdAHufez81GVzns5HIlqcFwKrNmxQ1G2YsNBi+P8smFlJ/NSNWLh+ZoMbYXqJoIj3S ip58l/B/4qGln2lGH1nDRYrToSr442SL22QTuy44bmyAoC70PbexGhq8aQFVXX5GW9 Qb8b6SttJre6w== Message-ID: <2f09ce72-315e-2a33-589a-8519ada8df61@postgrespro.ru> Date: Tue, 10 Oct 2023 12:31:32 +0400 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.9.0 Subject: Re: Problem, partition pruning for prepared statement with IS NULL clause. Content-Language: en-US To: David Rowley Cc: pgsql-hackers@lists.postgresql.org References: From: Sergei Glukhov In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Hi David, On 10/9/23 03:26, David Rowley wrote: > On Sat, 7 Oct 2023 at 03:11, Sergei Glukhov wrote: >> I noticed that combination of prepared statement with generic plan and >> 'IS NULL' clause could lead partition pruning to crash. >> Test case: >> ------ >> set plan_cache_mode to force_generic_plan; >> prepare stmt AS select * from hp where a is null and b = $1; >> explain execute stmt('xxx'); > Thanks for the detailed report and proposed patch. > > I think your proposed fix isn't quite correct. I think the problem > lies in InitPartitionPruneContext() where we assume that the list > positions of step->exprs are in sync with the keyno. If you look at > perform_pruning_base_step() the code there makes a special effort to > skip over any keyno when a bit is set in opstep->nullkeys. > > It seems that your patch is adjusting the keyno that's given to the > PruneCxtStateIdx() and it looks like (for your test case) it'll end up > passing keyno==0 when it should be passing keyno==1. keyno is the > index of the partition key, so you can't pass 0 when it's for key > index 1. > > I wonder if it's worth expanding the tests further to cover more of > the pruning cases to cover run-time pruning too. Thanks for the explanation. I thought by some reason that 'exprstates ' array doesn't contain elements related to 'IS NULL' clause. Now I see that they are there and just empty and untouched. I verified the patch and it fixes the problem. Regarding test case, besides the current test case and the test for dynamic partition pruning, say, select a, (select b from hp where a is null and b = a.b) AS b from hp a where a = 1 and b = 'xxx'; I would like to suggest to slightly refactor 'Test Partition pruning for HASH partitioning' test from 'partition_prune.sql' and add one more key field. The reason is that two-element key is not enough for thorough testing since it tests mostly corner cases. Let me know if it's worth doing. Example: ------ create table hp (a int, b text, c int, d int)   partition by hash (a part_test_int4_ops, b part_test_text_ops, c part_test_int4_ops); create table hp0 partition of hp for values with (modulus 4, remainder 0); create table hp3 partition of hp for values with (modulus 4, remainder 3); create table hp1 partition of hp for values with (modulus 4, remainder 1); create table hp2 partition of hp for values with (modulus 4, remainder 2); insert into hp values (null, null, null, 0); insert into hp values (1, null, 1, 1); insert into hp values (1, 'xxx', 1, 2); insert into hp values (null, 'xxx', null, 3); insert into hp values (2, 'xxx', 2, 4); insert into hp values (1, 'abcde', 1, 5); ------ Another crash in the different place even with the fix: ------ explain select * from hp where a = 1 and b is null and c = 1; ------ Regards, Gluh