@@ -1235,9 +1235,13 @@ index_create(Relation heapRelation,
1235
1235
* Create concurrently an index based on the definition of the one provided by
1236
1236
* caller. The index is inserted into catalogs and needs to be built later
1237
1237
* on. This is called during concurrent reindex processing.
1238
+ *
1239
+ * "tablespaceOid" is the new tablespace to use for this index. If
1240
+ * InvalidOid, use the tablespace in-use instead.
1238
1241
*/
1239
1242
Oid
1240
- index_concurrently_create_copy (Relation heapRelation ,Oid oldIndexId ,const char * newName )
1243
+ index_concurrently_create_copy (Relation heapRelation ,Oid oldIndexId ,
1244
+ Oid tablespaceOid ,const char * newName )
1241
1245
{
1242
1246
Relation indexRelation ;
1243
1247
IndexInfo * oldInfo ,
@@ -1367,7 +1371,8 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId, const char
1367
1371
newInfo ,
1368
1372
indexColNames ,
1369
1373
indexRelation -> rd_rel -> relam ,
1370
- indexRelation -> rd_rel -> reltablespace ,
1374
+ OidIsValid (tablespaceOid ) ?
1375
+ tablespaceOid :indexRelation -> rd_rel -> reltablespace ,
1371
1376
indexRelation -> rd_indcollation ,
1372
1377
indclass -> values ,
1373
1378
indcoloptions -> values ,
@@ -3415,10 +3420,12 @@ IndexGetRelation(Oid indexId, bool missing_ok)
3415
3420
3416
3421
/*
3417
3422
* reindex_index - This routine is used to recreate a single index
3423
+ *
3424
+ * See comments of reindex_relation() for details about "tablespaceOid".
3418
3425
*/
3419
3426
void
3420
- reindex_index (Oid indexId ,bool skip_constraint_checks , char persistence ,
3421
- int options )
3427
+ reindex_index (Oid indexId ,Oid tablespaceOid , bool skip_constraint_checks ,
3428
+ char persistence , int options )
3422
3429
{
3423
3430
Relation iRel ,
3424
3431
heapRelation ;
@@ -3427,6 +3434,7 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
3427
3434
volatile bool skipped_constraint = false;
3428
3435
PGRUsage ru0 ;
3429
3436
bool progress = (options & REINDEXOPT_REPORT_PROGRESS )!= 0 ;
3437
+ bool set_tablespace = OidIsValid (tablespaceOid );
3430
3438
3431
3439
pg_rusage_init (& ru0 );
3432
3440
@@ -3465,6 +3473,27 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
3465
3473
elog (ERROR ,"unsupported relation kind for index \"%s\"" ,
3466
3474
RelationGetRelationName (iRel ));
3467
3475
3476
+ /*
3477
+ * We don't support moving system relations into different tablespaces,
3478
+ * unless allow_system_table_mods=1.
3479
+ */
3480
+ if (set_tablespace &&
3481
+ !allowSystemTableMods && IsSystemRelation (iRel ))
3482
+ ereport (ERROR ,
3483
+ (errcode (ERRCODE_INSUFFICIENT_PRIVILEGE ),
3484
+ errmsg ("permission denied: \"%s\" is a system catalog" ,
3485
+ RelationGetRelationName (iRel ))));
3486
+
3487
+ /*
3488
+ * We cannot support moving mapped relations into different tablespaces.
3489
+ * (In particular this eliminates all shared catalogs.)
3490
+ */
3491
+ if (set_tablespace && RelationIsMapped (iRel ))
3492
+ ereport (ERROR ,
3493
+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
3494
+ errmsg ("cannot change tablespace of mapped relation \"%s\"" ,
3495
+ RelationGetRelationName (iRel ))));
3496
+
3468
3497
/*
3469
3498
* Don't allow reindex on temp tables of other backends ... their local
3470
3499
* buffer manager is not going to cope.
@@ -3491,6 +3520,47 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
3491
3520
*/
3492
3521
CheckTableNotInUse (iRel ,"REINDEX INDEX" );
3493
3522
3523
+ if (tablespaceOid == MyDatabaseTableSpace )
3524
+ tablespaceOid = InvalidOid ;
3525
+
3526
+ /*
3527
+ * Set the new tablespace for the relation. Do that only in the
3528
+ * case where the reindex caller wishes to enforce a new tablespace.
3529
+ */
3530
+ if (set_tablespace &&
3531
+ tablespaceOid != iRel -> rd_rel -> reltablespace )
3532
+ {
3533
+ Relation pg_class ;
3534
+ Form_pg_class rd_rel ;
3535
+ HeapTuple tuple ;
3536
+
3537
+ /* First get a modifiable copy of the relation's pg_class row */
3538
+ pg_class = table_open (RelationRelationId ,RowExclusiveLock );
3539
+
3540
+ tuple = SearchSysCacheCopy1 (RELOID ,ObjectIdGetDatum (indexId ));
3541
+ if (!HeapTupleIsValid (tuple ))
3542
+ elog (ERROR ,"cache lookup failed for relation %u" ,indexId );
3543
+ rd_rel = (Form_pg_class )GETSTRUCT (tuple );
3544
+
3545
+ /*
3546
+ * Mark the relation as ready to be dropped at transaction commit,
3547
+ * before making visible the new tablespace change so as this won't
3548
+ * miss things.
3549
+ */
3550
+ RelationDropStorage (iRel );
3551
+
3552
+ /* Update the pg_class row */
3553
+ rd_rel -> reltablespace = tablespaceOid ;
3554
+ CatalogTupleUpdate (pg_class ,& tuple -> t_self ,tuple );
3555
+
3556
+ heap_freetuple (tuple );
3557
+
3558
+ table_close (pg_class ,RowExclusiveLock );
3559
+
3560
+ /* Make sure the reltablespace change is visible */
3561
+ CommandCounterIncrement ();
3562
+ }
3563
+
3494
3564
/*
3495
3565
* All predicate locks on the index are about to be made invalid. Promote
3496
3566
* them to relation locks on the heap.
@@ -3629,6 +3699,10 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
3629
3699
* reindex_relation - This routine is used to recreate all indexes
3630
3700
* of a relation (and optionally its toast relation too, if any).
3631
3701
*
3702
+ * "tablespaceOid" defines the new tablespace where the indexes of
3703
+ * the relation will be rebuilt. If InvalidOid is used, the current
3704
+ * tablespace of each index is used instead.
3705
+ *
3632
3706
* "flags" is a bitmask that can include any combination of these bits:
3633
3707
*
3634
3708
* REINDEX_REL_PROCESS_TOAST: if true, process the toast table too (if any).
@@ -3661,7 +3735,7 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
3661
3735
* index rebuild.
3662
3736
*/
3663
3737
bool
3664
- reindex_relation (Oid relid ,int flags ,int options )
3738
+ reindex_relation (Oid relid ,Oid tablespaceOid , int flags ,int options )
3665
3739
{
3666
3740
Relation rel ;
3667
3741
Oid toast_relid ;
@@ -3752,7 +3826,8 @@ reindex_relation(Oid relid, int flags, int options)
3752
3826
continue ;
3753
3827
}
3754
3828
3755
- reindex_index (indexOid , !(flags & REINDEX_REL_CHECK_CONSTRAINTS ),
3829
+ reindex_index (indexOid ,tablespaceOid ,
3830
+ !(flags & REINDEX_REL_CHECK_CONSTRAINTS ),
3756
3831
persistence ,options );
3757
3832
3758
3833
CommandCounterIncrement ();
@@ -3785,7 +3860,7 @@ reindex_relation(Oid relid, int flags, int options)
3785
3860
* still hold the lock on the master table.
3786
3861
*/
3787
3862
if ((flags & REINDEX_REL_PROCESS_TOAST )&& OidIsValid (toast_relid ))
3788
- result |=reindex_relation (toast_relid ,flags ,options );
3863
+ result |=reindex_relation (toast_relid ,tablespaceOid , flags ,options );
3789
3864
3790
3865
return result ;
3791
3866
}