Header And Logo

PostgreSQL
| The world's most advanced open source database.

Functions

dbsize.c File Reference

#include "postgres.h"
#include <sys/types.h>
#include <sys/stat.h>
#include "access/heapam.h"
#include "access/htup_details.h"
#include "catalog/catalog.h"
#include "catalog/namespace.h"
#include "catalog/pg_tablespace.h"
#include "commands/dbcommands.h"
#include "commands/tablespace.h"
#include "common/relpath.h"
#include "miscadmin.h"
#include "storage/fd.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/numeric.h"
#include "utils/rel.h"
#include "utils/relmapper.h"
#include "utils/syscache.h"
Include dependency graph for dbsize.c:

Go to the source code of this file.

Functions

static int64 db_dir_size (const char *path)
static int64 calculate_database_size (Oid dbOid)
Datum pg_database_size_oid (PG_FUNCTION_ARGS)
Datum pg_database_size_name (PG_FUNCTION_ARGS)
static int64 calculate_tablespace_size (Oid tblspcOid)
Datum pg_tablespace_size_oid (PG_FUNCTION_ARGS)
Datum pg_tablespace_size_name (PG_FUNCTION_ARGS)
static int64 calculate_relation_size (RelFileNode *rfn, BackendId backend, ForkNumber forknum)
Datum pg_relation_size (PG_FUNCTION_ARGS)
static int64 calculate_toast_table_size (Oid toastrelid)
static int64 calculate_table_size (Relation rel)
static int64 calculate_indexes_size (Relation rel)
Datum pg_table_size (PG_FUNCTION_ARGS)
Datum pg_indexes_size (PG_FUNCTION_ARGS)
static int64 calculate_total_relation_size (Relation rel)
Datum pg_total_relation_size (PG_FUNCTION_ARGS)
Datum pg_size_pretty (PG_FUNCTION_ARGS)
static char * numeric_to_cstring (Numeric n)
static Numeric int64_to_numeric (int64 v)
static bool numeric_is_less (Numeric a, Numeric b)
static Numeric numeric_plus_one_over_two (Numeric n)
static Numeric numeric_shift_right (Numeric n, unsigned count)
Datum pg_size_pretty_numeric (PG_FUNCTION_ARGS)
Datum pg_relation_filenode (PG_FUNCTION_ARGS)
Datum pg_relation_filepath (PG_FUNCTION_ARGS)
Datum pg_relation_is_scannable (PG_FUNCTION_ARGS)

Function Documentation

static int64 calculate_database_size ( Oid  dbOid  )  [static]

Definition at line 81 of file dbsize.c.

References ACL_CONNECT, ACL_KIND_DATABASE, aclcheck_error(), ACLCHECK_OK, AllocateDir(), CHECK_FOR_INTERRUPTS, dirent::d_name, db_dir_size(), ereport, errcode_for_file_access(), errmsg(), ERROR, FreeDir(), get_database_name(), GetUserId(), MAXPGPATH, NULL, pg_database_aclcheck(), ReadDir(), snprintf(), TABLESPACE_VERSION_DIRECTORY, and totalsize.

Referenced by pg_database_size_name(), and pg_database_size_oid().

{
    int64       totalsize;
    DIR        *dirdesc;
    struct dirent *direntry;
    char        dirpath[MAXPGPATH];
    char        pathname[MAXPGPATH];
    AclResult   aclresult;

    /* User must have connect privilege for target database */
    aclresult = pg_database_aclcheck(dbOid, GetUserId(), ACL_CONNECT);
    if (aclresult != ACLCHECK_OK)
        aclcheck_error(aclresult, ACL_KIND_DATABASE,
                       get_database_name(dbOid));

    /* Shared storage in pg_global is not counted */

    /* Include pg_default storage */
    snprintf(pathname, MAXPGPATH, "base/%u", dbOid);
    totalsize = db_dir_size(pathname);

    /* Scan the non-default tablespaces */
    snprintf(dirpath, MAXPGPATH, "pg_tblspc");
    dirdesc = AllocateDir(dirpath);
    if (!dirdesc)
        ereport(ERROR,
                (errcode_for_file_access(),
                 errmsg("could not open tablespace directory \"%s\": %m",
                        dirpath)));

    while ((direntry = ReadDir(dirdesc, dirpath)) != NULL)
    {
        CHECK_FOR_INTERRUPTS();

        if (strcmp(direntry->d_name, ".") == 0 ||
            strcmp(direntry->d_name, "..") == 0)
            continue;

        snprintf(pathname, MAXPGPATH, "pg_tblspc/%s/%s/%u",
                 direntry->d_name, TABLESPACE_VERSION_DIRECTORY, dbOid);
        totalsize += db_dir_size(pathname);
    }

    FreeDir(dirdesc);

    return totalsize;
}

