PostgreSQL Source Code git master
Loading...
Searching...
No Matches
queryjumblefuncs.c File Reference
#include "postgres.h"
#include "access/transam.h"
#include "catalog/pg_proc.h"
#include "common/hashfn.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "nodes/queryjumble.h"
#include "utils/lsyscache.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_ELEMENTS(list, node)    _jumbleElements(jstate, (List *) expr->list, node)
 
#define JUMBLE_LOCATION(location)    RecordConstLocation(jstate, false, expr->location, -1)
 
#define JUMBLE_FIELD(item)
 
#define JUMBLE_STRING(str)
 
#define JUMBLE_CUSTOM(nodetype, item)    _jumble##nodetype##_##item(jstate, expr, expr->item)
 

Functions

static JumbleStateInitJumble (void)
 
static int64 DoJumble (JumbleState *jstate, Node *node)
 
static void AppendJumble (JumbleState *jstate, const unsigned char *value, Size size)
 
static void FlushPendingNulls (JumbleState *jstate)
 
static void RecordConstLocation (JumbleState *jstate, bool extern_param, int location, int len)
 
static void _jumbleNode (JumbleState *jstate, Node *node)
 
static void _jumbleList (JumbleState *jstate, Node *node)
 
static void _jumbleElements (JumbleState *jstate, List *elements, Node *node)
 
static void _jumbleParam (JumbleState *jstate, Node *node)
 
static void _jumbleA_Const (JumbleState *jstate, Node *node)
 
static void _jumbleVariableSetStmt (JumbleState *jstate, Node *node)
 
static void _jumbleRangeTblEntry_eref (JumbleState *jstate, RangeTblEntry *rte, Alias *expr)
 
const charCleanQuerytext (const char *query, int *location, int *len)
 
JumbleStateJumbleQuery (Query *query)
 
void EnableQueryId (void)
 
static pg_attribute_always_inline void AppendJumbleInternal (JumbleState *jstate, const unsigned char *item, Size size)
 
static pg_attribute_always_inline void AppendJumbleNull (JumbleState *jstate)
 
static pg_noinline void AppendJumble8 (JumbleState *jstate, const unsigned char *value)
 
static pg_noinline void AppendJumble16 (JumbleState *jstate, const unsigned char *value)
 
static pg_noinline void AppendJumble32 (JumbleState *jstate, const unsigned char *value)
 
static pg_noinline void AppendJumble64 (JumbleState *jstate, const unsigned char *value)
 
static bool IsSquashableConstant (Node *element)
 
static bool IsSquashableConstantList (List *elements)
 

Variables

int compute_query_id = COMPUTE_QUERY_ID_AUTO
 
bool query_id_enabled = false
 

Macro Definition Documentation

◆ JUMBLE_CUSTOM

#define JUMBLE_CUSTOM (   nodetype,
  item 
)     _jumble##nodetype##_##item(jstate, expr, expr->item)

Definition at line 555 of file queryjumblefuncs.c.

