@@ -197,6 +197,7 @@ static bool alldb = false;
197
197
static bool noorder = false;
198
198
static SimpleStringList table_list = {NULL , NULL };
199
199
static char * orderby = NULL ;
200
+ static char * tablespace = NULL ;
200
201
static int wait_timeout = 60 ; /* in seconds */
201
202
static int jobs = 0 ; /* number of concurrent worker conns. */
202
203
@@ -214,6 +215,7 @@ static pgut_option options[] =
214
215
{ 'l' , 't' , "table" , & table_list },
215
216
{ 'b' , 'n' , "no-order" , & noorder },
216
217
{ 's' , 'o' , "order-by" , & orderby },
218
+ { 's' , 's' , "tablespace" , & tablespace },
217
219
{ 'i' , 'T' , "wait-timeout" , & wait_timeout },
218
220
{ 'B' , 'Z' , "no-analyze" , & analyze },
219
221
{ 'i' , 'j' , "jobs" , & jobs },
@@ -360,10 +362,15 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize)
360
362
StringInfoData sql ;
361
363
SimpleStringListCell * cell ;
362
364
const char * * params = NULL ;
363
- size_t num_params = simple_string_list_size (table_list );
365
+ int iparam = 0 ;
366
+ size_t num_tables ;
367
+ size_t num_params ;
364
368
365
- if (num_params )
366
- params = pgut_malloc (num_params * sizeof (char * ));
369
+ num_tables = simple_string_list_size (table_list );
370
+
371
+ /* 1st param is the user-specified tablespace */
372
+ num_params = num_tables + 1 ;
373
+ params = pgut_malloc (num_params * sizeof (char * ));
367
374
368
375
initStringInfo (& sql );
369
376
@@ -442,29 +449,46 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize)
442
449
command ("SET client_min_messages = warning" , 0 , NULL );
443
450
444
451
/* acquire target tables */
445
- appendStringInfoString (& sql , "SELECT * FROM repack.tables WHERE " );
446
- if (num_params )
452
+ appendStringInfoString (& sql ,
453
+ "SELECT t.*,"
454
+ " coalesce(v.tablespace, t.tablespace_orig) as tablespace_dest"
455
+ " FROM repack.tables t, "
456
+ " (VALUES (quote_ident($1::text))) as v (tablespace)"
457
+ " WHERE " );
458
+
459
+ params [iparam ++ ] = tablespace ;
460
+ if (num_tables )
447
461
{
448
462
appendStringInfoString (& sql , "(" );
449
- for (i = 0 , cell = table_list .head ; cell ; cell = cell -> next , i ++ )
463
+ for (cell = table_list .head ; cell ; cell = cell -> next )
450
464
{
451
465
/* Construct table name placeholders to be used by PQexecParams */
452
- appendStringInfo (& sql , "relid = $%d::regclass" , i + 1 );
453
- params [i ] = cell -> val ;
466
+ appendStringInfo (& sql , "relid = $%d::regclass" , iparam + 1 );
467
+ params [iparam ++ ] = cell -> val ;
454
468
if (cell -> next )
455
469
appendStringInfoString (& sql , " OR " );
456
470
}
457
471
appendStringInfoString (& sql , ")" );
458
- res = execute_elevel (sql .data , (int ) num_params , params , DEBUG2 );
459
472
}
460
473
else
461
474
{
462
475
appendStringInfoString (& sql , "pkid IS NOT NULL" );
463
476
if (!orderby )
464
477
appendStringInfoString (& sql , " AND ckid IS NOT NULL" );
465
- res = execute_elevel (sql .data , 0 , NULL , DEBUG2 );
466
478
}
467
479
480
+ /* double check the parameters array is sane */
481
+ if (iparam != num_params )
482
+ {
483
+ if (errbuf )
484
+ snprintf (errbuf , errsize ,
485
+ "internal error: bad parameters count: %i instead of %zi" ,
486
+ iparam , num_params );
487
+ goto cleanup ;
488
+ }
489
+
490
+ res = execute_elevel (sql .data , (int ) num_params , params , DEBUG2 );
491
+
468
492
/* on error skip the database */
469
493
if (PQresultStatus (res ) != PGRES_TUPLES_OK )
470
494
{
@@ -489,7 +513,9 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize)
489
513
for (i = 0 ; i < num ; i ++ )
490
514
{
491
515
repack_table table ;
492
- const char * create_table ;
516
+ const char * create_table_1 ;
517
+ const char * create_table_2 ;
518
+ const char * tablespace ;
493
519
const char * ckey ;
494
520
int c = 0 ;
495
521
@@ -512,13 +538,24 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize)
512
538
table .create_trigger = getstr (res , i , c ++ );
513
539
table .enable_trigger = getstr (res , i , c ++ );
514
540
515
- create_table = getstr (res , i , c ++ );
541
+ create_table_1 = getstr (res , i , c ++ );
542
+ tablespace = getstr (res , i , c ++ ); /* to be clobbered */
543
+ create_table_2 = getstr (res , i , c ++ );
516
544
table .drop_columns = getstr (res , i , c ++ );
517
545
table .delete_log = getstr (res , i , c ++ );
518
546
table .lock_table = getstr (res , i , c ++ );
519
547
ckey = getstr (res , i , c ++ );
548
+ table .sql_peek = getstr (res , i , c ++ );
549
+ table .sql_insert = getstr (res , i , c ++ );
550
+ table .sql_delete = getstr (res , i , c ++ );
551
+ table .sql_update = getstr (res , i , c ++ );
552
+ table .sql_pop = getstr (res , i , c ++ );
553
+ tablespace = getstr (res , i , c ++ );
520
554
521
555
resetStringInfo (& sql );
556
+ appendStringInfoString (& sql , create_table_1 );
557
+ appendStringInfoString (& sql , tablespace );
558
+ appendStringInfoString (& sql , create_table_2 );
522
559
if (!orderby )
523
560
{
524
561
/* CLUSTER mode */
@@ -529,27 +566,23 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize)
529
566
errmsg ("relation \"%s\" has no cluster key" , table .target_name )));
530
567
continue ;
531
568
}
532
- appendStringInfo (& sql , "%s ORDER BY %s" , create_table , ckey );
533
- table .create_table = sql .data ;
569
+ appendStringInfoString (& sql , " ORDER BY " );
570
+ appendStringInfoString (& sql , ckey );
571
+ table .create_table = sql .data ;
534
572
}
535
573
else if (!orderby [0 ])
536
574
{
537
575
/* VACUUM FULL mode */
538
- table .create_table = create_table ;
576
+ table .create_table = sql . data ;
539
577
}
540
578
else
541
579
{
542
580
/* User specified ORDER BY */
543
- appendStringInfo (& sql , "%s ORDER BY %s" , create_table , orderby );
544
- table .create_table = sql .data ;
581
+ appendStringInfoString (& sql , " ORDER BY " );
582
+ appendStringInfoString (& sql , orderby );
583
+ table .create_table = sql .data ;
545
584
}
546
585
547
- table .sql_peek = getstr (res , i , c ++ );
548
- table .sql_insert = getstr (res , i , c ++ );
549
- table .sql_delete = getstr (res , i , c ++ );
550
- table .sql_update = getstr (res , i , c ++ );
551
- table .sql_pop = getstr (res , i , c ++ );
552
-
553
586
repack_one_table (& table , orderby );
554
587
}
555
588
ret = true;
@@ -1430,6 +1463,7 @@ pgut_help(bool details)
1430
1463
printf (" -n, --no-order do vacuum full instead of cluster\n" );
1431
1464
printf (" -o, --order-by=COLUMNS order by columns instead of cluster keys\n" );
1432
1465
printf (" -t, --table=TABLE repack specific table only\n" );
1466
+ printf (" -s, --tablespace=TABLESPC move repacked tables to a new tablespace\n" );
1433
1467
printf (" -T, --wait-timeout=SECS timeout to cancel other backends on conflict\n" );
1434
1468
printf (" -Z, --no-analyze don't analyze at end\n" );
1435
1469
}
0 commit comments