PostgreSQL Source Code  git master
queryjumble.c File Reference
#include "postgres.h"
#include "common/hashfn.h"
#include "miscadmin.h"
#include "parser/scansup.h"
#include "utils/queryjumble.h"
Include dependency graph for queryjumble.c:

Go to the source code of this file.

Macros

#define JUMBLE_SIZE   1024 /* query serialization buffer size */
 
#define APP_JUMB(item)   AppendJumble(jstate, (const unsigned char *) &(item), sizeof(item))
 
#define APP_JUMB_STRING(str)   AppendJumble(jstate, (const unsigned char *) (str), strlen(str) + 1)
 

Functions

static uint64 compute_utility_query_id (const char *str, int query_location, int query_len)
 
static void AppendJumble (JumbleState *jstate, const unsigned char *item, Size size)
 
static void JumbleQueryInternal (JumbleState *jstate, Query *query)
 
static void JumbleRangeTable (JumbleState *jstate, List *rtable)
 
static void JumbleRowMarks (JumbleState *jstate, List *rowMarks)
 
static void JumbleExpr (JumbleState *jstate, Node *node)
 
static void RecordConstLocation (JumbleState *jstate, int location)
 
const char * CleanQuerytext (const char *query, int *location, int *len)
 
JumbleStateJumbleQuery (Query *query, const char *querytext)
 
void EnableQueryId (void)
 

Variables

int compute_query_id = COMPUTE_QUERY_ID_AUTO
 
bool query_id_enabled = false
 

Macro Definition Documentation

◆ APP_JUMB

#define APP_JUMB (   item)    AppendJumble(jstate, (const unsigned char *) &(item), sizeof(item))

Definition at line 225 of file queryjumble.c.

Referenced by JumbleExpr(), JumbleQueryInternal(), JumbleRangeTable(), and JumbleRowMarks().

◆ APP_JUMB_STRING

#define APP_JUMB_STRING (   str)    AppendJumble(jstate, (const unsigned char *) (str), strlen(str) + 1)

Definition at line 227 of file queryjumble.c.

Referenced by JumbleExpr(), and JumbleRangeTable().

◆ JUMBLE_SIZE

#define JUMBLE_SIZE   1024 /* query serialization buffer size */

Definition at line 40 of file queryjumble.c.

Referenced by AppendJumble(), and JumbleQuery().

Function Documentation

◆ AppendJumble()

static void AppendJumble ( JumbleState jstate,
const unsigned char *  item,
Size  size 
)
static

Definition at line 189 of file queryjumble.c.

References DatumGetUInt64, hash_any_extended(), JumbleState::jumble, JumbleState::jumble_len, JUMBLE_SIZE, and Min.

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 }
Size jumble_len
Definition: queryjumble.h:40
#define Min(x, y)
Definition: c.h:986
static Datum hash_any_extended(const unsigned char *k, int keylen, uint64 seed)
Definition: hashfn.h:37
#define DatumGetUInt64(X)
Definition: postgres.h:678
unsigned char * jumble
Definition: queryjumble.h:37
size_t Size
Definition: c.h:540
#define JUMBLE_SIZE
Definition: queryjumble.c:40

◆ CleanQuerytext()

const char* CleanQuerytext ( const char *  query,
int *  location,
int *  len 
)

Definition at line 62 of file queryjumble.c.

References Assert, and scanner_isspace().

Referenced by compute_utility_query_id(), and pgss_store().

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 }
bool scanner_isspace(char ch)
Definition: scansup.c:117
#define Assert(condition)
Definition: c.h:804

◆ compute_utility_query_id()

static uint64 compute_utility_query_id ( const char *  str,
int  query_location,
int  query_len 
)
static

Definition at line 160 of file queryjumble.c.

References CleanQuerytext(), DatumGetUInt64, and hash_any_extended().

Referenced by JumbleQuery().

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 }
static Datum hash_any_extended(const unsigned char *k, int keylen, uint64 seed)
Definition: hashfn.h:37
#define DatumGetUInt64(X)
Definition: postgres.h:678
const char * CleanQuerytext(const char *query, int *location, int *len)
Definition: queryjumble.c:62

◆ EnableQueryId()

void EnableQueryId ( void  )

