]> granicus.if.org Git - pgbouncer/commitdiff
Send stats columns as numeric instead of bigint
authorPeter Eisentraut <peter@eisentraut.org>
Mon, 9 Sep 2019 16:56:50 +0000 (18:56 +0200)
committerPeter Eisentraut <peter@eisentraut.org>
Mon, 9 Sep 2019 16:56:50 +0000 (18:56 +0200)
Internally, most statistiscs are kept as uint64_t.  Sending those
with a row descriptor that claims they are bigint can lead to problems
if uint64_t values can overflow the signed 64-bit integer range.  Then
a client library that wants to convert the value to its locally
appropriate signed 64-bit integer type would run into errors.

based on patch by @stanhu

fixes #360 #401

include/system.h
src/pktbuf.c
src/stats.c

index e4763373a50452bbdbde4a9587ecc6ba7d92cca4..6022119f42f41adde0c924fff442f49f536bc6c0 100644 (file)
 #define UNIX_PATH_MAX  128 /* actual sizeof() will be applied later anyway */
 #endif
 
-/*
- * PostgreSQL type OIDs for resultsets.
- */
-
-#define INT8OID 20
-#define INT4OID 23
-#define TEXTOID 25
-
 /*
  * libc compat functions.
  */
index b61870b47061f3b2639c8abafc290fec70b61993..722f8b431ad5f47c0f8e5354452ce2c6ebd5cdd1 100644 (file)
 
 #include "bouncer.h"
 
+
+/*
+ * PostgreSQL type OIDs for result sets
+ */
+#define INT8OID 20
+#define INT4OID 23
+#define TEXTOID 25
+#define NUMERICOID 1700
+
+
 void pktbuf_free(PktBuf *buf)
 {
        if (!buf || buf->fixed_buf)
@@ -341,6 +351,7 @@ void pktbuf_write_generic(PktBuf *buf, int type, const char *pktdesc, ...)
  * 'i' - int4
  * 'q' - int8
  * 's' - string
+ * 'N' - uint64_t to numeric
  * 'T' - usec_t to date
  */
 void pktbuf_write_RowDescription(PktBuf *buf, const char *tupdesc, ...)
@@ -372,13 +383,16 @@ void pktbuf_write_RowDescription(PktBuf *buf, const char *tupdesc, ...)
                } else if (tupdesc[i] == 'q') {
                        pktbuf_put_uint32(buf, INT8OID);
                        pktbuf_put_uint16(buf, 8);
+               } else if (tupdesc[i] == 'N') {
+                       pktbuf_put_uint32(buf, NUMERICOID);
+                       pktbuf_put_uint16(buf, -1);
                } else if (tupdesc[i] == 'T') {
                        pktbuf_put_uint32(buf, TEXTOID);
                        pktbuf_put_uint16(buf, -1);
                } else {
                        fatal("bad tupdesc");
                }
-               pktbuf_put_uint32(buf, 0);
+               pktbuf_put_uint32(buf, -1);
                pktbuf_put_uint16(buf, 0);
        }
        va_end(ap);
@@ -394,6 +408,7 @@ void pktbuf_write_RowDescription(PktBuf *buf, const char *tupdesc, ...)
  * 'i' - int4
  * 'q' - int8
  * 's' - string
+ * 'N' - uint64_t to numeric
  * 'T' - usec_t to date
  */
 void pktbuf_write_DataRow(PktBuf *buf, const char *tupdesc, ...)
