PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
queryjumblefuncs.c File Reference
#include "postgres.h"
#include "common/hashfn.h"
#include "miscadmin.h"
#include "nodes/queryjumble.h"
#include "parser/scansup.h"
#include "queryjumblefuncs.funcs.c"
#include "queryjumblefuncs.switch.c"
Include dependency graph for queryjumblefuncs.c:

Go to the source code of this file.

Macros

#define JUMBLE_SIZE   1024 /* query serialization buffer size */
 
#define JUMBLE_NODE(item)    _jumbleNode(jstate, (Node *) expr->item)
 
#define JUMBLE_LOCATION(location)    RecordConstLocation(jstate, expr->location)
 
#define JUMBLE_FIELD(item)    AppendJumble(jstate, (const unsigned char *) &(expr->item), sizeof(expr->item))
 
#define JUMBLE_FIELD_SINGLE(item)    AppendJumble(jstate, (const unsigned char *) &(item), sizeof(item))
 
#define JUMBLE_STRING(str)
 

Functions

static void AppendJumble (JumbleState *jstate, const unsigned char *item, Size size)
 
static void RecordConstLocation (JumbleState *jstate, int location)
 
static void _jumbleNode (JumbleState *jstate, Node *node)
 
static void _jumbleA_Const (JumbleState *jstate, Node *node)
 
static void _jumbleList (JumbleState *jstate, Node *node)
 
static void _jumbleVariableSetStmt (JumbleState *jstate, Node *node)
 
const char * CleanQuerytext (const char *query, int *location, int *len)
 
JumbleStateJumbleQuery (Query *query)
 
void EnableQueryId (void)
 

Variables

int compute_query_id = COMPUTE_QUERY_ID_AUTO
 
bool query_id_enabled = false
 

Macro Definition Documentation

◆ JUMBLE_FIELD

#define JUMBLE_FIELD (   item)     AppendJumble(jstate, (const unsigned char *) &(expr->item), sizeof(expr->item))

Definition at line 230 of file queryjumblefuncs.c.

◆ JUMBLE_FIELD_SINGLE

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

Definition at line 232 of file queryjumblefuncs.c.

◆ JUMBLE_LOCATION

#define JUMBLE_LOCATION (   location)     RecordConstLocation(jstate, expr->location)

Definition at line 228 of file queryjumblefuncs.c.

◆ JUMBLE_NODE

#define JUMBLE_NODE (   item)     _jumbleNode(jstate, (Node *) expr->item)

Definition at line 226 of file queryjumblefuncs.c.

◆ JUMBLE_SIZE

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

Definition at line 40 of file queryjumblefuncs.c.

◆ JUMBLE_STRING

#define JUMBLE_STRING (   str)
Value:
do { \
if (expr->str) \
AppendJumble(jstate, (const unsigned char *) (expr->str), strlen(expr->str) + 1); \
} while(0)

Definition at line 234 of file queryjumblefuncs.c.

Function Documentation

◆ _jumbleA_Const()

static void _jumbleA_Const ( JumbleState jstate,
Node node 
)
static

Definition at line 330 of file queryjumblefuncs.c.

331 {
332  A_Const *expr = (A_Const *) node;
333 
334  JUMBLE_FIELD(isnull);
335  if (!expr->isnull)
336  {
337  JUMBLE_FIELD(val.node.type);
338  switch (nodeTag(&expr->val))
339  {
340  case T_Integer:
341  JUMBLE_FIELD(val.ival.ival);
342  break;
343  case T_Float:
344  JUMBLE_STRING(val.fval.fval);
345  break;
346  case T_Boolean:
347  JUMBLE_FIELD(val.boolval.boolval);
348  break;
349  case T_String:
350  JUMBLE_STRING(val.sval.sval);
351  break;
352  case T_BitString:
353  JUMBLE_STRING(val.bsval.bsval);
354  break;
355  default:
356  elog(ERROR, "unrecognized node type: %d",
357  (int) nodeTag(&expr->val));
358  break;
359  }
360  }
361 }
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
long val
Definition: informix.c:689
#define nodeTag(nodeptr)
Definition: nodes.h:133
#define JUMBLE_STRING(str)
#define JUMBLE_FIELD(item)
bool isnull
Definition: parsenodes.h:365
union ValUnion val
Definition: parsenodes.h:364

References elog, ERROR, A_Const::isnull, JUMBLE_FIELD, JUMBLE_STRING, nodeTag, A_Const::val, and val.

◆ _jumbleList()

static void _jumbleList ( JumbleState jstate,
Node node 
)
static

Definition at line 299 of file queryjumblefuncs.c.

