56 #define STATENTRYHDRSZ (offsetof(StatEntry, lexeme))
88 else if (
a->size <
b->size)
90 else if (
a->size >
b->size)
100 for (
i = 0;
i <
a->size;
i++)
141 #define TSVECTORCMPFUNC( type, action, ret ) \
143 tsvector_##type(PG_FUNCTION_ARGS) \
145 TSVector a = PG_GETARG_TSVECTOR(0); \
146 TSVector b = PG_GETARG_TSVECTOR(1); \
147 int res = silly_cmp_tsvector(a, b); \
148 PG_FREE_IF_COPY(a,0); \
149 PG_FREE_IF_COPY(b,1); \
150 PG_RETURN_##ret( res action 0 ); \
153 extern int no_such_variable
186 arrout[
i].haspos = 0;
187 arrout[
i].len = arrin[
i].
len;
189 cur += arrout[
i].len;
238 elog(
ERROR,
"unrecognized weight: %d", cw);
304 elog(
ERROR,
"unrecognized weight: %c", char_weight);
308 memcpy(tsout, tsin,
VARSIZE(tsin));
312 &dlexemes, &nulls, &nlexemes);
319 for (
i = 0;
i < nlexemes;
i++)
333 if (lex_pos >= 0 && (
j =
POSDATALEN(tsout, entry + lex_pos)) != 0)
351 #define compareEntry(pa, a, pb, b) \
352 tsCompareString((pa) + (a)->pos, (a)->len, \
353 (pb) + (b)->pos, (b)->len, \
386 if (*clen != startlen)
388 return *clen - startlen;
401 StopHigh = tsv->
size,
405 while (StopLow < StopHigh)
407 StopMiddle = (StopLow + StopHigh) / 2;
410 STRPTR(tsv) + arrin[StopMiddle].pos,
411 arrin[StopMiddle].
len,
415 StopHigh = StopMiddle;
417 StopLow = StopMiddle + 1;
432 int a = *((
const int *) va);
433 int b = *((
const int *) vb);
437 return (
a >
b) ? 1 : -1;
481 if (indices_count > 1)
484 indices_count =
qunique(indices_to_delete, indices_count,
sizeof(
int),
495 tsout->
size = tsv->
size - indices_count;
503 for (
i =
j = k = 0;
i < tsv->
size;
i++)
510 if (k < indices_count &&
i == indices_to_delete[k])
517 memcpy(dataout + curoff,
data + arrin[
i].pos, arrin[
i].
len);
519 arrout[
j].len = arrin[
i].
len;
520 arrout[
j].pos = curoff;
521 curoff += arrin[
i].
len;
528 memcpy(dataout + curoff,
542 Assert(k == indices_count);
590 &dlexemes, &nulls, &nlex);
597 skip_indices =
palloc0(nlex *
sizeof(
int));
598 for (
i = skip_count = 0;
i < nlex;
i++)
613 skip_indices[skip_count++] = lex_pos;
649 INT2ARRAYOID, -1, 0);
651 TEXTARRAYOID, -1, 0);
669 bool nulls[] = {
false,
false,
false};
689 for (
j = 0;
j < posv->
npos;
j++)
698 INT2OID, 2,
true, TYPALIGN_SHORT));
700 TEXTOID, -1,
false, TYPALIGN_INT));
704 nulls[1] = nulls[2] =
true;
730 for (
i = 0;
i < tsin->
size;
i++)
760 deconstruct_array(v, TEXTOID, -1,
false, TYPALIGN_INT, &dlexemes, &nulls, &nitems);
766 for (
i = 0;
i < nitems;
i++)
770 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
771 errmsg(
"lexeme array may not contain nulls")));
775 (
errcode(ERRCODE_ZERO_LENGTH_CHARACTER_STRING),
776 errmsg(
"lexeme array may not contain empty strings")));
788 for (
i = 0;
i < nitems;
i++)
795 tsout->
size = nitems;
799 for (
i = 0;
i < nitems;
i++)
804 memcpy(
cur, lex, lex_len);
806 arrout[
i].
len = lex_len;
826 char *datain =
STRPTR(tsin),
837 &dweights, &nulls, &nweights);
839 for (
i = 0;
i < nweights;
i++)
845 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
846 errmsg(
"weight array may not contain nulls")));
869 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
870 errmsg(
"unrecognized weight: \"%c\"", char_weight)));
875 tsout->size = tsin->
size;
879 for (
i =
j = 0;
i < tsin->
size;
i++)
886 if (!arrin[
i].haspos)
893 for (k = 0; k < posvin->
npos; k++)
896 posvout->
pos[npos++] = posvin->
pos[k];
903 arrout[
j].haspos =
true;
904 arrout[
j].len = arrin[
i].
len;
905 arrout[
j].pos = cur_pos;
907 memcpy(dataout + cur_pos, datain + arrin[
i].pos, arrin[
i].
len);
908 posvout->
npos = npos;
916 if (dataout !=
STRPTR(tsout))
917 memmove(
STRPTR(tsout), dataout, cur_pos);
999 memcpy(
data + dataoff, data1 + ptr1->
pos, ptr1->
len);
1001 dataoff += ptr1->
len;
1017 memcpy(
data + dataoff, data2 + ptr2->
pos, ptr2->
len);
1019 dataoff += ptr2->
len;
1022 int addlen =
add_pos(in2, ptr2, out, ptr, maxpos);
1041 memcpy(
data + dataoff, data1 + ptr1->
pos, ptr1->
len);
1043 dataoff += ptr1->
len;
1056 int addlen =
add_pos(in2, ptr2, out, ptr, maxpos);
1080 memcpy(
data + dataoff, data1 + ptr1->
pos, ptr1->
len);
1082 dataoff += ptr1->
len;
1099 memcpy(
data + dataoff, data2 + ptr2->
pos, ptr2->
len);
1101 dataoff += ptr2->
len;
1104 int addlen =
add_pos(in2, ptr2, out, ptr, maxpos);
1126 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1127 errmsg(
"string is too long for tsvector (%d bytes, max %d bytes)", dataoff,
MAXSTRPOS)));
1133 output_size = ptr -
ARRPTR(out);
1134 Assert(output_size <= out->size);
1135 out->
size = output_size;
1162 cmp = (lenb > 0) ? -1 : 0;
1166 cmp = (lena > 0) ? 1 : 0;
1170 cmp = memcmp(
a,
b,
Min((
unsigned int) lena, (
unsigned int) lenb));
1174 if (
cmp == 0 && lena > lenb)
1177 else if (
cmp == 0 && lena != lenb)
1179 cmp = (lena < lenb) ? -1 : 1;
1217 data->allocated =
true;
1220 while (posvec_iter < posvec->pos + posvec->
npos)
1240 data->allocated =
false;
1243 else if (
val->weight)
1248 while (posvec_iter < posvec->pos + posvec->
npos)
1263 data->allocated =
false;
1305 while (StopLow < StopHigh)
1309 StopMiddle = StopLow + (StopHigh - StopLow) / 2;
1323 StopLow = StopMiddle + 1;
1325 StopHigh = StopMiddle;
1342 if (StopLow >= StopHigh)
1343 StopMiddle = StopHigh;
1348 if (
data->allocated)
1351 data->allocated =
false;
1357 StopMiddle < chkval->arre &&
1368 if (subres !=
TS_NO)
1390 while (npos +
data->npos > totalpos)
1408 if (
data->allocated)
1411 data->allocated =
false;
1426 if (
data && npos > 0)
1433 data->allocated =
true;
1464 #define TSPO_L_ONLY 0x01
1465 #define TSPO_R_ONLY 0x02
1466 #define TSPO_BOTH 0x04
1481 Lindex = Rindex = 0;
1482 while (Lindex < Ldata->npos || Rindex < Rdata->npos)
1492 if (Lindex < Ldata->npos)
1501 if (Rindex < Rdata->npos)
1519 else if (Lpos == Rpos)
1540 if (
data->pos == NULL)
1544 data->allocated =
true;
1546 data->pos[
data->npos++] = output_pos;
1640 data->negate =
true;
1648 data->negate =
true;
1657 else if (
data->negate)
1660 data->negate =
false;
1674 memset(&Ldata, 0,
sizeof(Ldata));
1675 memset(&Rdata, 0,
sizeof(Rdata));
1678 arg, flags, chkcond, &Ldata);
1679 if (lmatch ==
TS_NO)
1683 arg, flags, chkcond, &Rdata);
1684 if (rmatch ==
TS_NO)
1713 Loffset = maxwidth - Ldata.
width;
1714 Roffset = maxwidth - Rdata.
width;
1716 data->width = maxwidth;
1727 data->negate =
true;
1756 memset(&Ldata, 0,
sizeof(Ldata));
1757 memset(&Rdata, 0,
sizeof(Rdata));
1760 arg, flags, chkcond, &Ldata);
1762 arg, flags, chkcond, &Rdata);
1779 if (lmatch ==
TS_NO)
1781 if (rmatch ==
TS_NO)
1791 Loffset = maxwidth - Ldata.
width;
1792 Roffset = maxwidth - Rdata.
width;
1793 data->width = maxwidth;
1802 data->negate =
true;
1812 data->negate =
true;
1822 data->negate =
true;
1915 if (lmatch ==
TS_NO)
2137 #define compareStatWord(a,e,t) \
2138 tsCompareString((a)->lexeme, (a)->lenlexeme, \
2139 STRPTR(t) + (e)->pos, (e)->len, \
2152 if (
stat->weight == 0)
2176 if (depth >
stat->maxdepth)
2177 stat->maxdepth = depth;
2197 pnode->
right = node;
2212 uint32 middle = (low + high) >> 1;
2214 pos = (low + middle) >> 1;
2215 if (low != middle && pos >= offset && pos - offset < txt->size)
2217 pos = (high + middle + 1) >> 1;
2218 if (middle + 1 != high && pos >= offset && pos - offset < txt->size)
2223 if (high != middle + 1)
2254 if (txt == NULL || txt->
size == 0)
2262 for (;
i > 0;
i >>= 1)
2266 offset = (nbit - txt->
size) / 2;
2292 stat->stack[
stat->stackpos] = NULL;
2296 stat->stack[
stat->stackpos] = node;
2328 if (node->
ndoc != 0)
2342 stat->stack[
stat->stackpos] = node;
2356 if (
stat->stackpos == 0)
2417 elog(
ERROR,
"SPI_prepare(\"%s\") failed", query);
2421 elog(
ERROR,
"SPI_cursor_open(\"%s\") failed", query);
2430 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2431 errmsg(
"ts_stat query must return one tsvector column")));
2449 stat->weight |= 1 << 3;
2453 stat->weight |= 1 << 2;
2457 stat->weight |= 1 << 1;
2577 int tsvector_attr_num,
2588 elog(
ERROR,
"tsvector_update_trigger: not fired by trigger manager");
2592 elog(
ERROR,
"tsvector_update_trigger: must be fired for row");
2594 elog(
ERROR,
"tsvector_update_trigger: must be fired BEFORE event");
2599 update_needed =
true;
2604 update_needed =
false;
2607 elog(
ERROR,
"tsvector_update_trigger: must be fired for INSERT or UPDATE");
2613 elog(
ERROR,
"tsvector_update_trigger: arguments must be tsvector_field, ts_config, text_field1, ...)");
2619 (
errcode(ERRCODE_UNDEFINED_COLUMN),
2620 errmsg(
"tsvector column \"%s\" does not exist",
2626 (
errcode(ERRCODE_DATATYPE_MISMATCH),
2627 errmsg(
"column \"%s\" is not of tsvector type",
2633 int config_attr_num;
2638 (
errcode(ERRCODE_UNDEFINED_COLUMN),
2639 errmsg(
"configuration column \"%s\" does not exist",
2644 (
errcode(ERRCODE_DATATYPE_MISMATCH),
2645 errmsg(
"column \"%s\" is not of regconfig type",
2651 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
2652 errmsg(
"configuration column \"%s\" must not be null",
2664 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2665 errmsg(
"text search configuration name \"%s\" must be schema-qualified",
2684 (
errcode(ERRCODE_UNDEFINED_COLUMN),
2685 errmsg(
"column \"%s\" does not exist",
2689 (
errcode(ERRCODE_DATATYPE_MISMATCH),
2690 errmsg(
"column \"%s\" is not of a character type",
2694 update_needed =
true;
2716 1, &tsvector_attr_num,
#define PG_GETARG_ARRAYTYPE_P(n)
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
bool bms_is_member(int x, const Bitmapset *a)
static Datum values[MAXATTR]
#define FLEXIBLE_ARRAY_MEMBER
static void PGresult * res
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
AttInMetadata * TupleDescGetAttInMetadata(TupleDesc tupdesc)
#define PG_FREE_IF_COPY(ptr, n)
#define PG_GETARG_TEXT_PP(n)
#define DirectFunctionCall2(func, arg1, arg2)
#define PG_GETARG_CHAR(n)
#define DatumGetTextPP(X)
#define DirectFunctionCall1(func, arg1)
#define PG_GETARG_DATUM(n)
#define PG_RETURN_INT32(x)
#define PG_RETURN_DATUM(x)
#define PG_RETURN_POINTER(x)
#define PG_RETURN_BOOL(x)
#define SRF_IS_FIRSTCALL()
#define SRF_PERCALL_SETUP()
#define HeapTupleGetDatum(tuple)
#define SRF_RETURN_NEXT(_funcctx, _result)
#define SRF_FIRSTCALL_INIT()
#define SRF_RETURN_DONE(_funcctx)
Datum difference(PG_FUNCTION_ARGS)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
HeapTuple heap_modify_tuple_by_cols(HeapTuple tuple, TupleDesc tupleDesc, int nCols, int *replCols, Datum *replValues, bool *replIsnull)
#define CALCDATASIZE(x, lenstr)
Assert(fmt[strlen(fmt) - 1] !='\n')
int pg_mblen(const char *mbstr)
void pfree(void *pointer)
void * palloc0(Size size)
void * MemoryContextAllocZero(MemoryContext context, Size size)
void * repalloc(void *pointer, Size size)
void * MemoryContextAlloc(MemoryContext context, Size size)
#define CHECK_FOR_INTERRUPTS()
Oid get_ts_config_oid(List *names, bool missing_ok)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
bool IsBinaryCoercible(Oid srctype, Oid targettype)
static int list_length(const List *l)
#define qsort(a, b, c, d)
void check_stack_depth(void)
#define DatumGetObjectId(X)
#define DatumGetPointer(X)
#define SET_VARSIZE(PTR, len)
#define PointerGetDatum(X)
#define VARSIZE_ANY_EXHDR(PTR)
static size_t qunique(void *array, size_t elements, size_t width, int(*compare)(const void *, const void *))
static int cmp(const chr *x, const chr *y, size_t len)
List * stringToQualifiedNameList(const char *string)
int SPI_fnumber(TupleDesc tupdesc, const char *fname)
Oid SPI_gettypeid(TupleDesc tupdesc, int fnumber)
int SPI_freeplan(SPIPlanPtr plan)
SPITupleTable * SPI_tuptable
void SPI_cursor_fetch(Portal portal, bool forward, long count)
void SPI_freetuptable(SPITupleTable *tuptable)
Portal SPI_cursor_open(const char *name, SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only)
SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes)
void SPI_cursor_close(Portal portal)
Datum SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)
#define SPI_ERROR_NOATTRIBUTE
AttInMetadata * attinmeta
MemoryContext multi_call_memory_ctx
char lexeme[FLEXIBLE_ARRAY_MEMBER]
const Bitmapset * tg_updatedcols
WordEntryPos pos[FLEXIBLE_ARRAY_MEMBER]
#define FirstLowInvalidHeapAttributeNumber
Datum to_tsvector(PG_FUNCTION_ARGS)
TSVector make_tsvector(ParsedText *prs)
Datum plainto_tsquery(PG_FUNCTION_ARGS)
#define TRIGGER_FIRED_BEFORE(event)
#define CALLED_AS_TRIGGER(fcinfo)
#define TRIGGER_FIRED_FOR_ROW(event)
#define TRIGGER_FIRED_BY_INSERT(event)
#define TRIGGER_FIRED_BY_UPDATE(event)
void parsetext(Oid cfgId, ParsedText *prs, char *buf, int buflen)
#define PG_GETARG_TSVECTOR(n)
#define TSQueryGetDatum(X)
#define PG_GETARG_TSQUERY(n)
#define DatumGetTSVector(X)
#define PG_GETARG_TSVECTOR_COPY(n)
#define WEP_SETWEIGHT(x, v)
#define DatumGetTSQuery(X)
#define TSVectorGetDatum(X)
#define TS_EXEC_PHRASE_NO_POS
TSTernaryValue(* TSExecuteCallback)(void *arg, QueryOperand *val, ExecPhraseData *data)
static const float weights[]
int compareWordEntryPos(const void *a, const void *b)
Datum tsvector_setweight_by_filter(PG_FUNCTION_ARGS)
static Datum ts_process_call(FuncCallContext *funcctx)
static TSTernaryValue checkcondition_str(void *checkval, QueryOperand *val, ExecPhraseData *data)
bool TS_execute(QueryItem *curitem, void *arg, uint32 flags, TSExecuteCallback chkcond)
Datum ts_match_vq(PG_FUNCTION_ARGS)
Datum tsvector_update_trigger_byid(PG_FUNCTION_ARGS)
static int32 add_pos(TSVector src, WordEntry *srcptr, TSVector dest, WordEntry *destptr, int32 maxpos)
Datum tsvector_delete_arr(PG_FUNCTION_ARGS)
Datum array_to_tsvector(PG_FUNCTION_ARGS)
Datum tsvector_filter(PG_FUNCTION_ARGS)
static TSTernaryValue TS_phrase_output(ExecPhraseData *data, ExecPhraseData *Ldata, ExecPhraseData *Rdata, int emit, int Loffset, int Roffset, int max_npos)
#define compareEntry(pa, a, pb, b)
Datum tsvector_setweight(PG_FUNCTION_ARGS)
#define TSVECTORCMPFUNC(type, action, ret)
static int check_weight(TSVector txt, WordEntry *wptr, int8 weight)
Datum tsvector_strip(PG_FUNCTION_ARGS)
struct StatEntry StatEntry
Datum tsvector_length(PG_FUNCTION_ARGS)
Datum tsvector_to_array(PG_FUNCTION_ARGS)
Datum ts_match_tq(PG_FUNCTION_ARGS)
Datum ts_stat1(PG_FUNCTION_ARGS)
int32 tsCompareString(char *a, int lena, char *b, int lenb, bool prefix)
Datum tsvector_delete_str(PG_FUNCTION_ARGS)
static Datum tsvector_update_trigger(PG_FUNCTION_ARGS, bool config_column)
Datum ts_match_qv(PG_FUNCTION_ARGS)
static int silly_cmp_tsvector(const TSVector a, const TSVector b)
static int tsvector_bsearch(const TSVector tsv, char *lexeme, int lexeme_len)
bool tsquery_requires_match(QueryItem *curitem)
Datum tsvector_concat(PG_FUNCTION_ARGS)
Datum tsvector_update_trigger_bycolumn(PG_FUNCTION_ARGS)
static TSTernaryValue TS_execute_recurse(QueryItem *curitem, void *arg, uint32 flags, TSExecuteCallback chkcond)
TSTernaryValue TS_execute_ternary(QueryItem *curitem, void *arg, uint32 flags, TSExecuteCallback chkcond)
static int compare_int(const void *va, const void *vb)
static StatEntry * walkStatEntryTree(TSVectorStat *stat)
static void ts_setup_firstcall(FunctionCallInfo fcinfo, FuncCallContext *funcctx, TSVectorStat *stat)
static void chooseNextStatEntry(MemoryContext persistentContext, TSVectorStat *stat, TSVector txt, uint32 low, uint32 high, uint32 offset)
Datum ts_match_tt(PG_FUNCTION_ARGS)
static TSVectorStat * ts_accum(MemoryContext persistentContext, TSVectorStat *stat, Datum data)
static TSTernaryValue TS_phrase_execute(QueryItem *curitem, void *arg, uint32 flags, TSExecuteCallback chkcond, ExecPhraseData *data)
static int compare_text_lexemes(const void *va, const void *vb)
static TSTernaryValue checkclass_str(CHKVAL *chkval, WordEntry *entry, QueryOperand *val, ExecPhraseData *data)
#define compareStatWord(a, e, t)
Datum tsvector_unnest(PG_FUNCTION_ARGS)
static TSVectorStat * ts_stat_sql(MemoryContext persistentContext, text *txt, text *ws)
Datum ts_stat2(PG_FUNCTION_ARGS)
static void insertStatEntry(MemoryContext persistentContext, TSVectorStat *stat, TSVector txt, uint32 off)
static TSVector tsvector_delete_by_indices(TSVector tsv, int *indices_to_delete, int indices_count)
TupleDesc CreateTemplateTupleDesc(int natts)
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
char * text_to_cstring(const text *t)
text * cstring_to_text_with_len(const char *s, int len)