@@ -59,12 +59,13 @@ static void transientrel_receive(TupleTableSlot *slot, DestReceiver *self);
59
59
static void transientrel_shutdown (DestReceiver * self );
60
60
static void transientrel_destroy (DestReceiver * self );
61
61
static void refresh_matview_datafill (DestReceiver * dest , Query * query ,
62
- const char * queryString , Oid relowner );
62
+ const char * queryString );
63
63
64
64
static char * make_temptable_name_n (char * tempname , int n );
65
65
static void mv_GenerateOper (StringInfo buf , Oid opoid );
66
66
67
- static void refresh_by_match_merge (Oid matviewOid , Oid tempOid );
67
+ static void refresh_by_match_merge (Oid matviewOid , Oid tempOid , Oid relowner ,
68
+ int save_sec_context );
68
69
static void refresh_by_heap_swap (Oid matviewOid , Oid OIDNewHeap );
69
70
70
71
static void OpenMatViewIncrementalMaintenance (void );
@@ -142,12 +143,15 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
142
143
List * actions ;
143
144
Query * dataQuery ;
144
145
Oid tableSpace ;
145
- Oid owner ;
146
+ Oid relowner ;
146
147
Oid OIDNewHeap ;
147
148
DestReceiver * dest ;
148
149
bool concurrent ;
149
150
LOCKMODE lockmode ;
150
151
char relpersistence ;
152
+ Oid save_userid ;
153
+ int save_sec_context ;
154
+ int save_nestlevel ;
151
155
152
156
/* Determine strength of lock needed. */
153
157
concurrent = stmt -> concurrent ;
@@ -232,6 +236,19 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
232
236
*/
233
237
SetMatViewPopulatedState (matviewRel , !stmt -> skipData );
234
238
239
+ relowner = matviewRel -> rd_rel -> relowner ;
240
+
241
+ /*
242
+ * Switch to the owner's userid, so that any functions are run as that
243
+ * user. Also arrange to make GUC variable changes local to this command.
244
+ * Don't lock it down too tight to create a temporary table just yet. We
245
+ * will switch modes when we are about to execute user code.
246
+ */
247
+ GetUserIdAndSecContext (& save_userid , & save_sec_context );
248
+ SetUserIdAndSecContext (relowner ,
249
+ save_sec_context | SECURITY_LOCAL_USERID_CHANGE );
250
+ save_nestlevel = NewGUCNestLevel ();
251
+
235
252
/* Concurrent refresh builds new data in temp tablespace, and does diff. */
236
253
if (concurrent )
237
254
{
@@ -244,8 +261,6 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
244
261
relpersistence = matviewRel -> rd_rel -> relpersistence ;
245
262
}
246
263
247
- owner = matviewRel -> rd_rel -> relowner ;
248
-
249
264
/*
250
265
* Create the transient table that will receive the regenerated data. Lock
251
266
* it against access by any other process until commit (by which time it
@@ -256,9 +271,15 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
256
271
LockRelationOid (OIDNewHeap , AccessExclusiveLock );
257
272
dest = CreateTransientRelDestReceiver (OIDNewHeap );
258
273
274
+ /*
275
+ * Now lock down security-restricted operations.
276
+ */
277
+ SetUserIdAndSecContext (relowner ,
278
+ save_sec_context | SECURITY_RESTRICTED_OPERATION );
279
+
259
280
/* Generate the data, if wanted. */
260
281
if (!stmt -> skipData )
261
- refresh_matview_datafill (dest , dataQuery , queryString , owner );
282
+ refresh_matview_datafill (dest , dataQuery , queryString );
262
283
263
284
heap_close (matviewRel , NoLock );
264
285
@@ -269,7 +290,8 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
269
290
270
291
PG_TRY ();
271
292
{
272
- refresh_by_match_merge (matviewOid , OIDNewHeap );
293
+ refresh_by_match_merge (matviewOid , OIDNewHeap , relowner ,
294
+ save_sec_context );
273
295
}
274
296
PG_CATCH ();
275
297
{
@@ -282,6 +304,12 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
282
304
else
283
305
refresh_by_heap_swap (matviewOid , OIDNewHeap );
284
306
307
+ /* Roll back any GUC changes */
308
+ AtEOXact_GUC (false, save_nestlevel );
309
+
310
+ /* Restore userid and security context */
311
+ SetUserIdAndSecContext (save_userid , save_sec_context );
312
+
285
313
return matviewOid ;
286
314
}
287
315
@@ -290,26 +318,13 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
290
318
*/
291
319
static void
292
320
refresh_matview_datafill (DestReceiver * dest , Query * query ,
293
- const char * queryString , Oid relowner )
321
+ const char * queryString )
294
322
{
295
323
List * rewritten ;
296
324
PlannedStmt * plan ;
297
325
QueryDesc * queryDesc ;
298
- Oid save_userid ;
299
- int save_sec_context ;
300
- int save_nestlevel ;
301
326
Query * copied_query ;
302
327
303
- /*
304
- * Switch to the owner's userid, so that any functions are run as that
305
- * user. Also lock down security-restricted operations and arrange to
306
- * make GUC variable changes local to this command.
307
- */
308
- GetUserIdAndSecContext (& save_userid , & save_sec_context );
309
- SetUserIdAndSecContext (relowner ,
310
- save_sec_context | SECURITY_RESTRICTED_OPERATION );
311
- save_nestlevel = NewGUCNestLevel ();
312
-
313
328
/* Lock and rewrite, using a copy to preserve the original query. */
314
329
copied_query = copyObject (query );
315
330
AcquireRewriteLocks (copied_query , true, false);
@@ -353,12 +368,6 @@ refresh_matview_datafill(DestReceiver *dest, Query *query,
353
368
FreeQueryDesc (queryDesc );
354
369
355
370
PopActiveSnapshot ();
356
-
357
- /* Roll back any GUC changes */
358
- AtEOXact_GUC (false, save_nestlevel );
359
-
360
- /* Restore userid and security context */
361
- SetUserIdAndSecContext (save_userid , save_sec_context );
362
371
}
363
372
364
373
DestReceiver *
@@ -529,7 +538,8 @@ mv_GenerateOper(StringInfo buf, Oid opoid)
529
538
* this command.
530
539
*/
531
540
static void
532
- refresh_by_match_merge (Oid matviewOid , Oid tempOid )
541
+ refresh_by_match_merge (Oid matviewOid , Oid tempOid , Oid relowner ,
542
+ int save_sec_context )
533
543
{
534
544
StringInfoData querybuf ;
535
545
Relation matviewRel ;
@@ -543,9 +553,6 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid)
543
553
ListCell * indexoidscan ;
544
554
int16 relnatts ;
545
555
bool * usedForQual ;
546
- Oid save_userid ;
547
- int save_sec_context ;
548
- int save_nestlevel ;
549
556
550
557
initStringInfo (& querybuf );
551
558
matviewRel = heap_open (matviewOid , NoLock );
@@ -596,6 +603,9 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid)
596
603
SPI_getvalue (SPI_tuptable -> vals [0 ], SPI_tuptable -> tupdesc , 1 ))));
597
604
}
598
605
606
+ SetUserIdAndSecContext (relowner ,
607
+ save_sec_context | SECURITY_LOCAL_USERID_CHANGE );
608
+
599
609
/* Start building the query for creating the diff table. */
600
610
resetStringInfo (& querybuf );
601
611
appendStringInfo (& querybuf ,
@@ -690,9 +700,12 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid)
690
700
if (SPI_exec (querybuf .data , 0 ) != SPI_OK_UTILITY )
691
701
elog (ERROR , "SPI_exec failed: %s" , querybuf .data );
692
702
703
+ SetUserIdAndSecContext (relowner ,
704
+ save_sec_context | SECURITY_RESTRICTED_OPERATION );
705
+
693
706
/*
694
707
* We have no further use for data from the "full-data" temp table, but we
695
- * must keep it around because its type is reference from the diff table.
708
+ * must keep it around because its type is referenced from the diff table.
696
709
*/
697
710
698
711
/* Analyze the diff table. */
@@ -703,16 +716,6 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid)
703
716
704
717
OpenMatViewIncrementalMaintenance ();
705
718
706
- /*
707
- * Switch to the owner's userid, so that any functions are run as that
708
- * user. Also lock down security-restricted operations and arrange to
709
- * make GUC variable changes local to this command.
710
- */
711
- GetUserIdAndSecContext (& save_userid , & save_sec_context );
712
- SetUserIdAndSecContext (matviewRel -> rd_rel -> relowner ,
713
- save_sec_context | SECURITY_RESTRICTED_OPERATION );
714
- save_nestlevel = NewGUCNestLevel ();
715
-
716
719
/* Deletes must come before inserts; do them first. */
717
720
resetStringInfo (& querybuf );
718
721
appendStringInfo (& querybuf ,
@@ -733,12 +736,6 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid)
733
736
if (SPI_exec (querybuf .data , 0 ) != SPI_OK_INSERT )
734
737
elog (ERROR , "SPI_exec failed: %s" , querybuf .data );
735
738
736
- /* Roll back any GUC changes */
737
- AtEOXact_GUC (false, save_nestlevel );
738
-
739
- /* Restore userid and security context */
740
- SetUserIdAndSecContext (save_userid , save_sec_context );
741
-
742
739
/* We're done maintaining the materialized view. */
743
740
CloseMatViewIncrementalMaintenance ();
744
741
heap_close (tempRel , NoLock );
0 commit comments