Skip to content

Commit 260a1f1

Browse files
Add to_bin() and to_oct().
This commit introduces functions for converting numbers to their equivalent binary and octal representations. Also, the base conversion code for these functions and to_hex() has been moved to a common helper function. Co-authored-by: Eric Radman Reviewed-by: Ian Barwick, Dag Lem, Vignesh C, Tom Lane, Peter Eisentraut, Kirk Wolak, Vik Fearing, John Naylor, Dean Rasheed Discussion: https://postgr.es/m/Y6IyTQQ/TsD5wnsH%40vm3.eradman.com
1 parent ccadf73 commit 260a1f1

File tree

5 files changed

+204
-30
lines changed

5 files changed

+204
-30
lines changed

doc/src/sgml/func.sgml

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3737,6 +3737,32 @@ repeat('Pg', 4) <returnvalue>PgPgPgPg</returnvalue>
37373737
</para></entry>
37383738
</row>
37393739

3740+
<row>
3741+
<entry role="func_table_entry"><para role="func_signature">
3742+
<indexterm>
3743+
<primary>to_bin</primary>
3744+
</indexterm>
3745+
<function>to_bin</function> ( <type>integer</type> )
3746+
<returnvalue>text</returnvalue>
3747+
</para>
3748+
<para role="func_signature">
3749+
<function>to_bin</function> ( <type>bigint</type> )
3750+
<returnvalue>text</returnvalue>
3751+
</para>
3752+
<para>
3753+
Converts the number to its equivalent two's complement binary
3754+
representation.
3755+
</para>
3756+
<para>
3757+
<literal>to_bin(2147483647)</literal>
3758+
<returnvalue>1111111111111111111111111111111</returnvalue>
3759+
</para>
3760+
<para>
3761+
<literal>to_bin(-1234)</literal>
3762+
<returnvalue>11111111111111111111101100101110</returnvalue>
3763+
</para></entry>
3764+
</row>
3765+
37403766
<row>
37413767
<entry role="func_table_entry"><para role="func_signature">
37423768
<indexterm>
@@ -3750,11 +3776,42 @@ repeat('Pg', 4) <returnvalue>PgPgPgPg</returnvalue>
37503776
<returnvalue>text</returnvalue>
37513777
</para>
37523778
<para>
3753-
Converts the number to its equivalent hexadecimal representation.
3779+
Converts the number to its equivalent two's complement hexadecimal
3780+
representation.
37543781
</para>
37553782
<para>
37563783
<literal>to_hex(2147483647)</literal>
37573784
<returnvalue>7fffffff</returnvalue>
3785+
</para>
3786+
<para>
3787+
<literal>to_hex(-1234)</literal>
3788+
<returnvalue>fffffb2e</returnvalue>
3789+
</para></entry>
3790+
</row>
3791+
3792+
<row>
3793+
<entry role="func_table_entry"><para role="func_signature">
3794+
<indexterm>
3795+
<primary>to_oct</primary>
3796+
</indexterm>
3797+
<function>to_oct</function> ( <type>integer</type> )
3798+
<returnvalue>text</returnvalue>
3799+
</para>
3800+
<para role="func_signature">
3801+
<function>to_oct</function> ( <type>bigint</type> )
3802+
<returnvalue>text</returnvalue>
3803+
</para>
3804+
<para>
3805+
Converts the number to its equivalent two's complement octal
3806+
representation.
3807+
</para>
3808+
<para>
3809+
<literal>to_oct(2147483647)</literal>
3810+
<returnvalue>17777777777</returnvalue>
3811+
</para>
3812+
<para>
3813+
<literal>to_oct(-1234)</literal>
3814+
<returnvalue>37777775456</returnvalue>
37583815
</para></entry>
37593816
</row>
37603817

src/backend/utils/adt/varlena.c

Lines changed: 60 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4919,53 +4919,87 @@ array_to_text_internal(FunctionCallInfo fcinfo, ArrayType *v,
49194919
return result;
49204920
}
49214921