@@ -411,7 +426,7 @@ void pktbuf_write_DataRow(PktBuf *buf, const char *tupdesc, ...)
                if (tupdesc[i] == 'i') {
                        snprintf(tmp, sizeof(tmp), "%d", va_arg(ap, int));
                        val = tmp;
-               } else if (tupdesc[i] == 'q') {
+               } else if (tupdesc[i] == 'q' || tupdesc[i] == 'N') {
                        snprintf(tmp, sizeof(tmp), "%" PRIu64, va_arg(ap, uint64_t));
                        val = tmp;
                } else if (tupdesc[i] == 's') {
index a9a9de86b0b731e9a3231abbb8ee11f6bedfb01d..a02252cda2b684bc44fb94aee9fe580b4362a507 100644 (file)
@@ -77,7 +77,7 @@ static void write_stats(PktBuf *buf, PgStats *stat, PgStats *old, char *dbname)
 {
        PgStats avg;
        calc_average(&avg, stat, old);
-       pktbuf_write_DataRow(buf, "sqqqqqqqqqqqqqq", dbname,
+       pktbuf_write_DataRow(buf, "sNNNNNNNNNNNNNN", dbname,
                             stat->xact_count, stat->query_count,
                             stat->client_bytes, stat->server_bytes,
                             stat->xact_time, stat->query_time,
@@ -108,7 +108,7 @@ bool admin_database_stats(PgSocket *client, struct StatList *pool_list)
                return true;
        }
 
-       pktbuf_write_RowDescription(buf, "sqqqqqqqqqqqqqq", "database",
+       pktbuf_write_RowDescription(buf, "sNNNNNNNNNNNNNN", "database",
                                    "total_xact_count", "total_query_count",
                                    "total_received", "total_sent",
                                    "total_xact_time", "total_query_time",
@@ -152,7 +152,7 @@ static void write_stats_totals(PktBuf *buf, PgStats *stat, PgStats *old, char *d
 {
        PgStats avg;
        calc_average(&avg, stat, old);
-       pktbuf_write_DataRow(buf, "sqqqqqqq", dbname,
+       pktbuf_write_DataRow(buf, "sNNNNNNN", dbname,
                             stat->xact_count, stat->query_count,
                             stat->client_bytes, stat->server_bytes,
                             stat->xact_time, stat->query_time,
@@ -179,7 +179,7 @@ bool admin_database_stats_totals(PgSocket *client, struct StatList *pool_list)
                return true;
        }
 
-       pktbuf_write_RowDescription(buf, "sqqqqqqq", "database",
+       pktbuf_write_RowDescription(buf, "sNNNNNNN", "database",
                                    "xact_count", "query_count",
                                    "bytes_received", "bytes_sent",
                                    "xact_time", "query_time",
@@ -219,7 +219,7 @@ static void write_stats_averages(PktBuf *buf, PgStats *stat, PgStats *old, char
 {
        PgStats avg;
        calc_average(&avg, stat, old);
-       pktbuf_write_DataRow(buf, "sqqqqqqq", dbname,
+       pktbuf_write_DataRow(buf, "sNNNNNNN", dbname,
                             avg.xact_count, avg.query_count,
                             avg.client_bytes, avg.server_bytes,
                             avg.xact_time, avg.query_time,
@@ -246,7 +246,7 @@ bool admin_database_stats_averages(PgSocket *client, struct StatList *pool_list)
                return true;
        }
 
-       pktbuf_write_RowDescription(buf, "sqqqqqqq", "database",
+       pktbuf_write_RowDescription(buf, "sNNNNNNN", "database",
                                    "xact_count", "query_count",
                                    "bytes_received", "bytes_sent",
                                    "xact_time", "query_time",
@@ -307,10 +307,10 @@ bool show_stat_totals(PgSocket *client, struct StatList *pool_list)
 
        calc_average(&avg, &st_total, &old_total);
 
-       pktbuf_write_RowDescription(buf, "sq", "name", "value");
+       pktbuf_write_RowDescription(buf, "sN", "name", "value");
 
-#define WTOTAL(name) pktbuf_write_DataRow(buf, "sq", "total_" #name, st_total.name)
-#define WAVG(name) pktbuf_write_DataRow(buf, "sq", "avg_" #name, avg.name)
+#define WTOTAL(name) pktbuf_write_DataRow(buf, "sN", "total_" #name, st_total.name)
+#define WAVG(name) pktbuf_write_DataRow(buf, "sN", "avg_" #name, avg.name)
 
        WTOTAL(xact_count);
        WTOTAL(query_count);