static int64 calculate_indexes_size ( Relation  rel  )  [static]

Definition at line 401 of file dbsize.c.

References AccessShareLock, calculate_relation_size(), lfirst_oid, list_free(), RelationData::rd_backend, RelationData::rd_node, RelationData::rd_rel, relation_close(), relation_open(), and RelationGetIndexList().

Referenced by calculate_total_relation_size(), and pg_indexes_size().

{
    int64       size = 0;

    /*
     * Aggregate all indexes on the given relation
     */
    if (rel->rd_rel->relhasindex)
    {
        List       *index_oids = RelationGetIndexList(rel);
        ListCell   *cell;

        foreach(cell, index_oids)
        {
            Oid         idxOid = lfirst_oid(cell);
            Relation    idxRel;
            ForkNumber  forkNum;

            idxRel = relation_open(idxOid, AccessShareLock);

            for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
                size += calculate_relation_size(&(idxRel->rd_node),
                                                idxRel->rd_backend,
                                                forkNum);

            relation_close(idxRel, AccessShareLock);
        }

        list_free(index_oids);
    }

    return size;
}

static int64 calculate_relation_size ( RelFileNode rfn,
BackendId  backend,
ForkNumber  forknum 
) [static]

Definition at line 269 of file dbsize.c.

References CHECK_FOR_INTERRUPTS, ereport, errcode_for_file_access(), errmsg(), ERROR, MAXPGPATH, relpathbackend(), snprintf(), and totalsize.

Referenced by calculate_indexes_size(), calculate_table_size(), calculate_toast_table_size(), and pg_relation_size().

{
    int64       totalsize = 0;
    char       *relationpath;
    char        pathname[MAXPGPATH];
    unsigned int segcount = 0;

    relationpath = relpathbackend(*rfn, backend, forknum);

    for (segcount = 0;; segcount++)
    {
        struct stat fst;

        CHECK_FOR_INTERRUPTS();

        if (segcount == 0)
            snprintf(pathname, MAXPGPATH, "%s",
                     relationpath);
        else
            snprintf(pathname, MAXPGPATH, "%s.%u",
                     relationpath, segcount);

        if (stat(pathname, &fst) < 0)
        {
            if (errno == ENOENT)
                break;
            else
                ereport(ERROR,
                        (errcode_for_file_access(),
                         errmsg("could not stat file \"%s\": %m", pathname)));
        }
        totalsize += fst.st_size;
    }

    return totalsize;
}

static int64 calculate_table_size ( Relation  rel  )  [static]

Definition at line 374 of file dbsize.c.

References calculate_relation_size(), calculate_toast_table_size(), OidIsValid, RelationData::rd_backend, RelationData::rd_node, and RelationData::rd_rel.

Referenced by calculate_total_relation_size(), and pg_table_size().

{
    int64       size = 0;
    ForkNumber  forkNum;

    /*
     * heap size, including FSM and VM
     */
    for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
        size += calculate_relation_size(&(rel->rd_node), rel->rd_backend,
                                        forkNum);

    /*
     * Size of toast relation
     */
    if (OidIsValid(rel->rd_rel->reltoastrelid))
        size += calculate_toast_table_size(rel->rd_rel->reltoastrelid);

    return size;
}

static int64 calculate_tablespace_size ( Oid  tblspcOid  )  [static]

Definition at line 164 of file dbsize.c.