Definition at line 150 of file queryjumble.c.

References compute_query_id, COMPUTE_QUERY_ID_OFF, and query_id_enabled.

Referenced by _PG_init().

151 {
153  query_id_enabled = true;
154 }
int compute_query_id
Definition: queryjumble.c:43
bool query_id_enabled
Definition: queryjumble.c:46

◆ JumbleExpr()

static void JumbleExpr ( JumbleState jstate,
Node node 
)
static

Definition at line 359 of file queryjumble.c.

References OnConflictExpr::action, Aggref::aggdirectargs, Aggref::aggdistinct, Aggref::aggfilter, WindowFunc::aggfilter, Aggref::aggfnoid, GroupingFunc::agglevelsup, Aggref::aggorder, SetOperationStmt::all, APP_JUMB, APP_JUMB_STRING, OnConflictExpr::arbiterElems, OnConflictExpr::arbiterWhere, NamedArgExpr::arg, FieldSelect::arg, FieldStore::arg, RelabelType::arg, CoerceViaIO::arg, ArrayCoerceExpr::arg, ConvertRowtypeExpr::arg, CollateExpr::arg, CaseExpr::arg, NullTest::arg, BooleanTest::arg, CoerceToDomain::arg, NamedArgExpr::argnumber, generate_unaccent_rules::args, Aggref::args, WindowFunc::args, FuncExpr::args, OpExpr::args, ScalarArrayOpExpr::args, BoolExpr::args, CaseExpr::args, MinMaxExpr::args, TableSampleClause::args, XmlExpr::args, BoolExpr::boolop, BooleanTest::booltesttype, castNode, check_stack_depth(), TableFunc::colexprs, CollateExpr::collOid, OnConflictExpr::constraint, Const::consttype, GroupingSet::content, CommonTableExpr::ctematerialized, CommonTableExpr::ctename, CommonTableExpr::ctequery, CurrentOfExpr::cursor_name, CurrentOfExpr::cursor_param, CurrentOfExpr::cvarno, CaseExpr::defresult, TableFunc::docexpr, ArrayCoerceExpr::elemexpr, elog, WindowClause::endOffset, SortGroupClause::eqop, OnConflictExpr::exclRelIndex, OnConflictExpr::exclRelTlist, CaseWhen::expr, InferenceElem::expr, TargetEntry::expr, FieldSelect::fieldnum, WindowClause::frameOptions, FromExpr::fromlist, RangeTblFunction::funcexpr, FuncExpr::funcid, JumbleState::highest_extern_param_id, InferenceElem::infercollid, InferenceElem::inferopclass, JoinExpr::isNatural, JoinExpr::jointype, JumbleQueryInternal(), JoinExpr::larg, SetOperationStmt::larg, RowCompareExpr::largs, lfirst, lfirst_int, lfirst_node, Const::location, XmlExpr::named_args, FieldStore::newvals, nodeTag, SortGroupClause::nulls_first, NullTest::nulltesttype, OnConflictExpr::onConflictSet, OnConflictExpr::onConflictWhere, MinMaxExpr::op, SQLValueFunction::op, XmlExpr::op, SetOperationStmt::op, OpExpr::opno, ScalarArrayOpExpr::opno, WindowClause::orderClause, PARAM_EXTERN, Param::paramid, Param::paramkind, Param::paramtype, WindowClause::partitionClause, JoinExpr::quals, FromExpr::quals, JoinExpr::rarg, SetOperationStmt::rarg, RowCompareExpr::rargs, RowCompareExpr::rctype, RecordConstLocation(), SubscriptingRef::refassgnexpr, SubscriptingRef::refexpr, SubscriptingRef::reflowerindexpr, GroupingFunc::refs, SubscriptingRef::refupperindexpr, TableSampleClause::repeatable, TargetEntry::resno, TargetEntry::ressortgroupref, CaseWhen::result, RelabelType::resulttype, CoerceViaIO::resulttype, ArrayCoerceExpr::resulttype, ConvertRowtypeExpr::resulttype, CoerceToDomain::resulttype, TableFunc::rowexpr, RangeTblRef::rtindex, JoinExpr::rtindex, NextValueExpr::seqid, SortGroupClause::sortop, WindowClause::startOffset, SubLink::subLinkId, SubLink::subLinkType, SubLink::subselect, T_Aggref, T_ArrayCoerceExpr, T_ArrayExpr, T_BooleanTest, T_BoolExpr, T_CaseExpr, T_CaseTestExpr, T_CoalesceExpr, T_CoerceToDomain, T_CoerceToDomainValue, T_CoerceViaIO, T_CollateExpr, T_CommonTableExpr, T_Const, T_ConvertRowtypeExpr, T_CurrentOfExpr, T_DistinctExpr, T_FieldSelect, T_FieldStore, T_FromExpr, T_FuncExpr, T_GroupingFunc, T_GroupingSet, T_InferenceElem, T_IntList, T_JoinExpr, T_List, T_MinMaxExpr, T_NamedArgExpr, T_NextValueExpr, T_NullIfExpr, T_NullTest, T_OnConflictExpr, T_OpExpr, T_Param, T_RangeTblFunction, T_RangeTblRef, T_RelabelType, T_RowCompareExpr, T_RowExpr, T_ScalarArrayOpExpr, T_SetOperationStmt, T_SetToDefault, T_SortGroupClause, T_SQLValueFunction, T_SubLink, T_SubscriptingRef, T_TableFunc, T_TableSampleClause, T_TargetEntry, T_Var, T_WindowClause, T_WindowFunc, T_XmlExpr, SubLink::testexpr, SortGroupClause::tleSortGroupRef, TableSampleClause::tsmhandler, Node::type, CaseTestExpr::typeId, CoerceToDomainValue::typeId, SetToDefault::typeId, NextValueExpr::typeId, SQLValueFunction::typmod, ScalarArrayOpExpr::useOr, Var::varattno, Var::varlevelsup, Var::varno, WARNING, WindowFunc::winfnoid, WindowFunc::winref, and WindowClause::winref.

