PostgreSQL Source Code  git master
queryjumble.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * queryjumble.c
4  * Query normalization and fingerprinting.
5  *
6  * Normalization is a process whereby similar queries, typically differing only
7  * in their constants (though the exact rules are somewhat more subtle than
8  * that) are recognized as equivalent, and are tracked as a single entry. This
9  * is particularly useful for non-prepared queries.
10  *
11  * Normalization is implemented by fingerprinting queries, selectively
12  * serializing those fields of each query tree's nodes that are judged to be
13  * essential to the query. This is referred to as a query jumble. This is
14  * distinct from a regular serialization in that various extraneous
15  * information is ignored as irrelevant or not essential to the query, such
16  * as the collations of Vars and, most notably, the values of constants.
17  *
18  * This jumble is acquired at the end of parse analysis of each query, and
19  * a 64-bit hash of it is stored into the query's Query.queryId field.
20  * The server then copies this value around, making it available in plan
21  * tree(s) generated from the query. The executor can then use this value
22  * to blame query costs on the proper queryId.
23  *
24  * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
25  * Portions Copyright (c) 1994, Regents of the University of California
26  *
27  *
28  * IDENTIFICATION
29  * src/backend/utils/misc/queryjumble.c
30  *
31  *-------------------------------------------------------------------------
32  */
33 #include "postgres.h"
34 
35 #include "common/hashfn.h"
36 #include "miscadmin.h"
37 #include "parser/scansup.h"
38 #include "utils/queryjumble.h"
39 
40 #define JUMBLE_SIZE 1024 /* query serialization buffer size */
41 
42 /* GUC parameters */
44 
45 /* True when compute_query_id is ON, or AUTO and a module requests them */
46 bool query_id_enabled = false;
47 
48 static uint64 compute_utility_query_id(const char *str, int query_location, int query_len);
49 static void AppendJumble(JumbleState *jstate,
50  const unsigned char *item, Size size);
51 static void JumbleQueryInternal(JumbleState *jstate, Query *query);
52 static void JumbleRangeTable(JumbleState *jstate, List *rtable);
53 static void JumbleRowMarks(JumbleState *jstate, List *rowMarks);
54 static void JumbleExpr(JumbleState *jstate, Node *node);
55 static void RecordConstLocation(JumbleState *jstate, int location);
56 
57 /*
58  * Given a possibly multi-statement source string, confine our attention to the
59  * relevant part of the string.
60  */
61 const char *
62 CleanQuerytext(const char *query, int *location, int *len)
63 {
64  int query_location = *location;
65  int query_len = *len;
66 
67  /* First apply starting offset, unless it's -1 (unknown). */
68  if (query_location >= 0)
69  {
70  Assert(query_location <= strlen(query));
71  query += query_location;
72  /* Length of 0 (or -1) means "rest of string" */
73  if (query_len <= 0)
74  query_len = strlen(query);
75  else
76  Assert(query_len <= strlen(query));
77  }
78  else
79  {
80  /* If query location is unknown, distrust query_len as well */
81  query_location = 0;
82  query_len = strlen(query);
83  }
84 
85  /*
86  * Discard leading and trailing whitespace, too. Use scanner_isspace()
87  * not libc's isspace(), because we want to match the lexer's behavior.
88  */
89  while (query_len > 0 && scanner_isspace(query[0]))
90  query++, query_location++, query_len--;
91  while (query_len > 0 && scanner_isspace(query[query_len - 1]))
92  query_len--;
93 
94  *location = query_location;
95  *len = query_len;
96 
97  return query;
98 }
99 
100 JumbleState *
101 JumbleQuery(Query *query, const char *querytext)
102 {
103  JumbleState *jstate = NULL;
104 
106 
107  if (query->utilityStmt)
108  {
109  query->queryId = compute_utility_query_id(querytext,
110  query->stmt_location,
111  query->stmt_len);
112  }
113  else
114  {
115  jstate = (JumbleState *) palloc(sizeof(JumbleState));
116 
117  /* Set up workspace for query jumbling */
118  jstate->jumble = (unsigned char *) palloc(JUMBLE_SIZE);
119  jstate->jumble_len = 0;
120  jstate->clocations_buf_size = 32;
121  jstate->clocations = (LocationLen *)
122  palloc(jstate->clocations_buf_size * sizeof(LocationLen));
123  jstate->clocations_count = 0;
124  jstate->highest_extern_param_id = 0;
125 
126  /* Compute query ID and mark the Query node with it */
127  JumbleQueryInternal(jstate, query);
129  jstate->jumble_len,
130  0));
131 
132  /*
133  * If we are unlucky enough to get a hash of zero, use 1 instead, to
134  * prevent confusion with the utility-statement case.
135  */
136  if (query->queryId == UINT64CONST(0))
137  query->queryId = UINT64CONST(1);
138  }
139 
140  return jstate;
141 }
142 
143 /*
144  * Enables query identifier computation.
145  *
146  * Third-party plugins can use this function to inform core that they require
147  * a query identifier to be computed.
148  */
149 void
151 {
153  query_id_enabled = true;
154 }
155 
156 /*
157  * Compute a query identifier for the given utility query string.
158  */
159 static uint64
160 compute_utility_query_id(const char *query_text, int query_location, int query_len)
161 {
162  uint64 queryId;
163  const char *sql;
164 
165  /*
166  * Confine our attention to the relevant part of the string, if the query
167  * is a portion of a multi-statement source string.
168  */
169  sql = CleanQuerytext(query_text, &query_location, &query_len);
170 
171  queryId = DatumGetUInt64(hash_any_extended((const unsigned char *) sql,
172  query_len, 0));
173 
174  /*
175  * If we are unlucky enough to get a hash of zero(invalid), use queryID as
176  * 2 instead, queryID 1 is already in use for normal statements.
177  */
178  if (queryId == UINT64CONST(0))
179  queryId = UINT64CONST(2);
180 
181  return queryId;
182 }
183 
184 /*
185  * AppendJumble: Append a value that is substantive in a given query to
186  * the current jumble.
187  */
188 static void
189 AppendJumble(JumbleState *jstate, const unsigned char *item, Size size)
190 {
191  unsigned char *jumble = jstate->jumble;
192  Size jumble_len = jstate->jumble_len;
193 
194  /*
195  * Whenever the jumble buffer is full, we hash the current contents and
196  * reset the buffer to contain just that hash value, thus relying on the
197  * hash to summarize everything so far.
198  */
199  while (size > 0)
200  {
201  Size part_size;
202 
203  if (jumble_len >= JUMBLE_SIZE)
204  {
205  uint64 start_hash;
206 
207  start_hash = DatumGetUInt64(hash_any_extended(jumble,
208  JUMBLE_SIZE, 0));
209  memcpy(jumble, &start_hash, sizeof(start_hash));
210  jumble_len = sizeof(start_hash);
211  }
212  part_size = Min(size, JUMBLE_SIZE - jumble_len);
213  memcpy(jumble + jumble_len, item, part_size);
214  jumble_len += part_size;
215  item += part_size;
216  size -= part_size;
217  }
218  jstate->jumble_len = jumble_len;
219 }
220 
221 /*
222  * Wrappers around AppendJumble to encapsulate details of serialization
223  * of individual local variable elements.
224  */
225 #define APP_JUMB(item) \
226  AppendJumble(jstate, (const unsigned char *) &(item), sizeof(item))
227 #define APP_JUMB_STRING(str) \
228  AppendJumble(jstate, (const unsigned char *) (str), strlen(str) + 1)
229 
230 /*
231  * JumbleQueryInternal: Selectively serialize the query tree, appending
232  * significant data to the "query jumble" while ignoring nonsignificant data.
233  *
234  * Rule of thumb for what to include is that we should ignore anything not
235  * semantically significant (such as alias names) as well as anything that can
236  * be deduced from child nodes (else we'd just be double-hashing that piece
237  * of information).
238  */
239 static void
241 {
242  Assert(IsA(query, Query));
243  Assert(query->utilityStmt == NULL);
244 
245  APP_JUMB(query->commandType);
246  /* resultRelation is usually predictable from commandType */
247  JumbleExpr(jstate, (Node *) query->cteList);
248  JumbleRangeTable(jstate, query->rtable);
249  JumbleExpr(jstate, (Node *) query->jointree);
250  JumbleExpr(jstate, (Node *) query->targetList);
251  JumbleExpr(jstate, (Node *) query->onConflict);
252  JumbleExpr(jstate, (Node *) query->returningList);
253  JumbleExpr(jstate, (Node *) query->groupClause);
254  APP_JUMB(query->groupDistinct);
255  JumbleExpr(jstate, (Node *) query->groupingSets);
256  JumbleExpr(jstate, query->havingQual);
257  JumbleExpr(jstate, (Node *) query->windowClause);
258  JumbleExpr(jstate, (Node *) query->distinctClause);
259  JumbleExpr(jstate, (Node *) query->sortClause);
260  JumbleExpr(jstate, query->limitOffset);
261  JumbleExpr(jstate, query->limitCount);
262  APP_JUMB(query->limitOption);
263  JumbleRowMarks(jstate, query->rowMarks);
264  JumbleExpr(jstate, query->setOperations);
265 }
266 
267 /*
268  * Jumble a range table
269  */
270 static void
272 {
273  ListCell *lc;
274 
275  foreach(lc, rtable)
276  {
278 
279  APP_JUMB(rte->rtekind);
280  switch (rte->rtekind)
281  {
282  case RTE_RELATION:
283  APP_JUMB(rte->relid);
284  JumbleExpr(jstate, (Node *) rte->tablesample);
285  APP_JUMB(rte->inh);
286  break;
287  case RTE_SUBQUERY:
288  JumbleQueryInternal(jstate, rte->subquery);
289  break;
290  case RTE_JOIN:
291  APP_JUMB(rte->jointype);
292  break;
293  case RTE_FUNCTION:
294  JumbleExpr(jstate, (Node *) rte->functions);
295  break;
296  case RTE_TABLEFUNC:
297  JumbleExpr(jstate, (Node *) rte->tablefunc);
298  break;
299  case RTE_VALUES:
300  JumbleExpr(jstate, (Node *) rte->values_lists);
301  break;
302  case RTE_CTE:
303 
304  /*
305  * Depending on the CTE name here isn't ideal, but it's the
306  * only info we have to identify the referenced WITH item.
307  */
308  APP_JUMB_STRING(rte->ctename);
309  APP_JUMB(rte->ctelevelsup);
310  break;
311  case RTE_NAMEDTUPLESTORE:
312  APP_JUMB_STRING(rte->enrname);
313  break;
314  case RTE_RESULT:
315  break;
316  default:
317  elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
318  break;
319  }
320  }
321 }
322 
323 /*
324  * Jumble a rowMarks list
325  */
326 static void
327 JumbleRowMarks(JumbleState *jstate, List *rowMarks)
328 {
329  ListCell *lc;
330 
331  foreach(lc, rowMarks)
332  {
333  RowMarkClause *rowmark = lfirst_node(RowMarkClause, lc);
334 
335  if (!rowmark->pushedDown)
336  {
337  APP_JUMB(rowmark->rti);
338  APP_JUMB(rowmark->strength);
339  APP_JUMB(rowmark->waitPolicy);
340  }
341  }
342 }
343 
344 /*
345  * Jumble an expression tree
346  *
347  * In general this function should handle all the same node types that
348  * expression_tree_walker() does, and therefore it's coded to be as parallel
349  * to that function as possible. However, since we are only invoked on
350  * queries immediately post-parse-analysis, we need not handle node types
351  * that only appear in planning.
352  *
353  * Note: the reason we don't simply use expression_tree_walker() is that the
354  * point of that function is to support tree walkers that don't care about
355  * most tree node types, but here we care about all types. We should complain
356  * about any unrecognized node type.
357  */
358 static void
359 JumbleExpr(JumbleState *jstate, Node *node)
360 {
361  ListCell *temp;
362 
363  if (node == NULL)
364  return;
365 
366  /* Guard against stack overflow due to overly complex expressions */
368 
369  /*
370  * We always emit the node's NodeTag, then any additional fields that are
371  * considered significant, and then we recurse to any child nodes.
372  */
373  APP_JUMB(node->type);
374 
375  switch (nodeTag(node))
376  {
377  case T_Var:
378  {
379  Var *var = (Var *) node;
380 
381  APP_JUMB(var->varno);
382  APP_JUMB(var->varattno);
383  APP_JUMB(var->varlevelsup);
384  }
385  break;
386  case T_Const:
387  {
388  Const *c = (Const *) node;
389 
390  /* We jumble only the constant's type, not its value */
391  APP_JUMB(c->consttype);
392  /* Also, record its parse location for query normalization */
393  RecordConstLocation(jstate, c->location);
394  }
395  break;
396  case T_Param:
397  {
398  Param *p = (Param *) node;
399 
400  APP_JUMB(p->paramkind);
401  APP_JUMB(p->paramid);
402  APP_JUMB(p->paramtype);
403  /* Also, track the highest external Param id */
404  if (p->paramkind == PARAM_EXTERN &&
405  p->paramid > jstate->highest_extern_param_id)
406  jstate->highest_extern_param_id = p->paramid;
407  }
408  break;
409  case T_Aggref:
410  {
411  Aggref *expr = (Aggref *) node;
412 
413  APP_JUMB(expr->aggfnoid);
414  JumbleExpr(jstate, (Node *) expr->aggdirectargs);
415  JumbleExpr(jstate, (Node *) expr->args);
416  JumbleExpr(jstate, (Node *) expr->aggorder);
417  JumbleExpr(jstate, (Node *) expr->aggdistinct);
418  JumbleExpr(jstate, (Node *) expr->aggfilter);
419  }
420  break;
421  case T_GroupingFunc:
422  {
423  GroupingFunc *grpnode = (GroupingFunc *) node;
424 
425  JumbleExpr(jstate, (Node *) grpnode->refs);
426  APP_JUMB(grpnode->agglevelsup);
427  }
428  break;
429  case T_WindowFunc:
430  {
431  WindowFunc *expr = (WindowFunc *) node;
432 
433  APP_JUMB(expr->winfnoid);
434  APP_JUMB(expr->winref);
435  JumbleExpr(jstate, (Node *) expr->args);
436  JumbleExpr(jstate, (Node *) expr->aggfilter);
437  }
438  break;
439  case T_SubscriptingRef:
440  {
441  SubscriptingRef *sbsref = (SubscriptingRef *) node;
442 
443  JumbleExpr(jstate, (Node *) sbsref->refupperindexpr);
444  JumbleExpr(jstate, (Node *) sbsref->reflowerindexpr);
445  JumbleExpr(jstate, (Node *) sbsref->refexpr);
446  JumbleExpr(jstate, (Node *) sbsref->refassgnexpr);
447  }
448  break;
449  case T_FuncExpr:
450  {
451  FuncExpr *expr = (FuncExpr *) node;
452 
453  APP_JUMB(expr->funcid);
454  JumbleExpr(jstate, (Node *) expr->args);
455  }
456  break;
457  case T_NamedArgExpr:
458  {
459  NamedArgExpr *nae = (NamedArgExpr *) node;
460 
461  APP_JUMB(nae->argnumber);
462  JumbleExpr(jstate, (Node *) nae->arg);
463  }
464  break;
465  case T_OpExpr:
466  case T_DistinctExpr: /* struct-equivalent to OpExpr */
467  case T_NullIfExpr: /* struct-equivalent to OpExpr */
468  {
469  OpExpr *expr = (OpExpr *) node;
470 
471  APP_JUMB(expr->opno);
472  JumbleExpr(jstate, (Node *) expr->args);
473  }
474  break;
475  case T_ScalarArrayOpExpr:
476  {
477  ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
478 
479  APP_JUMB(expr->opno);
480  APP_JUMB(expr->useOr);
481  JumbleExpr(jstate, (Node *) expr->args);
482  }
483  break;
484  case T_BoolExpr:
485  {
486  BoolExpr *expr = (BoolExpr *) node;
487 
488  APP_JUMB(expr->boolop);
489  JumbleExpr(jstate, (Node *) expr->args);
490  }
491  break;
492  case T_SubLink:
493  {
494  SubLink *sublink = (SubLink *) node;
495 
496  APP_JUMB(sublink->subLinkType);
497  APP_JUMB(sublink->subLinkId);
498  JumbleExpr(jstate, (Node *) sublink->testexpr);
499  JumbleQueryInternal(jstate, castNode(Query, sublink->subselect));
500  }
501  break;
502  case T_FieldSelect:
503  {
504  FieldSelect *fs = (FieldSelect *) node;
505 
506  APP_JUMB(fs->fieldnum);
507  JumbleExpr(jstate, (Node *) fs->arg);
508  }
509  break;
510  case T_FieldStore:
511  {
512  FieldStore *fstore = (FieldStore *) node;
513 
514  JumbleExpr(jstate, (Node *) fstore->arg);
515  JumbleExpr(jstate, (Node *) fstore->newvals);
516  }
517  break;
518  case T_RelabelType:
519  {
520  RelabelType *rt = (RelabelType *) node;
521 
522  APP_JUMB(rt->resulttype);
523  JumbleExpr(jstate, (Node *) rt->arg);
524  }
525  break;
526  case T_CoerceViaIO:
527  {
528  CoerceViaIO *cio = (CoerceViaIO *) node;
529 
530  APP_JUMB(cio->resulttype);
531  JumbleExpr(jstate, (Node *) cio->arg);
532  }
533  break;
534  case T_ArrayCoerceExpr:
535  {
536  ArrayCoerceExpr *acexpr = (ArrayCoerceExpr *) node;
537 
538  APP_JUMB(acexpr->resulttype);
539  JumbleExpr(jstate, (Node *) acexpr->arg);
540  JumbleExpr(jstate, (Node *) acexpr->elemexpr);
541  }
542  break;
544  {
545  ConvertRowtypeExpr *crexpr = (ConvertRowtypeExpr *) node;
546 
547  APP_JUMB(crexpr->resulttype);
548  JumbleExpr(jstate, (Node *) crexpr->arg);
549  }
550  break;
551  case T_CollateExpr:
552  {
553  CollateExpr *ce = (CollateExpr *) node;
554 
555  APP_JUMB(ce->collOid);
556  JumbleExpr(jstate, (Node *) ce->arg);
557  }
558  break;
559  case T_CaseExpr:
560  {
561  CaseExpr *caseexpr = (CaseExpr *) node;
562 
563  JumbleExpr(jstate, (Node *) caseexpr->arg);
564  foreach(temp, caseexpr->args)
565  {
566  CaseWhen *when = lfirst_node(CaseWhen, temp);
567 
568  JumbleExpr(jstate, (Node *) when->expr);
569  JumbleExpr(jstate, (Node *) when->result);
570  }
571  JumbleExpr(jstate, (Node *) caseexpr->defresult);
572  }
573  break;
574  case T_CaseTestExpr:
575  {
576  CaseTestExpr *ct = (CaseTestExpr *) node;
577 
578  APP_JUMB(ct->typeId);
579  }
580  break;
581  case T_ArrayExpr:
582  JumbleExpr(jstate, (Node *) ((ArrayExpr *) node)->elements);
583  break;
584  case T_RowExpr:
585  JumbleExpr(jstate, (Node *) ((RowExpr *) node)->args);
586  break;
587  case T_RowCompareExpr:
588  {
589  RowCompareExpr *rcexpr = (RowCompareExpr *) node;
590 
591  APP_JUMB(rcexpr->rctype);
592  JumbleExpr(jstate, (Node *) rcexpr->largs);
593  JumbleExpr(jstate, (Node *) rcexpr->rargs);
594  }
595  break;
596  case T_CoalesceExpr:
597  JumbleExpr(jstate, (Node *) ((CoalesceExpr *) node)->args);
598  break;
599  case T_MinMaxExpr:
600  {
601  MinMaxExpr *mmexpr = (MinMaxExpr *) node;
602 
603  APP_JUMB(mmexpr->op);
604  JumbleExpr(jstate, (Node *) mmexpr->args);
605  }
606  break;
607  case T_SQLValueFunction:
608  {
609  SQLValueFunction *svf = (SQLValueFunction *) node;
610 
611  APP_JUMB(svf->op);
612  /* type is fully determined by op */
613  APP_JUMB(svf->typmod);
614  }
615  break;
616  case T_XmlExpr:
617  {
618  XmlExpr *xexpr = (XmlExpr *) node;
619 
620  APP_JUMB(xexpr->op);
621  JumbleExpr(jstate, (Node *) xexpr->named_args);
622  JumbleExpr(jstate, (Node *) xexpr->args);
623  }
624  break;
625  case T_NullTest:
626  {
627  NullTest *nt = (NullTest *) node;
628 
629  APP_JUMB(nt->nulltesttype);
630  JumbleExpr(jstate, (Node *) nt->arg);
631  }
632  break;
633  case T_BooleanTest:
634  {
635  BooleanTest *bt = (BooleanTest *) node;
636 
637  APP_JUMB(bt->booltesttype);
638  JumbleExpr(jstate, (Node *) bt->arg);
639  }
640  break;
641  case T_CoerceToDomain:
642  {
643  CoerceToDomain *cd = (CoerceToDomain *) node;
644 
645  APP_JUMB(cd->resulttype);
646  JumbleExpr(jstate, (Node *) cd->arg);
647  }
648  break;
650  {
652 
653  APP_JUMB(cdv->typeId);
654  }
655  break;
656  case T_SetToDefault:
657  {
658  SetToDefault *sd = (SetToDefault *) node;
659 
660  APP_JUMB(sd->typeId);
661  }
662  break;
663  case T_CurrentOfExpr:
664  {
665  CurrentOfExpr *ce = (CurrentOfExpr *) node;
666 
667  APP_JUMB(ce->cvarno);
668  if (ce->cursor_name)
670  APP_JUMB(ce->cursor_param);
671  }
672  break;
673  case T_NextValueExpr:
674  {
675  NextValueExpr *nve = (NextValueExpr *) node;
676 
677  APP_JUMB(nve->seqid);
678  APP_JUMB(nve->typeId);
679  }
680  break;
681  case T_InferenceElem:
682  {
683  InferenceElem *ie = (InferenceElem *) node;
684 
685  APP_JUMB(ie->infercollid);
686  APP_JUMB(ie->inferopclass);
687  JumbleExpr(jstate, ie->expr);
688  }
689  break;
690  case T_TargetEntry:
691  {
692  TargetEntry *tle = (TargetEntry *) node;
693 
694  APP_JUMB(tle->resno);
696  JumbleExpr(jstate, (Node *) tle->expr);
697  }
698  break;
699  case T_RangeTblRef:
700  {
701  RangeTblRef *rtr = (RangeTblRef *) node;
702 
703  APP_JUMB(rtr->rtindex);
704  }
705  break;
706  case T_JoinExpr:
707  {
708  JoinExpr *join = (JoinExpr *) node;
709 
710  APP_JUMB(join->jointype);
711  APP_JUMB(join->isNatural);
712  APP_JUMB(join->rtindex);
713  JumbleExpr(jstate, join->larg);
714  JumbleExpr(jstate, join->rarg);
715  JumbleExpr(jstate, join->quals);
716  }
717  break;
718  case T_FromExpr:
719  {
720  FromExpr *from = (FromExpr *) node;
721 
722  JumbleExpr(jstate, (Node *) from->fromlist);
723  JumbleExpr(jstate, from->quals);
724  }
725  break;
726  case T_OnConflictExpr:
727  {
728  OnConflictExpr *conf = (OnConflictExpr *) node;
729 
730  APP_JUMB(conf->action);
731  JumbleExpr(jstate, (Node *) conf->arbiterElems);
732  JumbleExpr(jstate, conf->arbiterWhere);
733  JumbleExpr(jstate, (Node *) conf->onConflictSet);
734  JumbleExpr(jstate, conf->onConflictWhere);
735  APP_JUMB(conf->constraint);
736  APP_JUMB(conf->exclRelIndex);
737  JumbleExpr(jstate, (Node *) conf->exclRelTlist);
738  }
739  break;
740  case T_JsonFormat:
741  {
742  JsonFormat *format = (JsonFormat *) node;
743 
744  APP_JUMB(format->format_type);
745  APP_JUMB(format->encoding);
746  }
747  break;
748  case T_JsonReturning:
749  {
750  JsonReturning *returning = (JsonReturning *) node;
751 
752  JumbleExpr(jstate, (Node *) returning->format);
753  APP_JUMB(returning->typid);
754  APP_JUMB(returning->typmod);
755  }
756  break;
757  case T_JsonValueExpr:
758  {
759  JsonValueExpr *expr = (JsonValueExpr *) node;
760 
761  JumbleExpr(jstate, (Node *) expr->raw_expr);
762  JumbleExpr(jstate, (Node *) expr->formatted_expr);
763  JumbleExpr(jstate, (Node *) expr->format);
764  }
765  break;
767  {
768  JsonConstructorExpr *ctor = (JsonConstructorExpr *) node;
769 
770  APP_JUMB(ctor->type);
771  JumbleExpr(jstate, (Node *) ctor->args);
772  JumbleExpr(jstate, (Node *) ctor->func);
773  JumbleExpr(jstate, (Node *) ctor->coercion);
774  JumbleExpr(jstate, (Node *) ctor->returning);
775  APP_JUMB(ctor->absent_on_null);
776  APP_JUMB(ctor->unique);
777  }
778  break;
779  case T_JsonIsPredicate:
780  {
781  JsonIsPredicate *pred = (JsonIsPredicate *) node;
782 
783  JumbleExpr(jstate, (Node *) pred->expr);
784  JumbleExpr(jstate, (Node *) pred->format);
785  APP_JUMB(pred->item_type);
786  APP_JUMB(pred->unique_keys);
787  }
788  break;
789  case T_JsonExpr:
790  {
791  JsonExpr *jexpr = (JsonExpr *) node;
792 
793  APP_JUMB(jexpr->op);
794  JumbleExpr(jstate, jexpr->formatted_expr);
795  JumbleExpr(jstate, jexpr->path_spec);
796  foreach(temp, jexpr->passing_names)
797  {
798  APP_JUMB_STRING(lfirst_node(String, temp)->sval);
799  }
800  JumbleExpr(jstate, (Node *) jexpr->passing_values);
801  if (jexpr->on_empty)
802  {
803  APP_JUMB(jexpr->on_empty->btype);
804  JumbleExpr(jstate, jexpr->on_empty->default_expr);
805  }
806  APP_JUMB(jexpr->on_error->btype);
807  JumbleExpr(jstate, jexpr->on_error->default_expr);
808  }
809  break;
810  case T_List:
811  foreach(temp, (List *) node)
812  {
813  JumbleExpr(jstate, (Node *) lfirst(temp));
814  }
815  break;
816  case T_IntList:
817  foreach(temp, (List *) node)
818  {
819  APP_JUMB(lfirst_int(temp));
820  }
821  break;
822  case T_SortGroupClause:
823  {
824  SortGroupClause *sgc = (SortGroupClause *) node;
825 
827  APP_JUMB(sgc->eqop);
828  APP_JUMB(sgc->sortop);
829  APP_JUMB(sgc->nulls_first);
830  }
831  break;
832  case T_GroupingSet:
833  {
834  GroupingSet *gsnode = (GroupingSet *) node;
835 
836  JumbleExpr(jstate, (Node *) gsnode->content);
837  }
838  break;
839  case T_WindowClause:
840  {
841  WindowClause *wc = (WindowClause *) node;
842 
843  APP_JUMB(wc->winref);
844  APP_JUMB(wc->frameOptions);
845  JumbleExpr(jstate, (Node *) wc->partitionClause);
846  JumbleExpr(jstate, (Node *) wc->orderClause);
847  JumbleExpr(jstate, wc->startOffset);
848  JumbleExpr(jstate, wc->endOffset);
849  }
850  break;
851  case T_CommonTableExpr:
852  {
853  CommonTableExpr *cte = (CommonTableExpr *) node;
854 
855  /* we store the string name because RTE_CTE RTEs need it */
856  APP_JUMB_STRING(cte->ctename);
858  JumbleQueryInternal(jstate, castNode(Query, cte->ctequery));
859  }
860  break;
861  case T_SetOperationStmt:
862  {
863  SetOperationStmt *setop = (SetOperationStmt *) node;
864 
865  APP_JUMB(setop->op);
866  APP_JUMB(setop->all);
867  JumbleExpr(jstate, setop->larg);
868  JumbleExpr(jstate, setop->rarg);
869  }
870  break;
871  case T_RangeTblFunction:
872  {
873  RangeTblFunction *rtfunc = (RangeTblFunction *) node;
874 
875  JumbleExpr(jstate, rtfunc->funcexpr);
876  }
877  break;
878  case T_TableFunc:
879  {
880  TableFunc *tablefunc = (TableFunc *) node;
881 
882  APP_JUMB(tablefunc->functype);
883  JumbleExpr(jstate, tablefunc->docexpr);
884  JumbleExpr(jstate, tablefunc->rowexpr);
885  JumbleExpr(jstate, (Node *) tablefunc->colexprs);
886  JumbleExpr(jstate, (Node *) tablefunc->colvalexprs);
887  }
888  break;
889  case T_TableSampleClause:
890  {
891  TableSampleClause *tsc = (TableSampleClause *) node;
892 
893  APP_JUMB(tsc->tsmhandler);
894  JumbleExpr(jstate, (Node *) tsc->args);
895  JumbleExpr(jstate, (Node *) tsc->repeatable);
896  }
897  break;
898  default:
899  /* Only a warning, since we can stumble along anyway */
900  elog(WARNING, "unrecognized node type: %d",
901  (int) nodeTag(node));
902  break;
903  }
904 }
905 
906 /*
907  * Record location of constant within query string of query tree
908  * that is currently being walked.
909  */
910 static void
911 RecordConstLocation(JumbleState *jstate, int location)
912 {
913  /* -1 indicates unknown or undefined location */
914  if (location >= 0)
915  {
916  /* enlarge array if needed */
917  if (jstate->clocations_count >= jstate->clocations_buf_size)
918  {
919  jstate->clocations_buf_size *= 2;
920  jstate->clocations = (LocationLen *)
921  repalloc(jstate->clocations,
922  jstate->clocations_buf_size *
923  sizeof(LocationLen));
924  }
925  jstate->clocations[jstate->clocations_count].location = location;
926  /* initialize lengths to -1 to simplify third-party module usage */
927  jstate->clocations[jstate->clocations_count].length = -1;
928  jstate->clocations_count++;
929  }
930 }
#define Min(x, y)
Definition: c.h:997
size_t Size
Definition: c.h:551
#define WARNING
Definition: elog.h:30
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
static Datum hash_any_extended(const unsigned char *k, int keylen, uint64 seed)
Definition: hashfn.h:37
Assert(fmt[strlen(fmt) - 1] !='\n')
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1188
void * palloc(Size size)
Definition: mcxt.c:1068
#define IsA(nodeptr, _type_)
Definition: nodes.h:624
#define nodeTag(nodeptr)
Definition: nodes.h:578
@ T_FieldStore
Definition: nodes.h:175
@ T_CoalesceExpr
Definition: nodes.h:187
@ T_List
Definition: nodes.h:317
@ T_OnConflictExpr
Definition: nodes.h:203
@ T_SubLink
Definition: nodes.h:171
@ T_RangeTblRef
Definition: nodes.h:200
@ T_InferenceElem
Definition: nodes.h:198
@ T_SortGroupClause
Definition: nodes.h:483
@ T_CoerceToDomainValue
Definition: nodes.h:194
@ T_WindowFunc
Definition: nodes.h:162
@ T_FieldSelect
Definition: nodes.h:174
@ T_ArrayExpr
Definition: nodes.h:184
@ T_TableFunc
Definition: nodes.h:156
@ T_CollateExpr
Definition: nodes.h:180
@ T_BoolExpr
Definition: nodes.h:170
@ T_OpExpr
Definition: nodes.h:166
@ T_JoinExpr
Definition: nodes.h:201
@ T_ScalarArrayOpExpr
Definition: nodes.h:169
@ T_CaseExpr
Definition: nodes.h:181
@ T_RelabelType
Definition: nodes.h:176
@ T_XmlExpr
Definition: nodes.h:190
@ T_GroupingSet
Definition: nodes.h:484
@ T_JsonReturning
Definition: nodes.h:206
@ T_TableSampleClause
Definition: nodes.h:481
@ T_SetOperationStmt
Definition: nodes.h:342
@ T_ConvertRowtypeExpr
Definition: nodes.h:179
@ T_CommonTableExpr
Definition: nodes.h:499
@ T_JsonConstructorExpr
Definition: nodes.h:211
@ T_WindowClause
Definition: nodes.h:485
@ T_FromExpr
Definition: nodes.h:202
@ T_RowExpr
Definition: nodes.h:185
@ T_TargetEntry
Definition: nodes.h:199
@ T_ArrayCoerceExpr
Definition: nodes.h:178
@ T_MinMaxExpr
Definition: nodes.h:188
@ T_CurrentOfExpr
Definition: nodes.h:196
@ T_Aggref
Definition: nodes.h:160
@ T_BooleanTest
Definition: nodes.h:192
@ T_RangeTblFunction
Definition: nodes.h:480
@ T_IntList
Definition: nodes.h:318
@ T_JsonIsPredicate
Definition: nodes.h:518
@ T_JsonValueExpr
Definition: nodes.h:207
@ T_SQLValueFunction
Definition: nodes.h:189
@ T_NamedArgExpr
Definition: nodes.h:165
@ T_Const
Definition: nodes.h:158
@ T_CoerceViaIO
Definition: nodes.h:177
@ T_JsonExpr
Definition: nodes.h:212
@ T_NextValueExpr
Definition: nodes.h:197
@ T_Param
Definition: nodes.h:159
@ T_CoerceToDomain
Definition: nodes.h:193
@ T_GroupingFunc
Definition: nodes.h:161
@ T_DistinctExpr
Definition: nodes.h:167
@ T_FuncExpr
Definition: nodes.h:164
@ T_Var
Definition: nodes.h:157
@ T_RowCompareExpr
Definition: nodes.h:186
@ T_CaseTestExpr
Definition: nodes.h:183
@ T_NullTest
Definition: nodes.h:191
@ T_SubscriptingRef
Definition: nodes.h:163
@ T_SetToDefault
Definition: nodes.h:195
@ T_NullIfExpr
Definition: nodes.h:168
@ T_JsonFormat
Definition: nodes.h:205
#define castNode(_type_, nodeptr)
Definition: nodes.h:642
@ RTE_JOIN
Definition: parsenodes.h:1000
@ RTE_CTE
Definition: parsenodes.h:1004
@ RTE_NAMEDTUPLESTORE
Definition: parsenodes.h:1005
@ RTE_VALUES
Definition: parsenodes.h:1003
@ RTE_SUBQUERY
Definition: parsenodes.h:999
@ RTE_RESULT
Definition: parsenodes.h:1006
@ RTE_FUNCTION
Definition: parsenodes.h:1001
@ RTE_TABLEFUNC
Definition: parsenodes.h:1002
@ RTE_RELATION
Definition: parsenodes.h:998
static char format
const void size_t len
#define lfirst(lc)
Definition: pg_list.h:169
#define lfirst_node(type, lc)
Definition: pg_list.h:172
#define lfirst_int(lc)
Definition: pg_list.h:170
void check_stack_depth(void)
Definition: postgres.c:3500
#define DatumGetUInt64(X)
Definition: postgres.h:678
char * c
@ PARAM_EXTERN
Definition: primnodes.h:267
JumbleState * JumbleQuery(Query *query, const char *querytext)
Definition: queryjumble.c:101
bool query_id_enabled
Definition: queryjumble.c:46
static void AppendJumble(JumbleState *jstate, const unsigned char *item, Size size)
Definition: queryjumble.c:189
#define JUMBLE_SIZE
Definition: queryjumble.c:40
int compute_query_id
Definition: queryjumble.c:43
#define APP_JUMB(item)
Definition: queryjumble.c:225
static uint64 compute_utility_query_id(const char *str, int query_location, int query_len)
Definition: queryjumble.c:160
static void RecordConstLocation(JumbleState *jstate, int location)
Definition: queryjumble.c:911
#define APP_JUMB_STRING(str)
Definition: queryjumble.c:227
const char * CleanQuerytext(const char *query, int *location, int *len)
Definition: queryjumble.c:62
static void JumbleRangeTable(JumbleState *jstate, List *rtable)
Definition: queryjumble.c:271
void EnableQueryId(void)
Definition: queryjumble.c:150
static void JumbleRowMarks(JumbleState *jstate, List *rowMarks)
Definition: queryjumble.c:327
static void JumbleQueryInternal(JumbleState *jstate, Query *query)
Definition: queryjumble.c:240
static void JumbleExpr(JumbleState *jstate, Node *node)
Definition: queryjumble.c:359
@ COMPUTE_QUERY_ID_AUTO
Definition: queryjumble.h:60
@ COMPUTE_QUERY_ID_OFF
Definition: queryjumble.h:58
static bool IsQueryIdEnabled(void)
Definition: queryjumble.h:79
bool scanner_isspace(char ch)
Definition: scansup.c:117
Oid aggfnoid
Definition: primnodes.h:332
List * aggdistinct
Definition: primnodes.h:341
List * aggdirectargs
Definition: primnodes.h:338
List * args
Definition: primnodes.h:339
Expr * aggfilter
Definition: primnodes.h:342
List * aggorder
Definition: primnodes.h:340
Expr * elemexpr
Definition: primnodes.h:914
BoolExprType boolop
Definition: primnodes.h:634
List * args
Definition: primnodes.h:635
BoolTestType booltesttype
Definition: primnodes.h:1550
Expr * arg
Definition: primnodes.h:1549
Expr * arg
Definition: primnodes.h:987
Expr * defresult
Definition: primnodes.h:989
List * args
Definition: primnodes.h:988
Expr * arg
Definition: primnodes.h:889
Oid resulttype
Definition: primnodes.h:890
Expr * arg
Definition: primnodes.h:955
CTEMaterialize ctematerialized
Definition: parsenodes.h:1525
char * cursor_name
Definition: primnodes.h:1625
AttrNumber fieldnum
Definition: primnodes.h:818
Expr * arg
Definition: primnodes.h:817
List * newvals
Definition: primnodes.h:847
Expr * arg
Definition: primnodes.h:846
Node * quals
Definition: primnodes.h:1826
List * fromlist
Definition: primnodes.h:1825
Oid funcid
Definition: primnodes.h:504
List * args
Definition: primnodes.h:512
Index agglevelsup
Definition: primnodes.h:385
List * refs
Definition: primnodes.h:383
List * content
Definition: parsenodes.h:1375
Node * quals
Definition: primnodes.h:1808
JoinType jointype
Definition: primnodes.h:1802
int rtindex
Definition: primnodes.h:1810
Node * larg
Definition: primnodes.h:1804
bool isNatural
Definition: primnodes.h:1803
Node * rarg
Definition: primnodes.h:1805
JsonBehaviorType btype
Definition: primnodes.h:1409
Node * default_expr
Definition: primnodes.h:1410
JsonReturning * returning
Definition: primnodes.h:1370
JsonConstructorType type
Definition: primnodes.h:1366
Node * formatted_expr
Definition: primnodes.h:1454
List * passing_values
Definition: primnodes.h:1459
JsonBehavior * on_empty
Definition: primnodes.h:1461
List * passing_names
Definition: primnodes.h:1458
Node * path_spec
Definition: primnodes.h:1457
JsonExprOp op
Definition: primnodes.h:1453
JsonBehavior * on_error
Definition: primnodes.h:1462
JsonFormat * format
Definition: primnodes.h:1396
JsonValueType item_type
Definition: primnodes.h:1397
JsonFormat * format
Definition: primnodes.h:1331
Expr * formatted_expr
Definition: primnodes.h:1344
JsonFormat * format
Definition: primnodes.h:1345
Expr * raw_expr
Definition: primnodes.h:1343
unsigned char * jumble
Definition: queryjumble.h:37
int clocations_buf_size
Definition: queryjumble.h:46
Size jumble_len
Definition: queryjumble.h:40
int highest_extern_param_id
Definition: queryjumble.h:52
LocationLen * clocations
Definition: queryjumble.h:43
int clocations_count
Definition: queryjumble.h:49
Definition: pg_list.h:51
List * args
Definition: primnodes.h:1159
MinMaxOp op
Definition: primnodes.h:1158
Expr * arg
Definition: primnodes.h:533
Definition: nodes.h:574
NodeTag type
Definition: nodes.h:575
NullTestType nulltesttype
Definition: primnodes.h:1527
Expr * arg
Definition: primnodes.h:1526
List * arbiterElems
Definition: primnodes.h:1844
OnConflictAction action
Definition: primnodes.h:1841
List * onConflictSet
Definition: primnodes.h:1850
List * exclRelTlist
Definition: primnodes.h:1853
Node * onConflictWhere
Definition: primnodes.h:1851
Node * arbiterWhere
Definition: primnodes.h:1846
Oid opno
Definition: primnodes.h:551
List * args
Definition: primnodes.h:557
int paramid
Definition: primnodes.h:277
Oid paramtype
Definition: primnodes.h:278
ParamKind paramkind
Definition: primnodes.h:276
List * rowMarks
Definition: parsenodes.h:180
bool groupDistinct
Definition: parsenodes.h:164
Node * limitCount
Definition: parsenodes.h:177
int stmt_location
Definition: parsenodes.h:197
FromExpr * jointree
Definition: parsenodes.h:149
List * returningList
Definition: parsenodes.h:161
Node * setOperations
Definition: parsenodes.h:182
List * cteList
Definition: parsenodes.h:146
OnConflictExpr * onConflict
Definition: parsenodes.h:159
uint64 queryId
Definition: parsenodes.h:125
List * groupClause
Definition: parsenodes.h:163
int stmt_len
Definition: parsenodes.h:198
Node * havingQual
Definition: parsenodes.h:168
List * rtable
Definition: parsenodes.h:148
Node * limitOffset
Definition: parsenodes.h:176
CmdType commandType
Definition: parsenodes.h:121
LimitOption limitOption
Definition: parsenodes.h:178
Node * utilityStmt
Definition: parsenodes.h:129
List * windowClause
Definition: parsenodes.h:170
List * targetList
Definition: parsenodes.h:155
List * groupingSets
Definition: parsenodes.h:166
List * distinctClause
Definition: parsenodes.h:172
List * sortClause
Definition: parsenodes.h:174
char * ctename
Definition: parsenodes.h:1125
TableFunc * tablefunc
Definition: parsenodes.h:1115
Index ctelevelsup
Definition: parsenodes.h:1126
struct TableSampleClause * tablesample
Definition: parsenodes.h:1045
Query * subquery
Definition: parsenodes.h:1050
List * values_lists
Definition: parsenodes.h:1120
char * enrname
Definition: parsenodes.h:1154
JoinType jointype
Definition: parsenodes.h:1088
List * functions
Definition: parsenodes.h:1109
RTEKind rtekind
Definition: parsenodes.h:1015
Oid resulttype
Definition: primnodes.h:870
Expr * arg
Definition: primnodes.h:869
RowCompareType rctype
Definition: primnodes.h:1123
LockClauseStrength strength
Definition: parsenodes.h:1432
LockWaitPolicy waitPolicy
Definition: parsenodes.h:1433
SQLValueFunctionOp op
Definition: primnodes.h:1196
SetOperation op
Definition: parsenodes.h:2068
Index tleSortGroupRef
Definition: parsenodes.h:1305
Definition: value.h:58
Expr * refassgnexpr
Definition: primnodes.h:460
List * refupperindexpr
Definition: primnodes.h:453
Expr * refexpr
Definition: primnodes.h:458
List * reflowerindexpr
Definition: primnodes.h:455
List * colvalexprs
Definition: primnodes.h:102
Node * docexpr
Definition: primnodes.h:94
Node * rowexpr
Definition: primnodes.h:95
List * colexprs
Definition: primnodes.h:100
TableFuncType functype
Definition: primnodes.h:91
Expr * expr
Definition: primnodes.h:1716
AttrNumber resno
Definition: primnodes.h:1717
Index ressortgroupref
Definition: primnodes.h:1719
Definition: primnodes.h:196
AttrNumber varattno
Definition: primnodes.h:200
int varno
Definition: primnodes.h:198
Index varlevelsup
Definition: primnodes.h:205
Node * startOffset
Definition: parsenodes.h:1404
List * partitionClause
Definition: parsenodes.h:1401
Node * endOffset
Definition: parsenodes.h:1405
List * orderClause
Definition: parsenodes.h:1402
List * args
Definition: primnodes.h:399
Index winref
Definition: primnodes.h:401
Expr * aggfilter
Definition: primnodes.h:400
Oid winfnoid
Definition: primnodes.h:395
List * args
Definition: primnodes.h:1238
List * named_args
Definition: primnodes.h:1236
XmlExprOp op
Definition: primnodes.h:1234
Definition: type.h:83