Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Postgres/src/backend/utils/adt/   (Postgres Database Version 18.4©)  Datei vom 11.4.2026 mit Größe 9 kB image not shown  

Quelle  tsquery_util.c   Sprache: C

 

/*-------------------------------------------------------------------------
 *
 * tsquery_util.c
 *   Utilities for tsquery datatype
 *
 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
 *
 *
 * IDENTIFICATION
 *   src/backend/utils/adt/tsquery_util.c
 *
 *-------------------------------------------------------------------------
 */


#include "postgres.h"

#include "miscadmin.h"
#include "tsearch/ts_utils.h"
#include "varatt.h"

/*
 * Build QTNode tree for a tsquery given in QueryItem array format.
 */

QTNode *
QT2QTN(QueryItem *in, char *operand)
{
 QTNode    *node = (QTNode *) palloc0(sizeof(QTNode));

 /* since this function recurses, it could be driven to stack overflow. */
 check_stack_depth();

 node->valnode = in;

 if (in->type == QI_OPR)
 {
  node->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);
  node->child[0] = QT2QTN(in + 1, operand);
  node->sign = node->child[0]->sign;
  if (in->qoperator.oper == OP_NOT)
   node->nchild = 1;
  else
  {
   node->nchild = 2;
   node->child[1] = QT2QTN(in + in->qoperator.left, operand);
   node->sign |= node->child[1]->sign;
  }
 }
 else if (operand)
 {
  node->word = operand + in->qoperand.distance;
  node->sign = ((uint32) 1) << (((unsigned int) in->qoperand.valcrc) % 32);
 }

 return node;
}

/*
 * Free a QTNode tree.
 *
 * Referenced "word" and "valnode" items are freed if marked as transient
 * by flags.
 */

void
QTNFree(QTNode *in)
{
 if (!in)
  return;

 /* since this function recurses, it could be driven to stack overflow. */
 check_stack_depth();

 if (in->valnode->type == QI_VAL && in->word && (in->flags & QTN_WORDFREE) != 0)
  pfree(in->word);

 if (in->valnode->type == QI_OPR)
 {
  int   i;

  for (i = 0; i < in->nchild; i++)
   QTNFree(in->child[i]);
 }
 if (in->child)
  pfree(in->child);

 if (in->flags & QTN_NEEDFREE)
  pfree(in->valnode);

 pfree(in);
}

/*
 * Sort comparator for QTNodes.
 *
 * The sort order is somewhat arbitrary.
 */

int
QTNodeCompare(QTNode *an, QTNode *bn)
{
 /* since this function recurses, it could be driven to stack overflow. */
 check_stack_depth();

 if (an->valnode->type != bn->valnode->type)
  return (an->valnode->type > bn->valnode->type) ? -1 : 1;

 if (an->valnode->type == QI_OPR)
 {
  QueryOperator *ao = &an->valnode->qoperator;
  QueryOperator *bo = &bn->valnode->qoperator;

  if (ao->oper != bo->oper)
   return (ao->oper > bo->oper) ? -1 : 1;

  if (an->nchild != bn->nchild)
   return (an->nchild > bn->nchild) ? -1 : 1;

  {
   int   i,
      res;

   for (i = 0; i < an->nchild; i++)
    if ((res = QTNodeCompare(an->child[i], bn->child[i])) != 0)
     return res;
  }

  if (ao->oper == OP_PHRASE && ao->distance != bo->distance)
   return (ao->distance > bo->distance) ? -1 : 1;

  return 0;
 }
 else if (an->valnode->type == QI_VAL)
 {
  QueryOperand *ao = &an->valnode->qoperand;
  QueryOperand *bo = &bn->valnode->qoperand;

  if (ao->valcrc != bo->valcrc)
  {
   return (ao->valcrc > bo->valcrc) ? -1 : 1;
  }

  return tsCompareString(an->word, ao->length, bn->word, bo->length, false);
 }
 else
 {
  elog(ERROR, "unrecognized QueryItem type: %d", an->valnode->type);
  return 0;    /* keep compiler quiet */
 }
}