Referenced by JumbleQueryInternal(), and JumbleRangeTable().

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 }
List * aggdistinct
Definition: primnodes.h:332
List * args
Definition: primnodes.h:1152
Node * docexpr
Definition: primnodes.h:87
Expr * arg
Definition: primnodes.h:837
Index varlevelsup
Definition: primnodes.h:196
List * content
Definition: parsenodes.h:1353
List * refs
Definition: primnodes.h:374
List * args
Definition: primnodes.h:390
List * args
Definition: primnodes.h:503
#define castNode(_type_, nodeptr)
Definition: nodes.h:608
#define APP_JUMB(item)
Definition: queryjumble.c:225
Oid resulttype
Definition: primnodes.h:881
RowCompareType rctype
Definition: primnodes.h:1116
Index tleSortGroupRef
Definition: parsenodes.h:1283
Expr * arg
Definition: primnodes.h:860
ParamKind paramkind
Definition: primnodes.h:267
Definition: nodes.h:539
List * args
Definition: primnodes.h:330
AttrNumber varattno
Definition: primnodes.h:191
Expr * arg
Definition: primnodes.h:808
List * fromlist
Definition: primnodes.h:1563
Index winref
Definition: primnodes.h:392
Definition: primnodes.h:186
List * refupperindexpr
Definition: primnodes.h:444
Node * quals
Definition: primnodes.h:1564
SQLValueFunctionOp op
Definition: primnodes.h:1189
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
Oid funcid
Definition: primnodes.h:495
#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
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
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
Definition: nodes.h:305
List * newvals
Definition: primnodes.h:838
Definition: nodes.h:158
OnConflictAction action
Definition: primnodes.h:1579
bool isNatural
Definition: primnodes.h:1541
#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
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
List * args
Definition: primnodes.h:1231
Node * rarg
Definition: primnodes.h:1543
Expr * arg
Definition: primnodes.h:524
JoinType jointype
Definition: primnodes.h:1540
#define lfirst(lc)
Definition: pg_list.h:169
CTEMaterialize ctematerialized
Definition: parsenodes.h:1502
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
Node * endOffset
Definition: parsenodes.h:1383
Expr * arg
Definition: primnodes.h:946
Expr * aggfilter
Definition: primnodes.h:333
SetOperation op
Definition: parsenodes.h:1711
List * args
Definition: primnodes.h:626
#define nodeTag(nodeptr)
Definition: nodes.h:544
List * orderClause
Definition: parsenodes.h:1380
Node * arbiterWhere
Definition: primnodes.h:1584
Expr * refassgnexpr
Definition: primnodes.h:451
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
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
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
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

