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 1xCIcu-00000003i82-4Bv6 for pgsql-general@arkaria.postgresql.org; Thu, 01 Oct 2026 15:23:17 +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 1xCIct-00000007eaH-10sh for pgsql-general@arkaria.postgresql.org; Thu, 01 Oct 2026 15:23:15 +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.98.2) (envelope-from ) id 1xCIcs-00000007ea9-044U for pgsql-general@lists.postgresql.org; Thu, 01 Oct 2026 15:23:14 +0000 Received: from fhigh-a2-smtp.messagingengine.com ([103.168.172.153]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1xCIcp-00000002DYC-1GSJ for pgsql-general@postgresql.org; Thu, 01 Oct 2026 15:23:12 +0000 Received: from phl-compute-05.internal (phl-compute-05.internal [10.202.2.45]) by mailfhigh.phl.internal (Postfix) with ESMTP id 138941400147 for ; Thu, 1 Oct 2026 11:23:10 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-05.internal (MEProxy); Thu, 01 Oct 2026 11:23:10 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aklaver.com; h= cc:cc:content-transfer-encoding:content-type:content-type:date :date:from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:subject:subject:to:to; s=fm3; t=1790868190; x=1790954590; bh=PDDnw1rH1k5SZiRj/i/jK7AVW7JaDrDoaaUMXJ5EFLc=; b= inOWD1dyNYrkQMS7e5Vs1pNspWzMhH8pkrhNnBb719H38dHieWSSLk6Nl7R5d0Dg iFhjOw73n2iDZyhdJsbNAK0nQBul0kUlxxeHvZljaBk046CYdxa+WNbPKiuP82Sk O/3JwLjJnO4fmTZiaqscPBemLoK6EZmu+5R+kSd5yidk1LPeLP/O/MnpW2P3knPz 5dVdfojmVy3smjIzwU1+Or47pcCM2JTj+Q0XN59sEBmZze9mOcsl9CbzkSUAQYNE D+AwBrF9lQAi1yGustfQHpvkAhTn5qnzdWLswTBiNmWkLYH7H9uSaaC2yeOcB1xz DxARp31775CBm9+BitsmEQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:subject:subject:to:to:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1790868190; x= 1790954590; bh=PDDnw1rH1k5SZiRj/i/jK7AVW7JaDrDoaaUMXJ5EFLc=; b=J pUpYgPlIcdgmqUK8KI21F6xkbATYK3r4EtvWSqWCafDxeNNdM5e94iCprLQnhdBA CxVOSe+x8DNaK1NTP6TLu8WmSOahkAvrlSUVb2PKpv58qgeLZfdhD8aY3CYVJDcI FeN7s9pd/u0TIyV36T1LHiocMNPu5xr2zEz1GsecP1+Y8yxE+JsQ76KefVueyRqX rNShvOAzLUcXJUUdfUr7KC14868ERE5DUMH/l960oDpRQI6djdAQrmXYV0pRB2uy 2KjSaTsqeHiPI9nVk7JVP7RLL1cGHaCJXmLc/mFNt6KRDB/bzo8PXHhTT4AA72Fy rMR5oiVeqA17vAi446r5w== X-DKIM2-Info: draft=ietf-dkim-dkim2-spec-06; repo=github.com/dkim2wg/interop; date=2026-09-30; sw=lmtpprox; action=sign d=aklaver.com a=rsa-sha256; DKIM2-Signature: i=1; m=1; t=1790868190; d=aklaver.com; mf=PGFkcmlhbi5rbGF2ZXJAYWtsYXZlci5jb20+; rt=PHBnc3FsLWdlbmVyYWxAcG9zdGdyZXNxbC5vcmc+; s=fm3:rsa-sha256:OQP4Lfo1A1PrzIZG8Zsr03HC7M/m2MpnU1UEJYEmAx5ycPZ 8duTf9MQXOCSaougXNa9sH/w9jZf5FVGQzon098nofGJt+ja/dgWj9/tUB9t4Bq0 xakHB9bqQwzmCQ1V5O/VjdgtDLC0zSoozo/w8cB47xIAbmlLWp9fWU4OcNgLDb3O gm97HIQDr2ANnycQh7KEL6/Ae3OPACzskgZ5EBKor36ZM9ED0qxJ/R3ViEmJg+Z0 w+dZOctBOJUz7QkKdGRPGYiTdRQpdi0UO2Y91BTIWguLlSTwDyIQ0VrDCIGZLVgY iBKmLjV+KzsMHM6MqEHIKOCi+XpxHzaD9UMPLwQ==; X-DKIM2-Info: draft=ietf-dkim-dkim2-spec-06; repo=github.com/dkim2wg/interop; date=2026-09-30; sw=lmtpprox; action=mi-m=1; hc=14; hn=cc,content-language,content-transfer-encoding,content-type, date,feedback-id,from,in-reply-to,message-id,mime-version, references,subject,to,user-agent; Message-Instance: m=1; h=sha256:c9VTmQRIXJ4d12ZgwGU5t2GqH0uyUyYjiILKHLB89bU=:jgSZj2Ha0nn/AaoJ3AQrT4eqk4fLEz1AIu3jQlsdq7Q=; X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFKpW6L34A7Hgr3AegEpmia66QtphH0TBwIkEntxCn682uI3wNSZETL6IItaACSoJ AqEvG8CLm6CsAfXj+5AjJIEJ0y6+WRWU4nwbLbx7BCwv7unMf2aNMXOQDltdgHft8sYyAU rTqRCDCAiaTkh8Qh2sfLknhnveZjEs7XmoFpPd7tQqnWFh2pAv8xUXSQvV3PGHaCzFdM3o 733oxzCdzWkmk/D0JhZ8Rw+oWWIfp5rrn67N2/aqizY06/gANejEpN5rZllUuMa7fgqmZF Hiauq4gYLsLWLpkpNft1Cb9hntVjUITz6yyNzxdzVsPETiXy7J37PzDngOYaFwhO4BigYe LLtDZffXREl/AdBhROqeWkxC862b6dA9PPmno0eQj4w7JU9lnUUYVr2m3rcsrrQMOWtSBw uqIHZfRqZWX1FouR1jLOk7ZyRuwqi6ngYNK99dFD57UyyUaFTmulRP5pwJTN3+RG4Vd7/7 lDSMS0gWH83q9T+ENRV73qWTigsjbR4UpuSDEIaBQsEtP8deO5O178iVI8JcJZyZWhnttB eONXC1TNp3rzbqB2fLxqZH3mgWJbJkZxIsL8UeaMVERq4AaNd1qwJhHDiuKIQzeE9qXSCx yqNS8AnR0qAP9sHCJNutzGJqnUxgE9nwN2JkqIqu5OMsoibnn+aRxYKzLpfg X-ME-Proxy: Feedback-ID: i76984098:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Thu, 1 Oct 2026 11:23:08 -0400 (EDT) Message-ID: <61488cb9-5b84-449a-9886-e0d3b9671aa6@aklaver.com> Date: Thu, 1 Oct 2026 08:23:08 -0700 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: Why is materialized view creation a "security-restricted operation"? To: =?UTF-8?Q?F=C3=A4rber=2C_Franz-Josef_=28StMUK=29?= , "pgsql-general@postgresql.org" Cc: "Haupt, Matthias (StMUK)" References: <77826d7580a9488ca28eb4bcfe94aa37@stmuk.bayern.de> Content-Language: en-US From: Adrian Klaver In-Reply-To: <77826d7580a9488ca28eb4bcfe94aa37@stmuk.bayern.de> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On 10/1/26 6:11 AM, Färber, Franz-Josef (StMUK) wrote: > 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. > Postgres version? > > When writing an arbitrarily complex function my_func, I claim there are cases when you want to store intermediate results into variables. And what if the intermediate results are tables? Well, Postgres/plpgsql does not support table-valued variables, so the next best choice are temp tables. Code example of what you are trying to achieve. > 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 state"): The creation of this very temp table. > > What to do now? Well it turns out I actually CAN create a NON-temp table. Is that what you want me to do? Really? Isn't this the bigger side effect: Creating a table? > > It actually does not make sense to me, restricting one effect, while allowing the much bigger effect. From previous post: " /* * 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. */ [...] In this case, a new temporary table with the same name as a normal table might suddenly get used by one of your queries. " So the effect is different. > > * What I actually needed is a table-valued variable. One I can use inside my function. Which shall also be local/unique (i. e. not being used by concurrent 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 above, that gets destroyed when leaving the function. ?: BEGIN; CREATE TEMP TABLE some_table ... CREATE MATERIALIZED VIEW some_view AS SELECT * FROM my_func(); --Where function uses the table. > 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ärber > > > P.S.: Yes, I know SQL queries are Turing complete, using CASE and WITH RECURSIVE. So in theory you could solve anything using just one SQL query, without need for any variable. But such code in general can get incomprehensible 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 operation"? > Date: 2017-01-24 17:55:40 > Message-ID: CAFBoRzdU5tiJOBZW5-3MVHW68C58rpjwpeBBcBEhpMv0SLBJsA@mail.gmail.com > > Views: > 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 > 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 clear >> 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 makes >> 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 >> > > > -- Adrian Klaver adrian.klaver@aklaver.com