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 1w3vfc-001gwa-00 for pgsql-hackers@arkaria.postgresql.org; Sat, 21 Mar 2026 12:43:12 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1w3vfY-00AJW5-0a for pgsql-hackers@arkaria.postgresql.org; Sat, 21 Mar 2026 12:43:08 +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 1w3vfX-00AJVw-2J for pgsql-hackers@lists.postgresql.org; Sat, 21 Mar 2026 12:43:08 +0000 Received: from mail-pj1-x1032.google.com ([2607:f8b0:4864:20::1032]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1w3vfV-00000000K68-2GrA for pgsql-hackers@postgresql.org; Sat, 21 Mar 2026 12:43:07 +0000 Received: by mail-pj1-x1032.google.com with SMTP id 98e67ed59e1d1-35691a231a7so1623150a91.3 for ; Sat, 21 Mar 2026 05:43:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1774096984; cv=none; d=google.com; s=arc-20240605; b=k6Fw0fNr+OQDzGtgLkgWAlVm1JpoaHNDS25M6GQW+lGMaZUnS1+wsDOnsSbkP205fc YPsMD5Xb4cwGuNcKzOc/NZmIZXjPn8ALOQLfd7lIE/U4zZiJsRiSLPtQmm+L6TMapkSz nZodeFcbY6+so0dZJUEM6mPjSRYRCOKGhQ8W2IceeINopch6Q87Eh+VIRJ4MTqX13me3 CMQmAVwdCMYsfZyuuVS41CPdvz4yNWkglvkqWlClzs45Q4VfgDApBYa6qLGDoRbUL8k2 PkT+Hx4g9aG7p0czbgoutaRzrGofd/m64Oe9ges1FBsKuMUlKPTqUmohwLPcCriPuOOy 2n4A== 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:reply-to:in-reply-to:references :mime-version:dkim-signature; bh=17a1bzWqOS0DqBBiBor3Yo1kzq/uW23ODFpqkRurgjU=; fh=z6C4gDoQV1Z0m7NRKJVdITOMEvbWTz35JlyVP7grT40=; b=CYuRyqVe/2itQZYZyN3PUINsFW2JFKXSA5l55dBgzezH5QyuhKpH0i/LZyB4Wn2oop D3FuIrHFwCBWotSpwCf3WrJt8xdN7Q2FOZeSqK4AFNRHT9UHc2Xfe7bwDfud+v99Yggi 3JOe2vmu6lejuWMjqIdODQjj6ke/Q8S1RtmiCjmZkP3y6uYzqAD7TbqgRDAwp2NfXHXh HqS6/LlOKdFtdMWLc2nPHelVrDRS1G1ml3gZ4LxhIsqtCfaTcRFmzMFa3aWPzH3PtF1y MiTgzzY8z/1LE78DFnOej94iDbyqqDanAnWo9OxmdnJyUr1F7JhrBTLMeLx1+ybbu2VM 1Htw==; 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=20230601; t=1774096984; x=1774701784; darn=postgresql.org; h=cc:to:subject:message-id:date:from:reply-to:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=17a1bzWqOS0DqBBiBor3Yo1kzq/uW23ODFpqkRurgjU=; b=bnMAN2ZJCny59HHFmbkFgqfDUQygEAqCkQE6AdELGmjmvM8d5PSxYR1eaU6QA7Pyz7 BgQiPq14jyy5FpZWDBIMfxxF6PlvZpKICZ1tUUuFQoeIqKElIXUVQsoXAsvNgNXuZmId t44J1eB2Qkmo8w8t3bwNIOfQorpCE0aU3iYbRk8aDSHH7VmQXjuAkV1//aZgRB92mwTr jaPHt1szxAiTFU+uEyEw5TCafDXgVmIkBSwU48KU7JHKFgVzkNc5+Nv6OQJa9odNHWfc p7fD3fL10aM47kgAHwQoci3DgCO1WuXxL0OYj0d4pepR6uQyAEJWPvU2EZvR0hqe1Xtg 1OEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774096984; x=1774701784; h=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; bh=17a1bzWqOS0DqBBiBor3Yo1kzq/uW23ODFpqkRurgjU=; b=B2mC5rg098MyAYJSuaI9ZKZQJrmPFOiAtanAVbbztQyjdU4Vo84nz2NXg86GH2SGyd bD3egC7q02od3YE/8nkJMSAwlr2hZ2RtDdatq69kmMnn4QKLL2f6BsVMilcH6YoODXUK F94g2L+lHt+iqJU6drWG3sWM6mmP6Cwwr7eRKRNFFEqtjHc4kvvl+T08heEnxpzG4tj/ +oJWRztFtARHfOxG28McPUgbQbekrJg+fb7bjH0wD1Ey4PMk5s4jfmIr+vbr7q0BQOb5 +r0tVS+nnZh5/WbRBY8XNWvjKVMKQYFFU/17jHHgCaS8optJrtQA4PLIfq3azMIA5pO0 9x4w== X-Forwarded-Encrypted: i=1; AJvYcCWMJelKznLG0s/Z8N+IyD0rSSxxJ3hKrV8BOFIcUFjJLSMtjmQX9imUJSUPiE/+1doZWEPsSHe3iXfR7PXj@postgresql.org X-Gm-Message-State: AOJu0YxLP7tG/Ek7mUX64F4hBMSRMU8YVSqmjx8o95rK9z8I8U8ZzbtP 2YtZ6gNvEhZ1JwwV4x9aK6aGzw1JfB0Y4hIk0oXYsywkpOfcKXq0S14I86EqVhw+S4z4/glcK3X w/M6Hald1phHs9TsJxq9B6hIWnHKfO7Q= X-Gm-Gg: ATEYQzyPzs35z2qaxILa7aqAF6vANZyt0u0Df+I1483EFfLRXyrugqQ505dVnK2pQcf i1DglRmgYICVwNqdj7dAYPuK3AtGbnPIEkx4dKDFCO0P+p2B/Ne4EMxjtf1XOFpS1mrEv6YEwIc ct6BBltdkLbyYVlxGkrXGq5iMemyDsIxql/G1ygQveTnnHy7dlrJCdxQ4DlzBvOjNmCRsdqVKSM PuI1qqFVqq9F5rD31rFJq8JNDErlweYmxo/VtkB0/ZihSDUn0sRfnyipJxF1GHq1t+MzIUsrKDH A3sgzQywZqtzlTXJqB5hu2deWwzIoE7MExOheu+y X-Received: by 2002:a17:90a:517:b0:35b:e4f8:55ab with SMTP id 98e67ed59e1d1-35be4f87ae4mr328209a91.6.1774096984417; Sat, 21 Mar 2026 05:43:04 -0700 (PDT) MIME-Version: 1.0 References: <20260319.121550.1075916211106201460.ishii@postgresql.org> <20260319.191035.328225166092779523.ishii@postgresql.org> <20260321.140232.1947157589839395257.ishii@postgresql.org> In-Reply-To: <20260321.140232.1947157589839395257.ishii@postgresql.org> Reply-To: assam258@gmail.com From: Henson Choi Date: Sat, 21 Mar 2026 21:42:52 +0900 X-Gm-Features: AaiRm50XkPl_4dAYzXF-yQhcaSKaoKERXnRKqmhhUYx9xBRab1XFenYtalgWM8Q Message-ID: Subject: Re: Row pattern recognition To: Tatsuo Ishii Cc: 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, pgsql-hackers@postgresql.org Content-Type: multipart/alternative; boundary="0000000000008daba4064d8824da" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --0000000000008daba4064d8824da Content-Type: text/plain; charset="UTF-8" Hi Tatsuo, > 0004: Fix window_last_value set_mark during RPR > > Restore set_mark=true in window_last_value (normal behavior) > > and add an RPR-specific override inside WinGetFuncArgInFrame. > > This keeps the RPR workaround localized rather than changing > > the caller's semantics unconditionally. > > So, if RPR is active, WinSetMarkPosition() is not called at all? That > seems too strong limitation. Can't we set mark at frameheadpos even > if RPR is active? It seems safe since the only allowed franme start > option is ROWS BETWEEN CURRENT ROW and we never step back to the rows > before frameheadpos. You raise a valid point. Setting mark at frameheadpos would be safe for the window function's own read pointer, since we only allow ROWS BETWEEN CURRENT ROW. However, the difficulty is with the PREV/NEXT navigation. In the experimental patch, PREV accepts an optional offset argument -- e.g. PREV(price, N) -- and this offset can be a runtime expression whose value is not known until evaluation time. If the mark is advanced to frameheadpos, PREV(price, N) with a large N could try to access rows that the tuplestore has already truncated. This is why the experimental patch takes a different approach: it creates a separate nav_winobj with its own mark pointer pinned at position 0, so that the tuplestore never truncates rows that PREV might need. The window function's own mark management is left unchanged. The mark=0 approach is safe but conservative -- it prevents the tuplestore from releasing any rows within the partition. The SQL standard (ISO/IEC 19075-5, Subclause 5.6.2) requires the offset argument to be a "runtime constant" -- meaning it cannot reference columns or row pattern variables. So in practice, the maximum offset is always known at plan time, which opens the door for a future optimization: advance the mark to (currentpos - max_offset) when all PREV offsets in the DEFINE clause are constant. Since the experimental patch redesigns how mark works for PREV/NEXT navigation, I think we should drop 0004 from the current series and revisit the set_mark question together with the experimental patch. What do you think? Best regards, Henson --0000000000008daba4064d8824da Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi Tatsuo,

>=C2=A0 =C2=A00004: Fix window_last_value set_mark during RPR
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Restore set_mark=3Dtrue in window_las= t_value (normal behavior)
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0and add an RPR-specific override insi= de WinGetFuncArgInFrame.
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This keeps the RPR workaround localiz= ed rather than changing
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0the caller's semantics unconditio= nally.

So, if RPR is active, WinSetMarkPosition() is not called at all?=C2=A0 That=
seems too strong limitation.=C2=A0 Can't we set mark at frameheadpos ev= en
if RPR is active? It seems safe since the only allowed franme start
option is ROWS BETWEEN CURRENT ROW and we never step back to the rows
before frameheadpos.

You raise a valid point. Se= tting mark at frameheadpos would be safe
for the window function's o= wn read pointer, since we only allow
ROWS BETWEEN CURRENT ROW.

Ho= wever, the difficulty is with the PREV/NEXT navigation. In the
experimen= tal patch, PREV accepts an optional offset argument --
e.g. PREV(price, = N) -- and this offset can be a runtime expression
whose value is not kno= wn until evaluation time. If the mark is
advanced to frameheadpos, PREV(= price, N) with a large N could try
to access rows that the tuplestore ha= s already truncated.

This is why the experimental patch takes a diff= erent approach: it
creates a separate nav_winobj with its own mark point= er pinned at
position 0, so that the tuplestore never truncates rows tha= t PREV
might need. The window function's own mark management is left=
unchanged.

The mark=3D0 approach is safe but conservative -- it = prevents the
tuplestore from releasing any rows within the partition. Th= e SQL
standard (ISO/IEC 19075-5, Subclause 5.6.2) requires the offsetargument to be a "runtime constant" -- meaning it cannot referen= ce
columns or row pattern variables. So in practice, the maximum
offs= et is always known at plan time, which opens the door for a
future optim= ization: advance the mark to (currentpos - max_offset)
when all PREV off= sets in the DEFINE clause are constant.

Since the experimental patch= redesigns how mark works for PREV/NEXT
navigation, I think we should dr= op 0004 from the current series
and revisit the set_mark question togeth= er with the experimental
patch. What do you think?

Best regards,<= br>Henson=C2=A0
--0000000000008daba4064d8824da--