300 {
301  List *expr = (List *) node;
302  ListCell *l;
303 
304  switch (expr->type)
305  {
306  case T_List:
307  foreach(l, expr)
308  _jumbleNode(jstate, lfirst(l));
309  break;
310  case T_IntList:
311  foreach(l, expr)
313  break;
314  case T_OidList:
315  foreach(l, expr)
317  break;
318  case T_XidList:
319  foreach(l, expr)
321  break;
322  default:
323  elog(ERROR, "unrecognized list node type: %d",
324  (int) expr->type);
325  return;
326  }
327 }
#define lfirst(lc)
Definition: pg_list.h:172
#define lfirst_int(lc)
Definition: pg_list.h:173
#define lfirst_oid(lc)
Definition: pg_list.h:174
#define lfirst_xid(lc)
Definition: pg_list.h:175
static void _jumbleNode(JumbleState *jstate, Node *node)
#define JUMBLE_FIELD_SINGLE(item)
Definition: pg_list.h:54
NodeTag type
Definition: pg_list.h:55

References _jumbleNode(), elog, ERROR, JUMBLE_FIELD_SINGLE, lfirst, lfirst_int, lfirst_oid, lfirst_xid, and List::type.

Referenced by _jumbleNode().

◆ _jumbleNode()

static void _jumbleNode ( JumbleState jstate,
Node node 
)
static

Definition at line 243 of file queryjumblefuncs.c.

244 {
245  Node *expr = node;
246 
247  if (expr == NULL)
248  return;
249 
250  /* Guard against stack overflow due to overly complex expressions */
252 
253  /*
254  * We always emit the node's NodeTag, then any additional fields that are
255  * considered significant, and then we recurse to any child nodes.
256  */
258 
259  switch (nodeTag(expr))
260  {
261 #include "queryjumblefuncs.switch.c"
262 
263  case T_List:
264  case T_IntList:
265  case T_OidList:
266  case T_XidList:
267  _jumbleList(jstate, expr);
268  break;
269 
270  default:
271  /* Only a warning, since we can stumble along anyway */
272  elog(WARNING, "unrecognized node type: %d",
273  (int) nodeTag(expr));
274  break;
275  }
276 
277  /* Special cases to handle outside the automated code */
278  switch (nodeTag(expr))
279  {
280  case T_Param:
281  {
282  Param *p = (Param *) node;
283 
284  /*
285  * Update the highest Param id seen, in order to start
286  * normalization correctly.
287  */
288  if (p->paramkind == PARAM_EXTERN &&
289  p->paramid > jstate->highest_extern_param_id)
290  jstate->highest_extern_param_id = p->paramid;
291  }
292  break;
293  default:
294  break;
295  }
296 }
#define WARNING
Definition: elog.h:36
void check_stack_depth(void)
Definition: postgres.c:3574
@ PARAM_EXTERN
Definition: primnodes.h:367
static void _jumbleList(JumbleState *jstate, Node *node)
int highest_extern_param_id
Definition: queryjumble.h:50
Definition: nodes.h:129
int paramid
Definition: primnodes.h:377
ParamKind paramkind
Definition: primnodes.h:376
const char * type

References _jumbleList(), check_stack_depth(), elog, JumbleState::highest_extern_param_id, JUMBLE_FIELD, nodeTag, PARAM_EXTERN, Param::paramid, Param::paramkind, type, and WARNING.

Referenced by _jumbleList(), and JumbleQuery().

◆ _jumbleVariableSetStmt()

static void _jumbleVariableSetStmt ( JumbleState jstate,
Node node 
)
static

Definition at line 364 of file queryjumblefuncs.c.

365 {
366  VariableSetStmt *expr = (VariableSetStmt *) node;
367 
368  JUMBLE_FIELD(kind);
370 
371  /*
372  * Account for the list of arguments in query jumbling only if told by the
373  * parser.
374  */
375  if (expr->jumble_args)
376  JUMBLE_NODE(args);
377  JUMBLE_FIELD(is_local);
378  JUMBLE_LOCATION(location);
379 }
#define JUMBLE_NODE(item)
#define JUMBLE_LOCATION(location)
const char * name

References generate_unaccent_rules::args, VariableSetStmt::jumble_args, JUMBLE_FIELD, JUMBLE_LOCATION, JUMBLE_NODE, JUMBLE_STRING, and name.

◆ AppendJumble()

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

Definition at line 168 of file queryjumblefuncs.c.

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 }
#define Min(x, y)
Definition: c.h:1009
size_t Size
Definition: c.h:610
static Datum hash_any_extended(const unsigned char *k, int keylen, uint64 seed)
Definition: hashfn.h:37
static uint64 DatumGetUInt64(Datum X)
Definition: postgres.h:419
#define JUMBLE_SIZE
static pg_noinline void Size size
Definition: slab.c:607
unsigned char * jumble
Definition: queryjumble.h:35
Size jumble_len
Definition: queryjumble.h:38

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

◆ CleanQuerytext()

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

Definition at line 67 of file queryjumblefuncs.c.