561{
562 Node *expr = node;
563#ifdef USE_ASSERT_CHECKING
564 Size prev_jumble_len = jstate->total_jumble_len;
565#endif
566
567 if (expr == NULL)
568 {
570 return;
571 }
572
573 /* Guard against stack overflow due to overly complex expressions */
575
576 /*
577 * We always emit the node's NodeTag, then any additional fields that are
578 * considered significant, and then we recurse to any child nodes.
579 */
581
582 switch (nodeTag(expr))
583 {
584#include "queryjumblefuncs.switch.c"
585
586 case T_List:
587 case T_IntList:
588 case T_OidList:
589 case T_XidList:
590 _jumbleList(jstate, expr);
591 break;
592
593 default:
594 /* Only a warning, since we can stumble along anyway */
595 elog(WARNING, "unrecognized node type: %d",
596 (int) nodeTag(expr));
597 break;
598 }
599
600 /* Ensure we added something to the jumble buffer */
601 Assert(jstate->total_jumble_len > prev_jumble_len);
602}
603
604static void
606{
607 List *expr = (List *) node;
608 ListCell *l;
609
610 switch (expr->type)
611 {
612 case T_List:
613 foreach(l, expr)
615 break;
616 case T_IntList:
617 foreach(l, expr)
618 AppendJumble32(jstate, (const unsigned char *) &lfirst_int(l));
619 break;
620 case T_OidList:
621 foreach(l, expr)
622 AppendJumble32(jstate, (const unsigned char *) &lfirst_oid(l));
623 break;
624 case T_XidList:
625 foreach(l, expr)
626 AppendJumble32(jstate, (const unsigned char *) &lfirst_xid(l));
627 break;
628 default:
629 elog(ERROR, "unrecognized list node type: %d",
630 (int) expr->type);
631 return;
632 }
633}
634
635/*
636 * We try to jumble lists of expressions as one individual item regardless
637 * of how many elements are in the list. This is know as squashing, which
638 * results in different queries jumbling to the same query_id, if the only
639 * difference is the number of elements in the list.
640 *
641 * We allow constants and PARAM_EXTERN parameters to be squashed. To normalize
642 * such queries, we use the start and end locations of the list of elements in
643 * a list.
644 */
645static void
646_jumbleElements(JumbleState *jstate, List *elements, Node *node)
647{
648 bool normalize_list = false;
649
650 if (IsSquashableConstantList(elements))
651 {
652 if (IsA(node, ArrayExpr))
653 {
654 ArrayExpr *aexpr = (ArrayExpr *) node;
655
656 if (aexpr->list_start > 0 && aexpr->list_end > 0)
657 {
659 false,
660 aexpr->list_start + 1,
661 (aexpr->list_end - aexpr->list_start) - 1);
662 normalize_list = true;
663 jstate->has_squashed_lists = true;
664 }
665 }
666 }
667
668 if (!normalize_list)
669 {
670 _jumbleNode(jstate, (Node *) elements);
671 }
672}
673
674/*
675 * We store the highest param ID of extern params. This can later be used
676 * to start the numbering of the placeholder for squashed lists.
677 */
678static void
680{
681 Param *expr = (Param *) node;
682
683 JUMBLE_FIELD(paramkind);
684 JUMBLE_FIELD(paramid);
685 JUMBLE_FIELD(paramtype);
686 /* paramtypmod and paramcollid are ignored */
687
688 if (expr->paramkind == PARAM_EXTERN)
689 {
690 /*
691 * At this point, only external parameter locations outside of
692 * squashable lists will be recorded.
693 */
694 RecordConstLocation(jstate, true, expr->location, -1);
695
696 /*
697 * Update the highest Param id seen, in order to start normalization
698 * correctly.
699 *
700 * Note: This value is reset at the end of jumbling if there exists a
701 * squashable list. See the comment in the definition of JumbleState.
702 */
703 if (expr->paramid > jstate->highest_extern_param_id)
704 jstate->highest_extern_param_id = expr->paramid;
705 }
706}
707
708static void
710{
711 A_Const *expr = (A_Const *) node;
712
713 JUMBLE_FIELD(isnull);
714 if (!expr->isnull)
715 {
716 JUMBLE_FIELD(val.node.type);
717 switch (nodeTag(&expr->val))
718 {
719 case T_Integer:
720 JUMBLE_FIELD(val.ival.ival);
721 break;
722 case T_Float:
723 JUMBLE_STRING(val.fval.fval);
724 break;
725 case T_Boolean:
726 JUMBLE_FIELD(val.boolval.boolval);
727 break;
728 case T_String:
729 JUMBLE_STRING(val.sval.sval);
730 break;
731 case T_BitString:
732 JUMBLE_STRING(val.bsval.bsval);
733 break;
734 default:
735 elog(ERROR, "unrecognized node type: %d",
736 (int) nodeTag(&expr->val));
737 break;
738 }
739 }
740}
741
742static void
744{
745 VariableSetStmt *expr = (VariableSetStmt *) node;
746
747 JUMBLE_FIELD(kind);
749
750 /*
751 * Account for the list of arguments in query jumbling only if told by the
752 * parser.
753 */
754 if (expr->jumble_args)
755 JUMBLE_NODE(args);
756 JUMBLE_FIELD(is_local);
757 JUMBLE_LOCATION(location);
758}
759
760/*
761 * Custom query jumble function for RangeTblEntry.eref.
762 */
763static void
766 Alias *expr)
767{
769
770 /*
771 * This includes only the table name, the list of column names is ignored.
772 */
773 JUMBLE_STRING(aliasname);
774}
#define Assert(condition)
Definition c.h:873
size_t Size
Definition c.h:619
#define WARNING
Definition elog.h:36
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
long val
Definition informix.c:689
#define IsA(nodeptr, _type_)
Definition nodes.h:164
#define nodeTag(nodeptr)
Definition nodes.h:139
#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 int fb(int x)
@ PARAM_EXTERN
Definition primnodes.h:384
#define JUMBLE_NODE(item)
static void _jumbleNode(JumbleState *jstate, Node *node)
static void _jumbleVariableSetStmt(JumbleState *jstate, Node *node)
static bool IsSquashableConstantList(List *elements)
static pg_attribute_always_inline void AppendJumbleNull(JumbleState *jstate)
#define JUMBLE_LOCATION(location)
static void _jumbleParam(JumbleState *jstate, Node *node)
static void _jumbleList(JumbleState *jstate, Node *node)
static void RecordConstLocation(JumbleState *jstate, bool extern_param, int location, int len)
#define JUMBLE_STRING(str)
static pg_noinline void AppendJumble32(JumbleState *jstate, const unsigned char *value)
static void _jumbleA_Const(JumbleState *jstate, Node *node)
static void _jumbleElements(JumbleState *jstate, List *elements, Node *node)
static void _jumbleRangeTblEntry_eref(JumbleState *jstate, RangeTblEntry *rte, Alias *expr)
#define JUMBLE_FIELD(item)
void check_stack_depth(void)
Definition stack_depth.c:95
bool isnull
Definition parsenodes.h:388
union ValUnion val
Definition parsenodes.h:387
Definition pg_list.h:54
NodeTag type
Definition pg_list.h:55
Definition nodes.h:135
ParseLoc location
Definition primnodes.h:403
int paramid
Definition primnodes.h:396
ParamKind paramkind
Definition primnodes.h:395
const char * type
const char * name

