Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit56ff8b2

Browse files
committed
Use a lookup table for units in pg_size_pretty and pg_size_bytes
We've grown 2 versions of pg_size_pretty over the years, one for BIGINTand one for NUMERIC. Both should output the same, but keeping them insync is harder than needed due to neither function sharing a source oftruth about which units to use and how to transition to the next largestunit.Here we add a static array which defines the units that we recognize andhave both pg_size_pretty and pg_size_pretty_numeric use it. This willmake adding any units in the future a very simple task.The table contains all information required to allow us to also modifypg_size_bytes to use the lookup table, so adjust that too.There are no behavioral changes here.Author: David RowleyReviewed-by: Dean Rasheed, Tom Lane, David ChristensenDiscussion:https://postgr.es/m/CAApHDvru1F7qsEVL-iOHeezJ+5WVxXnyD_Jo9nht+Eh85ekK-Q@mail.gmail.com
1 parent55fe609 commit56ff8b2

File tree

1 file changed

+80
-90
lines changed

1 file changed

+80
-90
lines changed

‎src/backend/utils/adt/dbsize.c

Lines changed: 80 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,27 @@
3434
/* Divide by two and round away from zero */
3535
#definehalf_rounded(x) (((x) + ((x) < 0 ? -1 : 1)) / 2)
3636

