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 <laurenz.a...@wien.gv.at>
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
>

Reply via email to