◆ JumbleQuery()

JumbleState* JumbleQuery ( Query query,
const char *  querytext 
)

Definition at line 101 of file queryjumble.c.

References Assert, JumbleState::clocations, JumbleState::clocations_buf_size, JumbleState::clocations_count, compute_utility_query_id(), DatumGetUInt64, hash_any_extended(), JumbleState::highest_extern_param_id, IsQueryIdEnabled(), JumbleState::jumble, JumbleState::jumble_len, JUMBLE_SIZE, JumbleQueryInternal(), palloc(), Query::queryId, Query::stmt_len, Query::stmt_location, and Query::utilityStmt.

Referenced by ExplainQuery(), parse_analyze(), parse_analyze_varparams(), and pg_analyze_and_rewrite_params().

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 }
Size jumble_len
Definition: queryjumble.h:40
static bool IsQueryIdEnabled(void)
Definition: queryjumble.h:78
int stmt_location
Definition: parsenodes.h:192
static uint64 compute_utility_query_id(const char *str, int query_location, int query_len)
Definition: queryjumble.c:160
int clocations_buf_size
Definition: queryjumble.h:46
Node * utilityStmt
Definition: parsenodes.h:128
static Datum hash_any_extended(const unsigned char *k, int keylen, uint64 seed)
Definition: hashfn.h:37
int clocations_count
Definition: queryjumble.h:49
int highest_extern_param_id
Definition: queryjumble.h:52
static void JumbleQueryInternal(JumbleState *jstate, Query *query)
Definition: queryjumble.c:240
uint64 queryId
Definition: parsenodes.h:124
#define DatumGetUInt64(X)
Definition: postgres.h:678
unsigned char * jumble
Definition: queryjumble.h:37
#define Assert(condition)
Definition: c.h:804
LocationLen * clocations
Definition: queryjumble.h:43
void * palloc(Size size)
Definition: mcxt.c:1062
int stmt_len
Definition: parsenodes.h:193
#define JUMBLE_SIZE
Definition: queryjumble.c:40

◆ JumbleQueryInternal()

static void JumbleQueryInternal ( JumbleState jstate,
Query query 
)
static

Definition at line 240 of file queryjumble.c.

References APP_JUMB, Assert, Query::commandType, Query::cteList, Query::distinctClause, Query::groupClause, Query::groupDistinct, Query::groupingSets, Query::havingQual, IsA, Query::jointree, JumbleExpr(), JumbleRangeTable(), JumbleRowMarks(), Query::limitCount, Query::limitOffset, Query::limitOption, Query::onConflict, Query::returningList, Query::rowMarks, Query::rtable, Query::setOperations, Query::sortClause, Query::targetList, Query::utilityStmt, and Query::windowClause.

Referenced by JumbleExpr(), JumbleQuery(), and JumbleRangeTable().

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 }
Node * limitOffset
Definition: parsenodes.h:171
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
static void JumbleRangeTable(JumbleState *jstate, List *rtable)
Definition: queryjumble.c:271
List * sortClause
Definition: parsenodes.h:169
FromExpr * jointree
Definition: parsenodes.h:148
OnConflictExpr * onConflict
Definition: parsenodes.h:154
#define APP_JUMB(item)
Definition: queryjumble.c:225
bool groupDistinct
Definition: parsenodes.h:159
List * groupingSets
Definition: parsenodes.h:161
Definition: nodes.h:539
static void JumbleRowMarks(JumbleState *jstate, List *rowMarks)
Definition: queryjumble.c:327
List * rowMarks
Definition: parsenodes.h:175
Node * utilityStmt
Definition: parsenodes.h:128
List * windowClause
Definition: parsenodes.h:165
List * targetList
Definition: parsenodes.h:150
List * rtable
Definition: parsenodes.h:147
List * distinctClause
Definition: parsenodes.h:167
Node * limitCount
Definition: parsenodes.h:172
List * returningList
Definition: parsenodes.h:156
LimitOption limitOption
Definition: parsenodes.h:173
CmdType commandType
Definition: parsenodes.h:120
#define Assert(condition)
Definition: c.h:804
static void JumbleExpr(JumbleState *jstate, Node *node)
Definition: queryjumble.c:359
List * cteList
Definition: parsenodes.h:145
Node * setOperations
Definition: parsenodes.h:177
List * groupClause
Definition: parsenodes.h:158
Node * havingQual
Definition: parsenodes.h:163