37+
/* Units used in pg_size_pretty functions. All units must be powers of 2 */
38+
structsize_pretty_unit
39+
{
40+
constchar*name;/* bytes, kB, MB, GB etc */
41+
uint32limit;/* upper limit, prior to half rounding after
42+
* converting to this unit. */
43+
boolround;/* do half rounding for this unit */
44+
uint8unitbits;/* (1 << unitbits) bytes to make 1 of this
45+
* unit */
46+
};
47+
48+
/* When adding units here also update the error message in pg_size_bytes */
49+
staticconststructsize_pretty_unitsize_pretty_units[]= {
50+
{"bytes",10*1024, false,0},
51+
{"kB",20*1024-1, true,10},
52+
{"MB",20*1024-1, true,20},
53+
{"GB",20*1024-1, true,30},
54+
{"TB",20*1024-1, true,40},
55+
{NULL,0, false,0}
56+
};
57+
3758
/* Return physical size of directory contents, or 0 if dir doesn't exist */
3859
staticint64
3960
db_dir_size(constchar*path)
@@ -535,41 +556,34 @@ pg_size_pretty(PG_FUNCTION_ARGS)
535556
{
536557
int64size=PG_GETARG_INT64(0);
537558
charbuf[64];
538-
int64limit=10*1024;
539-
int64limit2=limit*2-1;
559+
conststructsize_pretty_unit*unit;
540560

541-
if (Abs(size)<limit)
542-
snprintf(buf,sizeof(buf),INT64_FORMAT" bytes",size);
543-
else
561+
for (unit=size_pretty_units;unit->name!=NULL;unit++)
544562
{
545-
/*
546-
* We use divide instead of bit shifting so that behavior matches for
547-
* both positive and negative size values.
548-
*/
549-
size /= (1 <<9);/* keep one extra bit for rounding */
550-
if (Abs(size)<limit2)
551-
snprintf(buf,sizeof(buf),INT64_FORMAT" kB",
552-
half_rounded(size));
553-
else
563+
uint8bits;
564+
565+
/* use this unit if there are no more units or we're below the limit */
566+
if (unit[1].name==NULL||Abs(size)<unit->limit)
554567
{
555-
size /= (1 <<10);
556-
if (Abs(size)<limit2)
557-
snprintf(buf,sizeof(buf),INT64_FORMAT" MB",
558-
half_rounded(size));
559-
else
560-
{
561-
size /= (1 <<10);
562-
if (Abs(size)<limit2)
563-
snprintf(buf,sizeof(buf),INT64_FORMAT" GB",
564-
half_rounded(size));
565-
else
566-
{
567-
size /= (1 <<10);
568-
snprintf(buf,sizeof(buf),INT64_FORMAT" TB",
569-
half_rounded(size));
570-
}
571-
}
568+
if (unit->round)
569+
size=half_rounded(size);
570+
571+
snprintf(buf,sizeof(buf),INT64_FORMAT" %s",size,unit->name);
572+
break;
572573
}
574+
575+
/*
576+
* Determine the number of bits to use to build the divisor. We may
577+
* need to use 1 bit less than the difference between this and the
578+
* next unit if the next unit uses half rounding. Or we may need to
579+
* shift an extra bit if this unit uses half rounding and the next one
580+
* does not. We use division rather than shifting right by this
581+
* number of bits to ensure positive and negative values are rounded
582+
* in the same way.
583+
*/
584+
bits= (unit[1].unitbits-unit->unitbits- (unit[1].round== true)
585+
+ (unit->round== true));
586+
size /= ((int64)1) <<bits;
573587
}
574588

575589
PG_RETURN_TEXT_P(cstring_to_text(buf));
@@ -640,57 +654,35 @@ Datum
640654
pg_size_pretty_numeric(PG_FUNCTION_ARGS)
641655
{
642656
Numericsize=PG_GETARG_NUMERIC(0);
643-
Numericlimit,
644-
limit2;
645-
char*result;
646-
647-
limit=int64_to_numeric(10*1024);
648-
limit2=int64_to_numeric(10*1024*2-1);
657+
char*result=NULL;
658+
conststructsize_pretty_unit*unit;
649659

650-
if (numeric_is_less(numeric_absolute(size),limit))
660+
for (unit=size_pretty_units;unit->name!=NULL;unit++)
651661
{
652-
result=psprintf("%s bytes",numeric_to_cstring(size));
653-
}
654-
else
655-
{
656-
/* keep one extra bit for rounding */
657-
/* size /= (1 << 9) */
658-
size=numeric_truncated_divide(size,1 <<9);
662+
unsignedintshiftby;
659663

660-
if (numeric_is_less(numeric_absolute(size),limit2))
664+
/* use this unit if there are no more units or we're below the limit */
665+
if (unit[1].name==NULL||
666+
numeric_is_less(numeric_absolute(size),
667+
int64_to_numeric(unit->limit)))
661668
{
662-
size=numeric_half_rounded(size);
663-
result=psprintf("%s kB",numeric_to_cstring(size));
664-
}
665-
else
666-
{
667-
/* size /= (1 << 10) */
668-
size=numeric_truncated_divide(size,1 <<10);
669-
670-
if (numeric_is_less(numeric_absolute(size),limit2))
671-
{
669+
if (unit->round)
672670
size=numeric_half_rounded(size);
673-
result=psprintf("%s MB",numeric_to_cstring(size));
674-
}
675-
else
676-
{
677-
/* size /= (1 << 10) */
678-
size=numeric_truncated_divide(size,1 <<10);
679-
680-
if (numeric_is_less(numeric_absolute(size),limit2))
681-
{
682-
size=numeric_half_rounded(size);
683-
result=psprintf("%s GB",numeric_to_cstring(size));
684-
}
685-
else
686-
{
687-
/* size /= (1 << 10) */
688-
size=numeric_truncated_divide(size,1 <<10);
689-
size=numeric_half_rounded(size);
690-
result=psprintf("%s TB",numeric_to_cstring(size));
691-
}
692-
}
671+
672+
result=psprintf("%s %s",numeric_to_cstring(size),unit->name);
673+
break;
693674
}
675+
676+
/*
677+
* Determine the number of bits to use to build the divisor. We may
678+
* need to use 1 bit less than the difference between this and the
679+
* next unit if the next unit uses half rounding. Or we may need to
680+
* shift an extra bit if this unit uses half rounding and the next one
681+
* does not.
682+
*/
683+
shiftby= (unit[1].unitbits-unit->unitbits- (unit[1].round== true)
684+
+ (unit->round== true));
685+
size=numeric_truncated_divide(size, ((int64)1) <<shiftby);
694686
}
695687

696688
PG_RETURN_TEXT_P(cstring_to_text(result));
@@ -791,6 +783,7 @@ pg_size_bytes(PG_FUNCTION_ARGS)
791783
/* Handle possible unit */
792784
if (*strptr!='\0')
793785
{
786+
conststructsize_pretty_unit*unit;
794787
int64multiplier=0;
795788

796789
/* Trim any trailing whitespace */
@@ -802,21 +795,18 @@ pg_size_bytes(PG_FUNCTION_ARGS)
802795
endptr++;
803796
*endptr='\0';
804797

805-
/* Parse the unit case-insensitively */
806-
if (pg_strcasecmp(strptr,"bytes")==0)
807-
multiplier= (int64)1;
808-
elseif (pg_strcasecmp(strptr,"kb")==0)
809-
multiplier= (int64)1024;
810-
elseif (pg_strcasecmp(strptr,"mb")==0)
811-
multiplier= ((int64)1024)*1024;
812-
813-
elseif (pg_strcasecmp(strptr,"gb")==0)
814-
multiplier= ((int64)1024)*1024*1024;
815-
816-
elseif (pg_strcasecmp(strptr,"tb")==0)
817-
multiplier= ((int64)1024)*1024*1024*1024;
798+
for (unit=size_pretty_units;unit->name!=NULL;unit++)
799+
{
800+
/* Parse the unit case-insensitively */
801+
if (pg_strcasecmp(strptr,unit->name)==0)
802+
{
803+
multiplier= ((int64)1) <<unit->unitbits;
804+
break;
805+
}
806+
}
818807

819-
else
808+
/* Verify we found a valid unit in the loop above */
809+
if (unit->name==NULL)
820810
ereport(ERROR,
821811
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
822812
errmsg("invalid size: \"%s\"",text_to_cstring(arg)),

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp