#include "postgres.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "tsearch/ts_locale.h"
#include "tsearch/ts_utils.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
Go to the source code of this file.
Data Structures | |
struct | TSQueryParserStateData |
struct | INFIX |
Defines | |
#define | WAITOPERAND 1 |
#define | WAITOPERATOR 2 |
#define | WAITFIRSTOPERAND 3 |
#define | WAITSINGLEOPERAND 4 |
#define | STACKDEPTH 32 |
#define | RESIZEBUF(inf, addsize) |
Enumerations | |
enum | ts_tokentype { PT_END = 0, PT_ERR = 1, PT_VAL = 2, PT_OPR = 3, PT_OPEN = 4, PT_CLOSE = 5 } |
Functions | |
static char * | get_modifiers (char *buf, int16 *weight, bool *prefix) |
static ts_tokentype | gettoken_query (TSQueryParserState state, int8 *operator, int *lenval, char **strval, int16 *weight, bool *prefix) |
void | pushOperator (TSQueryParserState state, int8 oper) |
static void | pushValue_internal (TSQueryParserState state, pg_crc32 valcrc, int distance, int lenval, int weight, bool prefix) |
void | pushValue (TSQueryParserState state, char *strval, int lenval, int16 weight, bool prefix) |
void | pushStop (TSQueryParserState state) |
static void | makepol (TSQueryParserState state, PushFunction pushval, Datum opaque) |
static void | findoprnd_recurse (QueryItem *ptr, uint32 *pos, int nnodes) |
static void | findoprnd (QueryItem *ptr, int size) |
TSQuery | parse_tsquery (char *buf, PushFunction pushval, Datum opaque, bool isplain) |
static void | pushval_asis (Datum opaque, TSQueryParserState state, char *strval, int lenval, int16 weight, bool prefix) |
Datum | tsqueryin (PG_FUNCTION_ARGS) |
static void | infix (INFIX *in, bool first) |
Datum | tsqueryout (PG_FUNCTION_ARGS) |
Datum | tsquerysend (PG_FUNCTION_ARGS) |
Datum | tsqueryrecv (PG_FUNCTION_ARGS) |
Datum | tsquerytree (PG_FUNCTION_ARGS) |
#define RESIZEBUF | ( | inf, | ||
addsize | ||||
) |
while( ( (inf)->cur - (inf)->buf ) + (addsize) + 1 >= (inf)->buflen ) \ { \ int len = (inf)->cur - (inf)->buf; \ (inf)->buflen *= 2; \ (inf)->buf = (char*) repalloc( (void*)(inf)->buf, (inf)->buflen ); \ (inf)->cur = (inf)->buf + len; \ }
Definition at line 588 of file tsquery.c.
Referenced by infix().
#define WAITFIRSTOPERAND 3 |
Definition at line 53 of file tsquery.c.
Referenced by gettoken_query(), and parse_tsquery().
#define WAITOPERAND 1 |
Definition at line 51 of file tsquery.c.
Referenced by gettoken_query().
#define WAITOPERATOR 2 |
Definition at line 52 of file tsquery.c.
Referenced by gettoken_query().
#define WAITSINGLEOPERAND 4 |
Definition at line 54 of file tsquery.c.
Referenced by gettoken_query(), and parse_tsquery().
enum ts_tokentype |
static void findoprnd | ( | QueryItem * | ptr, | |
int | size | |||
) | [static] |
Definition at line 446 of file tsquery.c.
References elog, ERROR, and findoprnd_recurse().
Referenced by parse_tsquery(), and tsqueryrecv().
{ uint32 pos; pos = 0; findoprnd_recurse(ptr, &pos, size); if (pos != size) elog(ERROR, "malformed tsquery: extra nodes"); }
Definition at line 401 of file tsquery.c.
References Assert, check_stack_depth(), elog, ERROR, QueryOperator::left, OP_AND, OP_NOT, OP_OR, QueryOperator::oper, QI_OPR, QI_VAL, QI_VALSTOP, and QueryItem::qoperator.
Referenced by findoprnd().
{ /* since this function recurses, it could be driven to stack overflow. */ check_stack_depth(); if (*pos >= nnodes) elog(ERROR, "malformed tsquery: operand not found"); if (ptr[*pos].type == QI_VAL || ptr[*pos].type == QI_VALSTOP) /* need to handle VALSTOP here, they * haven't been cleaned away yet. */ { (*pos)++; } else { Assert(ptr[*pos].type == QI_OPR); if (ptr[*pos].qoperator.oper == OP_NOT) { ptr[*pos].qoperator.left = 1; (*pos)++; findoprnd_recurse(ptr, pos, nnodes); } else { QueryOperator *curitem = &ptr[*pos].qoperator; int tmp = *pos; Assert(curitem->oper == OP_AND || curitem->oper == OP_OR); (*pos)++; findoprnd_recurse(ptr, pos, nnodes); curitem->left = *pos - tmp; findoprnd_recurse(ptr, pos, nnodes); } } }
Definition at line 61 of file tsquery.c.
References pg_mblen(), and t_iseq.
Referenced by gettoken_query().
{ *weight = 0; *prefix = false; if (!t_iseq(buf, ':')) return buf; buf++; while (*buf && pg_mblen(buf) == 1) { switch (*buf) { case 'a': case 'A': *weight |= 1 << 3; break; case 'b': case 'B': *weight |= 1 << 2; break; case 'c': case 'C': *weight |= 1 << 1; break; case 'd': case 'D': *weight |= 1; break; case '*': *prefix = true; break; default: return buf; } buf++; } return buf; }
static ts_tokentype gettoken_query | ( | TSQueryParserState | state, | |
int8 * | operator, | |||
int * | lenval, | |||
char ** | strval, | |||
int16 * | weight, | |||
bool * | prefix | |||
) | [static] |
Definition at line 122 of file tsquery.c.
References TSQueryParserStateData::buf, TSQueryParserStateData::buffer, TSQueryParserStateData::count, ereport, errcode(), errmsg(), ERROR, get_modifiers(), gettoken_tsvector(), NULL, pg_mblen(), PT_END, PT_ERR, reset_tsvector_parser(), TSQueryParserStateData::state, t_iseq, t_isspace, TSQueryParserStateData::valstate, WAITFIRSTOPERAND, WAITOPERAND, WAITOPERATOR, and WAITSINGLEOPERAND.
Referenced by makepol().
{ *weight = 0; *prefix = false; while (1) { switch (state->state) { case WAITFIRSTOPERAND: case WAITOPERAND: if (t_iseq(state->buf, '!')) { (state->buf)++; /* can safely ++, t_iseq guarantee * that pg_mblen()==1 */ *operator = OP_NOT; state->state = WAITOPERAND; return PT_OPR; } else if (t_iseq(state->buf, '(')) { state->count++; (state->buf)++; state->state = WAITOPERAND; return PT_OPEN; } else if (t_iseq(state->buf, ':')) { ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("syntax error in tsquery: \"%s\"", state->buffer))); } else if (!t_isspace(state->buf)) { /* * We rely on the tsvector parser to parse the value for * us */ reset_tsvector_parser(state->valstate, state->buf); if (gettoken_tsvector(state->valstate, strval, lenval, NULL, NULL, &state->buf)) { state->buf = get_modifiers(state->buf, weight, prefix); state->state = WAITOPERATOR; return PT_VAL; } else if (state->state == WAITFIRSTOPERAND) return PT_END; else ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("no operand in tsquery: \"%s\"", state->buffer))); } break; case WAITOPERATOR: if (t_iseq(state->buf, '&')) { state->state = WAITOPERAND; *operator = OP_AND; (state->buf)++; return PT_OPR; } if (t_iseq(state->buf, '|')) { state->state = WAITOPERAND; *operator = OP_OR; (state->buf)++; return PT_OPR; } else if (t_iseq(state->buf, ')')) { (state->buf)++; state->count--; return (state->count < 0) ? PT_ERR : PT_CLOSE; } else if (*(state->buf) == '\0') return (state->count) ? PT_ERR : PT_END; else if (!t_isspace(state->buf)) return PT_ERR; break; case WAITSINGLEOPERAND: if (*(state->buf) == '\0') return PT_END; *strval = state->buf; *lenval = strlen(state->buf); state->buf += strlen(state->buf); state->count++; return PT_VAL; default: return PT_ERR; break; } state->buf += pg_mblen(state->buf); } }
Definition at line 602 of file tsquery.c.
References INFIX::buf, INFIX::buflen, check_stack_depth(), COPYCHAR, INFIX::cur, INFIX::curpol, QueryOperand::distance, elog, ERROR, QueryOperand::length, INFIX::op, TSQueryParserStateData::op, OP_AND, OP_NOT, OP_OR, palloc(), pfree(), pg_database_encoding_max_length(), pg_mblen(), QueryOperand::prefix, QI_OPR, QI_VAL, RESIZEBUF, t_iseq, ITEM::type, and QueryOperand::weight.
Referenced by tsqueryout(), and tsquerytree().
{ /* since this function recurses, it could be driven to stack overflow. */ check_stack_depth(); if (in->curpol->type == QI_VAL) { QueryOperand *curpol = &in->curpol->qoperand; char *op = in->op + curpol->distance; int clen; RESIZEBUF(in, curpol->length * (pg_database_encoding_max_length() + 1) + 2 + 6); *(in->cur) = '\''; in->cur++; while (*op) { if (t_iseq(op, '\'')) { *(in->cur) = '\''; in->cur++; } else if (t_iseq(op, '\\')) { *(in->cur) = '\\'; in->cur++; } COPYCHAR(in->cur, op); clen = pg_mblen(op); op += clen; in->cur += clen; } *(in->cur) = '\''; in->cur++; if (curpol->weight || curpol->prefix) { *(in->cur) = ':'; in->cur++; if (curpol->prefix) { *(in->cur) = '*'; in->cur++; } if (curpol->weight & (1 << 3)) { *(in->cur) = 'A'; in->cur++; } if (curpol->weight & (1 << 2)) { *(in->cur) = 'B'; in->cur++; } if (curpol->weight & (1 << 1)) { *(in->cur) = 'C'; in->cur++; } if (curpol->weight & 1) { *(in->cur) = 'D'; in->cur++; } } *(in->cur) = '\0'; in->curpol++; } else if (in->curpol->qoperator.oper == OP_NOT) { bool isopr = false; RESIZEBUF(in, 1); *(in->cur) = '!'; in->cur++; *(in->cur) = '\0'; in->curpol++; if (in->curpol->type == QI_OPR) { isopr = true; RESIZEBUF(in, 2); sprintf(in->cur, "( "); in->cur = strchr(in->cur, '\0'); } infix(in, isopr); if (isopr) { RESIZEBUF(in, 2); sprintf(in->cur, " )"); in->cur = strchr(in->cur, '\0'); } } else { int8 op = in->curpol->qoperator.oper; INFIX nrm; in->curpol++; if (op == OP_OR && !first) { RESIZEBUF(in, 2); sprintf(in->cur, "( "); in->cur = strchr(in->cur, '\0'); } nrm.curpol = in->curpol; nrm.op = in->op; nrm.buflen = 16; nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen); /* get right operand */ infix(&nrm, false); /* get & print left operand */ in->curpol = nrm.curpol; infix(in, false); /* print operator & right operand */ RESIZEBUF(in, 3 + (nrm.cur - nrm.buf)); switch (op) { case OP_OR: sprintf(in->cur, " | %s", nrm.buf); break; case OP_AND: sprintf(in->cur, " & %s", nrm.buf); break; default: /* OP_NOT is handled in above if-branch */ elog(ERROR, "unrecognized operator type: %d", op); } in->cur = strchr(in->cur, '\0'); pfree(nrm.buf); if (op == OP_OR && !first) { RESIZEBUF(in, 2); sprintf(in->cur, " )"); in->cur = strchr(in->cur, '\0'); } } }
static void makepol | ( | TSQueryParserState | state, | |
PushFunction | pushval, | |||
Datum | opaque | |||
) | [static] |
Definition at line 328 of file tsquery.c.
References TSQueryParserStateData::buffer, check_stack_depth(), elog, ereport, errcode(), errmsg(), ERROR, gettoken_query(), OP_AND, OP_NOT, OP_OR, PT_CLOSE, PT_END, PT_ERR, PT_OPEN, PT_OPR, PT_VAL, pushOperator(), and STACKDEPTH.
Referenced by parse_tsquery().
{ int8 operator = 0; ts_tokentype type; int lenval = 0; char *strval = NULL; int8 opstack[STACKDEPTH]; int lenstack = 0; int16 weight = 0; bool prefix; /* since this function recurses, it could be driven to stack overflow */ check_stack_depth(); while ((type = gettoken_query(state, &operator, &lenval, &strval, &weight, &prefix)) != PT_END) { switch (type) { case PT_VAL: pushval(opaque, state, strval, lenval, weight, prefix); while (lenstack && (opstack[lenstack - 1] == OP_AND || opstack[lenstack - 1] == OP_NOT)) { lenstack--; pushOperator(state, opstack[lenstack]); } break; case PT_OPR: if (lenstack && operator == OP_OR) pushOperator(state, OP_OR); else { if (lenstack == STACKDEPTH) /* internal error */ elog(ERROR, "tsquery stack too small"); opstack[lenstack] = operator; lenstack++; } break; case PT_OPEN: makepol(state, pushval, opaque); while (lenstack && (opstack[lenstack - 1] == OP_AND || opstack[lenstack - 1] == OP_NOT)) { lenstack--; pushOperator(state, opstack[lenstack]); } break; case PT_CLOSE: while (lenstack) { lenstack--; pushOperator(state, opstack[lenstack]); }; return; case PT_ERR: default: ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("syntax error in tsquery: \"%s\"", state->buffer))); } } while (lenstack) { lenstack--; pushOperator(state, opstack[lenstack]); } }
TSQuery parse_tsquery | ( | char * | buf, | |
PushFunction | pushval, | |||
Datum | opaque, | |||
bool | isplain | |||
) |
Definition at line 473 of file tsquery.c.
References TSQueryParserStateData::buf, TSQueryParserStateData::buffer, close_tsvector_parser(), COMPUTESIZE, TSQueryParserStateData::count, TSQueryParserStateData::curop, elog, ereport, errmsg(), ERROR, findoprnd(), GETOPERAND, GETQUERY, HDRSIZETQ, i, init_tsvector_parser(), TSQueryParserStateData::lenop, lfirst, list_length(), makepol(), NOTICE, TSQueryParserStateData::op, palloc(), palloc0(), pfree(), TSQueryParserStateData::polstr, QI_OPR, QI_VAL, QI_VALSTOP, SET_VARSIZE, TSQueryData::size, TSQueryParserStateData::state, TSQueryParserStateData::sumlen, QueryItem::type, TSQueryParserStateData::valstate, WAITFIRSTOPERAND, and WAITSINGLEOPERAND.
Referenced by plainto_tsquery_byid(), to_tsquery_byid(), and tsqueryin().
{ struct TSQueryParserStateData state; int i; TSQuery query; int commonlen; QueryItem *ptr; ListCell *cell; /* init state */ state.buffer = buf; state.buf = buf; state.state = (isplain) ? WAITSINGLEOPERAND : WAITFIRSTOPERAND; state.count = 0; state.polstr = NIL; /* init value parser's state */ state.valstate = init_tsvector_parser(state.buffer, true, true); /* init list of operand */ state.sumlen = 0; state.lenop = 64; state.curop = state.op = (char *) palloc(state.lenop); *(state.curop) = '\0'; /* parse query & make polish notation (postfix, but in reverse order) */ makepol(&state, pushval, opaque); close_tsvector_parser(state.valstate); if (list_length(state.polstr) == 0) { ereport(NOTICE, (errmsg("text-search query doesn't contain lexemes: \"%s\"", state.buffer))); query = (TSQuery) palloc(HDRSIZETQ); SET_VARSIZE(query, HDRSIZETQ); query->size = 0; return query; } /* Pack the QueryItems in the final TSQuery struct to return to caller */ commonlen = COMPUTESIZE(list_length(state.polstr), state.sumlen); query = (TSQuery) palloc0(commonlen); SET_VARSIZE(query, commonlen); query->size = list_length(state.polstr); ptr = GETQUERY(query); /* Copy QueryItems to TSQuery */ i = 0; foreach(cell, state.polstr) { QueryItem *item = (QueryItem *) lfirst(cell); switch (item->type) { case QI_VAL: memcpy(&ptr[i], item, sizeof(QueryOperand)); break; case QI_VALSTOP: ptr[i].type = QI_VALSTOP; break; case QI_OPR: memcpy(&ptr[i], item, sizeof(QueryOperator)); break; default: elog(ERROR, "unrecognized QueryItem type: %d", item->type); } i++; } /* Copy all the operand strings to TSQuery */ memcpy((void *) GETOPERAND(query), (void *) state.op, state.sumlen); pfree(state.op); /* Set left operand pointers for every operator. */ findoprnd(ptr, query->size); return query; }
void pushOperator | ( | TSQueryParserState | state, | |
int8 | oper | |||
) |
Definition at line 225 of file tsquery.c.
References Assert, lcons(), OP_AND, OP_NOT, OP_OR, QueryOperator::oper, palloc0(), TSQueryParserStateData::polstr, and QueryOperator::type.
Referenced by makepol(), and pushval_morph().
void pushStop | ( | TSQueryParserState | state | ) |
Definition at line 309 of file tsquery.c.
References lcons(), palloc0(), TSQueryParserStateData::polstr, and QueryOperand::type.
Referenced by pushval_morph().
{ QueryOperand *tmp; tmp = (QueryOperand *) palloc0(sizeof(QueryOperand)); tmp->type = QI_VALSTOP; state->polstr = lcons(tmp, state->polstr); }
static void pushval_asis | ( | Datum | opaque, | |
TSQueryParserState | state, | |||
char * | strval, | |||
int | lenval, | |||
int16 | weight, | |||
bool | prefix | |||
) | [static] |
Definition at line 558 of file tsquery.c.
References pushValue().
Referenced by tsqueryin().
{ pushValue(state, strval, lenval, weight, prefix); }
void pushValue | ( | TSQueryParserState | state, | |
char * | strval, | |||
int | lenval, | |||
int16 | weight, | |||
bool | prefix | |||
) |
Definition at line 273 of file tsquery.c.
References TSQueryParserStateData::buffer, COMP_CRC32, TSQueryParserStateData::curop, ereport, errcode(), errmsg(), ERROR, FIN_CRC32, INIT_CRC32, TSQueryParserStateData::lenop, MAXSTRLEN, TSQueryParserStateData::op, pushValue_internal(), repalloc(), and TSQueryParserStateData::sumlen.
Referenced by pushval_asis(), and pushval_morph().
{ pg_crc32 valcrc; if (lenval >= MAXSTRLEN) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("word is too long in tsquery: \"%s\"", state->buffer))); INIT_CRC32(valcrc); COMP_CRC32(valcrc, strval, lenval); FIN_CRC32(valcrc); pushValue_internal(state, valcrc, state->curop - state->op, lenval, weight, prefix); /* append the value string to state.op, enlarging buffer if needed first */ while (state->curop - state->op + lenval + 1 >= state->lenop) { int used = state->curop - state->op; state->lenop *= 2; state->op = (char *) repalloc((void *) state->op, state->lenop); state->curop = state->op + used; } memcpy((void *) state->curop, (void *) strval, lenval); state->curop += lenval; *(state->curop) = '\0'; state->curop++; state->sumlen += lenval + 1 /* \0 */ ; }
static void pushValue_internal | ( | TSQueryParserState | state, | |
pg_crc32 | valcrc, | |||
int | distance, | |||
int | lenval, | |||
int | weight, | |||
bool | prefix | |||
) | [static] |
Definition at line 240 of file tsquery.c.
References TSQueryParserStateData::buffer, QueryOperand::distance, ereport, errcode(), errmsg(), ERROR, lcons(), QueryOperand::length, MAXSTRLEN, MAXSTRPOS, palloc0(), TSQueryParserStateData::polstr, QueryOperand::prefix, QueryOperand::type, QueryOperand::valcrc, and QueryOperand::weight.
Referenced by pushValue().
{ QueryOperand *tmp; if (distance >= MAXSTRPOS) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("value is too big in tsquery: \"%s\"", state->buffer))); if (lenval >= MAXSTRLEN) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("operand is too long in tsquery: \"%s\"", state->buffer))); tmp = (QueryOperand *) palloc0(sizeof(QueryOperand)); tmp->type = QI_VAL; tmp->weight = weight; tmp->prefix = prefix; tmp->valcrc = (int32) valcrc; tmp->length = lenval; tmp->distance = distance; state->polstr = lcons(tmp, state->polstr); }
Datum tsqueryin | ( | PG_FUNCTION_ARGS | ) |
Definition at line 568 of file tsquery.c.
References NULL, parse_tsquery(), PG_GETARG_CSTRING, PG_RETURN_TSQUERY, PointerGetDatum, and pushval_asis().
{ char *in = PG_GETARG_CSTRING(0); PG_RETURN_TSQUERY(parse_tsquery(in, pushval_asis, PointerGetDatum(NULL), false)); }
Datum tsqueryout | ( | PG_FUNCTION_ARGS | ) |
Definition at line 748 of file tsquery.c.
References INFIX::buf, INFIX::buflen, INFIX::cur, INFIX::curpol, GETOPERAND, GETQUERY, infix(), INFIX::op, palloc(), PG_FREE_IF_COPY, PG_GETARG_TSQUERY, PG_RETURN_CSTRING, PG_RETURN_POINTER, and TSQueryData::size.
{ TSQuery query = PG_GETARG_TSQUERY(0); INFIX nrm; if (query->size == 0) { char *b = palloc(1); *b = '\0'; PG_RETURN_POINTER(b); } nrm.curpol = GETQUERY(query); nrm.buflen = 32; nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen); *(nrm.cur) = '\0'; nrm.op = GETOPERAND(query); infix(&nrm, true); PG_FREE_IF_COPY(query, 0); PG_RETURN_CSTRING(nrm.buf); }
Datum tsqueryrecv | ( | PG_FUNCTION_ARGS | ) |
Definition at line 825 of file tsquery.c.
References Assert, buf, COMP_CRC32, QueryOperand::distance, elog, ERROR, FIN_CRC32, findoprnd(), GETOPERAND, GETQUERY, HDRSIZETQ, i, INIT_CRC32, QueryOperand::length, MaxAllocSize, MAXSTRLEN, MAXSTRPOS, OP_AND, OP_NOT, OP_OR, QueryOperator::oper, palloc(), palloc0(), pfree(), PG_GETARG_POINTER, PG_RETURN_TSVECTOR, pq_getmsgint(), pq_getmsgstring(), QueryOperand::prefix, QI_OPR, QI_VAL, QueryItem::qoperand, QueryItem::qoperator, repalloc(), SET_VARSIZE, QueryItem::type, val, QueryOperand::valcrc, and QueryOperand::weight.
{ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); TSQuery query; int i, len; QueryItem *item; int datalen; char *ptr; uint32 size; const char **operands; size = pq_getmsgint(buf, sizeof(uint32)); if (size > (MaxAllocSize / sizeof(QueryItem))) elog(ERROR, "invalid size of tsquery"); /* Allocate space to temporarily hold operand strings */ operands = palloc(size * sizeof(char *)); /* Allocate space for all the QueryItems. */ len = HDRSIZETQ + sizeof(QueryItem) * size; query = (TSQuery) palloc0(len); query->size = size; item = GETQUERY(query); datalen = 0; for (i = 0; i < size; i++) { item->type = (int8) pq_getmsgint(buf, sizeof(int8)); if (item->type == QI_VAL) { size_t val_len; /* length after recoding to server encoding */ uint8 weight; uint8 prefix; const char *val; pg_crc32 valcrc; weight = (uint8) pq_getmsgint(buf, sizeof(uint8)); prefix = (uint8) pq_getmsgint(buf, sizeof(uint8)); val = pq_getmsgstring(buf); val_len = strlen(val); /* Sanity checks */ if (weight > 0xF) elog(ERROR, "invalid tsquery: invalid weight bitmap"); if (val_len > MAXSTRLEN) elog(ERROR, "invalid tsquery: operand too long"); if (datalen > MAXSTRPOS) elog(ERROR, "invalid tsquery: total operand length exceeded"); /* Looks valid. */ INIT_CRC32(valcrc); COMP_CRC32(valcrc, val, val_len); FIN_CRC32(valcrc); item->qoperand.weight = weight; item->qoperand.prefix = (prefix) ? true : false; item->qoperand.valcrc = (int32) valcrc; item->qoperand.length = val_len; item->qoperand.distance = datalen; /* * Operand strings are copied to the final struct after this loop; * here we just collect them to an array */ operands[i] = val; datalen += val_len + 1; /* + 1 for the '\0' terminator */ } else if (item->type == QI_OPR) { int8 oper; oper = (int8) pq_getmsgint(buf, sizeof(int8)); if (oper != OP_NOT && oper != OP_OR && oper != OP_AND) elog(ERROR, "invalid tsquery: unrecognized operator type %d", (int) oper); if (i == size - 1) elog(ERROR, "invalid pointer to right operand"); item->qoperator.oper = oper; } else elog(ERROR, "unrecognized tsquery node type: %d", item->type); item++; } /* Enlarge buffer to make room for the operand values. */ query = (TSQuery) repalloc(query, len + datalen); item = GETQUERY(query); ptr = GETOPERAND(query); /* * Fill in the left-pointers. Checks that the tree is well-formed as a * side-effect. */ findoprnd(item, size); /* Copy operands to output struct */ for (i = 0; i < size; i++) { if (item->type == QI_VAL) { memcpy(ptr, operands[i], item->qoperand.length + 1); ptr += item->qoperand.length + 1; } item++; } pfree(operands); Assert(ptr - GETOPERAND(query) == datalen); SET_VARSIZE(query, len + datalen); PG_RETURN_TSVECTOR(query); }
Datum tsquerysend | ( | PG_FUNCTION_ARGS | ) |
Definition at line 789 of file tsquery.c.
References buf, QueryOperand::distance, elog, ERROR, GETOPERAND, GETQUERY, i, QueryOperator::oper, PG_FREE_IF_COPY, PG_GETARG_TSQUERY, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), pq_sendint(), pq_sendstring(), QueryOperand::prefix, QI_OPR, QI_VAL, QueryItem::qoperand, QueryItem::qoperator, TSQueryData::size, QueryItem::type, and QueryOperand::weight.
{ TSQuery query = PG_GETARG_TSQUERY(0); StringInfoData buf; int i; QueryItem *item = GETQUERY(query); pq_begintypsend(&buf); pq_sendint(&buf, query->size, sizeof(uint32)); for (i = 0; i < query->size; i++) { pq_sendint(&buf, item->type, sizeof(item->type)); switch (item->type) { case QI_VAL: pq_sendint(&buf, item->qoperand.weight, sizeof(uint8)); pq_sendint(&buf, item->qoperand.prefix, sizeof(uint8)); pq_sendstring(&buf, GETOPERAND(query) + item->qoperand.distance); break; case QI_OPR: pq_sendint(&buf, item->qoperator.oper, sizeof(item->qoperator.oper)); break; default: elog(ERROR, "unrecognized tsquery node type: %d", item->type); } item++; } PG_FREE_IF_COPY(query, 0); PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); }
Datum tsquerytree | ( | PG_FUNCTION_ARGS | ) |
Definition at line 954 of file tsquery.c.
References INFIX::buf, INFIX::buflen, clean_NOT(), cstring_to_text(), cstring_to_text_with_len(), INFIX::cur, INFIX::curpol, GETOPERAND, GETQUERY, infix(), INFIX::op, palloc(), pfree(), PG_FREE_IF_COPY, PG_GETARG_TSQUERY, PG_RETURN_POINTER, PG_RETURN_TEXT_P, SET_VARSIZE, TSQueryData::size, and VARHDRSZ.
{ TSQuery query = PG_GETARG_TSQUERY(0); INFIX nrm; text *res; QueryItem *q; int len; if (query->size == 0) { res = (text *) palloc(VARHDRSZ); SET_VARSIZE(res, VARHDRSZ); PG_RETURN_POINTER(res); } q = clean_NOT(GETQUERY(query), &len); if (!q) { res = cstring_to_text("T"); } else { nrm.curpol = q; nrm.buflen = 32; nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen); *(nrm.cur) = '\0'; nrm.op = GETOPERAND(query); infix(&nrm, true); res = cstring_to_text_with_len(nrm.buf, nrm.cur - nrm.buf); pfree(q); } PG_FREE_IF_COPY(query, 0); PG_RETURN_TEXT_P(res); }