/*
 * qsort comparator for QTNode pointers.
 */

static int
cmpQTN(const void *a, const void *b)
{
 return QTNodeCompare(*(QTNode *const *) a, *(QTNode *const *) b);
}

/*
 * Canonicalize a QTNode tree by sorting the children of AND/OR nodes
 * into an arbitrary but well-defined order.
 */

void
QTNSort(QTNode *in)
{
 int   i;

 /* since this function recurses, it could be driven to stack overflow. */
 check_stack_depth();

 if (in->valnode->type != QI_OPR)
  return;

 for (i = 0; i < in->nchild; i++)
  QTNSort(in->child[i]);
 if (in->nchild > 1 && in->valnode->qoperator.oper != OP_PHRASE)
  qsort(in->child, in->nchild, sizeof(QTNode *), cmpQTN);
}

/*
 * Are two QTNode trees equal according to QTNodeCompare?
 */

bool
QTNEq(QTNode *a, QTNode *b)
{
 uint32  sign = a->sign & b->sign;

 if (!(sign == a->sign && sign == b->sign))
  return false;

 return (QTNodeCompare(a, b) == 0);
}

/*
 * Remove unnecessary intermediate nodes. For example:
 *
 * OR   OR
 * a  OR -> a b c
 *  b c
 */

void
QTNTernary(QTNode *in)
{
 int   i;

 /* since this function recurses, it could be driven to stack overflow. */
 check_stack_depth();

 if (in->valnode->type != QI_OPR)
  return;

 for (i = 0; i < in->nchild; i++)
  QTNTernary(in->child[i]);

 /* Only AND and OR are associative, so don't flatten other node types */
 if (in->valnode->qoperator.oper != OP_AND &&
  in->valnode->qoperator.oper != OP_OR)
  return;

 for (i = 0; i < in->nchild; i++)
 {
  QTNode    *cc = in->child[i];

  if (cc->valnode->type == QI_OPR &&
   in->valnode->qoperator.oper == cc->valnode->qoperator.oper)
  {
   int   oldnchild = in->nchild;

   in->nchild += cc->nchild - 1;
   in->child = (QTNode **) repalloc(in->child, in->nchild * sizeof(QTNode *));

   if (i + 1 != oldnchild)
    memmove(in->child + i + cc->nchild, in->child + i + 1,
      (oldnchild - i - 1) * sizeof(QTNode *));

   memcpy(in->child + i, cc->child, cc->nchild * sizeof(QTNode *));
   i += cc->nchild - 1;

   if (cc->flags & QTN_NEEDFREE)
    pfree(cc->valnode);
   pfree(cc);
  }
 }
}

/*
 * Convert a tree to binary tree by inserting intermediate nodes.
 * (Opposite of QTNTernary)
 */

void
QTNBinary(QTNode *in)
{
 int   i;

 /* since this function recurses, it could be driven to stack overflow. */
 check_stack_depth();

 if (in->valnode->type != QI_OPR)
  return;

 for (i = 0; i < in->nchild; i++)
  QTNBinary(in->child[i]);

 while (in->nchild > 2)
 {
  QTNode    *nn = (QTNode *) palloc0(sizeof(QTNode));

  nn->valnode = (QueryItem *) palloc0(sizeof(QueryItem));
  nn->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);

  nn->nchild = 2;
  nn->flags = QTN_NEEDFREE;

  nn->child[0] = in->child[0];
  nn->child[1] = in->child[1];
  nn->sign = nn->child[0]->sign | nn->child[1]->sign;

  nn->valnode->type = in->valnode->type;
  nn->valnode->qoperator.oper = in->valnode->qoperator.oper;

  in->child[0] = nn;
  in->child[1] = in->child[in->nchild - 1];
  in->nchild--;
 }
}

/*
 * Count the total length of operand strings in tree (including '\0'-
 * terminators) and the total number of nodes.
 * Caller must initialize *sumlen and *nnode to zeroes.
 */