References ACL_CREATE, ACL_KIND_TABLESPACE, aclcheck_error(), ACLCHECK_OK, AllocateDir(), CHECK_FOR_INTERRUPTS, dirent::d_name, db_dir_size(), DEFAULTTABLESPACE_OID, ereport, errcode_for_file_access(), errmsg(), ERROR, FreeDir(), get_tablespace_name(), GetUserId(), GLOBALTABLESPACE_OID, MAXPGPATH, MyDatabaseTableSpace, NULL, pg_tablespace_aclcheck(), ReadDir(), snprintf(), TABLESPACE_VERSION_DIRECTORY, and totalsize.

Referenced by pg_tablespace_size_name(), and pg_tablespace_size_oid().

{
    char        tblspcPath[MAXPGPATH];
    char        pathname[MAXPGPATH];
    int64       totalsize = 0;
    DIR        *dirdesc;
    struct dirent *direntry;
    AclResult   aclresult;

    /*
     * User must have CREATE privilege for target tablespace, either
     * explicitly granted or implicitly because it is default for current
     * database.
     */
    if (tblspcOid != MyDatabaseTableSpace)
    {
        aclresult = pg_tablespace_aclcheck(tblspcOid, GetUserId(), ACL_CREATE);
        if (aclresult != ACLCHECK_OK)
            aclcheck_error(aclresult, ACL_KIND_TABLESPACE,
                           get_tablespace_name(tblspcOid));
    }

    if (tblspcOid == DEFAULTTABLESPACE_OID)
        snprintf(tblspcPath, MAXPGPATH, "base");
    else if (tblspcOid == GLOBALTABLESPACE_OID)
        snprintf(tblspcPath, MAXPGPATH, "global");
    else
        snprintf(tblspcPath, MAXPGPATH, "pg_tblspc/%u/%s", tblspcOid,
                 TABLESPACE_VERSION_DIRECTORY);

    dirdesc = AllocateDir(tblspcPath);

    if (!dirdesc)
        return -1;

    while ((direntry = ReadDir(dirdesc, tblspcPath)) != NULL)
    {
        struct stat fst;

        CHECK_FOR_INTERRUPTS();

        if (strcmp(direntry->d_name, ".") == 0 ||
            strcmp(direntry->d_name, "..") == 0)
            continue;

        snprintf(pathname, MAXPGPATH, "%s/%s", tblspcPath, direntry->d_name);

        if (stat(pathname, &fst) < 0)
        {
            if (errno == ENOENT)
                continue;
            else
                ereport(ERROR,
                        (errcode_for_file_access(),
                         errmsg("could not stat file \"%s\": %m", pathname)));
        }

        if (S_ISDIR(fst.st_mode))
            totalsize += db_dir_size(pathname);

        totalsize += fst.st_size;
    }

    FreeDir(dirdesc);

    return totalsize;
}

static int64 calculate_toast_table_size ( Oid  toastrelid  )  [static]

Definition at line 339 of file dbsize.c.

References AccessShareLock, calculate_relation_size(), RelationData::rd_backend, RelationData::rd_node, RelationData::rd_rel, relation_close(), and relation_open().

Referenced by calculate_table_size().

{
    int64       size = 0;
    Relation    toastRel;
    Relation    toastIdxRel;
    ForkNumber  forkNum;

    toastRel = relation_open(toastrelid, AccessShareLock);

    /* toast heap size, including FSM and VM size */
    for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
        size += calculate_relation_size(&(toastRel->rd_node),
                                        toastRel->rd_backend, forkNum);

    /* toast index size, including FSM and VM size */
    toastIdxRel = relation_open(toastRel->rd_rel->reltoastidxid, AccessShareLock);
    for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
        size += calculate_relation_size(&(toastIdxRel->rd_node),
                                        toastIdxRel->rd_backend, forkNum);

    relation_close(toastIdxRel, AccessShareLock);
    relation_close(toastRel, AccessShareLock);

    return size;
}

static int64 calculate_total_relation_size ( Relation  rel  )  [static]

Definition at line 478 of file dbsize.c.

References calculate_indexes_size(), and calculate_table_size().

Referenced by pg_total_relation_size().

{
    int64       size;

    /*
     * Aggregate the table size, this includes size of the heap, toast and
     * toast index with free space and visibility map
     */
    size = calculate_table_size(rel);

    /*
     * Add size of all attached indexes as well
     */
    size += calculate_indexes_size(rel);

    return size;
}

static int64 db_dir_size ( const char *  path  )  [static]

Definition at line 37 of file dbsize.c.

References AllocateDir(), CHECK_FOR_INTERRUPTS, dirent::d_name, ereport, errcode_for_file_access(), errmsg(), ERROR, filename, FreeDir(), MAXPGPATH, NULL, ReadDir(), and snprintf().

Referenced by calculate_database_size(), and calculate_tablespace_size().

{
    int64       dirsize = 0;
    struct dirent *direntry;
    DIR        *dirdesc;
    char        filename[MAXPGPATH];

    dirdesc = AllocateDir(path);

    if (!dirdesc)
        return 0;

    while ((direntry = ReadDir(dirdesc, path)) != NULL)
    {
        struct stat fst;

        CHECK_FOR_INTERRUPTS();

        if (strcmp(direntry->d_name, ".") == 0 ||
            strcmp(direntry->d_name, "..") == 0)
            continue;

        snprintf(filename, MAXPGPATH, "%s/%s", path, direntry->d_name);

        if (stat(filename, &fst) < 0)
        {
            if (errno == ENOENT)
                continue;
            else
                ereport(ERROR,
                        (errcode_for_file_access(),
                         errmsg("could not stat file \"%s\": %m", filename)));
        }
        dirsize += fst.st_size;
    }

    FreeDir(dirdesc);
    return dirsize;
}

static Numeric int64_to_numeric ( int64  v  )  [static]
static bool numeric_is_less ( Numeric  a,
Numeric  b 
) [static]

Definition at line 576 of file dbsize.c.

References DatumGetBool, DirectFunctionCall2, numeric_lt(), and NumericGetDatum.

Referenced by pg_size_pretty_numeric().

static Numeric numeric_plus_one_over_two ( Numeric  n  )  [static]
static Numeric numeric_shift_right ( Numeric  n,
unsigned  count 
) [static]

Definition at line 600 of file dbsize.c.

References DatumGetNumeric, DirectFunctionCall1, DirectFunctionCall2, Int64GetDatum(), int8_numeric(), numeric_div_trunc(), and NumericGetDatum.

Referenced by pg_size_pretty_numeric().

{
    Datum       d = NumericGetDatum(n);
    Datum       divisor_int64;
    Datum       divisor_numeric;
    Datum       result;

    divisor_int64 = Int64GetDatum((int64) (1 << count));
    divisor_numeric = DirectFunctionCall1(int8_numeric, divisor_int64);
    result = DirectFunctionCall2(numeric_div_trunc, d, divisor_numeric);
    return DatumGetNumeric(result);
}

static char* numeric_to_cstring ( Numeric  n  )  [static]
Datum pg_database_size_name ( PG_FUNCTION_ARGS   ) 

Definition at line 144 of file dbsize.c.

References calculate_database_size(), dbName, get_database_oid(), NameStr, PG_GETARG_NAME, PG_RETURN_INT64, and PG_RETURN_NULL.

{
    Name        dbName = PG_GETARG_NAME(0);
    Oid         dbOid = get_database_oid(NameStr(*dbName), false);
    int64       size;

    size = calculate_database_size(dbOid);

    if (size == 0)
        PG_RETURN_NULL();

    PG_RETURN_INT64(size);
}

Datum pg_database_size_oid ( PG_FUNCTION_ARGS   ) 

Definition at line 130 of file dbsize.c.

References calculate_database_size(), PG_GETARG_OID, PG_RETURN_INT64, and PG_RETURN_NULL.

{
    Oid         dbOid = PG_GETARG_OID(0);
    int64       size;

    size = calculate_database_size(dbOid);

    if (size == 0)
        PG_RETURN_NULL();

    PG_RETURN_INT64(size);
}

