@@ -120,35 +120,42 @@ calculate_database_size(Oid dbOid)
120
120
121
121
FreeDir (dirdesc );
122
122
123
- /* Complain if we found no trace of the DB at all */
124
- if (!totalsize )
125
- ereport (ERROR ,
126
- (ERRCODE_UNDEFINED_DATABASE ,
127
- errmsg ("database with OID %u does not exist" , dbOid )));
128
-
129
123
return totalsize ;
130
124
}
131
125
132
126
Datum
133
127
pg_database_size_oid (PG_FUNCTION_ARGS )
134
128
{
135
129
Oid dbOid = PG_GETARG_OID (0 );
130
+ int64 size ;
136
131
137
- PG_RETURN_INT64 (calculate_database_size (dbOid ));
132
+ size = calculate_database_size (dbOid );
133
+
134
+ if (size == 0 )
135
+ PG_RETURN_NULL ();
136
+
137
+ PG_RETURN_INT64 (size );
138
138
}
139
139
140
140
Datum
141
141
pg_database_size_name (PG_FUNCTION_ARGS )
142
142
{
143
143
Name dbName = PG_GETARG_NAME (0 );
144
144
Oid dbOid = get_database_oid (NameStr (* dbName ), false);
145
+ int64 size ;
146
+
147
+ size = calculate_database_size (dbOid );
145
148
146
- PG_RETURN_INT64 (calculate_database_size (dbOid ));
149
+ if (size == 0 )
150
+ PG_RETURN_NULL ();
151
+
152
+ PG_RETURN_INT64 (size );
147
153
}
148
154
149
155
150
156
/*
151
- * calculate total size of tablespace
157
+ * Calculate total size of tablespace. Returns -1 if the tablespace directory
158
+ * cannot be found.
152
159
*/
153
160
static int64
154
161
calculate_tablespace_size (Oid tblspcOid )
@@ -184,10 +191,7 @@ calculate_tablespace_size(Oid tblspcOid)
184
191
dirdesc = AllocateDir (tblspcPath );
185
192
186
193
if (!dirdesc )
187
- ereport (ERROR ,
188
- (errcode_for_file_access (),
189
- errmsg ("could not open tablespace directory \"%s\": %m" ,
190
- tblspcPath )));
194
+ return -1 ;
191
195
192
196
while ((direntry = ReadDir (dirdesc , tblspcPath )) != NULL )
193
197
{
@@ -226,17 +230,29 @@ Datum
226
230
pg_tablespace_size_oid (PG_FUNCTION_ARGS )
227
231
{
228
232
Oid tblspcOid = PG_GETARG_OID (0 );
233
+ int64 size ;
234
+
235
+ size = calculate_tablespace_size (tblspcOid );
229
236
230
- PG_RETURN_INT64 (calculate_tablespace_size (tblspcOid ));
237
+ if (size < 0 )
238
+ PG_RETURN_NULL ();
239
+
240
+ PG_RETURN_INT64 (size );
231
241
}
232
242
233
243
Datum
234
244
pg_tablespace_size_name (PG_FUNCTION_ARGS )
235
245
{
236
246
Name tblspcName = PG_GETARG_NAME (0 );
237
247
Oid tblspcOid = get_tablespace_oid (NameStr (* tblspcName ), false);
248
+ int64 size ;
238
249
239
- PG_RETURN_INT64 (calculate_tablespace_size (tblspcOid ));
250
+ size = calculate_tablespace_size (tblspcOid );
251
+
252
+ if (size < 0 )
253
+ PG_RETURN_NULL ();
254
+
255
+ PG_RETURN_INT64 (size );
240
256
}
241
257
242
258
@@ -289,7 +305,17 @@ pg_relation_size(PG_FUNCTION_ARGS)
289
305
Relation rel ;
290
306
int64 size ;
291
307
292
- rel = relation_open (relOid , AccessShareLock );
308
+ rel = try_relation_open (relOid , AccessShareLock );
309
+
310
+ /*
311
+ * Before 9.2, we used to throw an error if the relation didn't exist, but
312
+ * that makes queries like "SELECT pg_relation_size(oid) FROM pg_class"
313
+ * less robust, because while we scan pg_class with an MVCC snapshot,
314
+ * someone else might drop the table. It's better to return NULL for
315
+ * alread-dropped tables than throw an error and abort the whole query.
316
+ */
317
+ if (rel == NULL )
318
+ PG_RETURN_NULL ();
293
319
294
320
size = calculate_relation_size (& (rel -> rd_node ), rel -> rd_backend ,
295
321
forkname_to_number (text_to_cstring (forkName )));
@@ -339,14 +365,11 @@ calculate_toast_table_size(Oid toastrelid)
339
365
* those won't have attached toast tables, but they can have multiple forks.
340
366
*/
341
367
static int64
342
- calculate_table_size (Oid relOid )
368
+ calculate_table_size (Relation rel )
343
369
{
344
370
int64 size = 0 ;
345
- Relation rel ;
346
371
ForkNumber forkNum ;
347
372
348
- rel = relation_open (relOid , AccessShareLock );
349
-
350
373
/*
351
374
* heap size, including FSM and VM
352
375
*/
@@ -360,8 +383,6 @@ calculate_table_size(Oid relOid)
360
383
if (OidIsValid (rel -> rd_rel -> reltoastrelid ))
361
384
size += calculate_toast_table_size (rel -> rd_rel -> reltoastrelid );
362
385
363
- relation_close (rel , AccessShareLock );
364
-
365
386
return size ;
366
387
}
367
388
@@ -371,12 +392,9 @@ calculate_table_size(Oid relOid)
371
392
* Can be applied safely to an index, but you'll just get zero.
372
393
*/
373
394
static int64
374
- calculate_indexes_size (Oid relOid )
395
+ calculate_indexes_size (Relation rel )
375
396
{
376
397
int64 size = 0 ;
377
- Relation rel ;
378
-
379
- rel = relation_open (relOid , AccessShareLock );
380
398
381
399
/*
382
400
* Aggregate all indexes on the given relation
@@ -405,56 +423,87 @@ calculate_indexes_size(Oid relOid)
405
423
list_free (index_oids );
406
424
}
407
425
408
- relation_close (rel , AccessShareLock );
409
-
410
426
return size ;
411
427
}
412
428
413
429
Datum
414
430
pg_table_size (PG_FUNCTION_ARGS )
415
431
{
416
432
Oid relOid = PG_GETARG_OID (0 );
433
+ Relation rel ;
434
+ int64 size ;
435
+
436
+ rel = try_relation_open (relOid , AccessShareLock );
437
+
438
+ if (rel == NULL )
439
+ PG_RETURN_NULL ();
417
440
418
- PG_RETURN_INT64 (calculate_table_size (relOid ));
441
+ size = calculate_table_size (rel );
442
+
443
+ relation_close (rel , AccessShareLock );
444
+
445
+ PG_RETURN_INT64 (size );
419
446
}
420
447
421
448
Datum
422
449
pg_indexes_size (PG_FUNCTION_ARGS )
423
450
{
424
451
Oid relOid = PG_GETARG_OID (0 );
452
+ Relation rel ;
453
+ int64 size ;
425
454
426
- PG_RETURN_INT64 (calculate_indexes_size (relOid ));
455
+ rel = try_relation_open (relOid , AccessShareLock );
456
+
457
+ if (rel == NULL )
458
+ PG_RETURN_NULL ();
459
+
460
+ size = calculate_indexes_size (rel );
461
+
462
+ relation_close (rel , AccessShareLock );
463
+
464
+ PG_RETURN_INT64 (size );
427
465
}
428
466
429
467
/*
430
468
* Compute the on-disk size of all files for the relation,
431
469
* including heap data, index data, toast data, FSM, VM.
432
470
*/
433
471
static int64
434
- calculate_total_relation_size (Oid Relid )
472
+ calculate_total_relation_size (Relation rel )
435
473
{
436
474
int64 size ;
437
475
438
476
/*
439
477
* Aggregate the table size, this includes size of the heap, toast and
440
478
* toast index with free space and visibility map
441
479
*/
442
- size = calculate_table_size (Relid );
480
+ size = calculate_table_size (rel );
443
481
444
482
/*
445
483
* Add size of all attached indexes as well
446
484
*/
447
- size += calculate_indexes_size (Relid );
485
+ size += calculate_indexes_size (rel );
448
486
449
487
return size ;
450
488
}
451
489
452
490
Datum
453
491
pg_total_relation_size (PG_FUNCTION_ARGS )
454
492
{
455
- Oid relid = PG_GETARG_OID (0 );
493
+ Oid relOid = PG_GETARG_OID (0 );
494
+ Relation rel ;
495
+ int64 size ;
496
+
497
+ rel = try_relation_open (relOid , AccessShareLock );
498
+
499
+ if (rel == NULL )
500
+ PG_RETURN_NULL ();
456
501
457
- PG_RETURN_INT64 (calculate_total_relation_size (relid ));
502
+ size = calculate_total_relation_size (rel );
503
+
504
+ relation_close (rel , AccessShareLock );
505
+
506
+ PG_RETURN_INT64 (size );
458
507
}
459
508
460
509
/*
0 commit comments