◆ JUMBLE_ELEMENTS

#define JUMBLE_ELEMENTS (   list,
  node 
)     _jumbleElements(jstate, (List *) expr->list, node)

Definition at line 530 of file queryjumblefuncs.c.

◆ JUMBLE_FIELD

#define JUMBLE_FIELD (   item)
Value:
do { \
if (sizeof(expr->item) == 8) \
AppendJumble64(jstate, (const unsigned char *) &(expr->item)); \
else if (sizeof(expr->item) == 4) \
AppendJumble32(jstate, (const unsigned char *) &(expr->item)); \
else if (sizeof(expr->item) == 2) \
AppendJumble16(jstate, (const unsigned char *) &(expr->item)); \
else if (sizeof(expr->item) == 1) \
AppendJumble8(jstate, (const unsigned char *) &(expr->item)); \
AppendJumble(jstate, (const unsigned char *) &(expr->item), sizeof(expr->item)); \
} while (0)

Definition at line 534 of file queryjumblefuncs.c.

535 { \
536 if (sizeof(expr->item) == 8) \
537 AppendJumble64(jstate, (const unsigned char *) &(expr->item)); \
538 else if (sizeof(expr->item) == 4) \
539 AppendJumble32(jstate, (const unsigned char *) &(expr->item)); \
540 else if (sizeof(expr->item) == 2) \
541 AppendJumble16(jstate, (const unsigned char *) &(expr->item)); \
542 else if (sizeof(expr->item) == 1) \
543 AppendJumble8(jstate, (const unsigned char *) &(expr->item)); \
545 AppendJumble(jstate, (const unsigned char *) &(expr->item), sizeof(expr->item)); \
546} while (0)

◆ JUMBLE_LOCATION

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

Definition at line 532 of file queryjumblefuncs.c.

◆ JUMBLE_NODE

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

Definition at line 528 of file queryjumblefuncs.c.

◆ JUMBLE_SIZE

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

Definition at line 49 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 547 of file queryjumblefuncs.c.

548 { \
549 if (expr->str) \
550 AppendJumble(jstate, (const unsigned char *) (expr->str), strlen(expr->str) + 1); \
553} while(0)

Function Documentation

◆ _jumbleA_Const()

static void _jumbleA_Const ( JumbleState jstate,
Node node 
)
static

Definition at line 710 of file queryjumblefuncs.c.

