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 1wSnMs-0006QP-1L for pgsql-hackers@arkaria.postgresql.org; Fri, 29 May 2026 02:54:38 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wSnLr-0018c7-1p for pgsql-hackers@arkaria.postgresql.org; Fri, 29 May 2026 02:53:35 +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 1wSnLr-0018bz-0V for pgsql-hackers@lists.postgresql.org; Fri, 29 May 2026 02:53:35 +0000 Received: from mail-vs1-xe34.google.com ([2607:f8b0:4864:20::e34]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wSnLo-000000003UX-2vy3 for pgsql-hackers@lists.postgresql.org; Fri, 29 May 2026 02:53:34 +0000 Received: by mail-vs1-xe34.google.com with SMTP id ada2fe7eead31-6313157e181so476941137.1 for ; Thu, 28 May 2026 19:53:32 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1780023212; cv=none; d=google.com; s=arc-20240605; b=hHnV3R8Ci9f0ab+ETz93288QHbIuab6+vh2nwvJzZTaRfZMtqqjnaEgrg11xQZALt2 54MLXspyoM6aotrFaz2wqqt/1kUZAk2/dS1PTwLAox1JhV8mZZShhyO8Nd2gYa393wUG PB6KtcmmZ3bqiF4XpCdeOgevAt9WNEm8/h7o/mMlUPM8NdKffTDfL6olW0uSOwSLuZbM 8hdypZbEM/gmsA5c+zzWsaMb27ghApD1N+LlWK0PNyC9ympWbAjG8I1B2zuU4H9fNN99 l9is8zTiEoGq1nzGQAffJK+cJQI1MVOMEAtc6aSEALi3B5Zo2isuYEPYRJ/7SNOW3Kqp XEXA== 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=dUlhG8p5kpXoWLVr4og36ZNBqql3aBBWOLTApnqMG6U=; fh=jA1y0o48KsEr1ncbKeaqgkONBUmAh+4Dc8UAqTSPpFs=; b=L0EJHVRDeoBv8nlmOhewqJFqNg5z6jUdlqUBAxKFdDKECuZbdu4/PCGlrPM5Gd8nvh RXhoYxW/jDCRoBDbDdre+p2nvhwWT6qXeCcD4FuvnMpLQTKuQy8hFdS+3ZxmzRZoLm1N 67A9IA1fnT62OM7ClVLTUq4L/vdz9y7oF9YONZ6ASVPmRSwrXyW91YYFsD3kb0bzYExw LOF02iAsYtI1qWILon9uYF4WV/EepS+RLdII5veR7+ddOPVWhMW8yafZbQcBUQ4hZhOE zgkKpCfR6wo+Sj4/1DdQxJjliVmrQ8dLCIvICo6DhZ5noC+7vQrzSa0Ok5YFwDQB2S/f e3eg==; 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=1780023212; x=1780628012; 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=dUlhG8p5kpXoWLVr4og36ZNBqql3aBBWOLTApnqMG6U=; b=AAW57Fffy2SkzRDL1+lI3WFF4IWa0Ya9BmYL4PCWSovZcCYV/PWUnsymR9Je3uqPer /c21cyS1Se4V9ZKA38qnqGlvzcnafmJGohbV0s2ttrptDIIIhc+5MppJHeV6XY3dg0fz tMPwaqhiFQzzGMuExvXHnK/TtRBHMEG1+uiLPlkG6AYO8AdF83m0n3i+W2VfNNg0/Vkk lqnVqeOysCFFEftgx8HHtWZyczzSEiomofGtw7GWd0Td99CXGVy4bZMUKH+ye+uP6iK7 A6iuzLiCum20DXVWQrDVugE4hNwxhpS83faqXKYdp7SdmoNo+8991wthSZbxeH7kFqho 4TxA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780023212; x=1780628012; 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=dUlhG8p5kpXoWLVr4og36ZNBqql3aBBWOLTApnqMG6U=; b=R6XCnJOfKJsTInu/Jc62rmy4FBdrAJliC7FVPDS6eIHiJSFe8Ol8JDQoVIinGD68Vz VlO0AFBkjvH84sKk3HdVrZdafBOPdcOleZv/AKonVb527gqmEfbBYClLuvYHsimTyaZ8 Sxpn0O7hYuUt3QuhsiGz+GAAAtTKTyt9ZnnO08wQTrZfX+CAJtm0QNaGoSt0YeVH2oO8 HCxmgupkmnd8TfPtWuXnwybMxsv3xd2FrPGWAdwqsbPi+P/8XHQfIM+f3/W9Po5so+y+ Bea0xAwlZnFFCo4WWVhCzRovXQQ7rxbPGtqAxJMew7Emyidw1LK5d1tymulDmXr8x3Rs aUfw== X-Gm-Message-State: AOJu0YwIiSHJZyrKhU6HgYk8HXWX2NbgHiK0tZ3Byirfk89MsHSLw+eR PUfAAJuHK8+wWwBKb+fLq8rKPhcE62yoH24c1AIxn9fS7jwrhYPtqct40l5ysiRaqw4lnvKSibI p06w5YL3VC97TsrKzXS+DHpmV6zffZBY= X-Gm-Gg: Acq92OFwDEMrirzX6pcWJ1yochG3CsSFHoc7hazpAIR1doUnwrdVK6rKZul7XR08RZM BNklKdvrpBK6a0y3ATX/LAH1+29Vj6ShJQ3SlNtzkUj7lDNwoVMvsSV5aOXVuWhc+uVyFWRfAhh +NL88XEYPGmUOTXnRqj6wh9A72C8i8APL/ej5hgSKddVCBMeCf2CYsXbrFvhqqSA8w72UR1RaeB 8EhoAcq5LjkCVo7iKbiDieVM/4Jhm46M7W2n+ugomeE8SvlEd0nULwR6GTeG1L4zjNpKzhsnAb5 ecjgPgdTeDopMPgWlQ== X-Received: by 2002:a05:6102:2a56:b0:631:bcfa:39d2 with SMTP id ada2fe7eead31-6bf3efbe7afmr85067137.6.1780023211582; Thu, 28 May 2026 19:53:31 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Adam Brusselback Date: Thu, 28 May 2026 22:53:15 -0400 X-Gm-Features: AVHnY4I84ah2DDCpE7_O4ag_BhaFaFsrnusLFFQSPvF94cJT_RbiQz6AdkOZcPg Message-ID: Subject: Re: [Patch] Add WHERE clause support to REFRESH MATERIALIZED VIEW To: Zsolt Parragi Cc: pgsql-hackers@lists.postgresql.org Content-Type: multipart/alternative; boundary="00000000000037e7d90652ebf3d5" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --00000000000037e7d90652ebf3d5 Content-Type: text/plain; charset="UTF-8" Hi Zsolt, and hackers, On the privilege escalation: Yup, that isn't good. Thank you for catching that. In both paths the predicate is concatenated directly into the SQL that evaluates the view, e.g. in refresh_by_direct_modification: SELECT * FROM () mv WHERE () and in refresh_by_match_merge: SELECT ctid, * FROM WHERE () There's one plan, executed under one userid. I can't run the () subquery as the owner and the WHERE () as the invoker, SPI executes the whole statement in whatever security context is active when it runs. So the predicate runs as the owner. The levers left are what the predicate may contain and who may run it. Here is what I was thinking: - Predicate functions all leakproof: allow for anyone with the privilege to refresh today (MAINTAIN or owner). A leakproof predicate in owner context can't leak the owner's data or do anything the invoker couldn't, so nothing escalates. - Predicate contains a non-leakproof function: require ownership (or superuser). Invoker and owner are then the same trust domain, so owner-context execution doesn't escalate. This keeps MAINTAIN working for the common case, predicates over columns with built-in operators. The tightening only hits custom non-leakproof predicate functions. If anyone else has better ideas, i'm all ears. Your second issue is due to a missing PG_TRY around the OpenMatViewIncrementalMaintenance()/Close pair in the direct-modification path (the match/merge site already handles it). An error between open and close goes past the close and leaves matview_maintenance_depth above zero for the session, which is what lets plain DELETE/INSERT through afterward. Will fix. Thanks, Adam --00000000000037e7d90652ebf3d5 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi Zsolt, and hackers,

On the privilege escalation:= Yup, that isn't good. Thank you for catching that.=C2=A0
In both pa= ths the predicate is concatenated directly into the SQL that evaluates the = view, e.g. in refresh_by_direct_modification:
=C2=A0 =C2=A0 SELECT * FRO= M (<view definition>) mv WHERE (<predicate>)

and in refr= esh_by_match_merge:
=C2=A0 =C2=A0 SELECT ctid, * FROM <matview> WH= ERE (<predicate>)

There's one plan, executed under one use= rid. I can't run the (<view definition>) subquery as the owner an= d the WHERE (<predicate>) as the invoker, SPI executes the whole stat= ement in whatever security context is active when it runs.

So the pr= edicate runs as the owner. The levers left are what the predicate may conta= in and who may run it. Here is what I was thinking:
- Predicate function= s all leakproof: allow for anyone with the privilege to refresh today (MAIN= TAIN or owner). A leakproof predicate in owner context can't leak the o= wner's data or do anything the invoker couldn't, so nothing escalat= es.
- Predicate contains a non-leakproof function: require ownership (or= superuser). Invoker and owner are then the same trust domain, so owner-con= text execution doesn't escalate.

This keeps MAINTAIN working for= the common case, predicates over columns with built-in operators. The tigh= tening only hits custom non-leakproof predicate functions.

If anyone= else has better ideas, i'm all ears.


Your second issue is d= ue to a missing PG_TRY around the OpenMatViewIncrementalMaintenance()/Close= pair in the direct-modification path (the match/merge site already handles= it). An error between open and close goes past the close and leaves matvie= w_maintenance_depth above zero for the session, which is what lets plain DE= LETE/INSERT through afterward. Will fix.

Thanks,
Adam
--00000000000037e7d90652ebf3d5--