◆ JumbleRangeTable()

static void JumbleRangeTable ( JumbleState jstate,
List rtable 
)
static

Definition at line 271 of file queryjumble.c.

References APP_JUMB, APP_JUMB_STRING, RangeTblEntry::ctelevelsup, RangeTblEntry::ctename, elog, RangeTblEntry::enrname, ERROR, RangeTblEntry::functions, RangeTblEntry::inh, RangeTblEntry::jointype, JumbleExpr(), JumbleQueryInternal(), lfirst_node, RangeTblEntry::relid, RTE_CTE, RTE_FUNCTION, RTE_JOIN, RTE_NAMEDTUPLESTORE, RTE_RELATION, RTE_RESULT, RTE_SUBQUERY, RTE_TABLEFUNC, RTE_VALUES, RangeTblEntry::rtekind, RangeTblEntry::subquery, RangeTblEntry::tablefunc, RangeTblEntry::tablesample, and RangeTblEntry::values_lists.

Referenced by JumbleQueryInternal().

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 }
#define APP_JUMB(item)
Definition: queryjumble.c:225
Definition: nodes.h:539
List * values_lists
Definition: parsenodes.h:1100
#define APP_JUMB_STRING(str)
Definition: queryjumble.c:227
#define ERROR
Definition: elog.h:46
TableFunc * tablefunc
Definition: parsenodes.h:1095
#define lfirst_node(type, lc)
Definition: pg_list.h:172
static void JumbleQueryInternal(JumbleState *jstate, Query *query)
Definition: queryjumble.c:240
JoinType jointype
Definition: parsenodes.h:1068
char * enrname
Definition: parsenodes.h:1134
List * functions
Definition: parsenodes.h:1089
static void JumbleExpr(JumbleState *jstate, Node *node)
Definition: queryjumble.c:359
Index ctelevelsup
Definition: parsenodes.h:1106
RTEKind rtekind
Definition: parsenodes.h:995
char * ctename
Definition: parsenodes.h:1105
Query * subquery
Definition: parsenodes.h:1030
#define elog(elevel,...)
Definition: elog.h:232
struct TableSampleClause * tablesample
Definition: parsenodes.h:1025

◆ JumbleRowMarks()

static void JumbleRowMarks ( JumbleState jstate,
List rowMarks 
)
static

Definition at line 327 of file queryjumble.c.

References APP_JUMB, lfirst_node, RowMarkClause::pushedDown, RowMarkClause::rti, RowMarkClause::strength, and RowMarkClause::waitPolicy.

Referenced by JumbleQueryInternal().

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 }
#define APP_JUMB(item)
Definition: queryjumble.c:225
LockClauseStrength strength
Definition: parsenodes.h:1409
#define lfirst_node(type, lc)
Definition: pg_list.h:172
LockWaitPolicy waitPolicy
Definition: parsenodes.h:1410

◆ RecordConstLocation()

static void RecordConstLocation ( JumbleState jstate,
int  location 
)
static

Definition at line 839 of file queryjumble.c.

References JumbleState::clocations, JumbleState::clocations_buf_size, JumbleState::clocations_count, LocationLen::length, LocationLen::location, and repalloc().

Referenced by JumbleExpr().

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 }
int clocations_buf_size
Definition: queryjumble.h:46
int clocations_count
Definition: queryjumble.h:49
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
LocationLen * clocations
Definition: queryjumble.h:43

Variable Documentation

◆ compute_query_id

int compute_query_id = COMPUTE_QUERY_ID_AUTO

Definition at line 43 of file queryjumble.c.

Referenced by EnableQueryId(), and IsQueryIdEnabled().

◆ query_id_enabled

bool query_id_enabled = false

Definition at line 46 of file queryjumble.c.

Referenced by EnableQueryId(), IsQueryIdEnabled(), and PostmasterMarkPIDForWorkerNotify().