711{
712 A_Const *expr = (A_Const *) node;
713
714 JUMBLE_FIELD(isnull);
715 if (!expr->isnull)
716 {
717 JUMBLE_FIELD(val.node.type);
718 switch (nodeTag(&expr->val))
719 {
720 case T_Integer:
721 JUMBLE_FIELD(val.ival.ival);
722 break;
723 case T_Float:
724 JUMBLE_STRING(val.fval.fval);
725 break;
726 case T_Boolean:
727 JUMBLE_FIELD(val.boolval.boolval);
728 break;
729 case T_String:
730 JUMBLE_STRING(val.sval.sval);
731 break;
732 case T_BitString:
733 JUMBLE_STRING(val.bsval.bsval);
734 break;
735 default:
736 elog(ERROR, "unrecognized node type: %d",
737 (int) nodeTag(&expr->val));
738 break;
739 }
740 }
741}

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

◆ _jumbleElements()

static void _jumbleElements ( JumbleState jstate,
List elements,
Node node 
)
static

Definition at line 647 of file queryjumblefuncs.c.

648{
649 bool normalize_list = false;
650
651 if (IsSquashableConstantList(elements))
652 {
653 if (IsA(node, ArrayExpr))
654 {
655 ArrayExpr *aexpr = (ArrayExpr *) node;
656
657 if (aexpr->list_start > 0 && aexpr->list_end > 0)
658 {
660 false,
661 aexpr->list_start + 1,
662 (aexpr->list_end - aexpr->list_start) - 1);
663 normalize_list = true;
664 jstate->has_squashed_lists = true;
665 }
666 }
667 }
668
669 if (!normalize_list)
670 {
671 _jumbleNode(jstate, (Node *) elements);
672 }
673}

References _jumbleNode(), fb(), IsA, IsSquashableConstantList(), and RecordConstLocation().

◆ _jumbleList()

static void _jumbleList ( JumbleState jstate,
Node node 
)
static

Definition at line 606 of file queryjumblefuncs.c.

607{
608 List *expr = (List *) node;
609 ListCell *l;
610
611 switch (expr->type)
612 {
613 case T_List:
614 foreach(l, expr)
616 break;
617 case T_IntList:
618 foreach(l, expr)
619 AppendJumble32(jstate, (const unsigned char *) &lfirst_int(l));
620 break;
621 case T_OidList:
622 foreach(l, expr)
623 AppendJumble32(jstate, (const unsigned char *) &lfirst_oid(l));
624 break;
625 case T_XidList:
626 foreach(l, expr)
627 AppendJumble32(jstate, (const unsigned char *) &lfirst_xid(l));
628 break;
629 default:
630 elog(ERROR, "unrecognized list node type: %d",
631 (int) expr->type);
632 return;
633 }
634}

References _jumbleNode(), AppendJumble32(), elog, ERROR, fb(), 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 561 of file queryjumblefuncs.c.

562{
563 Node *expr = node;
564#ifdef USE_ASSERT_CHECKING
565 Size prev_jumble_len = jstate->total_jumble_len;
566#endif
567
568 if (expr == NULL)
569 {
571 return;
572 }
573
574 /* Guard against stack overflow due to overly complex expressions */
576
577 /*
578 * We always emit the node's NodeTag, then any additional fields that are
579 * considered significant, and then we recurse to any child nodes.
580 */
582
583 switch (nodeTag(expr))
584 {
585#include "queryjumblefuncs.switch.c"
586
587 case T_List:
588 case T_IntList:
589 case T_OidList:
590 case T_XidList:
591 _jumbleList(jstate, expr);
592 break;
593
594 default:
595 /* Only a warning, since we can stumble along anyway */
596 elog(WARNING, "unrecognized node type: %d",
597 (int) nodeTag(expr));
598 break;
599 }
600
601 /* Ensure we added something to the jumble buffer */
602 Assert(jstate->total_jumble_len > prev_jumble_len);
603}

References _jumbleList(), AppendJumbleNull(), Assert, check_stack_depth(), elog, fb(), JUMBLE_FIELD, nodeTag, type, and WARNING.

Referenced by _jumbleElements(), _jumbleList(), and DoJumble().

◆ _jumbleParam()

static void _jumbleParam ( JumbleState jstate,
Node node 
)
static

Definition at line 680 of file queryjumblefuncs.c.