4922-
#define HEXBASE 16
49234922
/*
4924-
* Convert an int32 to a string containing a base 16 (hex) representation of
4925-
* the number.
4923+
* Workhorse for to_bin, to_oct, and to_hex. Note that base must be > 1 and <=
4924+
* 16.
49264925
*/
4927-
Datum
4928-
to_hex32(PG_FUNCTION_ARGS)
4926+
static inline text *
4927+
convert_to_base(uint64 value, int base)
49294928
{
4930-
uint32 value = (uint32) PG_GETARG_INT32(0);
4931-
char *ptr;
49324929
const char *digits = "0123456789abcdef";
4933-
char buf[32]; /* bigger than needed, but reasonable */
49344930

4935-
ptr = buf + sizeof(buf) - 1;
4936-
*ptr = '\0';
4931+
/* We size the buffer for to_bin's longest possible return value. */
4932+
char buf[sizeof(uint64) * BITS_PER_BYTE];
4933+
char *const end = buf + sizeof(buf);
4934+
char *ptr = end;
4935+
4936+
Assert(base > 1);
4937+
Assert(base <= 16);
49374938

49384939
do
49394940
{
4940-
*--ptr = digits[value % HEXBASE];
4941-
value /= HEXBASE;
4941+
*--ptr = digits[value % base];
4942+
value /= base;
49424943
} while (ptr > buf && value);
49434944

4944-
PG_RETURN_TEXT_P(cstring_to_text(ptr));
4945+
return cstring_to_text_with_len(ptr, end - ptr);
4946+
}
4947+
4948+
/*
4949+
* Convert an integer to a string containing a base-2 (binary) representation
4950+
* of the number.
4951+
*/
4952+
Datum
4953+
to_bin32(PG_FUNCTION_ARGS)
4954+
{
4955+
uint64 value = (uint32) PG_GETARG_INT32(0);
4956+
4957+
PG_RETURN_TEXT_P(convert_to_base(value, 2));
4958+
}
4959+
Datum
4960+
to_bin64(PG_FUNCTION_ARGS)
4961+
{
4962+
uint64 value = (uint64) PG_GETARG_INT64(0);
4963+
4964+
PG_RETURN_TEXT_P(convert_to_base(value, 2));
49454965
}
49464966

49474967
/*
4948-
* Convert an int64 to a string containing a base 16 (hex) representation of
4968+
* Convert an integer to a string containing a base-8 (oct) representation of
49494969
* the number.
49504970
*/
49514971
Datum
4952-
to_hex64(PG_FUNCTION_ARGS)
4972+
to_oct32(PG_FUNCTION_ARGS)
4973+
{
4974+
uint64 value = (uint32) PG_GETARG_INT32(0);
4975+
4976+
PG_RETURN_TEXT_P(convert_to_base(value, 8));
4977+
}
4978+
Datum
4979+
to_oct64(PG_FUNCTION_ARGS)
49534980
{
49544981
uint64 value = (uint64) PG_GETARG_INT64(0);
4955-
char *ptr;
4956-
const char *digits = "0123456789abcdef";
4957-
char buf[32]; /* bigger than needed, but reasonable */
49584982

4959-
ptr = buf + sizeof(buf) - 1;
4960-
*ptr = '\0';
4983+
PG_RETURN_TEXT_P(convert_to_base(value, 8));
4984+
}
49614985

4962-
do
4963-
{
4964-
*--ptr = digits[value % HEXBASE];
4965-
value /= HEXBASE;
4966-
} while (ptr > buf && value);
4986+
/*
4987+
* Convert an integer to a string containing a base-16 (hex) representation of
4988+
* the number.
4989+
*/
4990+
Datum
4991+
to_hex32(PG_FUNCTION_ARGS)
4992+
{
4993+
uint64 value = (uint32) PG_GETARG_INT32(0);
4994+
4995+
PG_RETURN_TEXT_P(convert_to_base(value, 16));
4996+
}
4997+
Datum
4998+
to_hex64(PG_FUNCTION_ARGS)
4999+
{
5000+
uint64 value = (uint64) PG_GETARG_INT64(0);
49675001

4968-
PG_RETURN_TEXT_P(cstring_to_text(ptr));
5002+
PG_RETURN_TEXT_P(convert_to_base(value, 16));
49695003
}
49705004