static void
cntsize(QTNode *in, int *sumlen, int *nnode)
{
 /* since this function recurses, it could be driven to stack overflow. */
 check_stack_depth();

 *nnode += 1;
 if (in->valnode->type == QI_OPR)
 {
  int   i;

  for (i = 0; i < in->nchild; i++)
   cntsize(in->child[i], sumlen, nnode);
 }
 else
 {
  *sumlen += in->valnode->qoperand.length + 1;
 }
}

typedef struct
{
 QueryItem  *curitem;
 char    *operand;
 char    *curoperand;
} QTN2QTState;

/*
 * Recursively convert a QTNode tree into flat tsquery format.
 * Caller must have allocated arrays of the correct size.
 */

static void
fillQT(QTN2QTState *state, QTNode *in)
{
 /* since this function recurses, it could be driven to stack overflow. */
 check_stack_depth();

 if (in->valnode->type == QI_VAL)
 {
  memcpy(state->curitem, in->valnode, sizeof(QueryOperand));

  memcpy(state->curoperand, in->word, in->valnode->qoperand.length);
  state->curitem->qoperand.distance = state->curoperand - state->operand;
  state->curoperand[in->valnode->qoperand.length] = '\0';
  state->curoperand += in->valnode->qoperand.length + 1;
  state->curitem++;
 }
 else
 {
  QueryItem  *curitem = state->curitem;

  Assert(in->valnode->type == QI_OPR);

  memcpy(state->curitem, in->valnode, sizeof(QueryOperator));

  Assert(in->nchild <= 2);
  state->curitem++;

  fillQT(state, in->child[0]);

  if (in->nchild == 2)
  {
   curitem->qoperator.left = state->curitem - curitem;
   fillQT(state, in->child[1]);
  }
 }
}

/*
 * Build flat tsquery from a QTNode tree.
 */

TSQuery
QTN2QT(QTNode *in)
{
 TSQuery  out;
 int   len;
 int   sumlen = 0,
    nnode = 0;
 QTN2QTState state;

 cntsize(in, &sumlen, &nnode);

 if (TSQUERY_TOO_BIG(nnode, sumlen))
  ereport(ERROR,
    (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
     errmsg("tsquery is too large")));
 len = COMPUTESIZE(nnode, sumlen);

 out = (TSQuery) palloc0(len);
 SET_VARSIZE(out, len);
 out->size = nnode;

 state.curitem = GETQUERY(out);
 state.operand = state.curoperand = GETOPERAND(out);

 fillQT(&state, in);
 return out;
}

/*
 * Copy a QTNode tree.
 *
 * Modifiable copies of the words and valnodes are made, too.
 */

QTNode *
QTNCopy(QTNode *in)
{
 QTNode    *out;

 /* since this function recurses, it could be driven to stack overflow. */
 check_stack_depth();

 out = (QTNode *) palloc(sizeof(QTNode));

 *out = *in;
 out->valnode = (QueryItem *) palloc(sizeof(QueryItem));
 *(out->valnode) = *(in->valnode);
 out->flags |= QTN_NEEDFREE;

 if (in->valnode->type == QI_VAL)
 {
  out->word = palloc(in->valnode->qoperand.length + 1);
  memcpy(out->word, in->word, in->valnode->qoperand.length);
  out->word[in->valnode->qoperand.length] = '\0';
  out->flags |= QTN_WORDFREE;
 }
 else
 {
  int   i;

  out->child = (QTNode **) palloc(sizeof(QTNode *) * in->nchild);

  for (i = 0; i < in->nchild; i++)
   out->child[i] = QTNCopy(in->child[i]);
 }

 return out;
}

/*
 * Clear the specified flag bit(s) in all nodes of a QTNode tree.
 */

void
QTNClearFlags(QTNode *in, uint32 flags)
{
 /* since this function recurses, it could be driven to stack overflow. */
 check_stack_depth();

 in->flags &= ~flags;

 if (in->valnode->type != QI_VAL)
 {
  int   i;

  for (i = 0; i < in->nchild; i++)
   QTNClearFlags(in->child[i], flags);
 }
}

Messung V0.5 in Prozent
C=94 H=95 G=94

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet am  2026-09-28) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.