681{
682 Param *expr = (Param *) node;
683
684 JUMBLE_FIELD(paramkind);
685 JUMBLE_FIELD(paramid);
686 JUMBLE_FIELD(paramtype);
687 /* paramtypmod and paramcollid are ignored */
688
689 if (expr->paramkind == PARAM_EXTERN)
690 {
691 /*
692 * At this point, only external parameter locations outside of
693 * squashable lists will be recorded.
694 */
695 RecordConstLocation(jstate, true, expr->location, -1);
696
697 /*
698 * Update the highest Param id seen, in order to start normalization
699 * correctly.
700 *
701 * Note: This value is reset at the end of jumbling if there exists a
702 * squashable list. See the comment in the definition of JumbleState.
703 */
704 if (expr->paramid > jstate->highest_extern_param_id)
705 jstate->highest_extern_param_id = expr->paramid;
706 }
707}

References fb(), JUMBLE_FIELD, Param::location, PARAM_EXTERN, Param::paramid, Param::paramkind, and RecordConstLocation().

◆ _jumbleRangeTblEntry_eref()

static void _jumbleRangeTblEntry_eref ( JumbleState jstate,
RangeTblEntry rte,
Alias expr 
)
static

Definition at line 765 of file queryjumblefuncs.c.

768{
770
771 /*
772 * This includes only the table name, the list of column names is ignored.
773 */
774 JUMBLE_STRING(aliasname);
775}

References JUMBLE_FIELD, JUMBLE_STRING, and type.

◆ _jumbleVariableSetStmt()

static void _jumbleVariableSetStmt ( JumbleState jstate,
Node node 
)
static

Definition at line 744 of file queryjumblefuncs.c.

745{
746 VariableSetStmt *expr = (VariableSetStmt *) node;
747
748 JUMBLE_FIELD(kind);
750
751 /*
752 * Account for the list of arguments in query jumbling only if told by the
753 * parser.
754 */
755 if (expr->jumble_args)
756 JUMBLE_NODE(args);
757 JUMBLE_FIELD(is_local);
758 JUMBLE_LOCATION(location);
759}

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

◆ AppendJumble()

static pg_noinline void AppendJumble ( JumbleState jstate,
const unsigned char value,
Size  size 
)
static

Definition at line 297 of file queryjumblefuncs.c.

298{
299 if (jstate->pending_nulls > 0)
301
303}
static struct @172 value
static pg_attribute_always_inline void AppendJumbleInternal(JumbleState *jstate, const unsigned char *item, Size size)
static void FlushPendingNulls(JumbleState *jstate)

References AppendJumbleInternal(), fb(), FlushPendingNulls(), and value.

◆ AppendJumble16()

static pg_noinline void AppendJumble16 ( JumbleState jstate,
const unsigned char value 
)
static

Definition at line 334 of file queryjumblefuncs.c.

335{
336 if (jstate->pending_nulls > 0)
338
340}

References AppendJumbleInternal(), fb(), FlushPendingNulls(), and value.

◆ AppendJumble32()

static pg_noinline void AppendJumble32 ( JumbleState jstate,
const unsigned char value 
)
static

Definition at line 348 of file queryjumblefuncs.c.

349{
350 if (jstate->pending_nulls > 0)
352
354}

References AppendJumbleInternal(), fb(), FlushPendingNulls(), and value.

Referenced by _jumbleList().

◆ AppendJumble64()

static pg_noinline void AppendJumble64 ( JumbleState jstate,
const unsigned char value 
)
static

Definition at line 362 of file queryjumblefuncs.c.

363{
364 if (jstate->pending_nulls > 0)
366
368}

References AppendJumbleInternal(), fb(), FlushPendingNulls(), and value.

◆ AppendJumble8()

static pg_noinline void AppendJumble8 ( JumbleState jstate,
const unsigned char value 
)
static

Definition at line 320 of file queryjumblefuncs.c.

321{
322 if (jstate->pending_nulls > 0)
324
326}

References AppendJumbleInternal(), fb(), FlushPendingNulls(), and value.

◆ AppendJumbleInternal()

static pg_attribute_always_inline void AppendJumbleInternal ( JumbleState jstate,
const unsigned char item,
Size  size 
)
static

Definition at line 234 of file queryjumblefuncs.c.