Datum pg_indexes_size ( PG_FUNCTION_ARGS   ) 
Datum pg_relation_filenode ( PG_FUNCTION_ARGS   ) 

Definition at line 707 of file dbsize.c.

References GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum, OidIsValid, PG_GETARG_OID, PG_RETURN_NULL, PG_RETURN_OID, RelationMapOidToFilenode(), ReleaseSysCache(), RELKIND_INDEX, RELKIND_MATVIEW, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_TOASTVALUE, RELOID, and SearchSysCache1.

{
    Oid         relid = PG_GETARG_OID(0);
    Oid         result;
    HeapTuple   tuple;
    Form_pg_class relform;

    tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
    if (!HeapTupleIsValid(tuple))
        PG_RETURN_NULL();
    relform = (Form_pg_class) GETSTRUCT(tuple);

    switch (relform->relkind)
    {
        case RELKIND_RELATION:
        case RELKIND_MATVIEW:
        case RELKIND_INDEX:
        case RELKIND_SEQUENCE:
        case RELKIND_TOASTVALUE:
            /* okay, these have storage */
            if (relform->relfilenode)
                result = relform->relfilenode;
            else    /* Consult the relation mapper */
                result = RelationMapOidToFilenode(relid,
                                                  relform->relisshared);
            break;

        default:
            /* no storage, return NULL */
            result = InvalidOid;
            break;
    }

    ReleaseSysCache(tuple);

    if (!OidIsValid(result))
        PG_RETURN_NULL();

    PG_RETURN_OID(result);
}

Datum pg_relation_filepath ( PG_FUNCTION_ARGS   ) 

Definition at line 754 of file dbsize.c.

References Assert, cstring_to_text(), RelFileNode::dbNode, elog, ERROR, GETSTRUCT, GetTempNamespaceBackendId(), GLOBALTABLESPACE_OID, HeapTupleIsValid, InvalidBackendId, isTempOrToastNamespace(), MAIN_FORKNUM, MyBackendId, MyDatabaseId, MyDatabaseTableSpace, ObjectIdGetDatum, OidIsValid, PG_GETARG_OID, PG_RETURN_NULL, PG_RETURN_TEXT_P, RelationMapOidToFilenode(), ReleaseSysCache(), RELKIND_INDEX, RELKIND_MATVIEW, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_TOASTVALUE, RelFileNode::relNode, RELOID, relpathbackend(), RELPERSISTENCE_PERMANENT, RELPERSISTENCE_TEMP, RELPERSISTENCE_UNLOGGED, SearchSysCache1, and RelFileNode::spcNode.

{
    Oid         relid = PG_GETARG_OID(0);
    HeapTuple   tuple;
    Form_pg_class relform;
    RelFileNode rnode;
    BackendId   backend;
    char       *path;

    tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
    if (!HeapTupleIsValid(tuple))
        PG_RETURN_NULL();
    relform = (Form_pg_class) GETSTRUCT(tuple);

    switch (relform->relkind)
    {
        case RELKIND_RELATION:
        case RELKIND_MATVIEW:
        case RELKIND_INDEX:
        case RELKIND_SEQUENCE:
        case RELKIND_TOASTVALUE:
            /* okay, these have storage */

            /* This logic should match RelationInitPhysicalAddr */
            if (relform->reltablespace)
                rnode.spcNode = relform->reltablespace;
            else
                rnode.spcNode = MyDatabaseTableSpace;
            if (rnode.spcNode == GLOBALTABLESPACE_OID)
                rnode.dbNode = InvalidOid;
            else
                rnode.dbNode = MyDatabaseId;
            if (relform->relfilenode)
                rnode.relNode = relform->relfilenode;
            else    /* Consult the relation mapper */
                rnode.relNode = RelationMapOidToFilenode(relid,
                                                       relform->relisshared);
            break;

        default:
            /* no storage, return NULL */
            rnode.relNode = InvalidOid;
            /* some compilers generate warnings without these next two lines */
            rnode.dbNode = InvalidOid;
            rnode.spcNode = InvalidOid;
            break;
    }

    if (!OidIsValid(rnode.relNode))
    {
        ReleaseSysCache(tuple);
        PG_RETURN_NULL();
    }

    /* Determine owning backend. */
    switch (relform->relpersistence)
    {
        case RELPERSISTENCE_UNLOGGED:
        case RELPERSISTENCE_PERMANENT:
            backend = InvalidBackendId;
            break;
        case RELPERSISTENCE_TEMP:
            if (isTempOrToastNamespace(relform->relnamespace))
                backend = MyBackendId;
            else
            {
                /* Do it the hard way. */
                backend = GetTempNamespaceBackendId(relform->relnamespace);
                Assert(backend != InvalidBackendId);
            }
            break;
        default:
            elog(ERROR, "invalid relpersistence: %c", relform->relpersistence);
            backend = InvalidBackendId; /* placate compiler */
            break;
    }

    ReleaseSysCache(tuple);

    path = relpathbackend(rnode, backend, MAIN_FORKNUM);

    PG_RETURN_TEXT_P(cstring_to_text(path));
}

