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-2021, 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_List:
741  foreach(temp, (List *) node)
742  {
743  JumbleExpr(jstate, (Node *) lfirst(temp));
744  }
745  break;
746  case T_IntList:
747  foreach(temp, (List *) node)
748  {
749  APP_JUMB(lfirst_int(temp));
750  }
751  break;
752  case T_SortGroupClause:
753  {
754  SortGroupClause *sgc = (SortGroupClause *) node;
755 
757  APP_JUMB(sgc->eqop);
758  APP_JUMB(sgc->sortop);
759  APP_JUMB(sgc->nulls_first);
760  }
761  break;
762  case T_GroupingSet:
763  {
764  GroupingSet *gsnode = (GroupingSet *) node;
765 
766  JumbleExpr(jstate, (Node *) gsnode->content);
767  }
768  break;
769  case T_WindowClause:
770  {
771  WindowClause *wc = (WindowClause *) node;
772 
773  APP_JUMB(wc->winref);
774  APP_JUMB(wc->frameOptions);
775  JumbleExpr(jstate, (Node *) wc->partitionClause);
776  JumbleExpr(jstate, (Node *) wc->orderClause);
777  JumbleExpr(jstate, wc->startOffset);
778  JumbleExpr(jstate, wc->endOffset);
779  }
780  break;
781  case T_CommonTableExpr:
782  {
783  CommonTableExpr *cte = (CommonTableExpr *) node;
784 
785  /* we store the string name because RTE_CTE RTEs need it */
786  APP_JUMB_STRING(cte->ctename);
788  JumbleQueryInternal(jstate, castNode(Query, cte->ctequery));
789  }
790  break;
791  case T_SetOperationStmt:
792  {
793  SetOperationStmt *setop = (SetOperationStmt *) node;
794 
795  APP_JUMB(setop->op);
796  APP_JUMB(setop->all);
797  JumbleExpr(jstate, setop->larg);
798  JumbleExpr(jstate, setop->rarg);
799  }
800  break;
801  case T_RangeTblFunction:
802  {
803  RangeTblFunction *rtfunc = (RangeTblFunction *) node;
804 
805  JumbleExpr(jstate, rtfunc->funcexpr);
806  }
807  break;
808  case T_TableFunc:
809  {
810  TableFunc *tablefunc = (TableFunc *) node;
811 
812  JumbleExpr(jstate, tablefunc->docexpr);
813  JumbleExpr(jstate, tablefunc->rowexpr);
814  JumbleExpr(jstate, (Node *) tablefunc->colexprs);
815  }
816  break;
817  case T_TableSampleClause:
818  {
819  TableSampleClause *tsc = (TableSampleClause *) node;
820 
821  APP_JUMB(tsc->tsmhandler);
822  JumbleExpr(jstate, (Node *) tsc->args);
823  JumbleExpr(jstate, (Node *) tsc->repeatable);
824  }
825  break;
826  default:
827  /* Only a warning, since we can stumble along anyway */
828  elog(WARNING, "unrecognized node type: %d",
829  (int) nodeTag(node));
830  break;
831  }
832 }
833 
834 /*
835  * Record location of constant within query string of query tree
836  * that is currently being walked.
837  */
838 static void
839 RecordConstLocation(JumbleState *jstate, int location)
840 {
841  /* -1 indicates unknown or undefined location */
842  if (location >= 0)
843  {
844  /* enlarge array if needed */
845  if (jstate->clocations_count >= jstate->clocations_buf_size)
846  {
847  jstate->clocations_buf_size *= 2;
848  jstate->clocations = (LocationLen *)
849  repalloc(jstate->clocations,
850  jstate->clocations_buf_size *
851  sizeof(LocationLen));
852  }
853  jstate->clocations[jstate->clocations_count].location = location;
854  /* initialize lengths to -1 to simplify third-party module usage */
855  jstate->clocations[jstate->clocations_count].length = -1;
856  jstate->clocations_count++;
857  }
858 }
Size jumble_len
Definition: queryjumble.h:40
List * aggdistinct
Definition: primnodes.h:332
Node * limitOffset
Definition: parsenodes.h:171
List * args
Definition: primnodes.h:1152
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
Node * docexpr
Definition: primnodes.h:87
static void JumbleRangeTable(JumbleState *jstate, List *rtable)
Definition: queryjumble.c:271
static bool IsQueryIdEnabled(void)
Definition: queryjumble.h:78
Expr * arg
Definition: primnodes.h:837
Index varlevelsup
Definition: primnodes.h:196
int stmt_location
Definition: parsenodes.h:192
List * sortClause
Definition: parsenodes.h:169
List * content
Definition: parsenodes.h:1353
List * refs
Definition: primnodes.h:374
List * args
Definition: primnodes.h:390
List * args
Definition: primnodes.h:503
FromExpr * jointree
Definition: parsenodes.h:148
OnConflictExpr * onConflict
Definition: parsenodes.h:154
#define castNode(_type_, nodeptr)
Definition: nodes.h:608
#define APP_JUMB(item)
Definition: queryjumble.c:225
Oid resulttype
Definition: primnodes.h:881
static uint64 compute_utility_query_id(const char *str, int query_location, int query_len)
Definition: queryjumble.c:160
RowCompareType rctype
Definition: primnodes.h:1116
#define Min(x, y)
Definition: c.h:986
bool groupDistinct
Definition: parsenodes.h:159
static void AppendJumble(JumbleState *jstate, const unsigned char *item, Size size)
Definition: queryjumble.c:189
Index tleSortGroupRef
Definition: parsenodes.h:1283
Expr * arg
Definition: primnodes.h:860
List * groupingSets
Definition: parsenodes.h:161
ParamKind paramkind
Definition: primnodes.h:267
Definition: nodes.h:539
int clocations_buf_size
Definition: queryjumble.h:46
List * args
Definition: primnodes.h:330
static void JumbleRowMarks(JumbleState *jstate, List *rowMarks)
Definition: queryjumble.c:327
AttrNumber varattno
Definition: primnodes.h:191
Expr * arg
Definition: primnodes.h:808
List * fromlist
Definition: primnodes.h:1563
List * rowMarks
Definition: parsenodes.h:175
Index winref
Definition: primnodes.h:392
Node * utilityStmt
Definition: parsenodes.h:128
Definition: primnodes.h:186
static Datum hash_any_extended(const unsigned char *k, int keylen, uint64 seed)
Definition: hashfn.h:37
List * refupperindexpr
Definition: primnodes.h:444
List * values_lists
Definition: parsenodes.h:1100
Node * quals
Definition: primnodes.h:1564
SQLValueFunctionOp op
Definition: primnodes.h:1189
LockClauseStrength strength
Definition: parsenodes.h:1409
int clocations_count
Definition: queryjumble.h:49
List * windowClause
Definition: parsenodes.h:165
List * targetList
Definition: parsenodes.h:150
int compute_query_id
Definition: queryjumble.c:43
List * arbiterElems
Definition: primnodes.h:1582
Node * larg
Definition: primnodes.h:1542
Oid consttype
Definition: primnodes.h:215
#define APP_JUMB_STRING(str)
Definition: queryjumble.c:227
List * rtable
Definition: parsenodes.h:147
List * distinctClause
Definition: parsenodes.h:167
Oid funcid
Definition: primnodes.h:495
#define ERROR
Definition: elog.h:46
TableFunc * tablefunc
Definition: parsenodes.h:1095
#define lfirst_int(lc)
Definition: pg_list.h:170
List * partitionClause
Definition: parsenodes.h:1379
BoolExprType boolop
Definition: primnodes.h:625
int highest_extern_param_id
Definition: queryjumble.h:52
Expr * arg
Definition: primnodes.h:1265
#define lfirst_node(type, lc)
Definition: pg_list.h:172
Node * rowexpr
Definition: primnodes.h:88
Node * limitCount
Definition: parsenodes.h:172
char * c
NodeTag type
Definition: nodes.h:541
static void JumbleQueryInternal(JumbleState *jstate, Query *query)
Definition: queryjumble.c:240
List * exclRelTlist
Definition: primnodes.h:1591
void check_stack_depth(void)
Definition: postgres.c:3469
JoinType jointype
Definition: parsenodes.h:1068
List * aggorder
Definition: primnodes.h:331
Expr * arg
Definition: primnodes.h:1288
AttrNumber resno
Definition: primnodes.h:1455
char * cursor_name
Definition: primnodes.h:1363
List * aggdirectargs
Definition: primnodes.h:329
Oid winfnoid
Definition: primnodes.h:386
Expr * arg
Definition: primnodes.h:880
Expr * elemexpr
Definition: primnodes.h:905
Definition: type.h:82
List * returningList
Definition: parsenodes.h:156
bool query_id_enabled
Definition: queryjumble.c:46
char * enrname
Definition: parsenodes.h:1134
Definition: nodes.h:305
List * newvals
Definition: primnodes.h:838
Definition: nodes.h:158
OnConflictAction action
Definition: primnodes.h:1579
LimitOption limitOption
Definition: parsenodes.h:173
bool isNatural
Definition: primnodes.h:1541
uint64 queryId
Definition: parsenodes.h:124
#define WARNING
Definition: elog.h:40
Index varno
Definition: primnodes.h:189
Definition: nodes.h:157
XmlExprOp op
Definition: primnodes.h:1227
Node * startOffset
Definition: parsenodes.h:1382
List * args
Definition: primnodes.h:979
int location
Definition: primnodes.h:226
Node * quals
Definition: primnodes.h:1546
BoolTestType booltesttype
Definition: primnodes.h:1289
Index agglevelsup
Definition: primnodes.h:376
bool scanner_isspace(char ch)
Definition: scansup.c:117
Oid resulttype
Definition: primnodes.h:861
NullTestType nulltesttype
Definition: primnodes.h:1266
Oid aggfnoid
Definition: primnodes.h:323
List * colexprs
Definition: primnodes.h:93
List * named_args
Definition: primnodes.h:1229
CmdType commandType
Definition: parsenodes.h:120
List * args
Definition: primnodes.h:1231
#define DatumGetUInt64(X)
Definition: postgres.h:678
Node * rarg
Definition: primnodes.h:1543
Expr * arg
Definition: primnodes.h:524
unsigned char * jumble
Definition: queryjumble.h:37
JoinType jointype
Definition: primnodes.h:1540
const char * CleanQuerytext(const char *query, int *location, int *len)
Definition: queryjumble.c:62
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
CTEMaterialize ctematerialized
Definition: parsenodes.h:1502
List * functions
Definition: parsenodes.h:1089
Expr * aggfilter
Definition: primnodes.h:391
static void JumbleExpr(JumbleState *jstate, Node *node)
Definition: queryjumble.c:359
Expr * expr
Definition: primnodes.h:1454
int paramid
Definition: primnodes.h:268
void EnableQueryId(void)
Definition: queryjumble.c:150
size_t Size
Definition: c.h:540
Node * endOffset
Definition: parsenodes.h:1383
Expr * arg
Definition: primnodes.h:946
Expr * aggfilter
Definition: primnodes.h:333
SetOperation op
Definition: parsenodes.h:1711
Index ctelevelsup
Definition: parsenodes.h:1106
LockWaitPolicy waitPolicy
Definition: parsenodes.h:1410
List * args
Definition: primnodes.h:626
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
#define nodeTag(nodeptr)
Definition: nodes.h:544
RTEKind rtekind
Definition: parsenodes.h:995
List * orderClause
Definition: parsenodes.h:1380
Node * arbiterWhere
Definition: primnodes.h:1584
Expr * refassgnexpr
Definition: primnodes.h:451
LocationLen * clocations
Definition: queryjumble.h:43
char * ctename
Definition: parsenodes.h:1105
List * cteList
Definition: parsenodes.h:145
Node * setOperations
Definition: parsenodes.h:177
Query * subquery
Definition: parsenodes.h:1030
List * groupClause
Definition: parsenodes.h:158
void * palloc(Size size)
Definition: mcxt.c:1062
List * reflowerindexpr
Definition: primnodes.h:446
#define elog(elevel,...)
Definition: elog.h:232
List * onConflictSet
Definition: primnodes.h:1588
Index ressortgroupref
Definition: primnodes.h:1457
JumbleState * JumbleQuery(Query *query, const char *querytext)
Definition: queryjumble.c:101
MinMaxOp op
Definition: primnodes.h:1151
Expr * refexpr
Definition: primnodes.h:449
Expr * arg
Definition: primnodes.h:978
Oid opno
Definition: primnodes.h:542
Expr * result
Definition: primnodes.h:991
List * args
Definition: primnodes.h:548
Node * havingQual
Definition: parsenodes.h:163
Expr * defresult
Definition: primnodes.h:980
Expr * expr
Definition: primnodes.h:990
Node * onConflictWhere
Definition: primnodes.h:1589
int rtindex
Definition: primnodes.h:1548
Definition: pg_list.h:50
struct TableSampleClause * tablesample
Definition: parsenodes.h:1025
int stmt_len
Definition: parsenodes.h:193
#define JUMBLE_SIZE
Definition: queryjumble.c:40
Oid paramtype
Definition: primnodes.h:269
static void RecordConstLocation(JumbleState *jstate, int location)
Definition: queryjumble.c:839
Definition: nodes.h:159
AttrNumber fieldnum
Definition: primnodes.h:809