236{
237 unsigned char *jumble = jstate->jumble;
238 Size jumble_len = jstate->jumble_len;
239
240 /* Ensure the caller didn't mess up */
241 Assert(size > 0);
242
243 /*
244 * Fast path for when there's enough space left in the buffer. This is
245 * worthwhile as means the memcpy can be inlined into very efficient code
246 * when 'size' is a compile-time constant.
247 */
248 if (likely(size <= JUMBLE_SIZE - jumble_len))
249 {
250 memcpy(jumble + jumble_len, item, size);
251 jstate->jumble_len += size;
252
253#ifdef USE_ASSERT_CHECKING
254 jstate->total_jumble_len += size;
255#endif
256
257 return;
258 }
259
260 /*
261 * Whenever the jumble buffer is full, we hash the current contents and
262 * reset the buffer to contain just that hash value, thus relying on the
263 * hash to summarize everything so far.
264 */
265 do
266 {
268
269 if (unlikely(jumble_len >= JUMBLE_SIZE))
270 {
272
274 JUMBLE_SIZE, 0));
275 memcpy(jumble, &start_hash, sizeof(start_hash));
276 jumble_len = sizeof(start_hash);
277 }
278 part_size = Min(size, JUMBLE_SIZE - jumble_len);
279 memcpy(jumble + jumble_len, item, part_size);
280 jumble_len += part_size;
281 item += part_size;
282 size -= part_size;
283
284#ifdef USE_ASSERT_CHECKING
285 jstate->total_jumble_len += part_size;
286#endif
287 } while (size > 0);
288
289 jstate->jumble_len = jumble_len;
290}
#define Min(x, y)
Definition c.h:997
#define likely(x)
Definition c.h:411
int64_t int64
Definition c.h:543
#define unlikely(x)
Definition c.h:412
static Datum hash_any_extended(const unsigned char *k, int keylen, uint64 seed)
Definition hashfn.h:37
static int64 DatumGetInt64(Datum X)
Definition postgres.h:413
#define JUMBLE_SIZE

References Assert, DatumGetInt64(), fb(), hash_any_extended(), JUMBLE_SIZE, likely, Min, and unlikely.

Referenced by AppendJumble(), AppendJumble16(), AppendJumble32(), AppendJumble64(), AppendJumble8(), and FlushPendingNulls().

◆ AppendJumbleNull()

static pg_attribute_always_inline void AppendJumbleNull ( JumbleState jstate)
static

Definition at line 310 of file queryjumblefuncs.c.

311{
312 jstate->pending_nulls++;
313}

References fb().

Referenced by _jumbleNode().

◆ CleanQuerytext()

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

Definition at line 86 of file queryjumblefuncs.c.

87{
88 int query_location = *location;
89 int query_len = *len;
90
91 /* First apply starting offset, unless it's -1 (unknown). */
92 if (query_location >= 0)
93 {
94 Assert(query_location <= strlen(query));
95 query += query_location;
96 /* Length of 0 (or -1) means "rest of string" */
97 if (query_len <= 0)
98 query_len = strlen(query);
99 else
100 Assert(query_len <= strlen(query));
101 }
102 else
103 {
104 /* If query location is unknown, distrust query_len as well */
105 query_location = 0;
106 query_len = strlen(query);
107 }
108
109 /*
110 * Discard leading and trailing whitespace, too. Use scanner_isspace()
111 * not libc's isspace(), because we want to match the lexer's behavior.
112 *
113 * Note: the parser now strips leading comments and whitespace from the
114 * reported stmt_location, so this first loop will only iterate in the
115 * unusual case that the location didn't propagate to here. But the
116 * statement length will extend to the end-of-string or terminating
117 * semicolon, so the second loop often does something useful.
118 */
119 while (query_len > 0 && scanner_isspace(query[0]))
120 query++, query_location++, query_len--;
121 while (query_len > 0 && scanner_isspace(query[query_len - 1]))
122 query_len--;
123
124 *location = query_location;
125 *len = query_len;
126
127 return query;
128}
const void size_t len
bool scanner_isspace(char ch)
Definition scansup.c:105

References Assert, fb(), len, and scanner_isspace().

Referenced by pgss_store(), and script_error_callback().

◆ DoJumble()

static int64 DoJumble ( JumbleState jstate,
Node node 
)
static

Definition at line 209 of file queryjumblefuncs.c.

