Change internal queryid type from uint64 to int64
authorDavid Rowley <drowley@postgresql.org>
Fri, 30 May 2025 10:59:39 +0000 (22:59 +1200)
committerDavid Rowley <drowley@postgresql.org>
Fri, 30 May 2025 10:59:39 +0000 (22:59 +1200)
uint64 was perhaps chosen in cff440d36 as the type was uint32 prior to
that widening work.

Having this as uint64 doesn't make much sense and just adds the overhead of
having to remember that we always output this in its signed form.  Let's
remove that overhead.

The signed form output is seemingly required since we have no way to
represent the full range of uint64 in an SQL type.  We use BIGINT in places
like pg_stat_statements, which maps directly to int64.

The release notes "Source Code" section may want to mention this
adjustment as some extensions may wish to adjust their code.

Author: David Rowley <dgrowleyml@gmail.com>
Suggested-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Sami Imseih <samimseih@gmail.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/50cb0c8b-994b-48f9-a1c4-13039eb3536b@eisentraut.org

16 files changed:
contrib/pg_stat_statements/pg_stat_statements.c
src/backend/access/brin/brin.c
src/backend/access/nbtree/nbtsort.c
src/backend/commands/explain.c
src/backend/commands/vacuumparallel.c
src/backend/nodes/gen_node_support.pl
src/backend/nodes/outfuncs.c
src/backend/nodes/queryjumblefuncs.c
src/backend/nodes/readfuncs.c
src/backend/rewrite/rewriteHandler.c
src/backend/tcop/postgres.c
src/backend/utils/activity/backend_status.c
src/backend/utils/adt/pgstatfuncs.c
src/include/nodes/parsenodes.h
src/include/nodes/plannodes.h
src/include/utils/backend_status.h

index c58f34e9f304614dfe8694c57421d83b98dcfa13..129001c70c81bc9fc6e19320c05d17a1ee107e31 100644 (file)
@@ -144,7 +144,7 @@ typedef struct pgssHashKey
 {
    Oid         userid;         /* user OID */
    Oid         dbid;           /* database OID */
-   uint64      queryid;        /* query identifier */
+   int64       queryid;        /* query identifier */
    bool        toplevel;       /* query executed at top level */
 } pgssHashKey;
 
@@ -346,7 +346,7 @@ static void pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
                                ProcessUtilityContext context, ParamListInfo params,
                                QueryEnvironment *queryEnv,
                                DestReceiver *dest, QueryCompletion *qc);
-static void pgss_store(const char *query, uint64 queryId,
+static void pgss_store(const char *query, int64 queryId,
                       int query_location, int query_len,
                       pgssStoreKind kind,
                       double total_time, uint64 rows,
@@ -370,7 +370,7 @@ static char *qtext_fetch(Size query_offset, int query_len,
                         char *buffer, Size buffer_size);
 static bool need_gc_qtexts(void);
 static void gc_qtexts(void);
-static TimestampTz entry_reset(Oid userid, Oid dbid, uint64 queryid, bool minmax_only);
+static TimestampTz entry_reset(Oid userid, Oid dbid, int64 queryid, bool minmax_only);
 static char *generate_normalized_query(JumbleState *jstate, const char *query,
                                       int query_loc, int *query_len_p);
 static void fill_in_constant_lengths(JumbleState *jstate, const char *query,
@@ -852,7 +852,7 @@ pgss_post_parse_analyze(ParseState *pstate, Query *query, JumbleState *jstate)
    {
        if (pgss_track_utility && IsA(query->utilityStmt, ExecuteStmt))
        {
-           query->queryId = UINT64CONST(0);
+           query->queryId = INT64CONST(0);
            return;
        }
    }
@@ -899,7 +899,7 @@ pgss_planner(Query *parse,
     */
    if (pgss_enabled(nesting_level)
        && pgss_track_planning && query_string
-       && parse->queryId != UINT64CONST(0))
+       && parse->queryId != INT64CONST(0))
    {
        instr_time  start;
        instr_time  duration;
@@ -1002,7 +1002,7 @@ pgss_ExecutorStart(QueryDesc *queryDesc, int eflags)
     * counting of optimizable statements that are directly contained in
     * utility statements.
     */
-   if (pgss_enabled(nesting_level) && queryDesc->plannedstmt->queryId != UINT64CONST(0))
+   if (pgss_enabled(nesting_level) && queryDesc->plannedstmt->queryId != INT64CONST(0))
    {
        /*
         * Set up to track total elapsed time in ExecutorRun.  Make sure the
@@ -1068,9 +1068,9 @@ pgss_ExecutorFinish(QueryDesc *queryDesc)
 static void
 pgss_ExecutorEnd(QueryDesc *queryDesc)
 {
-   uint64      queryId = queryDesc->plannedstmt->queryId;
+   int64       queryId = queryDesc->plannedstmt->queryId;
 
-   if (queryId != UINT64CONST(0) && queryDesc->totaltime &&
+   if (queryId != INT64CONST(0) && queryDesc->totaltime &&
        pgss_enabled(nesting_level))
    {
        /*
@@ -1111,7 +1111,7 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
                    DestReceiver *dest, QueryCompletion *qc)
 {
    Node       *parsetree = pstmt->utilityStmt;
-   uint64      saved_queryId = pstmt->queryId;
+   int64       saved_queryId = pstmt->queryId;
    int         saved_stmt_location = pstmt->stmt_location;
    int         saved_stmt_len = pstmt->stmt_len;
    bool        enabled = pgss_track_utility && pgss_enabled(nesting_level);
@@ -1131,7 +1131,7 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
     * only.
     */
    if (enabled)
-       pstmt->queryId = UINT64CONST(0);
+       pstmt->queryId = INT64CONST(0);
 
    /*
     * If it's an EXECUTE statement, we don't track it and don't increment the
@@ -1278,7 +1278,7 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
  * for the arrays in the Counters field.
  */
 static void
-pgss_store(const char *query, uint64 queryId,
+pgss_store(const char *query, int64 queryId,
           int query_location, int query_len,
           pgssStoreKind kind,
           double total_time, uint64 rows,
@@ -1304,7 +1304,7 @@ pgss_store(const char *query, uint64 queryId,
     * Nothing to do if compute_query_id isn't enabled and no other module
     * computed a query identifier.
     */
-   if (queryId == UINT64CONST(0))
+   if (queryId == INT64CONST(0))
        return;
 
    /*
@@ -1514,11 +1514,11 @@ pg_stat_statements_reset_1_7(PG_FUNCTION_ARGS)
 {
    Oid         userid;
    Oid         dbid;
-   uint64      queryid;
+   int64       queryid;
 
    userid = PG_GETARG_OID(0);
    dbid = PG_GETARG_OID(1);
-   queryid = (uint64) PG_GETARG_INT64(2);
+   queryid = PG_GETARG_INT64(2);
 
    entry_reset(userid, dbid, queryid, false);
 
@@ -1530,12 +1530,12 @@ pg_stat_statements_reset_1_11(PG_FUNCTION_ARGS)
 {
    Oid         userid;
    Oid         dbid;
-   uint64      queryid;
+   int64       queryid;
    bool        minmax_only;
 
    userid = PG_GETARG_OID(0);
    dbid = PG_GETARG_OID(1);
-   queryid = (uint64) PG_GETARG_INT64(2);
+   queryid = PG_GETARG_INT64(2);
    minmax_only = PG_GETARG_BOOL(3);
 
    PG_RETURN_TIMESTAMPTZ(entry_reset(userid, dbid, queryid, minmax_only));
@@ -2671,7 +2671,7 @@ if (e) { \
  * Reset entries corresponding to parameters passed.
  */
 static TimestampTz
-entry_reset(Oid userid, Oid dbid, uint64 queryid, bool minmax_only)
+entry_reset(Oid userid, Oid dbid, int64 queryid, bool minmax_only)
 {
    HASH_SEQ_STATUS hash_seq;
    pgssEntry  *entry;
@@ -2691,7 +2691,7 @@ entry_reset(Oid userid, Oid dbid, uint64 queryid, bool minmax_only)
 
    stats_reset = GetCurrentTimestamp();
 
-   if (userid != 0 && dbid != 0 && queryid != UINT64CONST(0))
+   if (userid != 0 && dbid != 0 && queryid != INT64CONST(0))
    {
        /* If all the parameters are available, use the fast path. */
        memset(&key, 0, sizeof(pgssHashKey));
@@ -2714,7 +2714,7 @@ entry_reset(Oid userid, Oid dbid, uint64 queryid, bool minmax_only)
 
        SINGLE_ENTRY_RESET(entry);
    }
-   else if (userid != 0 || dbid != 0 || queryid != UINT64CONST(0))
+   else if (userid != 0 || dbid != 0 || queryid != INT64CONST(0))
    {
        /* Reset entries corresponding to valid parameters. */
        hash_seq_init(&hash_seq, pgss_hash);
index 01e1db7f856be10d77f8e01bfbc3a48a22b1a60e..4204088fa0d7d61aad4260875843a674eb488e97 100644 (file)
@@ -68,7 +68,7 @@ typedef struct BrinShared
    int         scantuplesortstates;
 
    /* Query ID, for report in worker processes */
-   uint64      queryid;
+   int64       queryid;
 
    /*
     * workersdonecv is used to monitor the progress of workers.  All parallel
index 3794cc924ad467366db61e75d07fb286c86ef6cb..9d70e89c1f3ce4bfa2793f7e2dc5671d65197226 100644 (file)
@@ -105,7 +105,7 @@ typedef struct BTShared
    int         scantuplesortstates;
 
    /* Query ID, for report in worker processes */
-   uint64      queryid;
+   int64       queryid;
 
    /*
     * workersdonecv is used to monitor the progress of workers.  All parallel
index bfa83fbc3fec8949ede97e020e2b4dac61a7d34d..7e2792ead715b8c1b7a54bb17101127e9ec5b884 100644 (file)
@@ -811,14 +811,10 @@ ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
     * the queryid in any of the EXPLAIN plans to keep stable the results
     * generated by regression test suites.
     */
-   if (es->verbose && queryDesc->plannedstmt->queryId != UINT64CONST(0) &&
+   if (es->verbose && queryDesc->plannedstmt->queryId != INT64CONST(0) &&
        compute_query_id != COMPUTE_QUERY_ID_REGRESS)
    {
-       /*
-        * Output the queryid as an int64 rather than a uint64 so we match
-        * what would be seen in the BIGINT pg_stat_statements.queryid column.
-        */
-       ExplainPropertyInteger("Query Identifier", NULL, (int64)
+       ExplainPropertyInteger("Query Identifier", NULL,
                               queryDesc->plannedstmt->queryId, es);
    }
 }
index 2b9d548cdeb1066e2002dab724686fabff394a02..0feea1d30ec36616718d9c1d80a11000644e2830 100644 (file)
@@ -63,7 +63,7 @@ typedef struct PVShared
     */
    Oid         relid;
    int         elevel;
-   uint64      queryid;
+   int64       queryid;
 
    /*
     * Fields for both index vacuum and cleanup.
index 77659b0f760208ff4ab915ceec366d4da6513888..c8595109b0e10c41d7fb81f78b2557a531dddf25 100644 (file)
@@ -1039,6 +1039,11 @@ _read${n}(void)
            print $off "\tWRITE_UINT_FIELD($f);\n";
            print $rff "\tREAD_UINT_FIELD($f);\n" unless $no_read;
        }
+       elsif ($t eq 'int64')
+       {
+           print $off "\tWRITE_INT64_FIELD($f);\n";
+           print $rff "\tREAD_INT64_FIELD($f);\n" unless $no_read;
+       }
        elsif ($t eq 'uint64'
            || $t eq 'AclMode')
        {
index ceac3fd8620140b87562a02914e3c319fe754498..25e08ba3426b7f59816fef91e4ca928b179dc118 100644 (file)
@@ -51,6 +51,12 @@ static void outDouble(StringInfo str, double d);
 #define WRITE_UINT_FIELD(fldname) \
    appendStringInfo(str, " :" CppAsString(fldname) " %u", node->fldname)
 
+/* Write a signed integer field (anything written with INT64_FORMAT) */
+#define WRITE_INT64_FIELD(fldname) \
+   appendStringInfo(str, \
+                    " :" CppAsString(fldname) " " INT64_FORMAT, \
+                    node->fldname)
+
 /* Write an unsigned integer field (anything written with UINT64_FORMAT) */
 #define WRITE_UINT64_FIELD(fldname) \
    appendStringInfo(str, " :" CppAsString(fldname) " " UINT64_FORMAT, \
index d1e82a63f09a8e93fb433b0a46d427dcc1b1c337..ac3cb3d9cafe2a74b27d9c4eaeb5cd4fd48390b9 100644 (file)
@@ -56,7 +56,7 @@ int           compute_query_id = COMPUTE_QUERY_ID_AUTO;
 bool       query_id_enabled = false;
 
 static JumbleState *InitJumble(void);
-static uint64 DoJumble(JumbleState *jstate, Node *node);
+static int64 DoJumble(JumbleState *jstate, Node *node);
 static void AppendJumble(JumbleState *jstate,
                         const unsigned char *value, Size size);
 static void FlushPendingNulls(JumbleState *jstate);
@@ -141,12 +141,12 @@ JumbleQuery(Query *query)
     * If we are unlucky enough to get a hash of zero, use 1 instead for
     * normal statements and 2 for utility queries.
     */
-   if (query->queryId == UINT64CONST(0))
+   if (query->queryId == INT64CONST(0))
    {
        if (query->utilityStmt)
-           query->queryId = UINT64CONST(2);
+           query->queryId = INT64CONST(2);
        else
-           query->queryId = UINT64CONST(1);
+           query->queryId = INT64CONST(1);
    }
 
    return jstate;
@@ -197,7 +197,7 @@ InitJumble(void)
  *     Jumble the given Node using the given JumbleState and return the resulting
  *     jumble hash.
  */
-static uint64
+static int64
 DoJumble(JumbleState *jstate, Node *node)
 {
    /* Jumble the given node */
@@ -208,9 +208,9 @@ DoJumble(JumbleState *jstate, Node *node)
        FlushPendingNulls(jstate);
 
    /* Process the jumble buffer and produce the hash value */
-   return DatumGetUInt64(hash_any_extended(jstate->jumble,
-                                           jstate->jumble_len,
-                                           0));
+   return DatumGetInt64(hash_any_extended(jstate->jumble,
+                                          jstate->jumble_len,
+                                          0));
 }
 
 /*
@@ -256,10 +256,10 @@ AppendJumbleInternal(JumbleState *jstate, const unsigned char *item,
 
        if (unlikely(jumble_len >= JUMBLE_SIZE))
        {
-           uint64      start_hash;
+           int64       start_hash;
 
-           start_hash = DatumGetUInt64(hash_any_extended(jumble,
-                                                         JUMBLE_SIZE, 0));
+           start_hash = DatumGetInt64(hash_any_extended(jumble,
+                                                        JUMBLE_SIZE, 0));
            memcpy(jumble, &start_hash, sizeof(start_hash));
            jumble_len = sizeof(start_hash);
        }
index 64d3a09f765bb7c124aabf2f3f46c63554bd2328..8c90ab54af81fe22395265b8ba23b06a53b8a955 100644 (file)
    token = pg_strtok(&length);     /* get field value */ \
    local_node->fldname = atoui(token)
 
+/* Read a signed integer field (anything written using INT64_FORMAT) */
+#define READ_INT64_FIELD(fldname) \
+   token = pg_strtok(&length); /* skip :fldname */ \
+   token = pg_strtok(&length); /* get field value */ \
+   local_node->fldname = strtoi64(token, NULL, 10)
+
 /* Read an unsigned integer field (anything written using UINT64_FORMAT) */
 #define READ_UINT64_FIELD(fldname) \
    token = pg_strtok(&length);     /* skip :fldname */ \
index f0bce5f9ed95711d9f27962db8081db7e96f4a19..2ef0e7fbf3a69da43ec80a6f6ab3b0341d4d3232 100644 (file)
@@ -4544,7 +4544,7 @@ build_generation_expression(Relation rel, int attrno)
 List *
 QueryRewrite(Query *parsetree)
 {
-   uint64      input_query_id = parsetree->queryId;
+   int64       input_query_id = parsetree->queryId;
    List       *querylist;
    List       *results;
    ListCell   *l;
index c242c8170b56276ec1cdd468f7e083b940fe8f48..4efd8120d2c2f908872ec56678aa4aeef9a91e78 100644 (file)
@@ -1682,7 +1682,7 @@ exec_bind_message(StringInfo input_message)
    {
        Query      *query = lfirst_node(Query, lc);
 
-       if (query->queryId != UINT64CONST(0))
+       if (query->queryId != INT64CONST(0))
        {
            pgstat_report_query_id(query->queryId, false);
            break;
@@ -2174,7 +2174,7 @@ exec_execute_message(const char *portal_name, long max_rows)
    {
        PlannedStmt *stmt = lfirst_node(PlannedStmt, lc);
 
-       if (stmt->queryId != UINT64CONST(0))
+       if (stmt->queryId != INT64CONST(0))
        {
            pgstat_report_query_id(stmt->queryId, false);
            break;
index e1576e64b6d4c3547c66f64dc149bf04bb080f80..9c2ed2cb9e0b8b220c170e0877c4b27115c61aea 100644 (file)
@@ -320,7 +320,7 @@ pgstat_bestart_initial(void)
    lbeentry.st_state = STATE_STARTING;
    lbeentry.st_progress_command = PROGRESS_COMMAND_INVALID;
    lbeentry.st_progress_command_target = InvalidOid;
-   lbeentry.st_query_id = UINT64CONST(0);
+   lbeentry.st_query_id = INT64CONST(0);
    lbeentry.st_plan_id = UINT64CONST(0);
 
    /*
@@ -599,7 +599,7 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
            beentry->st_activity_start_timestamp = 0;
            /* st_xact_start_timestamp and wait_event_info are also disabled */
            beentry->st_xact_start_timestamp = 0;
-           beentry->st_query_id = UINT64CONST(0);
+           beentry->st_query_id = INT64CONST(0);
            beentry->st_plan_id = UINT64CONST(0);
            proc->wait_event_info = 0;
            PGSTAT_END_WRITE_ACTIVITY(beentry);
@@ -662,7 +662,7 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
     */
    if (state == STATE_RUNNING)
    {
-       beentry->st_query_id = UINT64CONST(0);
+       beentry->st_query_id = INT64CONST(0);
        beentry->st_plan_id = UINT64CONST(0);
    }
 
@@ -683,7 +683,7 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
  * --------
  */
 void
-pgstat_report_query_id(uint64 query_id, bool force)
+pgstat_report_query_id(int64 query_id, bool force)
 {
    volatile PgBackendStatus *beentry = MyBEEntry;
 
@@ -702,7 +702,7 @@ pgstat_report_query_id(uint64 query_id, bool force)
     * command, so ignore the one provided unless it's an explicit call to
     * reset the identifier.
     */
-   if (beentry->st_query_id != 0 && !force)
+   if (beentry->st_query_id != INT64CONST(0) && !force)
        return;
 
    /*
@@ -1134,7 +1134,7 @@ pgstat_get_crashed_backend_activity(int pid, char *buffer, int buflen)
  *
  * Return current backend's query identifier.
  */
-uint64
+int64
 pgstat_get_my_query_id(void)
 {
    if (!MyBEEntry)
index 97af7c6554ff3c6870102ca22fe706d2c3bc115c..e980109f24522f53ee487288aad9111806ab05c4 100644 (file)
@@ -640,10 +640,10 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
                values[28] = BoolGetDatum(false);   /* GSS credentials not
                                                     * delegated */
            }
-           if (beentry->st_query_id == 0)
+           if (beentry->st_query_id == INT64CONST(0))
                nulls[30] = true;
            else
-               values[30] = UInt64GetDatum(beentry->st_query_id);
+               values[30] = Int64GetDatum(beentry->st_query_id);
        }
        else
        {
index 4610fc61293b0f1f7f37d260037c63b01fe6e6f1..dd00ab420b8a11fae2d3a3d9b51a8a409857a1fb 100644 (file)
@@ -127,8 +127,13 @@ typedef struct Query
     * query identifier (can be set by plugins); ignored for equal, as it
     * might not be set; also not stored.  This is the result of the query
     * jumble, hence ignored.
+    *
+    * We store this as a signed value as this is the form it's displayed to
+    * users in places such as EXPLAIN and pg_stat_statements.  Primarily this
+    * is done due to lack of an SQL type to represent the full range of
+    * uint64.
     */
-   uint64      queryId pg_node_attr(equal_ignore, query_jumble_ignore, read_write_ignore, read_as(0));
+   int64       queryId pg_node_attr(equal_ignore, query_jumble_ignore, read_write_ignore, read_as(0));
 
    /* do I set the command result tag? */
    bool        canSetTag pg_node_attr(query_jumble_ignore);
index f0d514e6e15264dbd44bb6e3b0862703acb8482b..e70e33afa9c4b17244ce892d92c21721b9a7c669 100644 (file)
@@ -53,7 +53,7 @@ typedef struct PlannedStmt
    CmdType     commandType;
 
    /* query identifier (copied from Query) */
-   uint64      queryId;
+   int64       queryId;
 
    /* plan identifier (can be set by plugins) */
    uint64      planId;
index 430ccd7d78e41e9083e3504368415cf65c717f02..bbebe517501f59eff852e7e6c08dba0c9925a732 100644 (file)
@@ -170,7 +170,7 @@ typedef struct PgBackendStatus
    int64       st_progress_param[PGSTAT_NUM_PROGRESS_PARAM];
 
    /* query identifier, optionally computed using post_parse_analyze_hook */
-   uint64      st_query_id;
+   int64       st_query_id;
 
    /* plan identifier, optionally computed using planner_hook */
    uint64      st_plan_id;
@@ -321,7 +321,7 @@ extern void pgstat_clear_backend_activity_snapshot(void);
 
 /* Activity reporting functions */
 extern void pgstat_report_activity(BackendState state, const char *cmd_str);
-extern void pgstat_report_query_id(uint64 query_id, bool force);
+extern void pgstat_report_query_id(int64 query_id, bool force);
 extern void pgstat_report_plan_id(uint64 plan_id, bool force);
 extern void pgstat_report_tempfile(size_t filesize);
 extern void pgstat_report_appname(const char *appname);
@@ -329,7 +329,7 @@ extern void pgstat_report_xact_timestamp(TimestampTz tstamp);
 extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
                                                       int buflen);
-extern uint64 pgstat_get_my_query_id(void);
+extern int64 pgstat_get_my_query_id(void);
 extern uint64 pgstat_get_my_plan_id(void);
 extern BackendType pgstat_get_backend_type_by_proc_number(ProcNumber procNumber);