68 {
69  int query_location = *location;
70  int query_len = *len;
71 
72  /* First apply starting offset, unless it's -1 (unknown). */
73  if (query_location >= 0)
74  {
75  Assert(query_location <= strlen(query));
76  query += query_location;
77  /* Length of 0 (or -1) means "rest of string" */
78  if (query_len <= 0)
79  query_len = strlen(query);
80  else
81  Assert(query_len <= strlen(query));
82  }
83  else
84  {
85  /* If query location is unknown, distrust query_len as well */
86  query_location = 0;
87  query_len = strlen(query);
88  }
89 
90  /*
91  * Discard leading and trailing whitespace, too. Use scanner_isspace()
92  * not libc's isspace(), because we want to match the lexer's behavior.
93  *
94  * Note: the parser now strips leading comments and whitespace from the
95  * reported stmt_location, so this first loop will only iterate in the
96  * unusual case that the location didn't propagate to here. But the
97  * statement length will extend to the end-of-string or terminating
98  * semicolon, so the second loop often does something useful.
99  */
100  while (query_len > 0 && scanner_isspace(query[0]))
101  query++, query_location++, query_len--;
102  while (query_len > 0 && scanner_isspace(query[query_len - 1]))
103  query_len--;
104 
105  *location = query_location;
106  *len = query_len;
107 
108  return query;
109 }
#define Assert(condition)
Definition: c.h:863
const void size_t len
bool scanner_isspace(char ch)
Definition: scansup.c:117

References Assert, len, and scanner_isspace().

Referenced by pgss_store(), and script_error_callback().

◆ EnableQueryId()

void EnableQueryId ( void  )

Definition at line 157 of file queryjumblefuncs.c.

158 {
160  query_id_enabled = true;
161 }
@ COMPUTE_QUERY_ID_OFF
Definition: queryjumble.h:56
bool query_id_enabled
int compute_query_id

References compute_query_id, COMPUTE_QUERY_ID_OFF, and query_id_enabled.

Referenced by _PG_init().

◆ JumbleQuery()

JumbleState* JumbleQuery ( Query query)

Definition at line 112 of file queryjumblefuncs.c.

113 {
114  JumbleState *jstate = NULL;
115 
117 
118  jstate = (JumbleState *) palloc(sizeof(JumbleState));
119 
120  /* Set up workspace for query jumbling */
121  jstate->jumble = (unsigned char *) palloc(JUMBLE_SIZE);
122  jstate->jumble_len = 0;
123  jstate->clocations_buf_size = 32;
124  jstate->clocations = (LocationLen *)
125  palloc(jstate->clocations_buf_size * sizeof(LocationLen));
126  jstate->clocations_count = 0;
127  jstate->highest_extern_param_id = 0;
128 
129  /* Compute query ID and mark the Query node with it */
130  _jumbleNode(jstate, (Node *) query);
131  query->queryId = DatumGetUInt64(hash_any_extended(jstate->jumble,
132  jstate->jumble_len,
133  0));
134 
135  /*
136  * If we are unlucky enough to get a hash of zero, use 1 instead for
137  * normal statements and 2 for utility queries.
138  */
139  if (query->queryId == UINT64CONST(0))
140  {
141  if (query->utilityStmt)
142  query->queryId = UINT64CONST(2);
143  else
144  query->queryId = UINT64CONST(1);
145  }
146 
147  return jstate;
148 }
void * palloc(Size size)
Definition: mcxt.c:1317
static bool IsQueryIdEnabled(void)
Definition: queryjumble.h:77
int clocations_buf_size
Definition: queryjumble.h:44
LocationLen * clocations
Definition: queryjumble.h:41
int clocations_count
Definition: queryjumble.h:47
Node * utilityStmt
Definition: parsenodes.h:136

References _jumbleNode(), Assert, JumbleState::clocations, JumbleState::clocations_buf_size, JumbleState::clocations_count, DatumGetUInt64(), hash_any_extended(), JumbleState::highest_extern_param_id, IsQueryIdEnabled(), JumbleState::jumble, JumbleState::jumble_len, JUMBLE_SIZE, palloc(), and Query::utilityStmt.

Referenced by ExecCreateTableAs(), ExplainOneUtility(), ExplainQuery(), parse_analyze_fixedparams(), parse_analyze_varparams(), parse_analyze_withcb(), and PerformCursorOpen().

◆ RecordConstLocation()

static void RecordConstLocation ( JumbleState jstate,
int  location 
)
static

Definition at line 205 of file queryjumblefuncs.c.

206 {
207  /* -1 indicates unknown or undefined location */
208  if (location >= 0)
209  {
210  /* enlarge array if needed */
211  if (jstate->clocations_count >= jstate->clocations_buf_size)
212  {
213  jstate->clocations_buf_size *= 2;
214  jstate->clocations = (LocationLen *)
215  repalloc(jstate->clocations,
216  jstate->clocations_buf_size *
217  sizeof(LocationLen));
218  }
219  jstate->clocations[jstate->clocations_count].location = location;
220  /* initialize lengths to -1 to simplify third-party module usage */
221  jstate->clocations[jstate->clocations_count].length = -1;
222  jstate->clocations_count++;
223  }
224 }
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541

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

Variable Documentation

◆ compute_query_id

int compute_query_id = COMPUTE_QUERY_ID_AUTO

Definition at line 43 of file queryjumblefuncs.c.

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

◆ query_id_enabled

bool query_id_enabled = false

Definition at line 52 of file queryjumblefuncs.c.

Referenced by EnableQueryId(), and IsQueryIdEnabled().