210{
211 /* Jumble the given node */
212 _jumbleNode(jstate, node);
213
214 /* Flush any pending NULLs before doing the final hash */
215 if (jstate->pending_nulls > 0)
217
218 /* Squashed list found, reset highest_extern_param_id */
219 if (jstate->has_squashed_lists)
220 jstate->highest_extern_param_id = 0;
221
222 /* Process the jumble buffer and produce the hash value */
224 jstate->jumble_len,
225 0));
226}

References _jumbleNode(), DatumGetInt64(), fb(), FlushPendingNulls(), and hash_any_extended().

Referenced by JumbleQuery().

◆ EnableQueryId()

void EnableQueryId ( void  )

Definition at line 169 of file queryjumblefuncs.c.

170{
172 query_id_enabled = true;
173}
@ COMPUTE_QUERY_ID_OFF
Definition queryjumble.h:83
bool query_id_enabled
int compute_query_id

References compute_query_id, COMPUTE_QUERY_ID_OFF, and query_id_enabled.

Referenced by _PG_init().

◆ FlushPendingNulls()

static pg_attribute_always_inline void FlushPendingNulls ( JumbleState jstate)
static

Definition at line 377 of file queryjumblefuncs.c.

378{
379 Assert(jstate->pending_nulls > 0);
380
382 (const unsigned char *) &jstate->pending_nulls, 4);
383 jstate->pending_nulls = 0;
384}

References AppendJumbleInternal(), Assert, and fb().

Referenced by AppendJumble(), AppendJumble16(), AppendJumble32(), AppendJumble64(), AppendJumble8(), and DoJumble().

◆ InitJumble()

static JumbleState * InitJumble ( void  )
static

Definition at line 180 of file queryjumblefuncs.c.

181{
183
185
186 /* Set up workspace for query jumbling */
187 jstate->jumble = (unsigned char *) palloc(JUMBLE_SIZE);
188 jstate->jumble_len = 0;
189 jstate->clocations_buf_size = 32;
190 jstate->clocations = (LocationLen *) palloc(jstate->clocations_buf_size *
191 sizeof(LocationLen));
192 jstate->clocations_count = 0;
193 jstate->highest_extern_param_id = 0;
194 jstate->pending_nulls = 0;
195 jstate->has_squashed_lists = false;
196#ifdef USE_ASSERT_CHECKING
197 jstate->total_jumble_len = 0;
198#endif
199
200 return jstate;
201}
#define palloc_object(type)
Definition fe_memutils.h:74
void * palloc(Size size)
Definition mcxt.c:1387

References fb(), JUMBLE_SIZE, palloc(), and palloc_object.

Referenced by JumbleQuery().

◆ IsSquashableConstant()

static bool IsSquashableConstant ( Node element)
static

Definition at line 437 of file queryjumblefuncs.c.

