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.98.2) (envelope-from ) id 1xCGZu-00000003gxJ-3qir for pgsql-general@arkaria.postgresql.org; Thu, 01 Oct 2026 13:12:04 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.98.2) (envelope-from ) id 1xCGZt-00000007Lrl-1dSz for pgsql-general@arkaria.postgresql.org; Thu, 01 Oct 2026 13:12:01 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with utf8esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1xCGZs-00000007LrX-3myF for pgsql-general@lists.postgresql.org; Thu, 01 Oct 2026 13:12:01 +0000 Received: from rex-mailout.bayern.de ([193.34.207.154]) by makus.postgresql.org with utf8esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1xCGZp-00000002CeL-1H65 for pgsql-general@postgresql.org; Thu, 01 Oct 2026 13:12:00 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=bayern.de; i=@bayern.de; s=cc-yang; t=1790860317; x=1806412317; h=from:to:cc:subject:date:message-id:content-type: content-transfer-encoding:mime-version; bh=yVML0LnLBFCPeN8tcycyrXL+BxOFiSctGHeHQICw9wU=; b=VtZGykSUxbHwYIUhGLOCgWjnSny+nDgfJLIH2Wzl21CVD8ahS5wdFX0c iCr8SzvCzlQVg8vFK7nCOvo2F0Mky0VU8aQw/52LbaZgxABprnFohZyJT w7m6cMPnpHt1oNl7LSDqdNaHyVJ2SPq76MV9OxcUmCHUvoYFlf+73SOLE EqM2WQT0RJcq3ssF3WvRVoaNnQtmH5wztQBIrYwBqmxYPP0K3Li22vP6G ZgrGd9DdNhIo6+gvZe53HBrz7x/lNtsWx+WVGo8LyP6Jo++hAkabYRJdI ZfIfgQF0YpFnTJSNTUgXAvB6mZo5bpWd2LhK4lj5270MEtqjihGOa6nmf g==; X-CSE-ConnectionGUID: YaRjHKbiQe6TUUke1pNKZw== X-CSE-MsgGUID: XUqELeEMR9SlS5I2BYFEpQ== Received: from unknown (HELO rin130.bayern.de) ([10.197.20.130]) by rex142.bayern.de with ESMTP/TLS/TLS_AES_256_GCM_SHA384; 01 Oct 2026 15:11:53 +0200 X-CSE-ConnectionGUID: bwl6keb+TzSgCI8koiIqpw== X-CSE-MsgGUID: vNit/MreRmmD2SGCQY7Vwg== X-Talos-CUID: 9a23:hFPFyWxq8XVWwF0ibXT0BgUeBcR7cXDXj0vCGECTKDZqT7y0UEePrfY= X-Talos-MUID: =?us-ascii?q?9a23=3AlYYbgQ1TUgsjtjIVbN/E1TddczUj/YKvFAcoi5g?= =?us-ascii?q?8vsyobxdfEA6s0wqoTdpy?= X-BYBN-routing: post Received: from zmx-ed1-p24372.max.bayern.de ([10.173.241.233]) by rin130.bayern.de with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Oct 2026 15:11:52 +0200 Received: from ZMX-EJ2-P25850.max.bayern.de (10.173.241.200) by ZMX-ED1-P24372.max.bayern.de (10.173.241.233) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Thu, 1 Oct 2026 15:11:52 +0200 Received: from ZMX-EJ2-P25850.max.bayern.de ([10.173.241.200]) by ZMX-EJ2-P25850.max.bayern.de ([10.173.241.200]) with mapi id 15.02.2562.049; Thu, 1 Oct 2026 15:11:52 +0200 From: =?iso-8859-1?Q?F=E4rber=2C_Franz-Josef_=28StMUK=29?= To: "pgsql-general@postgresql.org" CC: "Haupt, Matthias (StMUK)" Subject: Re: Why is materialized view creation a "security-restricted operation"? Thread-Topic: Re: Why is materialized view creation a "security-restricted operation"? Thread-Index: Ad1Roy5bDQ+Mv6wTTTiUHeJSrQLucQ== Date: Thu, 1 Oct 2026 13:11:52 +0000 Message-ID: <77826d7580a9488ca28eb4bcfe94aa37@stmuk.bayern.de> Accept-Language: de-DE, en-US Content-Language: de-DE X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.171.65.1] Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Dear Postgres Community, some questions about this 9-year-old post below. I also stumbled over a similar case as the failing CREATE MATERIALIZED VIEW some_view AS SELECT * FROM my_func(); . where my_func tries to create a temp table. When writing an arbitrarily complex function my_func, I claim there are cas= es when you want to store intermediate results into variables. And what if = the intermediate results are tables? Well, Postgres/plpgsql does not suppor= t table-valued variables, so the next best choice are temp tables. But here we have: Creating temp tables is forbidden inside a mat view, see = the mail below. Because we might have a side effect ("change of seesion sta= te"): The creation of this very temp table. What to do now? Well it turns out I actually CAN create a NON-temp table. I= s that what you want me to do? Really? Isn't this the bigger side effect: C= reating a table? It actually does not make sense to me, restricting one effect, while allowi= ng the much bigger effect. * What I actually needed is a table-valued variable. One I can use inside m= y function. Which shall also be local/unique (i. e. not being used by concu= rrent users or sessions, or even in the call stack of the very same session= ). * The next best thing would be a temp table, local/unique in the sense as a= bove, that gets destroyed when leaving the function. Invent some CREATE TEMP TABLE . ON EXIT FUNCTION DROP? (.and wouldn't that be quite equivalent to table-valued variables?) Any suggestions? Thank You. Regards, Franz-Josef F=E4rber P.S.: Yes, I know SQL queries are Turing complete, using CASE and WITH RECU= RSIVE. So in theory you could solve anything using just one SQL query, with= out need for any variable. But such code in general can get incomprehensibl= e and/or inperformant, I think. Re: Why is materialized view creation a "security-restricted operation"? From: Joshua Chamberlain To: Albe Laurenz Cc: "Joshua Chamberlain *EXTERN*" , "pgsql-general(= at)postgresql(dot)org" Subject: Re: Why is materialized view creation a "security-restricted opera= tion"? Date: 2017-01-24 17:55:40 Message-ID: CAFBoRzdU5tiJOBZW5-3MVHW68C58rpjwpeBBcBEhpMv0SLBJsA@mail.gmail.= com Views:=09 Thread: 2017-01-23 19:06:19 from Joshua Chamberlain 2017-01-24 11:18:34 from Albe Laurenz 2017-01-24 17:55:40 from Joshua Chamberlain =20 Lists: pgsql-general Thank you for the explanation! That's extremely helpful. It also makes sense now why my function can create a regular table even if not a temporary one. It seems a little strange that it doesn't apply to VIEWs as well, as I imagine selecting from a view would have the same potential for unexpected side-effects. But if REFRESH MATERIALIZED VIEW is generally used in higher-privilege session, I guess that could make sense. I'll just have to adjust my code a bit. Thanks, Joshua Chamberlain On Tue, Jan 24, 2017 at 3:18 AM, Albe Laurenz wrote: > Joshua Chamberlain wrote: > > I see this has been discussed briefly before[1], but I'm still not clea= r > on what's happening and why. > > > > I wrote a function that uses temporary tables in generating a result > set. I can use it when creating > > tables or views, e.g., > > CREATE TABLE some_table AS SELECT * FROM my_func(); > > CREATE VIEW some_view AS SELECT * FROM my_func(); > > > > But creating a materialized view fails: > > CREATE MATERIALIZED VIEW some_view AS SELECT * FROM my_func(); > > > > ERROR: cannot create temporary table within security-restricted > operation > > > > > > The docs explain that this is expected[2], but not why. On the contrary= , > this is actually quite > > surprising to me, given that tables and views work just fine. What make= s > a materialized view so > > different? Are there any plans to make this more consistent? > > There is a comment in the source that explains it quite well: > > /* > * Security check: disallow creating temp tables from > security-restricted > * code. This is needed because calling code might not expect > untrusted > * tables to appear in pg_temp at the front of its search path. > */ > > "Security-restricted" is explained in this comment: > > * SECURITY_RESTRICTED_OPERATION indicates that we are inside an operation > * that does not wish to trust called user-defined functions at all. This > * bit prevents not only SET ROLE, but various other changes of session > state > * that normally is unprotected but might possibly be used to subvert the > * calling session later. An example is replacing an existing prepared > * statement with new code, which will then be executed with the outer > * session's permissions when the prepared statement is next used. Since > * these restrictions are fairly draconian, we apply them only in contexts > * where the called functions are really supposed to be side-effect-free > * anyway, such as VACUUM/ANALYZE/REINDEX. > > > The idea here is that if you run REFRESH MATERIALIZED VIEW, > you don't want it to change the state of your session. > In this case, a new temporary table with the same name as a normal table > might suddenly get used by one of your queries. > > I guess that the problem is probably more relevant here that in other > places > because REFRESH MATERIALIZED VIEW is likely to be regularly called in > sessions > with high privileges. > > Yours, > Laurenz Albe >