56 #define STATENTRYHDRSZ (offsetof(StatEntry, lexeme))
92 else if (
a->size <
b->size)
94 else if (
a->size >
b->size)
104 for (
i = 0;
i <
a->size;
i++)
145 #define TSVECTORCMPFUNC( type, action, ret ) \
147 tsvector_##type(PG_FUNCTION_ARGS) \
149 TSVector a = PG_GETARG_TSVECTOR(0); \
150 TSVector b = PG_GETARG_TSVECTOR(1); \
151 int res = silly_cmp_tsvector(a, b); \
152 PG_FREE_IF_COPY(a,0); \
153 PG_FREE_IF_COPY(b,1); \
154 PG_RETURN_##ret( res action 0 ); \
157 extern int no_such_variable
190 arrout[
i].haspos = 0;
191 arrout[
i].len = arrin[
i].
len;
193 cur += arrout[
i].len;
242 elog(
ERROR,
"unrecognized weight: %d", cw);
308 elog(
ERROR,
"unrecognized weight: %c", char_weight);
312 memcpy(tsout, tsin,
VARSIZE(tsin));
322 for (
i = 0;
i < nlexemes;
i++)
336 if (lex_pos >= 0 && (
j =
POSDATALEN(tsout, entry + lex_pos)) != 0)
354 #define compareEntry(pa, a, pb, b) \
355 tsCompareString((pa) + (a)->pos, (a)->len, \
356 (pb) + (b)->pos, (b)->len, \
389 if (*clen != startlen)
391 return *clen - startlen;
404 StopHigh = tsv->
size,
408 while (StopLow < StopHigh)
410 StopMiddle = (StopLow + StopHigh) / 2;
413 STRPTR(tsv) + arrin[StopMiddle].pos,
414 arrin[StopMiddle].
len,
418 StopHigh = StopMiddle;
420 StopLow = StopMiddle + 1;
435 int a = *((
const int *) va);
436 int b = *((
const int *) vb);
482 if (indices_count > 1)
485 indices_count =
qunique(indices_to_delete, indices_count,
sizeof(
int),
496 tsout->
size = tsv->
size - indices_count;
504 for (
i =
j = k = 0;
i < tsv->
size;
i++)
511 if (k < indices_count &&
i == indices_to_delete[k])
518 memcpy(dataout + curoff,
data + arrin[
i].pos, arrin[
i].
len);
520 arrout[
j].len = arrin[
i].
len;
521 arrout[
j].pos = curoff;
522 curoff += arrin[
i].
len;
529 memcpy(dataout + curoff,
543 Assert(k == indices_count);
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);
653 elog(
ERROR,
"return type must be a row type");
671 bool nulls[] = {
false,
false,
false};
691 for (
j = 0;
j < posv->
npos;
j++)
704 nulls[1] = nulls[2] =
true;
730 for (
i = 0;
i < tsin->
size;
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")));
804 memcpy(
cur, lex, lex_len);
806 arrout[
i].
len = lex_len;
826 char *datain =
STRPTR(tsin),
838 for (
i = 0;
i < nweights;
i++)
844 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
845 errmsg(
"weight array may not contain nulls")));
868 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
869 errmsg(
"unrecognized weight: \"%c\"", char_weight)));
874 tsout->size = tsin->
size;
878 for (
i =
j = 0;
i < tsin->
size;
i++)
885 if (!arrin[
i].haspos)
892 for (k = 0; k < posvin->
npos; k++)
895 posvout->
pos[npos++] = posvin->
pos[k];
902 arrout[
j].haspos =
true;
903 arrout[
j].len = arrin[
i].
len;
904 arrout[
j].pos = cur_pos;
906 memcpy(dataout + cur_pos, datain + arrin[
i].pos, arrin[
i].
len);
907 posvout->
npos = npos;
915 if (dataout !=
STRPTR(tsout))
916 memmove(
STRPTR(tsout), dataout, cur_pos);
998 memcpy(
data + dataoff, data1 + ptr1->
pos, ptr1->
len);
1000 dataoff += ptr1->
len;
1016 memcpy(
data + dataoff, data2 + ptr2->
pos, ptr2->
len);
1018 dataoff += ptr2->
len;
1021 int addlen =
add_pos(in2, ptr2, out, ptr, maxpos);
1040 memcpy(
data + dataoff, data1 + ptr1->
pos, ptr1->
len);
1042 dataoff += ptr1->
len;
1055 int addlen =
add_pos(in2, ptr2, out, ptr, maxpos);
1079 memcpy(
data + dataoff, data1 + ptr1->
pos, ptr1->
len);
1081 dataoff += ptr1->
len;
1098 memcpy(
data + dataoff, data2 + ptr2->
pos, ptr2->
len);
1100 dataoff += ptr2->
len;
1103 int addlen =
add_pos(in2, ptr2, out, ptr, maxpos);
1125 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1126 errmsg(
"string is too long for tsvector (%d bytes, max %d bytes)", dataoff,
MAXSTRPOS)));
1132 output_size = ptr -
ARRPTR(out);
1134 out->
size = output_size;
1161 cmp = (lenb > 0) ? -1 : 0;
1165 cmp = (lena > 0) ? 1 : 0;
1169 cmp = memcmp(
a,
b,
Min((
unsigned int) lena, (
unsigned int) lenb));
1173 if (
cmp == 0 && lena > lenb)
1176 else if (
cmp == 0 && lena != lenb)
1178 cmp = (lena < lenb) ? -1 : 1;
1216 data->allocated =
true;
1219 while (posvec_iter < posvec->pos + posvec->
npos)
1239 data->allocated =
false;
1242 else if (
val->weight)
1247 while (posvec_iter < posvec->pos + posvec->
npos)
1262 data->allocated =
false;
1304 while (StopLow < StopHigh)
1308 StopMiddle = StopLow + (StopHigh - StopLow) / 2;
1322 StopLow = StopMiddle + 1;
1324 StopHigh = StopMiddle;
1341 if (StopLow >= StopHigh)
1342 StopMiddle = StopHigh;
1347 if (
data->allocated)
1350 data->allocated =
false;
1356 StopMiddle < chkval->arre &&
1367 if (subres !=
TS_NO)
1389 while (npos +
data->npos > totalpos)
1407 if (
data->allocated)
1410 data->allocated =
false;
1425 if (
data && npos > 0)
1432 data->allocated =
true;
1463 #define TSPO_L_ONLY 0x01
1464 #define TSPO_R_ONLY 0x02
1465 #define TSPO_BOTH 0x04
1480 Lindex = Rindex = 0;
1481 while (Lindex < Ldata->npos || Rindex < Rdata->npos)
1491 if (Lindex < Ldata->npos)
1500 if (Rindex < Rdata->npos)
1518 else if (Lpos == Rpos)
1539 if (
data->pos == NULL)
1543 data->allocated =
true;
1545 data->pos[
data->npos++] = output_pos;
1642 data->negate =
true;
1650 data->negate =
true;
1659 else if (
data->negate)
1662 data->negate =
false;
1676 memset(&Ldata, 0,
sizeof(Ldata));
1677 memset(&Rdata, 0,
sizeof(Rdata));
1680 arg, flags, chkcond, &Ldata);
1681 if (lmatch ==
TS_NO)
1685 arg, flags, chkcond, &Rdata);
1686 if (rmatch ==
TS_NO)
1715 Loffset = maxwidth - Ldata.
width;
1716 Roffset = maxwidth - Rdata.
width;
1718 data->width = maxwidth;
1729 data->negate =
true;
1758 memset(&Ldata, 0,
sizeof(Ldata));
1759 memset(&Rdata, 0,
sizeof(Rdata));
1762 arg, flags, chkcond, &Ldata);
1764 arg, flags, chkcond, &Rdata);
1781 if (lmatch ==
TS_NO)
1783 if (rmatch ==
TS_NO)
1793 Loffset = maxwidth - Ldata.
width;
1794 Roffset = maxwidth - Rdata.
width;
1795 data->width = maxwidth;
1804 data->negate =
true;
1814 data->negate =
true;
1824 data->negate =
true;
1917 if (lmatch ==
TS_NO)
2083 if (lmatch || rmatch)
2093 if (llocations ==
NIL)
2094 *locations = rlocations;
2095 else if (rlocations ==
NIL)
2096 *locations = llocations;
2101 foreach(ll, llocations)
2106 foreach(lr, rlocations)
2310 #define compareStatWord(a,e,t) \
2311 tsCompareString((a)->lexeme, (a)->lenlexeme, \
2312 STRPTR(t) + (e)->pos, (e)->len, \
2325 if (
stat->weight == 0)
2349 if (depth >
stat->maxdepth)
2350 stat->maxdepth = depth;
2370 pnode->
right = node;
2385 uint32 middle = (low + high) >> 1;
2387 pos = (low + middle) >> 1;
2388 if (low != middle && pos >= offset && pos - offset < txt->
size)
2390 pos = (high + middle + 1) >> 1;
2391 if (middle + 1 != high && pos >= offset && pos - offset < txt->
size)
2396 if (high != middle + 1)
2427 if (txt == NULL || txt->
size == 0)
2435 for (;
i > 0;
i >>= 1)
2439 offset = (nbit - txt->
size) / 2;
2465 stat->stack[
stat->stackpos] = NULL;
2469 stat->stack[
stat->stackpos] = node;
2481 elog(
ERROR,
"return type must be a row type");
2496 if (node->
ndoc != 0)
2510 stat->stack[
stat->stackpos] = node;
2524 if (
stat->stackpos == 0)
2585 elog(
ERROR,
"SPI_prepare(\"%s\") failed", query);
2589 elog(
ERROR,
"SPI_cursor_open(\"%s\") failed", query);
2598 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2599 errmsg(
"ts_stat query must return one tsvector column")));
2617 stat->weight |= 1 << 3;
2621 stat->weight |= 1 << 2;
2625 stat->weight |= 1 << 1;
2745 int tsvector_attr_num,
2756 elog(
ERROR,
"tsvector_update_trigger: not fired by trigger manager");
2760 elog(
ERROR,
"tsvector_update_trigger: must be fired for row");
2762 elog(
ERROR,
"tsvector_update_trigger: must be fired BEFORE event");
2767 update_needed =
true;
2772 update_needed =
false;
2775 elog(
ERROR,
"tsvector_update_trigger: must be fired for INSERT or UPDATE");
2781 elog(
ERROR,
"tsvector_update_trigger: arguments must be tsvector_field, ts_config, text_field1, ...)");
2787 (
errcode(ERRCODE_UNDEFINED_COLUMN),
2788 errmsg(
"tsvector column \"%s\" does not exist",
2794 (
errcode(ERRCODE_DATATYPE_MISMATCH),
2795 errmsg(
"column \"%s\" is not of tsvector type",
2801 int config_attr_num;
2806 (
errcode(ERRCODE_UNDEFINED_COLUMN),
2807 errmsg(
"configuration column \"%s\" does not exist",
2812 (
errcode(ERRCODE_DATATYPE_MISMATCH),
2813 errmsg(
"column \"%s\" is not of regconfig type",
2819 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
2820 errmsg(
"configuration column \"%s\" must not be null",
2832 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2833 errmsg(
"text search configuration name \"%s\" must be schema-qualified",
2852 (
errcode(ERRCODE_UNDEFINED_COLUMN),
2853 errmsg(
"column \"%s\" does not exist",
2857 (
errcode(ERRCODE_DATATYPE_MISMATCH),
2858 errmsg(
"column \"%s\" is not of a character type",
2862 update_needed =
true;
2884 1, &tsvector_attr_num,
#define PG_GETARG_ARRAYTYPE_P(n)
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
bool bms_is_member(int x, const Bitmapset *a)
static Datum values[MAXATTR]
#define Assert(condition)
#define FLEXIBLE_ARRAY_MEMBER
static void PGresult * res
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
AttInMetadata * TupleDescGetAttInMetadata(TupleDesc tupdesc)
#define palloc0_object(type)
#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)
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
#define SRF_IS_FIRSTCALL()
#define SRF_PERCALL_SETUP()
#define SRF_RETURN_NEXT(_funcctx, _result)
#define SRF_FIRSTCALL_INIT()
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
#define SRF_RETURN_DONE(_funcctx)
Datum difference(PG_FUNCTION_ARGS)
HeapTuple heap_modify_tuple_by_cols(HeapTuple tuple, TupleDesc tupleDesc, int nCols, const int *replCols, const Datum *replValues, const bool *replIsnull)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
#define CALCDATASIZE(x, lenstr)
static int pg_cmp_s32(int32 a, int32 b)
if(TABLE==NULL||TABLE_index==NULL)
List * lappend(List *list, void *datum)
List * list_concat(List *list1, const List *list2)
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)
bool IsBinaryCoercible(Oid srctype, Oid targettype)
static int list_length(const List *l)
#define qsort(a, b, c, d)
void check_stack_depth(void)
static bool DatumGetBool(Datum X)
static Datum PointerGetDatum(const void *X)
static Oid DatumGetObjectId(Datum X)
static Datum Int16GetDatum(int16 X)
static Pointer DatumGetPointer(Datum X)
static char DatumGetChar(Datum X)
static size_t qunique(void *array, size_t elements, size_t width, int(*compare)(const void *, const void *))
MemoryContextSwitchTo(old_ctx)
static int cmp(const chr *x, const chr *y, size_t len)
List * stringToQualifiedNameList(const char *string, Node *escontext)
static pg_noinline void Size size
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)
static TSQuery DatumGetTSQuery(Datum X)
static TSVector DatumGetTSVector(Datum X)
static Datum TSVectorGetDatum(const TSVectorData *X)
#define PG_GETARG_TSQUERY(n)
#define PG_GETARG_TSVECTOR_COPY(n)
#define WEP_SETWEIGHT(x, v)
static Datum TSQueryGetDatum(const TSQueryData *X)
#define TS_EXEC_PHRASE_NO_POS
TSTernaryValue(* TSExecuteCallback)(void *arg, QueryOperand *val, ExecPhraseData *data)
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 bool TS_execute_locations_recurse(QueryItem *curitem, void *arg, TSExecuteCallback chkcond, List **locations)
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)
List * TS_execute_locations(QueryItem *curitem, void *arg, uint32 flags, TSExecuteCallback chkcond)
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)
#define SET_VARSIZE(PTR, len)
#define VARSIZE_ANY_EXHDR(PTR)
char * text_to_cstring(const text *t)
text * cstring_to_text_with_len(const char *s, int len)