/* Divide by two and round away from zero */ #define half_rounded(x) (((x) + ((x) < 0 ? -1 : 1)) / 2)
/* Units used in pg_size_pretty functions. All units must be powers of 2 */ struct size_pretty_unit
{ constchar *name; /* bytes, kB, MB, GB etc */
uint32 limit; /* upper limit, prior to half rounding after
* converting to this unit. */ bool round; /* do half rounding for this unit */
uint8 unitbits; /* (1 << unitbits) bytes to make 1 of this
* unit */
};
/* When adding units here also update the docs and the error message in pg_size_bytes */ staticconststruct size_pretty_unit size_pretty_units[] = {
{"bytes", 10 * 1024, false, 0},
{"kB", 20 * 1024 - 1, true, 10},
{"MB", 20 * 1024 - 1, true, 20},
{"GB", 20 * 1024 - 1, true, 30},
{"TB", 20 * 1024 - 1, true, 40},
{"PB", 20 * 1024 - 1, true, 50},
{NULL, 0, false, 0}
};
/* Additional unit aliases accepted by pg_size_bytes */ struct size_bytes_unit_alias
{ constchar *alias; int unit_index; /* corresponding size_pretty_units element */
};
/* When adding units here also update the docs and the error message in pg_size_bytes */ staticconststruct size_bytes_unit_alias size_bytes_aliases[] = {
{"B", 0},
{NULL}
};
/* Return physical size of directory contents, or 0 if dir doesn't exist */ static int64
db_dir_size(constchar *path)
{
int64 dirsize = 0; struct dirent *direntry;
DIR *dirdesc; char filename[MAXPGPATH * 2];
dirdesc = AllocateDir(path);
if (!dirdesc) return0;
while ((direntry = ReadDir(dirdesc, path)) != NULL)
{ struct stat fst;
Datum
pg_database_size_oid(PG_FUNCTION_ARGS)
{
Oid dbOid = PG_GETARG_OID(0);
int64 size;
/* *Notneededforcorrectness,butavoidnon-user-facingerrormessage *laterifthedatabasedoesn'texist.
*/ if (!SearchSysCacheExists1(DATABASEOID, ObjectIdGetDatum(dbOid)))
ereport(ERROR,
errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("database with OID %u does not exist", dbOid));
size = calculate_database_size(dbOid);
if (size == 0)
PG_RETURN_NULL();
PG_RETURN_INT64(size);
}
Datum
pg_database_size_name(PG_FUNCTION_ARGS)
{
Name dbName = PG_GETARG_NAME(0);
Oid dbOid = get_database_oid(NameStr(*dbName), false);
int64 size;
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;
}
Datum
pg_tablespace_size_oid(PG_FUNCTION_ARGS)
{
Oid tblspcOid = PG_GETARG_OID(0);
int64 size;
/* *Notneededforcorrectness,butavoidnon-user-facingerrormessage *laterifthetablespacedoesn'texist.
*/ if (!SearchSysCacheExists1(TABLESPACEOID, ObjectIdGetDatum(tblspcOid)))
ereport(ERROR,
errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("tablespace with OID %u does not exist", tblspcOid));
size = calculate_tablespace_size(tblspcOid);
if (size < 0)
PG_RETURN_NULL();
PG_RETURN_INT64(size);
}
Datum
pg_tablespace_size_name(PG_FUNCTION_ARGS)
{
Name tblspcName = PG_GETARG_NAME(0);
Oid tblspcOid = get_tablespace_oid(NameStr(*tblspcName), false);
int64 size;
staticbool
numeric_is_less(Numeric a, Numeric b)
{
Datum da = NumericGetDatum(a);
Datum db = NumericGetDatum(b);
return DatumGetBool(DirectFunctionCall2(numeric_lt, da, db));
}
static Numeric
numeric_absolute(Numeric n)
{
Datum d = NumericGetDatum(n);
Datum result;
result = DirectFunctionCall1(numeric_abs, d); return DatumGetNumeric(result);
}
static Numeric
numeric_half_rounded(Numeric n)
{
Datum d = NumericGetDatum(n);
Datum zero;
Datum one;
Datum two;
Datum result;
zero = NumericGetDatum(int64_to_numeric(0));
one = NumericGetDatum(int64_to_numeric(1));
two = NumericGetDatum(int64_to_numeric(2));
if (DatumGetBool(DirectFunctionCall2(numeric_ge, d, zero)))
d = DirectFunctionCall2(numeric_add, d, one); else
d = DirectFunctionCall2(numeric_sub, d, one);
result = DirectFunctionCall2(numeric_div_trunc, d, two); return DatumGetNumeric(result);
}
static Numeric
numeric_truncated_divide(Numeric n, int64 divisor)
{
Datum d = NumericGetDatum(n);
Datum divisor_numeric;
Datum result;
/* use this unit if there are no more units or we're below the limit */ if (unit[1].name == NULL ||
numeric_is_less(numeric_absolute(size),
int64_to_numeric(unit->limit)))
{ if (unit->round)
size = numeric_half_rounded(size);
result = psprintf("%s %s", numeric_to_cstring(size), unit->name); break;
}
/* Skip leading whitespace */
strptr = str; while (isspace((unsignedchar) *strptr))
strptr++;
/* Check that we have a valid number and determine where it ends */
endptr = strptr;
/* Part (1): sign */ if (*endptr == '-' || *endptr == '+')
endptr++;
/* Part (2): main digit string */ if (isdigit((unsignedchar) *endptr))
{
have_digits = true; do
endptr++; while (isdigit((unsignedchar) *endptr));
}
/* Part (3): optional decimal point and fractional digits */ if (*endptr == '.')
{
endptr++; if (isdigit((unsignedchar) *endptr))
{
have_digits = true; do
endptr++; while (isdigit((unsignedchar) *endptr));
}
}
/* Complain if we don't have a valid number at this point */ if (!have_digits)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid size: \"%s\"", str)));
/* Part (4): optional exponent */ if (*endptr == 'e' || *endptr == 'E')
{ long exponent; char *cp;
num = DatumGetNumeric(DirectFunctionCall3(numeric_in,
CStringGetDatum(strptr),
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(-1)));
*endptr = saved_char;
/* Skip whitespace between number and unit */
strptr = endptr; while (isspace((unsignedchar) *strptr))
strptr++;
/* Handle possible unit */ if (*strptr != '\0')
{ conststruct size_pretty_unit *unit;
int64 multiplier = 0;
/* Trim any trailing whitespace */
endptr = str + VARSIZE_ANY_EXHDR(arg) - 1;
while (isspace((unsignedchar) *endptr))
endptr--;
endptr++;
*endptr = '\0';
for (unit = size_pretty_units; unit->name != NULL; unit++)
{ /* Parse the unit case-insensitively */ if (pg_strcasecmp(strptr, unit->name) == 0) break;
}
/* If not found, look in table of aliases */ if (unit->name == NULL)
{ for (conststruct size_bytes_unit_alias *a = size_bytes_aliases; a->alias != NULL; a++)
{ if (pg_strcasecmp(strptr, a->alias) == 0)
{
unit = &size_pretty_units[a->unit_index]; break;
}
}
}
/* Verify we found a valid unit in the loop above */ if (unit->name == NULL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid size: \"%s\"", text_to_cstring(arg)),
errdetail("Invalid size unit: \"%s\".", strptr),
errhint("Valid units are \"bytes\", \"B\", \"kB\", \"MB\", \"GB\", \"TB\", and \"PB\".")));
multiplier = ((int64) 1) << unit->unitbits;
if (multiplier > 1)
{
Numeric mul_num;
mul_num = int64_to_numeric(multiplier);
num = DatumGetNumeric(DirectFunctionCall2(numeric_mul,
NumericGetDatum(mul_num),
NumericGetDatum(num)));
}
}
result = DatumGetInt64(DirectFunctionCall1(numeric_int8,
NumericGetDatum(num)));
if (RELKIND_HAS_STORAGE(relform->relkind))
{ if (relform->relfilenode)
result = relform->relfilenode; else/* Consult the relation mapper */
result = RelationMapOidToFilenumber(relid,
relform->relisshared);
} else
{ /* no storage, return NULL */
result = InvalidRelFileNumber;
}
ReleaseSysCache(tuple);
if (!RelFileNumberIsValid(result))
PG_RETURN_NULL();
PG_RETURN_OID(result);
}
/* *Gettherelationvia(reltablespace,relfilenumber) * *Thisisexpectedtobeusedwhensomebodywantstomatchanindividualfile *onthefilesystembacktoitstable.That'snottriviallypossiblevia *pg_class,becausethatdoesn'tcontaintherelfilenumbersofsharedandnailed *tables. * *Wedon'tfailbutreturnNULLifwecannotfindamapping. * *Temporaryrelationsarenotdetected,returningNULL(see *RelidByRelfilenumber()forthereasons). * *InvalidOidcanbepassedinsteadofthecurrentdatabase'sdefault *tablespace.
*/
Datum
pg_filenode_relation(PG_FUNCTION_ARGS)
{
Oid reltablespace = PG_GETARG_OID(0);
RelFileNumber relfilenumber = PG_GETARG_OID(1);
Oid heaprel;
/* test needed so RelidByRelfilenumber doesn't misbehave */ if (!RelFileNumberIsValid(relfilenumber))
PG_RETURN_NULL();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.