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 *query_text,
49  int query_location, int query_len);
50 static void AppendJumble(JumbleState *jstate,
51  const unsigned char *item, Size size);
52 static void JumbleQueryInternal(JumbleState *jstate, Query *query);
53 static void JumbleRangeTable(JumbleState *jstate, List *rtable);
54 static void JumbleRowMarks(JumbleState *jstate, List *rowMarks);
55 static void JumbleExpr(JumbleState *jstate, Node *node);
56 static void RecordConstLocation(JumbleState *jstate, int location);
57 
58 /*
59  * Given a possibly multi-statement source string, confine our attention to the
60  * relevant part of the string.
61  */
62 const char *
63 CleanQuerytext(const char *query, int *location, int *len)
64 {
65  int query_location = *location;
66  int query_len = *len;
67 
68  /* First apply starting offset, unless it's -1 (unknown). */
69  if (query_location >= 0)
70  {
71  Assert(query_location <= strlen(query));
72  query += query_location;
73  /* Length of 0 (or -1) means "rest of string" */
74  if (query_len <= 0)
75  query_len = strlen(query);
76  else
77  Assert(query_len <= strlen(query));
78  }
79  else
80  {
81  /* If query location is unknown, distrust query_len as well */
82  query_location = 0;
83  query_len = strlen(query);
84  }
85 
86  /*
87  * Discard leading and trailing whitespace, too. Use scanner_isspace()
88  * not libc's isspace(), because we want to match the lexer's behavior.
89  */
90  while (query_len > 0 && scanner_isspace(query[0]))
91  query++, query_location++, query_len--;
92  while (query_len > 0 && scanner_isspace(query[query_len - 1]))
93  query_len--;
94 
95  *location = query_location;
96  *len = query_len;
97 
98  return query;
99 }
100 
101 JumbleState *
102 JumbleQuery(Query *query, const char *querytext)
103 {
104  JumbleState *jstate = NULL;
105 
107 
108  if (query->utilityStmt)
109  {
110  query->queryId = compute_utility_query_id(querytext,
111  query->stmt_location,
112  query->stmt_len);
113  }
114  else
115  {
116  jstate = (JumbleState *) palloc(sizeof(JumbleState));
117 
118  /* Set up workspace for query jumbling */
119  jstate->jumble = (unsigned char *) palloc(JUMBLE_SIZE);
120  jstate->jumble_len = 0;
121  jstate->clocations_buf_size = 32;
122  jstate->clocations = (LocationLen *)
123  palloc(jstate->clocations_buf_size * sizeof(LocationLen));
124  jstate->clocations_count = 0;
125  jstate->highest_extern_param_id = 0;
126 
127  /* Compute query ID and mark the Query node with it */
128  JumbleQueryInternal(jstate, query);
129  query->queryId = DatumGetUInt64(hash_any_extended(jstate->jumble,
130  jstate->jumble_len,
131  0));
132 
133  /*
134  * If we are unlucky enough to get a hash of zero, use 1 instead, to
135  * prevent confusion with the utility-statement case.
136  */
137  if (query->queryId == UINT64CONST(0))
138  query->queryId = UINT64CONST(1);
139  }
140 
141  return jstate;
142 }
143 
144 /*
145  * Enables query identifier computation.
146  *
147  * Third-party plugins can use this function to inform core that they require
148  * a query identifier to be computed.
149  */
150 void
152 {
154  query_id_enabled = true;
155 }
156 
157 /*
158  * Compute a query identifier for the given utility query string.
159  */
160 static uint64
161 compute_utility_query_id(const char *query_text, int query_location, int query_len)
162 {
163  uint64 queryId;
164  const char *sql;
165 
166  /*
167  * Confine our attention to the relevant part of the string, if the query
168  * is a portion of a multi-statement source string.
169  */
170  sql = CleanQuerytext(query_text, &query_location, &query_len);
171 
172  queryId = DatumGetUInt64(hash_any_extended((const unsigned char *) sql,
173  query_len, 0));
174 
175  /*
176  * If we are unlucky enough to get a hash of zero(invalid), use queryID as
177  * 2 instead, queryID 1 is already in use for normal statements.
178  */
179  if (queryId == UINT64CONST(0))
180  queryId = UINT64CONST(2);
181 
182  return queryId;
183 }
184 
185 /*
186  * AppendJumble: Append a value that is substantive in a given query to
187  * the current jumble.
188  */
189 static void
190 AppendJumble(JumbleState *jstate, const unsigned char *item, Size size)
191 {
192  unsigned char *jumble = jstate->jumble;
193  Size jumble_len = jstate->jumble_len;
194 
195  /*
196  * Whenever the jumble buffer is full, we hash the current contents and
197  * reset the buffer to contain just that hash value, thus relying on the
198  * hash to summarize everything so far.
199  */
200  while (size > 0)
201  {
202  Size part_size;
203 
204  if (jumble_len >= JUMBLE_SIZE)
205  {
206  uint64 start_hash;
207 
208  start_hash = DatumGetUInt64(hash_any_extended(jumble,
209  JUMBLE_SIZE, 0));
210  memcpy(jumble, &start_hash, sizeof(start_hash));
211  jumble_len = sizeof(start_hash);
212  }
213  part_size = Min(size, JUMBLE_SIZE - jumble_len);
214  memcpy(jumble + jumble_len, item, part_size);
215  jumble_len += part_size;
216  item += part_size;
217  size -= part_size;
218  }
219  jstate->jumble_len = jumble_len;
220 }
221 
222 /*
223  * Wrappers around AppendJumble to encapsulate details of serialization
224  * of individual local variable elements.
225  */
226 #define APP_JUMB(item) \
227  AppendJumble(jstate, (const unsigned char *) &(item), sizeof(item))
228 #define APP_JUMB_STRING(str) \
229  AppendJumble(jstate, (const unsigned char *) (str), strlen(str) + 1)
230 
231 /*
232  * JumbleQueryInternal: Selectively serialize the query tree, appending
233  * significant data to the "query jumble" while ignoring nonsignificant data.
234  *
235  * Rule of thumb for what to include is that we should ignore anything not
236  * semantically significant (such as alias names) as well as anything that can
237  * be deduced from child nodes (else we'd just be double-hashing that piece
238  * of information).
239  */
240 static void
242 {
243  Assert(IsA(query, Query));
244  Assert(query->utilityStmt == NULL);
245 
246  APP_JUMB(query->commandType);
247  /* resultRelation is usually predictable from commandType */
248  JumbleExpr(jstate, (Node *) query->cteList);
249  JumbleRangeTable(jstate, query->rtable);
250  JumbleExpr(jstate, (Node *) query->jointree);
251  JumbleExpr(jstate, (Node *) query->mergeActionList);
252  JumbleExpr(jstate, (Node *) query->targetList);
253  JumbleExpr(jstate, (Node *) query->onConflict);
254  JumbleExpr(jstate, (Node *) query->returningList);
255  JumbleExpr(jstate, (Node *) query->groupClause);
256  APP_JUMB(query->groupDistinct);
257  JumbleExpr(jstate, (Node *) query->groupingSets);
258  JumbleExpr(jstate, query->havingQual);
259  JumbleExpr(jstate, (Node *) query->windowClause);
260  JumbleExpr(jstate, (Node *) query->distinctClause);
261  JumbleExpr(jstate, (Node *) query->sortClause);
262  JumbleExpr(jstate, query->limitOffset);
263  JumbleExpr(jstate, query->limitCount);
264  APP_JUMB(query->limitOption);
265  JumbleRowMarks(jstate, query->rowMarks);
266  JumbleExpr(jstate, query->setOperations);
267 }
268 
269 /*
270  * Jumble a range table
271  */
272 static void
274 {
275  ListCell *lc;
276 
277  foreach(lc, rtable)
278  {
280 
281  APP_JUMB(rte->rtekind);
282  switch (rte->rtekind)
283  {
284  case RTE_RELATION:
285  APP_JUMB(rte->relid);
286  JumbleExpr(jstate, (Node *) rte->tablesample);
287  APP_JUMB(rte->inh);
288  break;
289  case RTE_SUBQUERY:
290  JumbleQueryInternal(jstate, rte->subquery);
291  break;
292  case RTE_JOIN:
293  APP_JUMB(rte->jointype);
294  break;
295  case RTE_FUNCTION:
296  JumbleExpr(jstate, (Node *) rte->functions);
297  break;
298  case RTE_TABLEFUNC:
299  JumbleExpr(jstate, (Node *) rte->tablefunc);
300  break;
301  case RTE_VALUES:
302  JumbleExpr(jstate, (Node *) rte->values_lists);
303  break;
304  case RTE_CTE:
305 
306  /*
307  * Depending on the CTE name here isn't ideal, but it's the
308  * only info we have to identify the referenced WITH item.
309  */
310  APP_JUMB_STRING(rte->ctename);
311  APP_JUMB(rte->ctelevelsup);
312  break;
313  case RTE_NAMEDTUPLESTORE:
314  APP_JUMB_STRING(rte->enrname);
315  break;
316  case RTE_RESULT:
317  break;
318  default:
319  elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
320  break;
321  }
322  }
323 }
324 
325 /*
326  * Jumble a rowMarks list
327  */
328 static void
329 JumbleRowMarks(JumbleState *jstate, List *rowMarks)
330 {
331  ListCell *lc;
332 
333  foreach(lc, rowMarks)
334  {
335  RowMarkClause *rowmark = lfirst_node(RowMarkClause, lc);
336 
337  if (!rowmark->pushedDown)
338  {
339  APP_JUMB(rowmark->rti);
340  APP_JUMB(rowmark->strength);
341  APP_JUMB(rowmark->waitPolicy);
342  }
343  }
344 }
345 
346 /*
347  * Jumble an expression tree
348  *
349  * In general this function should handle all the same node types that
350  * expression_tree_walker() does, and therefore it's coded to be as parallel
351  * to that function as possible. However, since we are only invoked on
352  * queries immediately post-parse-analysis, we need not handle node types
353  * that only appear in planning.
354  *
355  * Note: the reason we don't simply use expression_tree_walker() is that the
356  * point of that function is to support tree walkers that don't care about
357  * most tree node types, but here we care about all types. We should complain
358  * about any unrecognized node type.
359  */
360 static void
361 JumbleExpr(JumbleState *jstate, Node *node)
362 {
363  ListCell *temp;
364 
365  if (node == NULL)
366  return;
367 
368  /* Guard against stack overflow due to overly complex expressions */
370 
371  /*
372  * We always emit the node's NodeTag, then any additional fields that are
373  * considered significant, and then we recurse to any child nodes.
374  */
375  APP_JUMB(node->type);
376 
377  switch (nodeTag(node))
378  {
379  case T_Var:
380  {
381  Var *var = (Var *) node;
382 
383  APP_JUMB(var->varno);
384  APP_JUMB(var->varattno);
385  APP_JUMB(var->varlevelsup);
386  }
387  break;
388  case T_Const:
389  {
390  Const *c = (Const *) node;
391 
392  /* We jumble only the constant's type, not its value */
393  APP_JUMB(c->consttype);
394  /* Also, record its parse location for query normalization */
395  RecordConstLocation(jstate, c->location);
396  }
397  break;
398  case T_Param:
399  {
400  Param *p = (Param *) node;
401 
402  APP_JUMB(p->paramkind);
403  APP_JUMB(p->paramid);
404  APP_JUMB(p->paramtype);
405  /* Also, track the highest external Param id */
406  if (p->paramkind == PARAM_EXTERN &&
407  p->paramid > jstate->highest_extern_param_id)
408  jstate->highest_extern_param_id = p->paramid;
409  }
410  break;
411  case T_Aggref:
412  {
413  Aggref *expr = (Aggref *) node;
414 
415  APP_JUMB(expr->aggfnoid);
416  JumbleExpr(jstate, (Node *) expr->aggdirectargs);
417  JumbleExpr(jstate, (Node *) expr->args);
418  JumbleExpr(jstate, (Node *) expr->aggorder);
419  JumbleExpr(jstate, (Node *) expr->aggdistinct);
420  JumbleExpr(jstate, (Node *) expr->aggfilter);
421  }
422  break;
423  case T_GroupingFunc:
424  {
425  GroupingFunc *grpnode = (GroupingFunc *) node;
426 
427  JumbleExpr(jstate, (Node *) grpnode->refs);
428  APP_JUMB(grpnode->agglevelsup);
429  }
430  break;
431  case T_WindowFunc:
432  {
433  WindowFunc *expr = (WindowFunc *) node;
434 
435  APP_JUMB(expr->winfnoid);
436  APP_JUMB(expr->winref);
437  JumbleExpr(jstate, (Node *) expr->args);
438  JumbleExpr(jstate, (Node *) expr->aggfilter);
439  }
440  break;
441  case T_SubscriptingRef:
442  {
443  SubscriptingRef *sbsref = (SubscriptingRef *) node;
444 
445  JumbleExpr(jstate, (Node *) sbsref->refupperindexpr);
446  JumbleExpr(jstate, (Node *) sbsref->reflowerindexpr);
447  JumbleExpr(jstate, (Node *) sbsref->refexpr);
448  JumbleExpr(jstate, (Node *) sbsref->refassgnexpr);
449  }
450  break;
451  case T_FuncExpr:
452  {
453  FuncExpr *expr = (FuncExpr *) node;
454 
455  APP_JUMB(expr->funcid);
456  JumbleExpr(jstate, (Node *) expr->args);
457  }
458  break;
459  case T_NamedArgExpr:
460  {
461  NamedArgExpr *nae = (NamedArgExpr *) node;
462 
463  APP_JUMB(nae->argnumber);
464  JumbleExpr(jstate, (Node *) nae->arg);
465  }
466  break;
467  case T_OpExpr:
468  case T_DistinctExpr: /* struct-equivalent to OpExpr */
469  case T_NullIfExpr: /* struct-equivalent to OpExpr */
470  {
471  OpExpr *expr = (OpExpr *) node;
472 
473  APP_JUMB(expr->opno);
474  JumbleExpr(jstate, (Node *) expr->args);
475  }
476  break;
477  case T_ScalarArrayOpExpr:
478  {
479  ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
480 
481  APP_JUMB(expr->opno);
482  APP_JUMB(expr->useOr);
483  JumbleExpr(jstate, (Node *) expr->args);
484  }
485  break;
486  case T_BoolExpr:
487  {
488  BoolExpr *expr = (BoolExpr *) node;
489 
490  APP_JUMB(expr->boolop);
491  JumbleExpr(jstate, (Node *) expr->args);
492  }
493  break;
494  case T_SubLink:
495  {
496  SubLink *sublink = (SubLink *) node;
497 
498  APP_JUMB(sublink->subLinkType);
499  APP_JUMB(sublink->subLinkId);
500  JumbleExpr(jstate, (Node *) sublink->testexpr);
501  JumbleQueryInternal(jstate, castNode(Query, sublink->subselect));
502  }
503  break;
504  case T_FieldSelect:
505  {
506  FieldSelect *fs = (FieldSelect *) node;
507 
508  APP_JUMB(fs->fieldnum);
509  JumbleExpr(jstate, (Node *) fs->arg);
510  }
511  break;
512  case T_FieldStore:
513  {
514  FieldStore *fstore = (FieldStore *) node;
515 
516  JumbleExpr(jstate, (Node *) fstore->arg);
517  JumbleExpr(jstate, (Node *) fstore->newvals);
518  }
519  break;
520  case T_RelabelType:
521  {
522  RelabelType *rt = (RelabelType *) node;
523 
524  APP_JUMB(rt->resulttype);
525  JumbleExpr(jstate, (Node *) rt->arg);
526  }
527  break;
528  case T_CoerceViaIO:
529  {
530  CoerceViaIO *cio = (CoerceViaIO *) node;
531 
532  APP_JUMB(cio->resulttype);
533  JumbleExpr(jstate, (Node *) cio->arg);
534  }
535  break;
536  case T_ArrayCoerceExpr:
537  {
538  ArrayCoerceExpr *acexpr = (ArrayCoerceExpr *) node;
539 
540  APP_JUMB(acexpr->resulttype);
541  JumbleExpr(jstate, (Node *) acexpr->arg);
542  JumbleExpr(jstate, (Node *) acexpr->elemexpr);
543  }
544  break;
545  case T_ConvertRowtypeExpr:
546  {
547  ConvertRowtypeExpr *crexpr = (ConvertRowtypeExpr *) node;
548 
549  APP_JUMB(crexpr->resulttype);
550  JumbleExpr(jstate, (Node *) crexpr->arg);
551  }
552  break;
553  case T_CollateExpr:
554  {
555  CollateExpr *ce = (CollateExpr *) node;
556 
557  APP_JUMB(ce->collOid);
558  JumbleExpr(jstate, (Node *) ce->arg);
559  }
560  break;
561  case T_CaseExpr:
562  {
563  CaseExpr *caseexpr = (CaseExpr *) node;
564 
565  JumbleExpr(jstate, (Node *) caseexpr->arg);
566  foreach(temp, caseexpr->args)
567  {
568  CaseWhen *when = lfirst_node(CaseWhen, temp);
569 
570  JumbleExpr(jstate, (Node *) when->expr);
571  JumbleExpr(jstate, (Node *) when->result);
572  }
573  JumbleExpr(jstate, (Node *) caseexpr->defresult);
574  }
575  break;
576  case T_CaseTestExpr:
577  {
578  CaseTestExpr *ct = (CaseTestExpr *) node;
579 
580  APP_JUMB(ct->typeId);
581  }
582  break;
583  case T_ArrayExpr:
584  JumbleExpr(jstate, (Node *) ((ArrayExpr *) node)->elements);
585  break;
586  case T_RowExpr:
587  JumbleExpr(jstate, (Node *) ((RowExpr *) node)->args);
588  break;
589  case T_RowCompareExpr:
590  {
591  RowCompareExpr *rcexpr = (RowCompareExpr *) node;
592 
593  APP_JUMB(rcexpr->rctype);
594  JumbleExpr(jstate, (Node *) rcexpr->largs);
595  JumbleExpr(jstate, (Node *) rcexpr->rargs);
596  }
597  break;
598  case T_CoalesceExpr:
599  JumbleExpr(jstate, (Node *) ((CoalesceExpr *) node)->args);
600  break;
601  case T_MinMaxExpr:
602  {
603  MinMaxExpr *mmexpr = (MinMaxExpr *) node;
604 
605  APP_JUMB(mmexpr->op);
606  JumbleExpr(jstate, (Node *) mmexpr->args);
607  }
608  break;
609  case T_XmlExpr:
610  {
611  XmlExpr *xexpr = (XmlExpr *) node;
612 
613  APP_JUMB(xexpr->op);
614  JumbleExpr(jstate, (Node *) xexpr->named_args);
615  JumbleExpr(jstate, (Node *) xexpr->args);
616  }
617  break;
618  case T_NullTest:
619  {
620  NullTest *nt = (NullTest *) node;
621 
622  APP_JUMB(nt->nulltesttype);
623  JumbleExpr(jstate, (Node *) nt->arg);
624  }
625  break;
626  case T_BooleanTest:
627  {
628  BooleanTest *bt = (BooleanTest *) node;
629 
630  APP_JUMB(bt->booltesttype);
631  JumbleExpr(jstate, (Node *) bt->arg);
632  }
633  break;
634  case T_CoerceToDomain:
635  {
636  CoerceToDomain *cd = (CoerceToDomain *) node;
637 
638  APP_JUMB(cd->resulttype);
639  JumbleExpr(jstate, (Node *) cd->arg);
640  }
641  break;
642  case T_CoerceToDomainValue:
643  {
645 
646  APP_JUMB(cdv->typeId);
647  }
648  break;
649  case T_SetToDefault:
650  {
651  SetToDefault *sd = (SetToDefault *) node;
652 
653  APP_JUMB(sd->typeId);
654  }
655  break;
656  case T_CurrentOfExpr:
657  {
658  CurrentOfExpr *ce = (CurrentOfExpr *) node;
659 
660  APP_JUMB(ce->cvarno);
661  if (ce->cursor_name)
663  APP_JUMB(ce->cursor_param);
664  }
665  break;
666  case T_NextValueExpr:
667  {
668  NextValueExpr *nve = (NextValueExpr *) node;
669 
670  APP_JUMB(nve->seqid);
671  APP_JUMB(nve->typeId);
672  }
673  break;
674  case T_InferenceElem:
675  {
676  InferenceElem *ie = (InferenceElem *) node;
677 
678  APP_JUMB(ie->infercollid);
679  APP_JUMB(ie->inferopclass);
680  JumbleExpr(jstate, ie->expr);
681  }
682  break;
683  case T_TargetEntry:
684  {
685  TargetEntry *tle = (TargetEntry *) node;
686 
687  APP_JUMB(tle->resno);
689  JumbleExpr(jstate, (Node *) tle->expr);
690  }
691  break;
692  case T_RangeTblRef:
693  {
694  RangeTblRef *rtr = (RangeTblRef *) node;
695 
696  APP_JUMB(rtr->rtindex);
697  }
698  break;
699  case T_JoinExpr:
700  {
701  JoinExpr *join = (JoinExpr *) node;
702 
703  APP_JUMB(join->jointype);
704  APP_JUMB(join->isNatural);
705  APP_JUMB(join->rtindex);
706  JumbleExpr(jstate, join->larg);
707  JumbleExpr(jstate, join->rarg);
708  JumbleExpr(jstate, join->quals);
709  }
710  break;
711  case T_FromExpr:
712  {
713  FromExpr *from = (FromExpr *) node;
714 
715  JumbleExpr(jstate, (Node *) from->fromlist);
716  JumbleExpr(jstate, from->quals);
717  }
718  break;
719  case T_OnConflictExpr:
720  {
721  OnConflictExpr *conf = (OnConflictExpr *) node;
722 
723  APP_JUMB(conf->action);
724  JumbleExpr(jstate, (Node *) conf->arbiterElems);
725  JumbleExpr(jstate, conf->arbiterWhere);
726  JumbleExpr(jstate, (Node *) conf->onConflictSet);
727  JumbleExpr(jstate, conf->onConflictWhere);
728  APP_JUMB(conf->constraint);
729  APP_JUMB(conf->exclRelIndex);
730  JumbleExpr(jstate, (Node *) conf->exclRelTlist);
731  }
732  break;
733  case T_MergeAction:
734  {
735  MergeAction *mergeaction = (MergeAction *) node;
736 
737  APP_JUMB(mergeaction->matched);
738  APP_JUMB(mergeaction->commandType);
739  JumbleExpr(jstate, mergeaction->qual);
740  JumbleExpr(jstate, (Node *) mergeaction->targetList);
741  }
742  break;
743  case T_List:
744  foreach(temp, (List *) node)
745  {
746  JumbleExpr(jstate, (Node *) lfirst(temp));
747  }
748  break;
749  case T_IntList:
750  foreach(temp, (List *) node)
751  {
752  APP_JUMB(lfirst_int(temp));
753  }
754  break;
755  case T_SortGroupClause:
756  {
757  SortGroupClause *sgc = (SortGroupClause *) node;
758 
760  APP_JUMB(sgc->eqop);
761  APP_JUMB(sgc->sortop);
762  APP_JUMB(sgc->nulls_first);
763  }
764  break;
765  case T_GroupingSet:
766  {
767  GroupingSet *gsnode = (GroupingSet *) node;
768 
769  JumbleExpr(jstate, (Node *) gsnode->content);
770  }
771  break;
772  case T_WindowClause:
773  {
774  WindowClause *wc = (WindowClause *) node;
775 
776  APP_JUMB(wc->winref);
777  APP_JUMB(wc->frameOptions);
778  JumbleExpr(jstate, (Node *) wc->partitionClause);
779  JumbleExpr(jstate, (Node *) wc->orderClause);
780  JumbleExpr(jstate, wc->startOffset);
781  JumbleExpr(jstate, wc->endOffset);
782  }
783  break;
784  case T_CommonTableExpr:
785  {
786  CommonTableExpr *cte = (CommonTableExpr *) node;
787 
788  /* we store the string name because RTE_CTE RTEs need it */
789  APP_JUMB_STRING(cte->ctename);
791  JumbleQueryInternal(jstate, castNode(Query, cte->ctequery));
792  }
793  break;
794  case T_SetOperationStmt:
795  {
796  SetOperationStmt *setop = (SetOperationStmt *) node;
797 
798  APP_JUMB(setop->op);
799  APP_JUMB(setop->all);
800  JumbleExpr(jstate, setop->larg);
801  JumbleExpr(jstate, setop->rarg);
802  }
803  break;
804  case T_RangeTblFunction:
805  {
806  RangeTblFunction *rtfunc = (RangeTblFunction *) node;
807 
808  JumbleExpr(jstate, rtfunc->funcexpr);
809  }
810  break;
811  case T_TableFunc:
812  {
813  TableFunc *tablefunc = (TableFunc *) node;
814 
815  JumbleExpr(jstate, tablefunc->docexpr);
816  JumbleExpr(jstate, tablefunc->rowexpr);
817  JumbleExpr(jstate, (Node *) tablefunc->colexprs);
818  }
819  break;
820  case T_TableSampleClause:
821  {
822  TableSampleClause *tsc = (TableSampleClause *) node;
823 
824  APP_JUMB(tsc->tsmhandler);
825  JumbleExpr(jstate, (Node *) tsc->args);
826  JumbleExpr(jstate, (Node *) tsc->repeatable);
827  }
828  break;
829  default:
830  /* Only a warning, since we can stumble along anyway */
831  elog(WARNING, "unrecognized node type: %d",
832  (int) nodeTag(node));
833  break;
834  }
835 }
836 
837 /*
838  * Record location of constant within query string of query tree
839  * that is currently being walked.
840  */
841 static void
842 RecordConstLocation(JumbleState *jstate, int location)
843 {
844  /* -1 indicates unknown or undefined location */
845  if (location >= 0)
846  {
847  /* enlarge array if needed */
848  if (jstate->clocations_count >= jstate->clocations_buf_size)
849  {
850  jstate->clocations_buf_size *= 2;
851  jstate->clocations = (LocationLen *)
852  repalloc(jstate->clocations,
853  jstate->clocations_buf_size *
854  sizeof(LocationLen));
855  }
856  jstate->clocations[jstate->clocations_count].location = location;
857  /* initialize lengths to -1 to simplify third-party module usage */
858  jstate->clocations[jstate->clocations_count].length = -1;
859  jstate->clocations_count++;
860  }
861 }
#define Min(x, y)
Definition: c.h:937
size_t Size
Definition: c.h:541
#define WARNING
Definition: elog.h:32
#define ERROR
Definition: elog.h:35
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:1321
void * palloc(Size size)
Definition: mcxt.c:1199
#define IsA(nodeptr, _type_)
Definition: nodes.h:168
#define nodeTag(nodeptr)
Definition: nodes.h:122
#define castNode(_type_, nodeptr)
Definition: nodes.h:186
@ RTE_JOIN
Definition: parsenodes.h:984
@ RTE_CTE
Definition: parsenodes.h:988
@ RTE_NAMEDTUPLESTORE
Definition: parsenodes.h:989
@ RTE_VALUES
Definition: parsenodes.h:987
@ RTE_SUBQUERY
Definition: parsenodes.h:983
@ RTE_RESULT
Definition: parsenodes.h:990
@ RTE_FUNCTION
Definition: parsenodes.h:985
@ RTE_TABLEFUNC
Definition: parsenodes.h:986
@ RTE_RELATION
Definition: parsenodes.h:982
const void size_t len
#define lfirst(lc)
Definition: pg_list.h:170
#define lfirst_node(type, lc)
Definition: pg_list.h:174
#define lfirst_int(lc)
Definition: pg_list.h:171
void check_stack_depth(void)
Definition: postgres.c:3440
static uint64 DatumGetUInt64(Datum X)
Definition: postgres.h:767
char * c
@ PARAM_EXTERN
Definition: primnodes.h:302
JumbleState * JumbleQuery(Query *query, const char *querytext)
Definition: queryjumble.c:102
bool query_id_enabled
Definition: queryjumble.c:46
static void AppendJumble(JumbleState *jstate, const unsigned char *item, Size size)
Definition: queryjumble.c:190
#define JUMBLE_SIZE
Definition: queryjumble.c:40
int compute_query_id
Definition: queryjumble.c:43
#define APP_JUMB(item)
Definition: queryjumble.c:226
static void RecordConstLocation(JumbleState *jstate, int location)
Definition: queryjumble.c:842
#define APP_JUMB_STRING(str)
Definition: queryjumble.c:228
static uint64 compute_utility_query_id(const char *query_text, int query_location, int query_len)
Definition: queryjumble.c:161
const char * CleanQuerytext(const char *query, int *location, int *len)
Definition: queryjumble.c:63
static void JumbleRangeTable(JumbleState *jstate, List *rtable)
Definition: queryjumble.c:273
void EnableQueryId(void)
Definition: queryjumble.c:151
static void JumbleRowMarks(JumbleState *jstate, List *rowMarks)
Definition: queryjumble.c:329
static void JumbleQueryInternal(JumbleState *jstate, Query *query)
Definition: queryjumble.c:241
static void JumbleExpr(JumbleState *jstate, Node *node)
Definition: queryjumble.c:361
@ COMPUTE_QUERY_ID_AUTO
Definition: queryjumble.h:58
@ COMPUTE_QUERY_ID_OFF
Definition: queryjumble.h:56
static bool IsQueryIdEnabled(void)
Definition: queryjumble.h:77
bool scanner_isspace(char ch)
Definition: scansup.c:117
Oid aggfnoid
Definition: primnodes.h:373
List * aggdistinct
Definition: primnodes.h:403
List * aggdirectargs
Definition: primnodes.h:394
List * args
Definition: primnodes.h:397
Expr * aggfilter
Definition: primnodes.h:406
List * aggorder
Definition: primnodes.h:400
BoolExprType boolop
Definition: primnodes.h:766
List * args
Definition: primnodes.h:767
BoolTestType booltesttype
Definition: primnodes.h:1389
Expr * arg
Definition: primnodes.h:1388
Expr * arg
Definition: primnodes.h:1119
Expr * defresult
Definition: primnodes.h:1121
List * args
Definition: primnodes.h:1120
Expr * arg
Definition: primnodes.h:1021
Oid resulttype
Definition: primnodes.h:1022
Expr * arg
Definition: primnodes.h:1087
CTEMaterialize ctematerialized
Definition: parsenodes.h:1566
char * cursor_name
Definition: primnodes.h:1464
AttrNumber fieldnum
Definition: primnodes.h:950
Expr * arg
Definition: primnodes.h:949
List * newvals
Definition: primnodes.h:979
Expr * arg
Definition: primnodes.h:978
Node * quals
Definition: primnodes.h:1665
List * fromlist
Definition: primnodes.h:1664
Oid funcid
Definition: primnodes.h:598
List * args
Definition: primnodes.h:606
Index agglevelsup
Definition: primnodes.h:477
List * content
Definition: parsenodes.h:1416
Node * quals
Definition: primnodes.h:1647
JoinType jointype
Definition: primnodes.h:1641
int rtindex
Definition: primnodes.h:1649
Node * larg
Definition: primnodes.h:1643
bool isNatural
Definition: primnodes.h:1642
Node * rarg
Definition: primnodes.h:1644
unsigned char * jumble
Definition: queryjumble.h:35
int clocations_buf_size
Definition: queryjumble.h:44
Size jumble_len
Definition: queryjumble.h:38
int highest_extern_param_id
Definition: queryjumble.h:50
LocationLen * clocations
Definition: queryjumble.h:41
int clocations_count
Definition: queryjumble.h:47
Definition: pg_list.h:52
Node * qual
Definition: parsenodes.h:1617
CmdType commandType
Definition: parsenodes.h:1615
List * targetList
Definition: parsenodes.h:1618
List * args
Definition: primnodes.h:1291
MinMaxOp op
Definition: primnodes.h:1290
Expr * arg
Definition: primnodes.h:627
Definition: nodes.h:118
NodeTag type
Definition: nodes.h:119
NullTestType nulltesttype
Definition: primnodes.h:1366
Expr * arg
Definition: primnodes.h:1365
List * arbiterElems
Definition: primnodes.h:1683
OnConflictAction action
Definition: primnodes.h:1680
List * onConflictSet
Definition: primnodes.h:1689
List * exclRelTlist
Definition: primnodes.h:1692
Node * onConflictWhere
Definition: primnodes.h:1690
Node * arbiterWhere
Definition: primnodes.h:1685
Oid opno
Definition: primnodes.h:648
List * args
Definition: primnodes.h:666
int paramid
Definition: primnodes.h:312
Oid paramtype
Definition: primnodes.h:313
ParamKind paramkind
Definition: primnodes.h:311
List * rowMarks
Definition: parsenodes.h:189
bool groupDistinct
Definition: parsenodes.h:173
Node * limitCount
Definition: parsenodes.h:186
int stmt_location
Definition: parsenodes.h:206
FromExpr * jointree
Definition: parsenodes.h:158
List * returningList
Definition: parsenodes.h:170
Node * setOperations
Definition: parsenodes.h:191
List * cteList
Definition: parsenodes.h:153
OnConflictExpr * onConflict
Definition: parsenodes.h:168
List * groupClause
Definition: parsenodes.h:172
int stmt_len
Definition: parsenodes.h:207
Node * havingQual
Definition: parsenodes.h:177
List * rtable
Definition: parsenodes.h:155
Node * limitOffset
Definition: parsenodes.h:185
CmdType commandType
Definition: parsenodes.h:124
LimitOption limitOption
Definition: parsenodes.h:187
Node * utilityStmt
Definition: parsenodes.h:136
List * mergeActionList
Definition: parsenodes.h:161
List * windowClause
Definition: parsenodes.h:179
List * targetList
Definition: parsenodes.h:164
List * groupingSets
Definition: parsenodes.h:175
List * distinctClause
Definition: parsenodes.h:181
List * sortClause
Definition: parsenodes.h:183
char * ctename
Definition: parsenodes.h:1116
TableFunc * tablefunc
Definition: parsenodes.h:1106
Index ctelevelsup
Definition: parsenodes.h:1117
struct TableSampleClause * tablesample
Definition: parsenodes.h:1035
Query * subquery
Definition: parsenodes.h:1041
List * values_lists
Definition: parsenodes.h:1111
char * enrname
Definition: parsenodes.h:1145
JoinType jointype
Definition: parsenodes.h:1079
List * functions
Definition: parsenodes.h:1100
RTEKind rtekind
Definition: parsenodes.h:1001
Oid resulttype
Definition: primnodes.h:1002
Expr * arg
Definition: primnodes.h:1001
RowCompareType rctype
Definition: primnodes.h:1255
LockClauseStrength strength
Definition: parsenodes.h:1473
LockWaitPolicy waitPolicy
Definition: parsenodes.h:1474
SetOperation op
Definition: parsenodes.h:1822
Index tleSortGroupRef
Definition: parsenodes.h:1346
Expr * refassgnexpr
Definition: primnodes.h:554
List * refupperindexpr
Definition: primnodes.h:547
Expr * refexpr
Definition: primnodes.h:552
List * reflowerindexpr
Definition: primnodes.h:549
Node * docexpr
Definition: primnodes.h:103
Node * rowexpr
Definition: primnodes.h:104
List * colexprs
Definition: primnodes.h:109
Expr * expr
Definition: primnodes.h:1555
AttrNumber resno
Definition: primnodes.h:1556
Index ressortgroupref
Definition: primnodes.h:1558
Definition: primnodes.h:205
AttrNumber varattno
Definition: primnodes.h:217
int varno
Definition: primnodes.h:212
Index varlevelsup
Definition: primnodes.h:230
Node * startOffset
Definition: parsenodes.h:1445
List * partitionClause
Definition: parsenodes.h:1442
Node * endOffset
Definition: parsenodes.h:1446
List * orderClause
Definition: parsenodes.h:1443
List * args
Definition: primnodes.h:493
Index winref
Definition: primnodes.h:495
Expr * aggfilter
Definition: primnodes.h:494
Oid winfnoid
Definition: primnodes.h:489
List * args
Definition: primnodes.h:1331
List * named_args
Definition: primnodes.h:1329
XmlExprOp op
Definition: primnodes.h:1327
Definition: type.h:88