438{
439restart:
440 switch (nodeTag(element))
441 {
442 case T_RelabelType:
443 /* Unwrap RelabelType */
444 element = (Node *) ((RelabelType *) element)->arg;
445 goto restart;
446
447 case T_CoerceViaIO:
448 /* Unwrap CoerceViaIO */
449 element = (Node *) ((CoerceViaIO *) element)->arg;
450 goto restart;
451
452 case T_Const:
453 return true;
454
455 case T_Param:
456 return castNode(Param, element)->paramkind == PARAM_EXTERN;
457
458 case T_FuncExpr:
459 {
460 FuncExpr *func = (FuncExpr *) element;
461 ListCell *temp;
462
463 if (func->funcformat != COERCE_IMPLICIT_CAST &&
464 func->funcformat != COERCE_EXPLICIT_CAST)
465 return false;
466
467 if (func->funcid > FirstGenbkiObjectId)
468 return false;
469
470 /*
471 * We can check function arguments recursively, being careful
472 * about recursing too deep. At each recursion level it's
473 * enough to test the stack on the first element. (Note that
474 * I wasn't able to hit this without bloating the stack
475 * artificially in this function: the parser errors out before
476 * stack size becomes a problem here.)
477 */
478 foreach(temp, func->args)
479 {
480 Node *arg = lfirst(temp);
481
482 if (!IsA(arg, Const))
483 {
484 if (foreach_current_index(temp) == 0 &&
486 return false;
487 else if (!IsSquashableConstant(arg))
488 return false;
489 }
490 }
491
492 return true;
493 }
494
495 default:
496 return false;
497 }
498}
#define castNode(_type_, nodeptr)
Definition nodes.h:182
void * arg
#define foreach_current_index(var_or_cell)
Definition pg_list.h:403
@ COERCE_IMPLICIT_CAST
Definition primnodes.h:768
@ COERCE_EXPLICIT_CAST
Definition primnodes.h:767
static bool IsSquashableConstant(Node *element)
static chr element(struct vars *v, const chr *startp, const chr *endp)
bool stack_is_too_deep(void)
Oid funcid
Definition primnodes.h:782
List * args
Definition primnodes.h:800
#define FirstGenbkiObjectId
Definition transam.h:195

References arg, FuncExpr::args, castNode, COERCE_EXPLICIT_CAST, COERCE_IMPLICIT_CAST, element(), fb(), FirstGenbkiObjectId, foreach_current_index, FuncExpr::funcid, IsA, IsSquashableConstant(), lfirst, nodeTag, PARAM_EXTERN, and stack_is_too_deep().

Referenced by IsSquashableConstant(), and IsSquashableConstantList().

◆ IsSquashableConstantList()

static bool IsSquashableConstantList ( List elements)
static

Definition at line 511 of file queryjumblefuncs.c.

512{
513 ListCell *temp;
514
515 /* If the list is too short, we don't try to squash it. */
516 if (list_length(elements) < 2)
517 return false;
518
519 foreach(temp, elements)
520 {
522 return false;
523 }
524
525 return true;
526}
static int list_length(const List *l)
Definition pg_list.h:152

References fb(), IsSquashableConstant(), lfirst, and list_length().

Referenced by _jumbleElements().

◆ JumbleQuery()

JumbleState * JumbleQuery ( Query query)

Definition at line 137 of file queryjumblefuncs.c.

138{
140
142
143 jstate = InitJumble();
144
145 query->queryId = DoJumble(jstate, (Node *) query);
146
147 /*
148 * If we are unlucky enough to get a hash of zero, use 1 instead for
149 * normal statements and 2 for utility queries.
150 */
151 if (query->queryId == INT64CONST(0))
152 {
153 if (query->utilityStmt)
154 query->queryId = INT64CONST(2);
155 else
156 query->queryId = INT64CONST(1);
157 }
158
159 return jstate;
160}
#define INT64CONST(x)
Definition c.h:560
static bool IsQueryIdEnabled(void)
static int64 DoJumble(JumbleState *jstate, Node *node)
static JumbleState * InitJumble(void)
Node * utilityStmt
Definition parsenodes.h:141

References Assert, DoJumble(), fb(), InitJumble(), INT64CONST, IsQueryIdEnabled(), 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,
bool  extern_param,
int  location,
int  len 
)
static

Definition at line 398 of file queryjumblefuncs.c.

399{
400 /* -1 indicates unknown or undefined location */
401 if (location >= 0)
402 {
403 /* enlarge array if needed */
404 if (jstate->clocations_count >= jstate->clocations_buf_size)
405 {
406 jstate->clocations_buf_size *= 2;
407 jstate->clocations = (LocationLen *)
408 repalloc(jstate->clocations,
409 jstate->clocations_buf_size *
410 sizeof(LocationLen));
411 }
412 jstate->clocations[jstate->clocations_count].location = location;
413
414 /*
415 * Lengths are either positive integers (indicating a squashable
416 * list), or -1.
417 */
418 Assert(len > -1 || len == -1);
419 jstate->clocations[jstate->clocations_count].length = len;
420 jstate->clocations[jstate->clocations_count].squashed = (len > -1);
421 jstate->clocations[jstate->clocations_count].extern_param = extern_param;
422 jstate->clocations_count++;
423 }
424}
void * repalloc(void *pointer, Size size)
Definition mcxt.c:1632

References Assert, fb(), len, and repalloc().

Referenced by _jumbleElements(), and _jumbleParam().

Variable Documentation

◆ compute_query_id

int compute_query_id = COMPUTE_QUERY_ID_AUTO

Definition at line 52 of file queryjumblefuncs.c.

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

◆ query_id_enabled

bool query_id_enabled = false

Definition at line 61 of file queryjumblefuncs.c.

Referenced by EnableQueryId(), and IsQueryIdEnabled().