Commit 1fd687a0 authored by Andrew Gierth's avatar Andrew Gierth

Optimizations for integer to decimal output.

Using a lookup table of digit pairs reduces the number of divisions
needed, and calculating the length upfront saves some work; these
ideas are taken from the code previously committed for floats.

David Fetter, reviewed by Kyotaro Horiguchi, Tels, and me.

Discussion: https://postgr.es/m/20190924052620.GP31596%40fetter.org
parent 7bae0ad9
......@@ -112,7 +112,7 @@ printsimple(TupleTableSlot *slot, DestReceiver *self)
case INT8OID:
{
int64 num = DatumGetInt64(value);
char str[23]; /* sign, 21 digits and '\0' */
char str[MAXINT8LEN + 1];
pg_lltoa(num, str);
pq_sendcountedtext(&buf, str, strlen(str), false);
......
......@@ -388,9 +388,9 @@ AppendSeconds(char *cp, int sec, fsec_t fsec, int precision, bool fillzeros)
Assert(precision >= 0);
if (fillzeros)
cp = pg_ltostr_zeropad(cp, Abs(sec), 2);
cp = pg_ultostr_zeropad(cp, Abs(sec), 2);
else
cp = pg_ltostr(cp, Abs(sec));
cp = pg_ultostr(cp, Abs(sec));
/* fsec_t is just an int32 */
if (fsec != 0)
......@@ -430,7 +430,7 @@ AppendSeconds(char *cp, int sec, fsec_t fsec, int precision, bool fillzeros)
* which will generate a correct answer in the minimum valid width.
*/
if (value)
return pg_ltostr(cp, Abs(fsec));
return pg_ultostr(cp, Abs(fsec));
return end;
}
......@@ -3831,20 +3831,20 @@ EncodeTimezone(char *str, int tz, int style)
if (sec != 0)
{
str = pg_ltostr_zeropad(str, hour, 2);
str = pg_ultostr_zeropad(str, hour, 2);
*str++ = ':';
str = pg_ltostr_zeropad(str, min, 2);
str = pg_ultostr_zeropad(str, min, 2);
*str++ = ':';
str = pg_ltostr_zeropad(str, sec, 2);
str = pg_ultostr_zeropad(str, sec, 2);
}
else if (min != 0 || style == USE_XSD_DATES)
{
str = pg_ltostr_zeropad(str, hour, 2);
str = pg_ultostr_zeropad(str, hour, 2);
*str++ = ':';
str = pg_ltostr_zeropad(str, min, 2);
str = pg_ultostr_zeropad(str, min, 2);
}
else
str = pg_ltostr_zeropad(str, hour, 2);
str = pg_ultostr_zeropad(str, hour, 2);
return str;
}
......@@ -3861,40 +3861,40 @@ EncodeDateOnly(struct pg_tm *tm, int style, char *str)
case USE_ISO_DATES:
case USE_XSD_DATES:
/* compatible with ISO date formats */
str = pg_ltostr_zeropad(str,
str = pg_ultostr_zeropad(str,
(tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
*str++ = '-';
str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
str = pg_ultostr_zeropad(str, tm->tm_mon, 2);
*str++ = '-';
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
str = pg_ultostr_zeropad(str, tm->tm_mday, 2);
break;
case USE_SQL_DATES:
/* compatible with Oracle/Ingres date formats */
if (DateOrder == DATEORDER_DMY)
{
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
str = pg_ultostr_zeropad(str, tm->tm_mday, 2);
*str++ = '/';
str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
str = pg_ultostr_zeropad(str, tm->tm_mon, 2);
}
else
{
str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
str = pg_ultostr_zeropad(str, tm->tm_mon, 2);
*str++ = '/';
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
str = pg_ultostr_zeropad(str, tm->tm_mday, 2);
}
*str++ = '/';
str = pg_ltostr_zeropad(str,
str = pg_ultostr_zeropad(str,
(tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
break;
case USE_GERMAN_DATES:
/* German-style date format */
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
str = pg_ultostr_zeropad(str, tm->tm_mday, 2);
*str++ = '.';
str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
str = pg_ultostr_zeropad(str, tm->tm_mon, 2);
*str++ = '.';
str = pg_ltostr_zeropad(str,
str = pg_ultostr_zeropad(str,
(tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
break;
......@@ -3903,18 +3903,18 @@ EncodeDateOnly(struct pg_tm *tm, int style, char *str)
/* traditional date-only style for Postgres */
if (DateOrder == DATEORDER_DMY)
{
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
str = pg_ultostr_zeropad(str, tm->tm_mday, 2);
*str++ = '-';
str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
str = pg_ultostr_zeropad(str, tm->tm_mon, 2);
}
else
{
str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
str = pg_ultostr_zeropad(str, tm->tm_mon, 2);
*str++ = '-';
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
str = pg_ultostr_zeropad(str, tm->tm_mday, 2);
}
*str++ = '-';
str = pg_ltostr_zeropad(str,
str = pg_ultostr_zeropad(str,
(tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
break;
}
......@@ -3939,9 +3939,9 @@ EncodeDateOnly(struct pg_tm *tm, int style, char *str)
void
EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, int style, char *str)
{
str = pg_ltostr_zeropad(str, tm->tm_hour, 2);
str = pg_ultostr_zeropad(str, tm->tm_hour, 2);
*str++ = ':';
str = pg_ltostr_zeropad(str, tm->tm_min, 2);
str = pg_ultostr_zeropad(str, tm->tm_min, 2);
*str++ = ':';
str = AppendSeconds(str, tm->tm_sec, fsec, MAX_TIME_PRECISION, true);
if (print_tz)
......@@ -3984,16 +3984,16 @@ EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char
case USE_ISO_DATES:
case USE_XSD_DATES:
/* Compatible with ISO-8601 date formats */
str = pg_ltostr_zeropad(str,
str = pg_ultostr_zeropad(str,
(tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
*str++ = '-';
str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
str = pg_ultostr_zeropad(str, tm->tm_mon, 2);
*str++ = '-';
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
str = pg_ultostr_zeropad(str, tm->tm_mday, 2);
*str++ = (style == USE_ISO_DATES) ? ' ' : 'T';
str = pg_ltostr_zeropad(str, tm->tm_hour, 2);
str = pg_ultostr_zeropad(str, tm->tm_hour, 2);
*str++ = ':';
str = pg_ltostr_zeropad(str, tm->tm_min, 2);
str = pg_ultostr_zeropad(str, tm->tm_min, 2);
*str++ = ':';
str = AppendTimestampSeconds(str, tm, fsec);
if (print_tz)
......@@ -4004,23 +4004,23 @@ EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char
/* Compatible with Oracle/Ingres date formats */
if (DateOrder == DATEORDER_DMY)
{
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
str = pg_ultostr_zeropad(str, tm->tm_mday, 2);
*str++ = '/';
str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
str = pg_ultostr_zeropad(str, tm->tm_mon, 2);
}
else
{
str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
str = pg_ultostr_zeropad(str, tm->tm_mon, 2);
*str++ = '/';
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
str = pg_ultostr_zeropad(str, tm->tm_mday, 2);
}
*str++ = '/';
str = pg_ltostr_zeropad(str,
str = pg_ultostr_zeropad(str,
(tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
*str++ = ' ';
str = pg_ltostr_zeropad(str, tm->tm_hour, 2);
str = pg_ultostr_zeropad(str, tm->tm_hour, 2);
*str++ = ':';
str = pg_ltostr_zeropad(str, tm->tm_min, 2);
str = pg_ultostr_zeropad(str, tm->tm_min, 2);
*str++ = ':';
str = AppendTimestampSeconds(str, tm, fsec);
......@@ -4043,16 +4043,16 @@ EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char
case USE_GERMAN_DATES:
/* German variant on European style */
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
str = pg_ultostr_zeropad(str, tm->tm_mday, 2);
*str++ = '.';
str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
str = pg_ultostr_zeropad(str, tm->tm_mon, 2);
*str++ = '.';
str = pg_ltostr_zeropad(str,
str = pg_ultostr_zeropad(str,
(tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
*str++ = ' ';
str = pg_ltostr_zeropad(str, tm->tm_hour, 2);
str = pg_ultostr_zeropad(str, tm->tm_hour, 2);
*str++ = ':';
str = pg_ltostr_zeropad(str, tm->tm_min, 2);
str = pg_ultostr_zeropad(str, tm->tm_min, 2);
*str++ = ':';
str = AppendTimestampSeconds(str, tm, fsec);
......@@ -4078,7 +4078,7 @@ EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char
*str++ = ' ';
if (DateOrder == DATEORDER_DMY)
{
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
str = pg_ultostr_zeropad(str, tm->tm_mday, 2);
*str++ = ' ';
memcpy(str, months[tm->tm_mon - 1], 3);
str += 3;
......@@ -4088,16 +4088,16 @@ EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char
memcpy(str, months[tm->tm_mon - 1], 3);
str += 3;
*str++ = ' ';
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
str = pg_ultostr_zeropad(str, tm->tm_mday, 2);
}
*str++ = ' ';
str = pg_ltostr_zeropad(str, tm->tm_hour, 2);
str = pg_ultostr_zeropad(str, tm->tm_hour, 2);
*str++ = ':';
str = pg_ltostr_zeropad(str, tm->tm_min, 2);
str = pg_ultostr_zeropad(str, tm->tm_min, 2);
*str++ = ':';
str = AppendTimestampSeconds(str, tm, fsec);
*str++ = ' ';
str = pg_ltostr_zeropad(str,
str = pg_ultostr_zeropad(str,
(tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
if (print_tz)
......
......@@ -26,7 +26,6 @@
#include "utils/builtins.h"
#include "utils/int8.h"
#define MAXINT8LEN 25
typedef struct
{
......
This diff is collapsed.
......@@ -18,6 +18,8 @@
#include "nodes/nodes.h"
#include "utils/fmgrprotos.h"
/* Sign + the most decimal digits an 8-byte number could have */
#define MAXINT8LEN 20
/* bool.c */
extern bool parse_bool(const char *value, bool *result);
......@@ -46,10 +48,12 @@ extern int32 pg_atoi(const char *s, int size, int c);
extern int16 pg_strtoint16(const char *s);
extern int32 pg_strtoint32(const char *s);
extern void pg_itoa(int16 i, char *a);
int pg_ultoa_n(uint32 l, char *a);
int pg_ulltoa_n(uint64 l, char *a);
extern void pg_ltoa(int32 l, char *a);
extern void pg_lltoa(int64 ll, char *a);
extern char *pg_ltostr_zeropad(char *str, int32 value, int32 minwidth);
extern char *pg_ltostr(char *str, int32 value);
extern char *pg_ultostr_zeropad(char *str, uint32 value, int32 minwidth);
extern char *pg_ultostr(char *str, uint32 value);
extern uint64 pg_strtouint64(const char *str, char **endptr, int base);
/* oid.c */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment