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 1wgzuF-006XeA-0F for pgsql-hackers@arkaria.postgresql.org; Tue, 07 Jul 2026 07:07: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 1wgzuD-0054qy-2c for pgsql-hackers@arkaria.postgresql.org; Tue, 07 Jul 2026 07:07:45 +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 1wgzuD-0054qq-1b for pgsql-hackers@lists.postgresql.org; Tue, 07 Jul 2026 07:07:45 +0000 Received: from mail-ed1-x52f.google.com ([2a00:1450:4864:20::52f]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wgzuB-00000002CRY-1qd6 for pgsql-hackers@postgresql.org; Tue, 07 Jul 2026 07:07:45 +0000 Received: by mail-ed1-x52f.google.com with SMTP id 4fb4d7f45d1cf-697bd21fdc2so6266302a12.1 for ; Tue, 07 Jul 2026 00:07:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1783408062; cv=none; d=google.com; s=arc-20260327; b=bR+XXQVVpKhtOJ0fEoXgY8idiYtaEFYTxFBHTAWjvq72zDp1OZ/6GPop7+VoV9fFlI JpTi7mf7WpbrYHV8izmluQjkcxR8cjo1i2hdU96+hlfNEn/QmSRnB8uNJoik2qBkoMpb Kwf4rK5bNUHdnHjTnWARzhpKojkkcd5eLpmEuGIWCAT+8Lv7O01X2Ub90AikmH8gp7iN JfFgHhD+S42P0N9beyASl+/NhQyu+TJYkWABJkJV5RReq+jjhtpZGU4gP1D/+tc2zNv+ l0fAqsl4ISUQeW8YJkWV7MiXut2qCCgPOud0iRf+6teP62/U6PlSDHOry1oi97IFzpNZ MwDA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=cc:to:subject:message-id:date:from:reply-to:in-reply-to:references :mime-version:dkim-signature; bh=d4Z5B9M3A1ysbHkJqENC8RpZVhCPfB+p6MevM15Er2U=; fh=A+ATpB1bClwcyPfLWfulaEaW+4ChVGGvSxfg+IrN9nk=; b=LmiT9kXTU+AgjnCM3IIpGDGtPwUkg/in141PaPPwBmSPIgSmhpE3nAGKk0Dhv4FULf 7AjnIVEzsAYJf0SoEwonNJwymJXHcWAMnrJkYipO3rXJIkSybHSnalLzqw68sq4ADQFn CQv1Szn2kEznbuaZ6Fc0neZDUeedaxGElk6ksErKjUieFe0DxboDFerJn0eb+gVHPiZO cWtf7Uw3qqnx1oyu3OaM2oQ5rH5scrDEeyu6YBKziCJ8T+dqCUs9/uDVosLaUN7vqXpi uv3j9egasPJI29AnCBMFn3c+lQhzn2sA0dBt8EJIA+dMsiB62QY8aUcYUfBKAtN5KhUL OBPA==; darn=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=1783408062; x=1784012862; darn=postgresql.org; h=content-type:cc:to:subject:message-id:date:from:reply-to :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to:content-type; bh=d4Z5B9M3A1ysbHkJqENC8RpZVhCPfB+p6MevM15Er2U=; b=IdJmKojkADC5Q75HkCujVd/fpZMILlyf4GW6dY+x8ho74v59Vn3KJ+IPMXypdPtEdF 5wUngH69lbkh9cRqUe1zE60+08OmvpEGRXXmDvgbWE4S5zG8BSS2q0waJHZWEIe4qDa1 Zj8ZaG3DB7xgPfmajlrObXeGQm9j34bVw8N4sojhIOCks4tYEoXhMjabbuL8wH0HXgIw HtoY6YAN26oIY+lcC7m36r25ItoVqYzfAp+GWUILHgZzvoqr9EOl9ADEsWOISziVodYt PmeVNLPSYsO1AucZhZrADQjGlooYh4ouu54OUHLhC43ttBK37XNbQJx2T+zb1uqe+lCW 07yg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783408062; x=1784012862; h=content-type:cc:to:subject:message-id:date:from:reply-to :in-reply-to:references:mime-version:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=d4Z5B9M3A1ysbHkJqENC8RpZVhCPfB+p6MevM15Er2U=; b=ACnB1JpjJMi96BOzeGIVRomvsbesdVXVzwIkKQyncesRo+4SXDUXcvJDev0MK1HHA5 lXk5P/1QUaYJt2eNFzbTH3cJf3A8t5OdbmThL++Oxy6QPBQ6zwxF9NkHZHO8GhlaQuQB jW2AT1AVOfBjvulSmg2TuLhpnEwGvTu8Kcd0YCcj2uwteyfm4I4JjRWnm7+RqcPCAyu2 2U0HtJhB1df6rKcaJG69CWOuBMADXW+pEUa8EOnThykrpG64zSLh8YrpUh8vvJDk9KYK n8PDZqtbTXrtNrFlFeUEuvNrcTDXKxraP7s745MFYkThRpYQjtSBtM6h5wBTMa4B+Qnk iH2A== X-Gm-Message-State: AOJu0Yx4IagE6TgD12Z87PsrfzmGhUE4zJfmkaOkuX4Y0xjMM9Na9kF8 p0pEYcGXzDTfHqS3CHJAiNcqOPide75GLw591feFQJAmwifRZXGnjlrYm3EKPm5EKAUkFoX3Bo0 fVRVcJQc3ctLCi6roOCfQtt0tGETMBeY= X-Gm-Gg: AfdE7ck+YpJUmzh3hWyelc37FOb47FbuXVnnP18Yrpv7NLgHLtnUCp75g2pmhMFF9ub oUZFUl7POkzmhYMlYXPBDn7zuH+aZQ7xg6R8nA9D++2ZAizs+Z6bPJYZHCSuIQ687HfgZ0cmJEy NHdRIOw9IpPsQMgSwyAP20PbixS9M7xYZ9+H3mDNWxYdcWKgATgtGhIFE0PKuHsmCpllKdJPL1T fHeNpPnRt3g2cpyUPm14tOw3fq1r3idoQgzGmjf+OFxzAbsKqSu0ZQxxEKy8VqybuTLYEF12Y71 dQpEF7hbHzlFb3aAb4800Xqa9UocK9bG8NMg21hGmbqqUhDBVRp3F+7scHE9FTBLJadWUTr5y5I QVb+0mTpQGg== X-Received: by 2002:a17:907:7387:b0:bfb:1e1c:3197 with SMTP id a640c23a62f3a-c15a67cf70bmr148345866b.41.1783408061679; Tue, 07 Jul 2026 00:07:41 -0700 (PDT) MIME-Version: 1.0 References: <20260704.162841.39857602849942465.ishii@postgresql.org> <20260706.150221.1117486145015185971.ishii@postgresql.org> In-Reply-To: Reply-To: assam258@gmail.com From: Henson Choi Date: Tue, 7 Jul 2026 16:07:29 +0900 X-Gm-Features: AVVi8Cf2-CcX9InyLdUhmQbZiEU7p5g0VC-cMKxBfsctV3gu8-v6H_syeDmB2oA Message-ID: Subject: Re: Row pattern recognition To: jian.universality@gmail.com, Tatsuo Ishii Cc: pgsql-hackers@postgresql.org, zsolt.parragi@percona.com, sjjang112233@gmail.com, vik@postgresfriends.org, er@xs4all.nl, jacob.champion@enterprisedb.com, david.g.johnston@gmail.com, peter@eisentraut.org, li.evan.chao@gmail.com Content-Type: multipart/alternative; boundary="000000000000018fc60656000cea" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --000000000000018fc60656000cea Content-Type: text/plain; charset="UTF-8" Hi Tatsuo, Jian, I found a wrong result that comes from the context-absorption optimization, and wanted to run it by you both. WITH d(id, a, c) AS ( VALUES (1, true, false), (2, true, true), (3, true, false), (4, false, false)) SELECT id, count(*) OVER w AS cnt FROM d WINDOW w AS ( ORDER BY id ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING AFTER MATCH SKIP PAST LAST ROW PATTERN (A{5,} | C) DEFINE A AS a, C AS c); id | cnt ----+----- 1 | 0 2 | 0 3 | 0 4 | 0 id = 2 returns cnt = 0, but C matches [2,2] there, so it should be 1. EXPLAIN ANALYZE on the query reports "0 matched" and "2 absorbed". The cause: whether a context can be absorbed is decided from its in-progress states. Once the id=2 context records the C match [2,2], that match moves to matchedState and its C state leaves the in-progress set, so only the A run remains and the context is judged fully absorbable. The id=1 context's longer A run then dominates it and frees the whole context -- including the recorded [2,2] match. The dominance argument only covers a context's future matches; it does not account for a match already recorded on the non-absorbable branch. The fix: bring matchedState into the absorption comparison as well -- a context should be absorbed only when the absorbing context also covers the recorded match, not just the in-progress states, so a match the absorber cannot reproduce is never dropped. Best regards, Henson --000000000000018fc60656000cea Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi Tatsuo, Jian,=

I found a wrong result that comes from the context-absorption
op= timization, and wanted to run it by you both.

=C2=A0 WITH d(id, a, c= ) AS (
=C2=A0 =C2=A0 VALUES (1, true, =C2=A0false),
=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0(2, true, =C2=A0true),
=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0(3, true, =C2=A0false),
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0(4, false, false))
=C2=A0 SELECT id, count(*) OVER w AS cnt=C2=A0 FROM d
=C2=A0 WINDOW w AS (
=C2=A0 =C2=A0 ORDER BY id
=C2= =A0 =C2=A0 ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
=C2=A0 =C2= =A0 AFTER MATCH SKIP PAST LAST ROW
=C2=A0 =C2=A0 PATTERN (A{5,} | C)
= =C2=A0 =C2=A0 DEFINE A AS a, C AS c);

=C2=A0 =C2=A0id | cnt
=C2= =A0 ----+-----
=C2=A0 =C2=A0 1 | =C2=A0 0
=C2=A0 =C2=A0 2 | =C2=A0 0<= br>=C2=A0 =C2=A0 3 | =C2=A0 0
=C2=A0 =C2=A0 4 | =C2=A0 0

id =3D 2= returns cnt =3D 0, but C matches [2,2] there, so it should be
1. EXPLAI= N ANALYZE on the query reports "0 matched" and "2 absorbed&q= uot;.

The cause: whether a context can be absorbed is decided from i= ts
in-progress states. Once the id=3D2 context records the C match [2,2]= ,
that match moves to matchedState and its C state leaves the
in-prog= ress set, so only the A run remains and the context is judged
fully abso= rbable. The id=3D1 context's longer A run then dominates it
and free= s the whole context -- including the recorded [2,2] match.
The dominance= argument only covers a context's future matches; it
does not accoun= t for a match already recorded on the non-absorbable
branch.

The = fix: bring matchedState into the absorption comparison as well --
a cont= ext should be absorbed only when the absorbing context also
covers the r= ecorded match, not just the in-progress states, so a
match the absorber = cannot reproduce is never dropped.

Best regards,
Henson
--000000000000018fc60656000cea--