@@ -120,35 +120,42 @@ calculate_database_size(Oid dbOid)
120120
121121 FreeDir (dirdesc );
122122
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-
129123 return totalsize ;
130124}
131125
132126Datum
133127pg_database_size_oid (PG_FUNCTION_ARGS )
134128{
135129 Oid dbOid = PG_GETARG_OID (0 );
130+ int64 size ;
136131
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 );
138138}
139139
140140Datum
141141pg_database_size_name (PG_FUNCTION_ARGS )
142142{
143143 Name dbName = PG_GETARG_NAME (0 );
144144 Oid dbOid = get_database_oid (NameStr (* dbName ), false);
145+ int64 size ;
146+
147+ size = calculate_database_size (dbOid );
145148
146- PG_RETURN_INT64 (calculate_database_size (dbOid ));
149+ if (size == 0 )
150+ PG_RETURN_NULL ();
151+
152+ PG_RETURN_INT64 (size );
147153}
148154
149155
150156/*
151- * calculate total size of tablespace
157+ * Calculate total size of tablespace. Returns -1 if the tablespace directory
158+ * cannot be found.
152159 */
153160static int64
154161calculate_tablespace_size (Oid tblspcOid )
@@ -184,10 +191,7 @@ calculate_tablespace_size(Oid tblspcOid)
184191 dirdesc = AllocateDir (tblspcPath );
185192
186193 if (!dirdesc )
187- ereport (ERROR ,
188- (errcode_for_file_access (),
189- errmsg ("could not open tablespace directory \"%s\": %m" ,
190- tblspcPath )));
194+ return -1 ;
191195
192196 while ((direntry = ReadDir (dirdesc , tblspcPath )) != NULL )
193197 {
@@ -226,17 +230,29 @@ Datum
226230pg_tablespace_size_oid (PG_FUNCTION_ARGS )
227231{
228232 Oid tblspcOid = PG_GETARG_OID (0 );
233+ int64 size ;
234+
235+ size = calculate_tablespace_size (tblspcOid );
229236
230- PG_RETURN_INT64 (calculate_tablespace_size (tblspcOid ));
237+ if (size < 0 )
238+ PG_RETURN_NULL ();
239+
240+ PG_RETURN_INT64 (size );
231241}
232242
233243Datum
234244pg_tablespace_size_name (PG_FUNCTION_ARGS )
235245{
236246 Name tblspcName = PG_GETARG_NAME (0 );
237247 Oid tblspcOid = get_tablespace_oid (NameStr (* tblspcName ), false);
248+ int64 size ;
238249
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 );
240256}
241257
242258
@@ -289,7 +305,17 @@ pg_relation_size(PG_FUNCTION_ARGS)
289305 Relation rel ;
290306 int64 size ;
291307
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 ();
293319
294320 size = calculate_relation_size (& (rel -> rd_node ), rel -> rd_backend ,
295321 forkname_to_number (text_to_cstring (forkName )));
@@ -339,14 +365,11 @@ calculate_toast_table_size(Oid toastrelid)
339365 * those won't have attached toast tables, but they can have multiple forks.
340366 */
341367static int64
342- calculate_table_size (Oid relOid )
368+ calculate_table_size (Relation rel )
343369{
344370 int64 size = 0 ;
345- Relation rel ;
346371 ForkNumber forkNum ;
347372
348- rel = relation_open (relOid , AccessShareLock );
349-
350373 /*
351374 * heap size, including FSM and VM
352375 */
@@ -360,8 +383,6 @@ calculate_table_size(Oid relOid)
360383 if (OidIsValid (rel -> rd_rel -> reltoastrelid ))
361384 size += calculate_toast_table_size (rel -> rd_rel -> reltoastrelid );
362385
363- relation_close (rel , AccessShareLock );
364-
365386 return size ;
366387}
367388
@@ -371,12 +392,9 @@ calculate_table_size(Oid relOid)
371392 * Can be applied safely to an index, but you'll just get zero.
372393 */
373394static int64
374- calculate_indexes_size (Oid relOid )
395+ calculate_indexes_size (Relation rel )
375396{
376397 int64 size = 0 ;
377- Relation rel ;
378-
379- rel = relation_open (relOid , AccessShareLock );
380398
381399 /*
382400 * Aggregate all indexes on the given relation
@@ -405,56 +423,87 @@ calculate_indexes_size(Oid relOid)
405423 list_free (index_oids );
406424 }
407425
408- relation_close (rel , AccessShareLock );
409-
410426 return size ;
411427}
412428
413429Datum
414430pg_table_size (PG_FUNCTION_ARGS )
415431{
416432 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 ();
417440
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 );
419446}
420447
421448Datum
422449pg_indexes_size (PG_FUNCTION_ARGS )
423450{
424451 Oid relOid = PG_GETARG_OID (0 );
452+ Relation rel ;
453+ int64 size ;
425454
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 );
427465}
428466
429467/*
430468 * Compute the on-disk size of all files for the relation,
431469 * including heap data, index data, toast data, FSM, VM.
432470 */
433471static int64
434- calculate_total_relation_size (Oid Relid )
472+ calculate_total_relation_size (Relation rel )
435473{
436474 int64 size ;
437475
438476 /*
439477 * Aggregate the table size, this includes size of the heap, toast and
440478 * toast index with free space and visibility map
441479 */
442- size = calculate_table_size (Relid );
480+ size = calculate_table_size (rel );
443481
444482 /*
445483 * Add size of all attached indexes as well
446484 */
447- size += calculate_indexes_size (Relid );
485+ size += calculate_indexes_size (rel );
448486
449487 return size ;
450488}
451489
452490Datum
453491pg_total_relation_size (PG_FUNCTION_ARGS )
454492{
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 ();
456501
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 );
458507}
459508
460509/*
0 commit comments