49715005
/*

src/include/catalog/pg_proc.dat

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3707,6 +3707,18 @@
37073707
{ oid => '2768', descr => 'split string by pattern',
37083708
proname => 'regexp_split_to_array', prorettype => '_text',
37093709
proargtypes => 'text text text', prosrc => 'regexp_split_to_array' },
3710+
{ oid => '9030', descr => 'convert int4 number to binary',
3711+
proname => 'to_bin', prorettype => 'text', proargtypes => 'int4',
3712+
prosrc => 'to_bin32' },
3713+
{ oid => '9031', descr => 'convert int8 number to binary',
3714+
proname => 'to_bin', prorettype => 'text', proargtypes => 'int8',
3715+
prosrc => 'to_bin64' },
3716+
{ oid => '9032', descr => 'convert int4 number to oct',
3717+
proname => 'to_oct', prorettype => 'text', proargtypes => 'int4',
3718+
prosrc => 'to_oct32' },
3719+
{ oid => '9033', descr => 'convert int8 number to oct',
3720+
proname => 'to_oct', prorettype => 'text', proargtypes => 'int8',
3721+
prosrc => 'to_oct64' },
37103722
{ oid => '2089', descr => 'convert int4 number to hex',
37113723
proname => 'to_hex', prorettype => 'text', proargtypes => 'int4',
37123724
prosrc => 'to_hex32' },

src/test/regress/expected/strings.out

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2129,8 +2129,68 @@ select split_part('@joeuser@mydatabase@','@',-2) AS "mydatabase";
21292129
(1 row)
21302130

21312131
--
2132-
-- test to_hex
2132+
-- test to_bin, to_oct, and to_hex
21332133
--
2134+
select to_bin(-1234) AS "11111111111111111111101100101110";
2135+
11111111111111111111101100101110
2136+
----------------------------------
2137+
11111111111111111111101100101110
2138+
(1 row)
2139+
2140+
select to_bin(-1234::bigint);
2141+
to_bin
2142+
------------------------------------------------------------------
2143+
1111111111111111111111111111111111111111111111111111101100101110
2144+
(1 row)
2145+
2146+
select to_bin(256*256*256 - 1) AS "111111111111111111111111";
2147+
111111111111111111111111
2148+
--------------------------
2149+
111111111111111111111111
2150+
(1 row)
2151+
2152+
select to_bin(256::bigint*256::bigint*256::bigint*256::bigint - 1) AS "11111111111111111111111111111111";
2153+
11111111111111111111111111111111
2154+
----------------------------------
2155+
11111111111111111111111111111111
2156+
(1 row)
2157+
2158+
select to_oct(-1234) AS "37777775456";
2159+
37777775456
2160+
-------------
2161+
37777775456
2162+
(1 row)
2163+
2164+
select to_oct(-1234::bigint) AS "1777777777777777775456";
2165+
1777777777777777775456
2166+
------------------------
2167+
1777777777777777775456
2168+
(1 row)
2169+
2170+
select to_oct(256*256*256 - 1) AS "77777777";
2171+
77777777
2172+
----------
2173+
77777777
2174+
(1 row)
2175+
2176+
select to_oct(256::bigint*256::bigint*256::bigint*256::bigint - 1) AS "37777777777";
2177+
37777777777
2178+
-------------
2179+
37777777777
2180+
(1 row)
2181+
2182+
select to_hex(-1234) AS "fffffb2e";
2183+
fffffb2e
2184+
----------
2185+
fffffb2e
2186+
(1 row)
2187+
2188+
select to_hex(-1234::bigint) AS "fffffffffffffb2e";
2189+
fffffffffffffb2e
2190+
------------------
2191+
fffffffffffffb2e
2192+
(1 row)
2193+
21342194
select to_hex(256*256*256 - 1) AS "ffffff";
21352195
ffffff
21362196
--------

src/test/regress/sql/strings.sql

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -685,10 +685,21 @@ select split_part('joeuser@mydatabase','@',-3) AS "empty string";
685685
select split_part('@joeuser@mydatabase@','@',-2) AS "mydatabase";
686686

687687
--
688-
-- test to_hex
688+
-- test to_bin, to_oct, and to_hex
689689
--
690-
select to_hex(256*256*256 - 1) AS "ffffff";
690+
select to_bin(-1234) AS "11111111111111111111101100101110";
691+
select to_bin(-1234::bigint);
692+
select to_bin(256*256*256 - 1) AS "111111111111111111111111";
693+
select to_bin(256::bigint*256::bigint*256::bigint*256::bigint - 1) AS "11111111111111111111111111111111";
694+
695+
select to_oct(-1234) AS "37777775456";
696+
select to_oct(-1234::bigint) AS "1777777777777777775456";
697+
select to_oct(256*256*256 - 1) AS "77777777";
698+
select to_oct(256::bigint*256::bigint*256::bigint*256::bigint - 1) AS "37777777777";
691699

700+
select to_hex(-1234) AS "fffffb2e";
701+
select to_hex(-1234::bigint) AS "fffffffffffffb2e";
702+
select to_hex(256*256*256 - 1) AS "ffffff";
692703
select to_hex(256::bigint*256::bigint*256::bigint*256::bigint - 1) AS "ffffffff";
693704

694705
--

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy