Skip to content

Commit 9ba37b2

Browse files
committed
Include values of A_Const nodes in query jumbling
Like the implementation for node copy, write and read, this node requires a custom implementation so as the query jumbling is able to consider the correct value assigned to it, depending on its type (int, float, bool, string, bitstring). Based on a dump of pg_stat_statements from the regression database, this would confuse the query jumbling of the following queries: - SET. - COPY TO with SELECT queries. - START TRANSACTION with different isolation levels. - ALTER TABLE with default expressions. - CREATE TABLE with partition bounds. Note that there may be a long-term argument in tracking the location of such nodes so as query strings holding such nodes could be normalized, but this is left as a separate discussion. Oversight in 3db72eb. Discussion: https://postgr.es/m/Y9+HuYslMAP6yyPb@paquier.xyz
1 parent 209f0f0 commit 9ba37b2

File tree

4 files changed

+59
-2
lines changed

4 files changed

+59
-2
lines changed

contrib/pg_stat_statements/expected/pg_stat_statements.out

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,14 @@ NOTICE: table "test" does not exist, skipping
579579
NOTICE: table "test" does not exist, skipping
580580
NOTICE: function plus_one(pg_catalog.int4) does not exist, skipping
581581
DROP FUNCTION PLUS_TWO(INTEGER);
582+
-- This SET query uses two different strings, still they count as one entry.
583+
SET work_mem = '1MB';
584+
Set work_mem = '1MB';
585+
SET work_mem = '2MB';
586+
RESET work_mem;
587+
SET enable_seqscan = off;
588+
SET enable_seqscan = on;
589+
RESET enable_seqscan;
582590
SELECT query, calls, rows FROM pg_stat_statements ORDER BY query COLLATE "C";
583591
query | calls | rows
584592
------------------------------------------------------------------------------+-------+------
@@ -588,10 +596,16 @@ SELECT query, calls, rows FROM pg_stat_statements ORDER BY query COLLATE "C";
588596
DROP FUNCTION PLUS_TWO(INTEGER) | 1 | 0
589597
DROP TABLE IF EXISTS test | 3 | 0
590598
DROP TABLE test | 1 | 0
599+
RESET enable_seqscan | 1 | 0
600+
RESET work_mem | 1 | 0
591601
SELECT $1 | 1 | 1
592602
SELECT pg_stat_statements_reset() | 1 | 1
593603
SELECT query, calls, rows FROM pg_stat_statements ORDER BY query COLLATE "C" | 0 | 0
594-
(9 rows)
604+
SET enable_seqscan = off | 1 | 0
605+
SET enable_seqscan = on | 1 | 0
606+
SET work_mem = '1MB' | 2 | 0
607+
SET work_mem = '2MB' | 1 | 0
608+
(15 rows)
595609

596610
--
597611
-- Track the total number of rows retrieved or affected by the utility

contrib/pg_stat_statements/sql/pg_stat_statements.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,14 @@ DROP TABLE IF EXISTS test \;
270270
Drop Table If Exists test \;
271271
DROP FUNCTION IF EXISTS PLUS_ONE(INTEGER);
272272
DROP FUNCTION PLUS_TWO(INTEGER);
273+
-- This SET query uses two different strings, still they count as one entry.
274+
SET work_mem = '1MB';
275+
Set work_mem = '1MB';
276+
SET work_mem = '2MB';
277+
RESET work_mem;
278+
SET enable_seqscan = off;
279+
SET enable_seqscan = on;
280+
RESET enable_seqscan;
273281

274282
SELECT query, calls, rows FROM pg_stat_statements ORDER BY query COLLATE "C";
275283

src/backend/nodes/queryjumblefuncs.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ static void AppendJumble(JumbleState *jstate,
4949
const unsigned char *item, Size size);
5050
static void RecordConstLocation(JumbleState *jstate, int location);
5151
static void _jumbleNode(JumbleState *jstate, Node *node);
52+
static void _jumbleA_Const(JumbleState *jstate, Node *node);
5253
static void _jumbleList(JumbleState *jstate, Node *node);
5354
static void _jumbleRangeTblEntry(JumbleState *jstate, Node *node);
5455

@@ -313,6 +314,40 @@ _jumbleList(JumbleState *jstate, Node *node)
313314
}
314315
}
315316

317+
static void
318+
_jumbleA_Const(JumbleState *jstate, Node *node)
319+
{
320+
A_Const *expr = (A_Const *) node;
321+
322+
JUMBLE_FIELD(isnull);
323+
if (!expr->isnull)
324+
{
325+
JUMBLE_FIELD(val.node.type);
326+
switch (nodeTag(&expr->val))
327+
{
328+
case T_Integer:
329+
JUMBLE_FIELD(val.ival.ival);
330+
break;
331+
case T_Float:
332+
JUMBLE_STRING(val.fval.fval);
333+
break;
334+
case T_Boolean:
335+
JUMBLE_FIELD(val.boolval.boolval);
336+
break;
337+
case T_String:
338+
JUMBLE_STRING(val.sval.sval);
339+
break;
340+
case T_BitString:
341+
JUMBLE_STRING(val.bsval.bsval);
342+
break;
343+
default:
344+
elog(ERROR, "unrecognized node type: %d",
345+
(int) nodeTag(&expr->val));
346+
break;
347+
}
348+
}
349+
}
350+
316351
static void
317352
_jumbleRangeTblEntry(JumbleState *jstate, Node *node)
318353
{

src/include/nodes/parsenodes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ union ValUnion
355355

356356
typedef struct A_Const
357357
{
358-
pg_node_attr(custom_copy_equal, custom_read_write)
358+
pg_node_attr(custom_copy_equal, custom_read_write, custom_query_jumble)
359359

360360
NodeTag type;
361361
union ValUnion val;

0 commit comments

Comments
 (0)