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);
440 return (
a >
b) ? 1 : -1;
484 if (indices_count > 1)
487 indices_count =
qunique(indices_to_delete, indices_count,
sizeof(
int),
498 tsout->
size = tsv->
size - indices_count;
506 for (
i =
j = k = 0;
i < tsv->
size;
i++)
513 if (k < indices_count &&
i == indices_to_delete[k])
520 memcpy(dataout + curoff,
data + arrin[
i].pos, arrin[
i].
len);
522 arrout[
j].len = arrin[
i].
len;
523 arrout[
j].pos = curoff;
524 curoff += arrin[
i].
len;
531 memcpy(dataout + curoff,
545 Assert(k == indices_count);
599 skip_indices =
palloc0(nlex *
sizeof(
int));
600 for (
i = skip_count = 0;
i < nlex;
i++)
615 skip_indices[skip_count++] = lex_pos;
651 INT2ARRAYOID, -1, 0);
653 TEXTARRAYOID, -1, 0);
655 elog(
ERROR,
"return type must be a row type");
673 bool nulls[] = {
false,
false,
false};
693 for (
j = 0;
j < posv->
npos;
j++)
706 nulls[1] = nulls[2] =
true;
732 for (
i = 0;
i < tsin->
size;
i++)
772 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
773 errmsg(
"lexeme array may not contain nulls")));
777 (
errcode(ERRCODE_ZERO_LENGTH_CHARACTER_STRING),
778 errmsg(
"lexeme array may not contain empty strings")));
806 memcpy(
cur, lex, lex_len);
808 arrout[
i].
len = lex_len;
828 char *datain =
STRPTR(tsin),
840 for (
i = 0;
i < nweights;
i++)
846 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
847 errmsg(
"weight array may not contain nulls")));
870 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
871 errmsg(
"unrecognized weight: \"%c\"", char_weight)));
876 tsout->size = tsin->
size;
880 for (
i =
j = 0;
i < tsin->
size;
i++)
887 if (!arrin[
i].haspos)
894 for (k = 0; k < posvin->
npos; k++)
897 posvout->
pos[npos++] = posvin->
pos[k];
904 arrout[
j].haspos =
true;
905 arrout[
j].len = arrin[
i].
len;
906 arrout[
j].pos = cur_pos;
908 memcpy(dataout + cur_pos, datain + arrin[
i].pos, arrin[
i].
len);
909 posvout->
npos = npos;
917 if (dataout !=
STRPTR(tsout))
918 memmove(
STRPTR(tsout), dataout, cur_pos);
1000 memcpy(
data + dataoff, data1 + ptr1->
pos, ptr1->
len);
1002 dataoff += ptr1->
len;
1018 memcpy(
data + dataoff, data2 + ptr2->
pos, ptr2->
len);
1020 dataoff += ptr2->
len;
1023 int addlen =
add_pos(in2, ptr2, out, ptr, maxpos);
1042 memcpy(
data + dataoff, data1 + ptr1->
pos, ptr1->
len);
1044 dataoff += ptr1->
len;
1057 int addlen =
add_pos(in2, ptr2, out, ptr, maxpos);
1081 memcpy(
data + dataoff, data1 + ptr1->
pos, ptr1->
len);
1083 dataoff += ptr1->
len;
1100 memcpy(
data + dataoff, data2 + ptr2->
pos, ptr2->
len);
1102 dataoff += ptr2->
len;
1105 int addlen =
add_pos(in2, ptr2, out, ptr, maxpos);
1127 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1128 errmsg(
"string is too long for tsvector (%d bytes, max %d bytes)", dataoff,
MAXSTRPOS)));
1134 output_size = ptr -
ARRPTR(out);
1135 Assert(output_size <= out->size);
1136 out->
size = output_size;
1163 cmp = (lenb > 0) ? -1 : 0;
1167 cmp = (lena > 0) ? 1 : 0;
1171 cmp = memcmp(
a,
b,
Min((
unsigned int) lena, (
unsigned int) lenb));
1175 if (
cmp == 0 && lena > lenb)
1178 else if (
cmp == 0 && lena != lenb)
1180 cmp = (lena < lenb) ? -1 : 1;
1218 data->allocated =
true;
1221 while (posvec_iter < posvec->pos + posvec->
npos)
1241 data->allocated =
false;
1244 else if (
val->weight)
1249 while (posvec_iter < posvec->pos + posvec->
npos)
1264 data->allocated =
false;
1306 while (StopLow < StopHigh)
1310 StopMiddle = StopLow + (StopHigh - StopLow) / 2;
1324 StopLow = StopMiddle + 1;
1326 StopHigh = StopMiddle;
1343 if (StopLow >= StopHigh)
1344 StopMiddle = StopHigh;
1349 if (
data->allocated)
1352 data->allocated =
false;
1358 StopMiddle < chkval->arre &&
1369 if (subres !=
TS_NO)
1391 while (npos +
data->npos > totalpos)
1409 if (
data->allocated)
1412 data->allocated =
false;
1427 if (
data && npos > 0)
1434 data->allocated =
true;
1465 #define TSPO_L_ONLY 0x01
1466 #define TSPO_R_ONLY 0x02
1467 #define TSPO_BOTH 0x04
1482 Lindex = Rindex = 0;
1483 while (Lindex < Ldata->npos || Rindex < Rdata->npos)
1493 if (Lindex < Ldata->npos)
1502 if (Rindex < Rdata->npos)
1520 else if (Lpos == Rpos)
1541 if (
data->pos == NULL)
1545 data->allocated =
true;
1547 data->pos[
data->npos++] = output_pos;
1644 data->negate =
true;
1652 data->negate =
true;
1661 else if (
data->negate)
1664 data->negate =
false;
1678 memset(&Ldata, 0,
sizeof(Ldata));
1679 memset(&Rdata, 0,
sizeof(Rdata));
1682 arg, flags, chkcond, &Ldata);
1683 if (lmatch ==
TS_NO)
1687 arg, flags, chkcond, &Rdata);
1688 if (rmatch ==
TS_NO)
1717 Loffset = maxwidth - Ldata.
width;
1718 Roffset = maxwidth - Rdata.
width;
1720 data->width = maxwidth;
1731 data->negate =
true;
1760 memset(&Ldata, 0,
sizeof(Ldata));
1761 memset(&Rdata, 0,
sizeof(Rdata));
1764 arg, flags, chkcond, &Ldata);
1766 arg, flags, chkcond, &Rdata);
1783 if (lmatch ==
TS_NO)
1785 if (rmatch ==
TS_NO)
1795 Loffset = maxwidth - Ldata.
width;
1796 Roffset = maxwidth - Rdata.
width;
1797 data->width = maxwidth;
1806 data->negate =
true;
1816 data->negate =
true;
1826 data->negate =
true;
1919 if (lmatch ==
TS_NO)
2085 if (lmatch || rmatch)
2095 if (llocations ==
NIL)
2096 *locations = rlocations;
2097 else if (rlocations ==
NIL)
2098 *locations = llocations;
2103 foreach(ll, llocations)
2108 foreach(lr, rlocations)
2312 #define compareStatWord(a,e,t) \
2313 tsCompareString((a)->lexeme, (a)->lenlexeme, \
2314 STRPTR(t) + (e)->pos, (e)->len, \
2327 if (
stat->weight == 0)
2351 if (depth >
stat->maxdepth)
2352 stat->maxdepth = depth;
2372 pnode->
right = node;
2387 uint32 middle = (low + high) >> 1;
2389 pos = (low + middle) >> 1;
2390 if (low != middle && pos >= offset && pos - offset < txt->size)
2392 pos = (high + middle + 1) >> 1;
2393 if (middle + 1 != high && pos >= offset && pos - offset < txt->size)
2398 if (high != middle + 1)
2429 if (txt == NULL || txt->
size == 0)
2437 for (;
i > 0;
i >>= 1)
2441 offset = (nbit - txt->
size) / 2;
2467 stat->stack[
stat->stackpos] = NULL;
2471 stat->stack[
stat->stackpos] = node;
2483 elog(
ERROR,
"return type must be a row type");
2498 if (node->
ndoc != 0)
2512 stat->stack[
stat->stackpos] = node;
2526 if (
stat->stackpos == 0)
2587 elog(
ERROR,
"SPI_prepare(\"%s\") failed", query);
2591 elog(
ERROR,
"SPI_cursor_open(\"%s\") failed", query);
2600 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2601 errmsg(
"ts_stat query must return one tsvector column")));
2619 stat->weight |= 1 << 3;
2623 stat->weight |= 1 << 2;
2627 stat->weight |= 1 << 1;
2747 int tsvector_attr_num,
2758 elog(
ERROR,
"tsvector_update_trigger: not fired by trigger manager");
2762 elog(
ERROR,
"tsvector_update_trigger: must be fired for row");
2764 elog(
ERROR,
"tsvector_update_trigger: must be fired BEFORE event");
2769 update_needed =
true;
2774 update_needed =
false;
2777 elog(
ERROR,
"tsvector_update_trigger: must be fired for INSERT or UPDATE");
2783 elog(
ERROR,
"tsvector_update_trigger: arguments must be tsvector_field, ts_config, text_field1, ...)");
2789 (
errcode(ERRCODE_UNDEFINED_COLUMN),
2790 errmsg(
"tsvector column \"%s\" does not exist",
2796 (
errcode(ERRCODE_DATATYPE_MISMATCH),
2797 errmsg(
"column \"%s\" is not of tsvector type",
2803 int config_attr_num;
2808 (
errcode(ERRCODE_UNDEFINED_COLUMN),
2809 errmsg(
"configuration column \"%s\" does not exist",
2814 (
errcode(ERRCODE_DATATYPE_MISMATCH),
2815 errmsg(
"column \"%s\" is not of regconfig type",
2821 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
2822 errmsg(
"configuration column \"%s\" must not be null",
2834 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2835 errmsg(
"text search configuration name \"%s\" must be schema-qualified",
2854 (
errcode(ERRCODE_UNDEFINED_COLUMN),
2855 errmsg(
"column \"%s\" does not exist",
2859 (
errcode(ERRCODE_DATATYPE_MISMATCH),
2860 errmsg(
"column \"%s\" is not of a character type",
2864 update_needed =
true;
2886 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 FLEXIBLE_ARRAY_MEMBER
static void PGresult * res
elog(ERROR, "%s: %s", p2, msg)
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_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)
if(TABLE==NULL||TABLE_index==NULL)
Assert(fmt[strlen(fmt) - 1] !='\n')
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)
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)
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 *))
static int cmp(const chr *x, const chr *y, size_t len)
List * stringToQualifiedNameList(const char *string, Node *escontext)
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)
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 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)