Datum pg_relation_is_scannable ( PG_FUNCTION_ARGS   ) 

Definition at line 847 of file dbsize.c.

References AccessShareLock, NULL, PG_GETARG_OID, PG_RETURN_BOOL, relation_close(), RelationIsScannable, and try_relation_open().

{
    Oid         relid;
    Relation    relation;
    bool        result;

    relid = PG_GETARG_OID(0);
    relation = try_relation_open(relid, AccessShareLock);

    if (relation == NULL)
        PG_RETURN_BOOL(false);

    result = RelationIsScannable(relation);

    relation_close(relation, AccessShareLock);
    PG_RETURN_BOOL(result);
}

Datum pg_relation_size ( PG_FUNCTION_ARGS   ) 

Definition at line 307 of file dbsize.c.

References AccessShareLock, calculate_relation_size(), forkname_to_number(), NULL, PG_GETARG_OID, PG_GETARG_TEXT_P, PG_RETURN_INT64, PG_RETURN_NULL, RelationData::rd_backend, RelationData::rd_node, relation_close(), text_to_cstring(), and try_relation_open().

{
    Oid         relOid = PG_GETARG_OID(0);
    text       *forkName = PG_GETARG_TEXT_P(1);
    Relation    rel;
    int64       size;

    rel = try_relation_open(relOid, AccessShareLock);

    /*
     * Before 9.2, we used to throw an error if the relation didn't exist, but
     * that makes queries like "SELECT pg_relation_size(oid) FROM pg_class"
     * less robust, because while we scan pg_class with an MVCC snapshot,
     * someone else might drop the table. It's better to return NULL for
     * already-dropped tables than throw an error and abort the whole query.
     */
    if (rel == NULL)
        PG_RETURN_NULL();

    size = calculate_relation_size(&(rel->rd_node), rel->rd_backend,
                              forkname_to_number(text_to_cstring(forkName)));

    relation_close(rel, AccessShareLock);

    PG_RETURN_INT64(size);
}

Datum pg_size_pretty ( PG_FUNCTION_ARGS   ) 

Definition at line 519 of file dbsize.c.

References buf, cstring_to_text(), PG_GETARG_INT64, PG_RETURN_TEXT_P, and snprintf().

{
    int64       size = PG_GETARG_INT64(0);
    char        buf[64];
    int64       limit = 10 * 1024;
    int64       limit2 = limit * 2 - 1;

    if (size < limit)
        snprintf(buf, sizeof(buf), INT64_FORMAT " bytes", size);
    else
    {
        size >>= 9;             /* keep one extra bit for rounding */
        if (size < limit2)
            snprintf(buf, sizeof(buf), INT64_FORMAT " kB",
                     (size + 1) / 2);
        else
        {
            size >>= 10;
            if (size < limit2)
                snprintf(buf, sizeof(buf), INT64_FORMAT " MB",
                         (size + 1) / 2);
            else
            {
                size >>= 10;
                if (size < limit2)
                    snprintf(buf, sizeof(buf), INT64_FORMAT " GB",
                             (size + 1) / 2);
                else
                {
                    size >>= 10;
                    snprintf(buf, sizeof(buf), INT64_FORMAT " TB",
                             (size + 1) / 2);
                }
            }
        }
    }

    PG_RETURN_TEXT_P(cstring_to_text(buf));
}

