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