@@ -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,11 +143,14 @@ 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 ;
151
+ Oid save_userid ;
152
+ int save_sec_context ;
153
+ int save_nestlevel ;
150
154
151
155
/* Determine strength of lock needed. */
152
156
concurrent = stmt -> concurrent ;
@@ -231,14 +235,25 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
231
235
*/
232
236
SetMatViewPopulatedState (matviewRel , !stmt -> skipData );
233
237
238
+ relowner = matviewRel -> rd_rel -> relowner ;
239
+
240
+ /*
241
+ * Switch to the owner's userid, so that any functions are run as that
242
+ * user. Also arrange to make GUC variable changes local to this command.
243
+ * Don't lock it down too tight to create a temporary table just yet. We
244
+ * will switch modes when we are about to execute user code.
245
+ */
246
+ GetUserIdAndSecContext (& save_userid , & save_sec_context );
247
+ SetUserIdAndSecContext (relowner ,
248
+ save_sec_context | SECURITY_LOCAL_USERID_CHANGE );
249
+ save_nestlevel = NewGUCNestLevel ();
250
+
234
251
/* Concurrent refresh builds new data in temp tablespace, and does diff. */
235
252
if (concurrent )
236
253
tableSpace = GetDefaultTablespace (RELPERSISTENCE_TEMP );
237
254
else
238
255
tableSpace = matviewRel -> rd_rel -> reltablespace ;
239
256
240
- owner = matviewRel -> rd_rel -> relowner ;
241
-
242
257
/*
243
258
* Create the transient table that will receive the regenerated data. Lock
244
259
* it against access by any other process until commit (by which time it
@@ -249,9 +264,15 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
249
264
LockRelationOid (OIDNewHeap , AccessExclusiveLock );
250
265
dest = CreateTransientRelDestReceiver (OIDNewHeap );
251
266
267
+ /*
268
+ * Now lock down security-restricted operations.
269
+ */
270
+ SetUserIdAndSecContext (relowner ,
271
+ save_sec_context | SECURITY_RESTRICTED_OPERATION );
272
+
252
273
/* Generate the data, if wanted. */
253
274
if (!stmt -> skipData )
254
- refresh_matview_datafill (dest , dataQuery , queryString , owner );
275
+ refresh_matview_datafill (dest , dataQuery , queryString );
255
276
256
277
heap_close (matviewRel , NoLock );
257
278
@@ -262,7 +283,8 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
262
283
263
284
PG_TRY ();
264
285
{
265
- refresh_by_match_merge (matviewOid , OIDNewHeap );
286
+ refresh_by_match_merge (matviewOid , OIDNewHeap , relowner ,
287
+ save_sec_context );
266
288
}
267
289
PG_CATCH ();
268
290
{
@@ -274,33 +296,26 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
274
296
}
275
297
else
276
298
refresh_by_heap_swap (matviewOid , OIDNewHeap );
299
+
300
+ /* Roll back any GUC changes */
301
+ AtEOXact_GUC (false, save_nestlevel );
302
+
303
+ /* Restore userid and security context */
304
+ SetUserIdAndSecContext (save_userid , save_sec_context );
277
305
}
278
306
279
307
/*
280
308
* refresh_matview_datafill
281
309
*/
282
310
static void
283
311
refresh_matview_datafill (DestReceiver * dest , Query * query ,
284
- const char * queryString , Oid relowner )
312
+ const char * queryString )
285
313
{
286
314
List * rewritten ;
287
315
PlannedStmt * plan ;
288
316
QueryDesc * queryDesc ;
289
- Oid save_userid ;
290
- int save_sec_context ;
291
- int save_nestlevel ;
292
317
Query * copied_query ;
293
318
294
- /*
295
- * Switch to the owner's userid, so that any functions are run as that
296
- * user. Also lock down security-restricted operations and arrange to
297
- * make GUC variable changes local to this command.
298
- */
299
- GetUserIdAndSecContext (& save_userid , & save_sec_context );
300
- SetUserIdAndSecContext (relowner ,
301
- save_sec_context | SECURITY_RESTRICTED_OPERATION );
302
- save_nestlevel = NewGUCNestLevel ();
303
-
304
319
/* Lock and rewrite, using a copy to preserve the original query. */
305
320
copied_query = copyObject (query );
306
321
AcquireRewriteLocks (copied_query , true, false);
@@ -344,12 +359,6 @@ refresh_matview_datafill(DestReceiver *dest, Query *query,
344
359
FreeQueryDesc (queryDesc );
345
360
346
361
PopActiveSnapshot ();
347
-
348
- /* Roll back any GUC changes */
349
- AtEOXact_GUC (false, save_nestlevel );
350
-
351
- /* Restore userid and security context */
352
- SetUserIdAndSecContext (save_userid , save_sec_context );
353
362
}
354
363
355
364
DestReceiver *
@@ -520,7 +529,8 @@ mv_GenerateOper(StringInfo buf, Oid opoid)
520
529
* this command.
521
530
*/
522
531
static void
523
- refresh_by_match_merge (Oid matviewOid , Oid tempOid )
532
+ refresh_by_match_merge (Oid matviewOid , Oid tempOid , Oid relowner ,
533
+ int save_sec_context )
524
534
{
525
535
StringInfoData querybuf ;
526
536
Relation matviewRel ;
@@ -534,9 +544,6 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid)
534
544
ListCell * indexoidscan ;
535
545
int16 relnatts ;
536
546
bool * usedForQual ;
537
- Oid save_userid ;
538
- int save_sec_context ;
539
- int save_nestlevel ;
540
547
541
548
initStringInfo (& querybuf );
542
549
matviewRel = heap_open (matviewOid , NoLock );
@@ -587,6 +594,9 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid)
587
594
SPI_getvalue (SPI_tuptable -> vals [0 ], SPI_tuptable -> tupdesc , 1 ))));
588
595
}
589
596
597
+ SetUserIdAndSecContext (relowner ,
598
+ save_sec_context | SECURITY_LOCAL_USERID_CHANGE );
599
+
590
600
/* Start building the query for creating the diff table. */
591
601
resetStringInfo (& querybuf );
592
602
appendStringInfo (& querybuf ,
@@ -681,9 +691,12 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid)
681
691
if (SPI_exec (querybuf .data , 0 ) != SPI_OK_UTILITY )
682
692
elog (ERROR , "SPI_exec failed: %s" , querybuf .data );
683
693
694
+ SetUserIdAndSecContext (relowner ,
695
+ save_sec_context | SECURITY_RESTRICTED_OPERATION );
696
+
684
697
/*
685
698
* We have no further use for data from the "full-data" temp table, but we
686
- * must keep it around because its type is reference from the diff table.
699
+ * must keep it around because its type is referenced from the diff table.
687
700
*/
688
701
689
702
/* Analyze the diff table. */
@@ -694,16 +707,6 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid)
694
707
695
708
OpenMatViewIncrementalMaintenance ();
696
709
697
- /*
698
- * Switch to the owner's userid, so that any functions are run as that
699
- * user. Also lock down security-restricted operations and arrange to
700
- * make GUC variable changes local to this command.
701
- */
702
- GetUserIdAndSecContext (& save_userid , & save_sec_context );
703
- SetUserIdAndSecContext (matviewRel -> rd_rel -> relowner ,
704
- save_sec_context | SECURITY_RESTRICTED_OPERATION );
705
- save_nestlevel = NewGUCNestLevel ();
706
-
707
710
/* Deletes must come before inserts; do them first. */
708
711
resetStringInfo (& querybuf );
709
712
appendStringInfo (& querybuf ,
@@ -724,12 +727,6 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid)
724
727
if (SPI_exec (querybuf .data , 0 ) != SPI_OK_INSERT )
725
728
elog (ERROR , "SPI_exec failed: %s" , querybuf .data );
726
729
727
- /* Roll back any GUC changes */
728
- AtEOXact_GUC (false, save_nestlevel );
729
-
730
- /* Restore userid and security context */
731
- SetUserIdAndSecContext (save_userid , save_sec_context );
732
-
733
730
/* We're done maintaining the materialized view. */
734
731
CloseMatViewIncrementalMaintenance ();
735
732
heap_close (tempRel , NoLock );
0 commit comments