Datum pg_size_pretty_numeric ( PG_FUNCTION_ARGS   ) 

Definition at line 614 of file dbsize.c.

References buf, cstring_to_text(), int64_to_numeric(), numeric_is_less(), numeric_plus_one_over_two(), numeric_shift_right(), numeric_to_cstring(), palloc(), PG_GETARG_NUMERIC, and PG_RETURN_TEXT_P.

{
    Numeric     size = PG_GETARG_NUMERIC(0);
    Numeric     limit,
                limit2;
    char       *buf,
               *result;

    limit = int64_to_numeric(10 * 1024);
    limit2 = int64_to_numeric(10 * 1024 * 2 - 1);

    if (numeric_is_less(size, limit))
    {
        buf = numeric_to_cstring(size);
        result = palloc(strlen(buf) + 7);
        strcpy(result, buf);
        strcat(result, " bytes");
    }
    else
    {
        /* keep one extra bit for rounding */
        /* size >>= 9 */
        size = numeric_shift_right(size, 9);

        if (numeric_is_less(size, limit2))
        {
            /* size = (size + 1) / 2 */
            size = numeric_plus_one_over_two(size);
            buf = numeric_to_cstring(size);
            result = palloc(strlen(buf) + 4);
            strcpy(result, buf);
            strcat(result, " kB");
        }
        else
        {
            /* size >>= 10 */
            size = numeric_shift_right(size, 10);
            if (numeric_is_less(size, limit2))
            {
                /* size = (size + 1) / 2 */
                size = numeric_plus_one_over_two(size);
                buf = numeric_to_cstring(size);
                result = palloc(strlen(buf) + 4);
                strcpy(result, buf);
                strcat(result, " MB");
            }
            else
            {
                /* size >>= 10 */
                size = numeric_shift_right(size, 10);

                if (numeric_is_less(size, limit2))
                {
                    /* size = (size + 1) / 2 */
                    size = numeric_plus_one_over_two(size);
                    buf = numeric_to_cstring(size);
                    result = palloc(strlen(buf) + 4);
                    strcpy(result, buf);
                    strcat(result, " GB");
                }
                else
                {
                    /* size >>= 10 */
                    size = numeric_shift_right(size, 10);
                    /* size = (size + 1) / 2 */
                    size = numeric_plus_one_over_two(size);
                    buf = numeric_to_cstring(size);
                    result = palloc(strlen(buf) + 4);
                    strcpy(result, buf);
                    strcat(result, " TB");
                }
            }
        }
    }

    PG_RETURN_TEXT_P(cstring_to_text(result));
}

Datum pg_table_size ( PG_FUNCTION_ARGS   ) 
Datum pg_tablespace_size_name ( PG_FUNCTION_ARGS   ) 

Definition at line 247 of file dbsize.c.

References calculate_tablespace_size(), get_tablespace_oid(), NameStr, PG_GETARG_NAME, PG_RETURN_INT64, and PG_RETURN_NULL.

{
    Name        tblspcName = PG_GETARG_NAME(0);
    Oid         tblspcOid = get_tablespace_oid(NameStr(*tblspcName), false);
    int64       size;

    size = calculate_tablespace_size(tblspcOid);

    if (size < 0)
        PG_RETURN_NULL();

    PG_RETURN_INT64(size);
}

Datum pg_tablespace_size_oid ( PG_FUNCTION_ARGS   ) 

Definition at line 233 of file dbsize.c.

References calculate_tablespace_size(), PG_GETARG_OID, PG_RETURN_INT64, and PG_RETURN_NULL.

{
    Oid         tblspcOid = PG_GETARG_OID(0);
    int64       size;

    size = calculate_tablespace_size(tblspcOid);

    if (size < 0)
        PG_RETURN_NULL();

    PG_RETURN_INT64(size);
}

Datum pg_total_relation_size ( PG_FUNCTION_ARGS   )