Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1qEODv-0003uN-N1 for pgsql-bugs@arkaria.postgresql.org; Wed, 28 Jun 2023 06:00:15 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1qEODt-0006uS-Au for pgsql-bugs@arkaria.postgresql.org; Wed, 28 Jun 2023 06:00:13 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1qEODs-0006os-S8 for pgsql-bugs@lists.postgresql.org; Wed, 28 Jun 2023 06:00:13 +0000 Received: from mail-lf1-x129.google.com ([2a00:1450:4864:20::129]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1qEODl-000rjJ-MW for pgsql-bugs@lists.postgresql.org; Wed, 28 Jun 2023 06:00:11 +0000 Received: by mail-lf1-x129.google.com with SMTP id 2adb3069b0e04-4fb863edcb6so2281124e87.0 for ; Tue, 27 Jun 2023 23:00:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1687932003; x=1690524003; h=in-reply-to:references:cc:to:from:content-language:subject :user-agent:mime-version:date:message-id:from:to:cc:subject:date :message-id:reply-to; bh=WUFfD3qZ7CcaAMzoNbsUoNQQk6Q8Mv1vgSAlXw7gqWs=; b=OeAHWt5mg1SGKKmTVH++hiCyRfE65LMkutzzoPSEQNTUgPnJ/k2IgUpAmpVt/Q9izY im+evXIG8w5LLcUNOGg4xr0DT3Z+xGbJIgb/EDW204X/RCIAPsqKMHwhh3CYKd7WIGjG 44gVWY8Z7hzEugn1z8FokMtcQUsliX8kTqDd9R/t37DLJ7bILpYRRkOC/bWeXRVdiJV8 F1Uqk+U3ZzzaKBy+kEg5A1xuDzVFNrtsQpANzXfqH7GWAMbXhrOSQS28wiiLhXKNYuYT 6ZDesT3R8LKCjDKGC1ZRIXSyhuWJSvJea/R1B+1hDXNlO6WQMzPDYF1V3Am+TkHvjE11 BHCw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1687932003; x=1690524003; h=in-reply-to:references:cc:to:from:content-language:subject :user-agent:mime-version:date:message-id:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=WUFfD3qZ7CcaAMzoNbsUoNQQk6Q8Mv1vgSAlXw7gqWs=; b=I0BafND6fIHVKWUMBiD8EbdhYa+Y4t15VDutkqyl4DVzXpCLaySwpxfVuXWVM+D1/j Ifl0pCt+r0ldNxsTwh2R3KI7i50Z3NscjRofRFZQt5JpuXoeuAA5lFi5HqInBS+e1FJD RGOyj7ZK9uOMNIoc0+/B+5FjZpxQ2l9XaM5koglVUnHHRPkt5VZTDBQky4lPS0vZmgbN UkrXvuAAsI5X4CCjnKW6BaOusDzLwbI3msrp+rcCWNWiND6xVPfpi/ug2MgDpgX3r5bo psrPKB1VQY4i1IlUJIAY6oZGHmRh9CJPWRf3RK2SAt5PzSkjJOI0654NWe7wwnITbzYA GAwA== X-Gm-Message-State: AC+VfDzw+tRHd4X26bGspnsWpkSLh6RKoUcMM/cwx3QuDi0BksMf9zl9 kISkWLQsMDjMW3tLXwSlC2s= X-Google-Smtp-Source: ACHHUZ4ry5Axyvz9PV11ex5ebpNyTzRrOb2TJXRzAht4f29isOO1tiv4O0SVERcPQEV8xpy7+oRsZw== X-Received: by 2002:a05:6512:110c:b0:4fb:758c:74ed with SMTP id l12-20020a056512110c00b004fb758c74edmr5976511lfg.35.1687932002769; Tue, 27 Jun 2023 23:00:02 -0700 (PDT) Received: from [1.0.0.7] ([178.155.23.108]) by smtp.gmail.com with ESMTPSA id i28-20020a056512007c00b004fb680fd3d7sm1347806lfo.291.2023.06.27.23.00.01 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 27 Jun 2023 23:00:02 -0700 (PDT) Content-Type: multipart/alternative; boundary="------------FtPRMuAm8ybwiksPndO209uL" Message-ID: <3eaa2c33-2ed1-2996-c6b6-0e7552a64cae@gmail.com> Date: Wed, 28 Jun 2023 09:00:00 +0300 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.4.2 Subject: Re: BUG #17997: Assert failed in validatePartitionedIndex() when attaching partition index to child of valid index Content-Language: en-US From: Alexander Lakhin To: Michael Paquier , Tom Lane Cc: pgsql-bugs@lists.postgresql.org References: <17997-a044c27aef95daf8@postgresql.org> <509915.1687704058@sss.pgh.pa.us> <14987634-43c0-0cb3-e075-94d423607e08@gmail.com> In-Reply-To: <14987634-43c0-0cb3-e075-94d423607e08@gmail.com> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk This is a multi-part message in MIME format. --------------FtPRMuAm8ybwiksPndO209uL Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit 27.06.2023 14:00, Alexander Lakhin wrote: > 26.06.2023 11:05, Michael Paquier wrote: >> A third solution that came into my mind just now would be to revisit >> the choice done in AttachPartitionEnsureIndexes() where an invalid >> index can be chosen as a match when creating the indexes on the >> partitions, so as we are able to get to the bottom of a chain with >> valid indexes for the whole tree.  I have been testing the attached >> and it has been working here the way I'd expect when manipulating >> partition trees with ATTACH PARTITION, though this breaks the scenario >> of this bug report because we would now get a failure when attempting >> to attach an index in the last command. > > Thanks for the fix! > > This solution seems sensible to me. The only downside I see is that an > invalid index would be left orphaned after ATTACH PARTITION, but I couldn't > find in doc/ or src/test/regress/ any promises that such index must be > used. I also don't see a way to make a previously valid index inside the > partition index tree invalid and available to attaching a child index to it > in the same time. There is also another scenario where the new behavior could be considered as more sensible: create table t(a int, b int) partition by range (a); create index on t((a / b)); create table tp1(a int, b int); insert into tp1 values (1, 0); create index concurrently on tp1((a/b)); --  division by zero occurs, but the index is created (as invalid) alter table t attach partition tp1 for values from (1) to (10); Without the fix you get partition tp1_1 attached and the following partition indexes: Partitioned index "public.t_expr_idx" btree, for table "public.t" Partitions: tp1_expr_idx Index "public.tp1_expr_idx" btree, for table "public.tp1", invalid But with the patch applied ATTACH PARTITION fails with ERROR: division by zero. Though we still can get a partition index chain with invalid indexes as follows: create table t(a int, b int) partition by range (a); create table tp1(a int, b int) partition by range (a); alter table t attach partition tp1 for values from (1) to (100); create table tp1_1(a int, b int); insert into tp1_1 values (1, 0); create index concurrently on tp1_1((a/b)); --  division by zero occurs, but the index is created (as invalid) alter table tp1 attach partition tp1_1 for values from (1) to (10); create index on t((a / b)); here we get the following index chain: Partitioned index "public.t_expr_idx" btree, for table "public.t" Partitions: tp1_expr_idx, PARTITIONED Partitioned index "public.tp1_expr_idx" btree, for table "public.tp1", invalid Partitions: tp1_1_expr_idx Index "public.tp1_1_expr_idx" btree, for table "public.tp1_1", invalid It's also interesting that REINDEX for the index tree validates only a leaf index: reindex index t_expr_idx; ERROR:  division by zero update tp1_1 set b=1; reindex index t_expr_idx; -- or even reindex index tp1_expr_idx; Partitioned index "public.t_expr_idx" btree, for table "public.t" Partitions: tp1_expr_idx, PARTITIONED Partitioned index "public.tp1_expr_idx" btree, for table "public.tp1", invalid Partitions: tp1_1_expr_idx Index "public.tp1_1_expr_idx" btree, for table "public.tp1_1" Although it looks like the invalid mark for a non-leaf index doesn't prevent using an index below it: set enable_seqscan = off; explain select * from t where a / b = 1;                                   QUERY PLAN ------------------------------------------------------------------------------  Index Scan using tp1_1_expr_idx on tp1_1 t  (cost=0.12..8.14 rows=1 width=8)    Index Cond: ((a / b) = 1) So it's not clear (to me, at least), what exactly indisvalid means for indexes in a partition tree. Best regards, Alexander --------------FtPRMuAm8ybwiksPndO209uL Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 8bit
27.06.2023 14:00, Alexander Lakhin wrote:
26.06.2023 11:05, Michael Paquier wrote:
A third solution that came into my mind just now would be to revisit
the choice done in AttachPartitionEnsureIndexes() where an invalid
index can be chosen as a match when creating the indexes on the
partitions, so as we are able to get to the bottom of a chain with
valid indexes for the whole tree.  I have been testing the attached
and it has been working here the way I'd expect when manipulating
partition trees with ATTACH PARTITION, though this breaks the scenario
of this bug report because we would now get a failure when attempting
to attach an index in the last command.

Thanks for the fix!

This solution seems sensible to me. The only downside I see is that an
invalid index would be left orphaned after ATTACH PARTITION, but I couldn't
find in doc/ or src/test/regress/ any promises that such index must be
used. I also don't see a way to make a previously valid index inside the
partition index tree invalid and available to attaching a child index to it
in the same time.

There is also another scenario where the new behavior could be considered as more sensible:
create table t(a int, b int) partition by range (a);
create index on t((a / b));
create table tp1(a int, b int);
insert into tp1 values (1, 0);
create index concurrently on tp1((a/b)); --  division by zero occurs, but the index is created (as invalid)
alter table t attach partition tp1 for values from (1) to (10);

Without the fix you get partition tp1_1 attached and the following partition indexes:
Partitioned index "public.t_expr_idx"
btree, for table "public.t"
Partitions: tp1_expr_idx

Index "public.tp1_expr_idx"
btree, for table "public.tp1", invalid

But with the patch applied ATTACH PARTITION fails with ERROR:  division by zero.

Though we still can get a partition index chain with invalid indexes as follows:
create table t(a int, b int) partition by range (a);
create table tp1(a int, b int) partition by range (a);
alter table t attach partition tp1 for values from (1) to (100);
create table tp1_1(a int, b int);
insert into tp1_1 values (1, 0);
create index concurrently on tp1_1((a/b)); --  division by zero occurs, but the index is created (as invalid)
alter table tp1 attach partition tp1_1 for values from (1) to (10);
create index on t((a / b));

here we get the following index chain:
Partitioned index "public.t_expr_idx"
btree, for table "public.t"
Partitions: tp1_expr_idx, PARTITIONED

Partitioned index "public.tp1_expr_idx"
btree, for table "public.tp1", invalid
Partitions: tp1_1_expr_idx

Index "public.tp1_1_expr_idx"
btree, for table "public.tp1_1", invalid

It's also interesting that REINDEX for the index tree validates only a leaf index:
reindex index t_expr_idx;
ERROR:  division by zero

update tp1_1 set b=1;
reindex index t_expr_idx; -- or even reindex index tp1_expr_idx;

Partitioned index "public.t_expr_idx"
btree, for table "public.t"
Partitions: tp1_expr_idx, PARTITIONED

Partitioned index "public.tp1_expr_idx"
btree, for table "public.tp1", invalid
Partitions: tp1_1_expr_idx

Index "public.tp1_1_expr_idx"
btree, for table "public.tp1_1"

Although it looks like the invalid mark for a non-leaf index doesn't prevent using an index below it:
set enable_seqscan = off;
explain select * from t where a / b = 1;
                                  QUERY PLAN                                  
------------------------------------------------------------------------------
 Index Scan using tp1_1_expr_idx on tp1_1 t  (cost=0.12..8.14 rows=1 width=8)
   Index Cond: ((a / b) = 1)

So it's not clear (to me, at least), what exactly indisvalid means for indexes in a partition tree.

Best regards,
Alexander
--------------FtPRMuAm8ybwiksPndO209uL--