PostgreSQL Source Code git master
Loading...
Searching...
No Matches
tsrank.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * tsrank.c
4 * rank tsvector by tsquery
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 *
8 *
9 * IDENTIFICATION
10 * src/backend/utils/adt/tsrank.c
11 *
12 *-------------------------------------------------------------------------
13 */
14#include "postgres.h"
15
16#include <limits.h>
17#include <math.h>
18
19#include "miscadmin.h"
20#include "tsearch/ts_utils.h"
21#include "utils/array.h"
22#include "utils/fmgrprotos.h"
23
24#define NUM_WEIGHTS 4
25static const float default_weights[NUM_WEIGHTS] = {0.1f, 0.2f, 0.4f, 1.0f};
26
27#define wpos(wep) ( w[ WEP_GETWEIGHT(wep) ] )
28
29#define RANK_NO_NORM 0x00
30#define RANK_NORM_LOGLENGTH 0x01
31#define RANK_NORM_LENGTH 0x02
32#define RANK_NORM_EXTDIST 0x04
33#define RANK_NORM_UNIQ 0x08
34#define RANK_NORM_LOGUNIQ 0x10
35#define RANK_NORM_RDIVRPLUS1 0x20
36#define DEF_NORM_METHOD RANK_NO_NORM
37
38static float calc_rank_or(const float *w, TSVector t, TSQuery q);
39static float calc_rank_and(const float *w, TSVector t, TSQuery q);
40
41/*
42 * Returns a weight of a word collocation
43 */
44static float4
46{
47 if (w > 100)
48 return 1e-30f;
49
50 return 1.0 / (1.005 + 0.05 * exp(((float4) w) / 1.5 - 2));
51}
52
53static int
55{
56 WordEntry *ptr = ARRPTR(t),
57 *end = (WordEntry *) STRPTR(t);
58 int len = 0;
59
60 while (ptr < end)
61 {
62 int clen = POSDATALEN(t, ptr);
63
64 if (clen == 0)
65 len += 1;
66 else
67 len += clen;
68
69 ptr++;
70 }
71
72 return len;
73}
74
75
76#define WordECompareQueryItem(e,q,p,i,m) \
77 tsCompareString((q) + (i)->distance, (i)->length, \
78 (e) + (p)->pos, (p)->len, (m))
79
80
81/*
82 * Returns a pointer to a WordEntry's array corresponding to 'item' from
83 * tsvector 't'. 'q' is the TSQuery containing 'item'.
84 * Returns NULL if not found.
85 */
86static WordEntry *
88{
92 int difference;
93
94 *nitem = 0;
95
96 /* Loop invariant: StopLow <= item < StopHigh */
97 while (StopLow < StopHigh)
98 {
101 if (difference == 0)
102 {
104 *nitem = 1;
105 break;
106 }
107 else if (difference > 0)
108 StopLow = StopMiddle + 1;
109 else
111 }
112
113 if (item->prefix)
114 {
115 if (StopLow >= StopHigh)
117
118 *nitem = 0;
119
120 while (StopMiddle < (WordEntry *) STRPTR(t) &&
121 WordECompareQueryItem(STRPTR(t), GETOPERAND(q), StopMiddle, item, true) == 0)
122 {
123 (*nitem)++;
124 StopMiddle++;
125 }
126 }
127
128 return (*nitem > 0) ? StopHigh : NULL;
129}
130
131
132/*
133 * sort QueryOperands by (length, word)
134 */
135static int
136compareQueryOperand(const void *a, const void *b, void *arg)
137{
138 char *operand = (char *) arg;
139 QueryOperand *qa = (*(QueryOperand *const *) a);
140 QueryOperand *qb = (*(QueryOperand *const *) b);
141
142 return tsCompareString(operand + qa->distance, qa->length,
143 operand + qb->distance, qb->length,
144 false);
145}
146
147/*
148 * Returns a sorted, de-duplicated array of QueryOperands in a query.
149 * The returned QueryOperands are pointers to the original QueryOperands
150 * in the query.
151 *
152 * Length of the returned array is stored in *size
153 */
154static QueryOperand **
156{
157 char *operand = GETOPERAND(q);
158 QueryItem *item = GETQUERY(q);
159 QueryOperand **res,
160 **ptr,
161 **prevptr;
162
163 ptr = res = palloc_array(QueryOperand *, *size);
164
165 /* Collect all operands from the tree to res */
166 while ((*size)--)
167 {
168 if (item->type == QI_VAL)
169 {
170 *ptr = (QueryOperand *) item;
171 ptr++;
172 }
173 item++;
174 }
175
176 *size = ptr - res;
177 if (*size < 2)
178 return res;
179
180 qsort_arg(res, *size, sizeof(QueryOperand *), compareQueryOperand, operand);
181
182 ptr = res + 1;
183 prevptr = res;
184
185 /* remove duplicates */
186 while (ptr - res < *size)
187 {
188 if (compareQueryOperand(ptr, prevptr, operand) != 0)
189 {
190 prevptr++;
191 *prevptr = *ptr;
192 }
193 ptr++;
194 }
195
196 *size = prevptr + 1 - res;
197 return res;
198}
199
200static float
201calc_rank_and(const float *w, TSVector t, TSQuery q)
202{
203 WordEntryPosVector **pos;
206 int i,
207 k,
208 l,
209 p;
210 WordEntry *entry,
211 *firstentry;
212 WordEntryPos *post,
213 *ct;
214 int32 dimt,
215 lenct,
216 dist,
217 nitem;
218 float res = -1.0;
219 QueryOperand **item;
220 int size = q->size;
221
222 item = SortAndUniqItems(q, &size);
223 if (size < 2)
224 {
225 pfree(item);
226 return calc_rank_or(w, t, q);
227 }
229
230 /* A dummy WordEntryPos array to use when haspos is false */
231 posnull.npos = 1;
232 posnull.pos[0] = 0;
233 WEP_SETPOS(posnull.pos[0], MAXENTRYPOS - 1);
235
236 for (i = 0; i < size; i++)
237 {
238 firstentry = entry = find_wordentry(t, q, item[i], &nitem);
239 if (!entry)
240 continue;
241
242 while (entry - firstentry < nitem)
243 {
244 if (entry->haspos)
245 pos[i] = _POSVECPTR(t, entry);
246 else
247 pos[i] = POSNULL;
248
249 dimt = pos[i]->npos;
250 post = pos[i]->pos;
251 for (k = 0; k < i; k++)
252 {
253 if (!pos[k])
254 continue;
255 lenct = pos[k]->npos;
256 ct = pos[k]->pos;
257 for (l = 0; l < dimt; l++)
258 {
259 for (p = 0; p < lenct; p++)
260 {
261 dist = abs((int) WEP_GETPOS(post[l]) - (int) WEP_GETPOS(ct[p]));
262 if (dist || (dist == 0 && (pos[i] == POSNULL || pos[k] == POSNULL)))
263 {
264 float curw;
265
266 if (!dist)
268 curw = sqrt(wpos(post[l]) * wpos(ct[p]) * word_distance(dist));
269 res = (res < 0) ? curw : 1.0 - (1.0 - res) * (1.0 - curw);
270 }
271 }
272 }
273 }
274
275 entry++;
276 }
277 }
278 pfree(pos);
279 pfree(item);
280 return res;
281}
282
283static float
284calc_rank_or(const float *w, TSVector t, TSQuery q)
285{
286 WordEntry *entry,
287 *firstentry;
289 WordEntryPos *post;
290 int32 dimt,
291 j,
292 i,
293 nitem;
294 float res = 0.0;
295 QueryOperand **item;
296 int size = q->size;
297
298 /* A dummy WordEntryPos array to use when haspos is false */
299 posnull.npos = 1;
300 posnull.pos[0] = 0;
301
302 item = SortAndUniqItems(q, &size);
303
304 for (i = 0; i < size; i++)
305 {
306 float resj,
307 wjm;
308 int32 jm;
309
310 firstentry = entry = find_wordentry(t, q, item[i], &nitem);
311 if (!entry)
312 continue;
313
314 while (entry - firstentry < nitem)
315 {
316 /* Identify the weight data to use */
317 if (entry->haspos)
318 {
319 dimt = POSDATALEN(t, entry);
320 post = POSDATAPTR(t, entry);
321 }
322 else
323 {
324 dimt = posnull.npos;
325 post = posnull.pos;
326 }
327
328 /*
329 * Compute the score for this term, then add it to "res".
330 *
331 * The ideal score for a term is the weighted harmonic sum:
332 *
333 * resj = sum(wi / i^2, i = 1..noccurrences)
334 *
335 * where wi is the weight of the i-th occurrence and weights are
336 * sorted in descending order so that the highest-weight
337 * occurrence gets the smallest divisor (i=1) and thus contributes
338 * the most.
339 *
340 * This result should be divided by pi^2/6 ~= 1.64493406685, which
341 * is the limit of sum(1/i^2, i=1..inf). This normalizes the score
342 * to the [0, 1] range.
343 *
344 * As an approximation for efficiency, we skip doing a sort and
345 * instead just promote the single highest-weight occurrence to
346 * position i=1. This is done by taking the raw (unsorted) sum
347 * resj, subtracting the maximum weight's actual contribution
348 * wjm/(jm+1)^2, and adding back its corrected contribution
349 * wjm/1^2 = wjm.
350 *
351 * The remaining occurrences are left in their original order.
352 */
353
354 /* calculate harmonic sum without re-ordering */
355 resj = 0.0;
356 wjm = -1.0;
357 jm = 0;
358 for (j = 0; j < dimt; j++)
359 {
360 resj = resj + wpos(post[j]) / ((j + 1) * (j + 1));
361 if (wpos(post[j]) > wjm)
362 {
363 wjm = wpos(post[j]);
364 jm = j;
365 }
366 }
367
368 /* apply correction as explained above, then add to res */
369 res = res + (resj - wjm / ((jm + 1) * (jm + 1)) + wjm) / 1.64493406685;
370
371 entry++;
372 }
373 }
374 if (size > 0)
375 res = res / size;
376 pfree(item);
377 return res;
378}
379
380static float
381calc_rank(const float *w, TSVector t, TSQuery q, int32 method)
382{
383 QueryItem *item = GETQUERY(q);
384 float res = 0.0;
385 int len;
386
387 if (!t->size || !q->size)
388 return 0.0;
389
390 /* XXX: What about NOT? */
391 res = (item->type == QI_OPR && (item->qoperator.oper == OP_AND ||
392 item->qoperator.oper == OP_PHRASE)) ?
393 calc_rank_and(w, t, q) :
394 calc_rank_or(w, t, q);
395
396 if (res < 0)
397 res = 1e-20f;
398
399 if ((method & RANK_NORM_LOGLENGTH) && t->size > 0)
400 res /= log((double) (cnt_length(t) + 1)) / log(2.0);
401
402 if (method & RANK_NORM_LENGTH)
403 {
404 len = cnt_length(t);
405 if (len > 0)
406 res /= (float) len;
407 }
408
409 /* RANK_NORM_EXTDIST not applicable */
410
411 if ((method & RANK_NORM_UNIQ) && t->size > 0)
412 res /= (float) (t->size);
413
414 if ((method & RANK_NORM_LOGUNIQ) && t->size > 0)
415 res /= log((double) (t->size + 1)) / log(2.0);
416
417 if (method & RANK_NORM_RDIVRPLUS1)
418 res /= (res + 1);
419
420 return res;
421}
422
423/*
424 * Extract weights from an array. The weights are stored in *ws, which must
425 * have space for NUM_WEIGHTS elements.
426 */
427static void
429{
430 int i;
432
433 Assert(win != NULL);
434
435 if (ARR_NDIM(win) != 1)
438 errmsg("array of weight must be one-dimensional")));
439
443 errmsg("array of weight is too short")));
444
448 errmsg("array of weight must not contain nulls")));
449
451 for (i = 0; i < NUM_WEIGHTS; i++)
452 {
453 ws[i] = (arrdata[i] >= 0) ? arrdata[i] : default_weights[i];
454 if (ws[i] > 1.0)
457 errmsg("weight out of range")));
458 }
459}
460
461Datum
463{
466 TSQuery query = PG_GETARG_TSQUERY(2);
467 int method = PG_GETARG_INT32(3);
468 float weights[NUM_WEIGHTS];
469 float res;
470
472 res = calc_rank(weights, txt, query, method);
473
476 PG_FREE_IF_COPY(query, 2);
477 PG_RETURN_FLOAT4(res);
478}
479
480Datum
482{
485 TSQuery query = PG_GETARG_TSQUERY(2);
486 float weights[NUM_WEIGHTS];
487 float res;
488
490 res = calc_rank(weights, txt, query, DEF_NORM_METHOD);
491
494 PG_FREE_IF_COPY(query, 2);
495 PG_RETURN_FLOAT4(res);
496}
497
498Datum
500{
502 TSQuery query = PG_GETARG_TSQUERY(1);
503 int method = PG_GETARG_INT32(2);
504 float res;
505
506 res = calc_rank(default_weights, txt, query, method);
507
509 PG_FREE_IF_COPY(query, 1);
510 PG_RETURN_FLOAT4(res);
511}
512
513Datum
515{
517 TSQuery query = PG_GETARG_TSQUERY(1);
518 float res;
519
521
523 PG_FREE_IF_COPY(query, 1);
524 PG_RETURN_FLOAT4(res);
525}
526
527typedef struct
528{
529 union
530 {
531 struct
532 { /* compiled doc representation */
535 } query;
536 struct
537 { /* struct is used for preparing doc
538 * representation */
541 } map;
545
546static int
547compareDocR(const void *va, const void *vb)
548{
549 const DocRepresentation *a = (const DocRepresentation *) va;
550 const DocRepresentation *b = (const DocRepresentation *) vb;
551
552 if (WEP_GETPOS(a->pos) == WEP_GETPOS(b->pos))
553 {
554 if (WEP_GETWEIGHT(a->pos) == WEP_GETWEIGHT(b->pos))
555 {
556 if (a->data.map.entry == b->data.map.entry)
557 return 0;
558
559 return (a->data.map.entry > b->data.map.entry) ? 1 : -1;
560 }
561
562 return (WEP_GETWEIGHT(a->pos) > WEP_GETWEIGHT(b->pos)) ? 1 : -1;
563 }
564
565 return (WEP_GETPOS(a->pos) > WEP_GETPOS(b->pos)) ? 1 : -1;
566}
567
568#define MAXQROPOS MAXENTRYPOS
569typedef struct
570{
572 bool reverseinsert; /* indicates insert order, true means
573 * descending order */
577
583
584#define QR_GET_OPERAND_DATA(q, v) \
585 ( (q)->operandData + (((QueryItem*)(v)) - GETQUERY((q)->query)) )
586
587/*
588 * TS_execute callback for matching a tsquery operand to QueryRepresentation
589 */
590static TSTernaryValue
593{
596
597 if (!opData->operandexists)
598 return TS_NO;
599
600 if (data)
601 {
602 data->npos = opData->npos;
603 data->pos = opData->pos;
604 if (opData->reverseinsert)
605 data->pos += MAXQROPOS - opData->npos;
606 }
607
608 return TS_YES;
609}
610
611typedef struct
612{
613 int pos;
614 int p;
615 int q;
618} CoverExt;
619
620static void
622{
623 int i;
624
625 for (i = 0; i < qr->query->size; i++)
626 {
627 qr->operandData[i].operandexists = false;
628 qr->operandData[i].reverseinsert = reverseinsert;
629 qr->operandData[i].npos = 0;
630 }
631}
632
633static void
635{
636 int i;
637 int lastPos;
639
640 for (i = 0; i < entry->data.query.nitem; i++)
641 {
642 if (entry->data.query.items[i]->type != QI_VAL)
643 continue;
644
646
647 opData->operandexists = true;
648
649 if (opData->npos == 0)
650 {
651 lastPos = (opData->reverseinsert) ? (MAXQROPOS - 1) : 0;
652 opData->pos[lastPos] = entry->pos;
653 opData->npos++;
654 continue;
655 }
656
657 lastPos = opData->reverseinsert ?
658 (MAXQROPOS - opData->npos) :
659 (opData->npos - 1);
660
661 if (WEP_GETPOS(opData->pos[lastPos]) != WEP_GETPOS(entry->pos))
662 {
663 lastPos = opData->reverseinsert ?
664 (MAXQROPOS - 1 - opData->npos) :
665 (opData->npos);
666
667 opData->pos[lastPos] = entry->pos;
668 opData->npos++;
669 }
670 }
671}
672
673static bool
675{
677 int lastpos = ext->pos;
678 bool found = false;
679
680 /*
681 * since this function recurses, it could be driven to stack overflow.
682 * (though any decent compiler will optimize away the tail-recursion.
683 */
685
687
688 ext->p = INT_MAX;
689 ext->q = 0;
690 ptr = doc + ext->pos;
691
692 /* find upper bound of cover from current position, move up */
693 while (ptr - doc < len)
694 {
696
697 if (TS_execute(GETQUERY(qr->query), qr,
699 {
700 if (WEP_GETPOS(ptr->pos) > ext->q)
701 {
702 ext->q = WEP_GETPOS(ptr->pos);
703 ext->end = ptr;
704 lastpos = ptr - doc;
705 found = true;
706 }
707 break;
708 }
709 ptr++;
710 }
711
712 if (!found)
713 return false;
714
716
717 ptr = doc + lastpos;
718
719 /* find lower bound of cover from found upper bound, move down */
720 while (ptr >= doc + ext->pos)
721 {
722 /*
723 * we scan doc from right to left, so pos info in reverse order!
724 */
726
727 if (TS_execute(GETQUERY(qr->query), qr,
729 {
730 if (WEP_GETPOS(ptr->pos) < ext->p)
731 {
732 ext->begin = ptr;
733 ext->p = WEP_GETPOS(ptr->pos);
734 }
735 break;
736 }
737 ptr--;
738 }
739
740 if (ext->p <= ext->q)
741 {
742 /*
743 * set position for next try to next lexeme after beginning of found
744 * cover
745 */
746 ext->pos = (ptr - doc) + 1;
747 return true;
748 }
749
750 ext->pos++;
751 return Cover(doc, len, qr, ext);
752}
753
754static DocRepresentation *
756{
757 QueryItem *item = GETQUERY(qr->query);
758 WordEntry *entry,
759 *firstentry;
760 WordEntryPos *post;
761 int32 dimt, /* number of 'post' items */
762 j,
763 i,
764 nitem;
765 int len = qr->query->size * 4,
766 cur = 0;
768
770
771 /*
772 * Iterate through query to make DocRepresentation for words and it's
773 * entries satisfied by query
774 */
775 for (i = 0; i < qr->query->size; i++)
776 {
777 QueryOperand *curoperand;
778
779 if (item[i].type != QI_VAL)
780 continue;
781
782 curoperand = &item[i].qoperand;
783
784 firstentry = entry = find_wordentry(txt, qr->query, curoperand, &nitem);
785 if (!entry)
786 continue;
787
788 /* iterations over entries in tsvector */
789 while (entry - firstentry < nitem)
790 {
791 if (entry->haspos)
792 {
793 dimt = POSDATALEN(txt, entry);
794 post = POSDATAPTR(txt, entry);
795 }
796 else
797 {
798 /* ignore words without positions */
799 entry++;
800 continue;
801 }
802
803 while (cur + dimt >= len)
804 {
805 len *= 2;
807 }
808
809 /* iterations over entry's positions */
810 for (j = 0; j < dimt; j++)
811 {
812 if (curoperand->weight == 0 ||
813 curoperand->weight & (1 << WEP_GETWEIGHT(post[j])))
814 {
815 doc[cur].pos = post[j];
816 doc[cur].data.map.entry = entry;
817 doc[cur].data.map.item = (QueryItem *) curoperand;
818 cur++;
819 }
820 }
821
822 entry++;
823 }
824 }
825
826 if (cur > 0)
827 {
829 *wptr = doc,
830 storage;
831
832 /*
833 * Sort representation in ascending order by pos and entry
834 */
836
837 /*
838 * Join QueryItem per WordEntry and its position
839 */
840 storage.pos = doc->pos;
841 storage.data.query.items = palloc_array(QueryItem *, qr->query->size);
842 storage.data.query.items[0] = doc->data.map.item;
843 storage.data.query.nitem = 1;
844
845 while (rptr - doc < cur)
846 {
847 if (rptr->pos == (rptr - 1)->pos &&
848 rptr->data.map.entry == (rptr - 1)->data.map.entry)
849 {
850 storage.data.query.items[storage.data.query.nitem] = rptr->data.map.item;
851 storage.data.query.nitem++;
852 }
853 else
854 {
855 *wptr = storage;
856 wptr++;
857 storage.pos = rptr->pos;
858 storage.data.query.items = palloc_array(QueryItem *, qr->query->size);
859 storage.data.query.items[0] = rptr->data.map.item;
860 storage.data.query.nitem = 1;
861 }
862
863 rptr++;
864 }
865
866 *wptr = storage;
867 wptr++;
868
869 *doclen = wptr - doc;
870 return doc;
871 }
872
873 pfree(doc);
874 return NULL;
875}
876
877static float4
878calc_rank_cd(const float4 *arrdata, TSVector txt, TSQuery query, int method)
879{
881 int len,
882 i,
883 doclen = 0;
884 CoverExt ext;
885 double Wdoc = 0.0;
886 double invws[NUM_WEIGHTS];
887 double SumDist = 0.0,
888 PrevExtPos = 0.0;
889 int NExtent = 0;
891
892
893 for (i = 0; i < NUM_WEIGHTS; i++)
894 {
895 invws[i] = ((double) ((arrdata[i] >= 0) ? arrdata[i] : default_weights[i]));
896 if (invws[i] > 1.0)
899 errmsg("weight out of range")));
900 invws[i] = 1.0 / invws[i];
901 }
902
903 qr.query = query;
904 qr.operandData = palloc0_array(QueryRepresentationOperand, query->size);
905
906 doc = get_docrep(txt, &qr, &doclen);
907 if (!doc)
908 {
909 pfree(qr.operandData);
910 return 0.0;
911 }
912
913 MemSet(&ext, 0, sizeof(CoverExt));
914 while (Cover(doc, doclen, &qr, &ext))
915 {
916 double Cpos = 0.0;
917 double InvSum = 0.0;
918 double CurExtPos;
919 int nNoise;
920 DocRepresentation *ptr = ext.begin;
921
922 while (ptr <= ext.end)
923 {
924 InvSum += invws[WEP_GETWEIGHT(ptr->pos)];
925 ptr++;
926 }
927
928 Cpos = ((double) (ext.end - ext.begin + 1)) / InvSum;
929
930 /*
931 * if doc are big enough then ext.q may be equal to ext.p due to limit
932 * of positional information. In this case we approximate number of
933 * noise word as half cover's length
934 */
935 nNoise = (ext.q - ext.p) - (ext.end - ext.begin);
936 if (nNoise < 0)
937 nNoise = (ext.end - ext.begin) / 2;
938 Wdoc += Cpos / ((double) (1 + nNoise));
939
940 CurExtPos = ((double) (ext.q + ext.p)) / 2.0;
941 if (NExtent > 0 && CurExtPos > PrevExtPos /* prevent division by
942 * zero in a case of
943 * multiple lexize */ )
944 SumDist += 1.0 / (CurExtPos - PrevExtPos);
945
947 NExtent++;
948 }
949
950 if ((method & RANK_NORM_LOGLENGTH) && txt->size > 0)
951 Wdoc /= log((double) (cnt_length(txt) + 1));
952
953 if (method & RANK_NORM_LENGTH)
954 {
955 len = cnt_length(txt);
956 if (len > 0)
957 Wdoc /= (double) len;
958 }
959
960 if ((method & RANK_NORM_EXTDIST) && NExtent > 0 && SumDist > 0)
961 Wdoc /= ((double) NExtent) / SumDist;
962
963 if ((method & RANK_NORM_UNIQ) && txt->size > 0)
964 Wdoc /= (double) (txt->size);
965
966 if ((method & RANK_NORM_LOGUNIQ) && txt->size > 0)
967 Wdoc /= log((double) (txt->size + 1)) / log(2.0);
968
969 if (method & RANK_NORM_RDIVRPLUS1)
970 Wdoc /= (Wdoc + 1);
971
972 pfree(doc);
973
974 pfree(qr.operandData);
975
976 return (float4) Wdoc;
977}
978
979Datum
981{
984 TSQuery query = PG_GETARG_TSQUERY(2);
985 int method = PG_GETARG_INT32(3);
986 float weights[NUM_WEIGHTS];
987 float res;
988
990 res = calc_rank_cd(weights, txt, query, method);
991
994 PG_FREE_IF_COPY(query, 2);
995 PG_RETURN_FLOAT4(res);
996}
997
998Datum
1000{
1003 TSQuery query = PG_GETARG_TSQUERY(2);
1004 float weights[NUM_WEIGHTS];
1005 float res;
1006
1008 res = calc_rank_cd(weights, txt, query, DEF_NORM_METHOD);
1009
1010 PG_FREE_IF_COPY(win, 0);
1011 PG_FREE_IF_COPY(txt, 1);
1012 PG_FREE_IF_COPY(query, 2);
1013 PG_RETURN_FLOAT4(res);
1014}
1015
1016Datum
1018{
1020 TSQuery query = PG_GETARG_TSQUERY(1);
1021 int method = PG_GETARG_INT32(2);
1022 float res;
1023
1024 res = calc_rank_cd(default_weights, txt, query, method);
1025
1026 PG_FREE_IF_COPY(txt, 0);
1027 PG_FREE_IF_COPY(query, 1);
1028 PG_RETURN_FLOAT4(res);
1029}
1030
1031Datum
1033{
1035 TSQuery query = PG_GETARG_TSQUERY(1);
1036 float res;
1037
1039
1040 PG_FREE_IF_COPY(txt, 0);
1041 PG_FREE_IF_COPY(query, 1);
1042 PG_RETURN_FLOAT4(res);
1043}
#define GETQUERY(x)
Definition _int.h:157
#define ARR_NDIM(a)
Definition array.h:290
#define ARR_DATA_PTR(a)
Definition array.h:322
#define ARR_DIMS(a)
Definition array.h:294
bool array_contains_nulls(const ArrayType *array)
int ArrayGetNItems(int ndim, const int *dims)
Definition arrayutils.c:57
#define Assert(condition)
Definition c.h:943
int16_t int16
Definition c.h:619
int32_t int32
Definition c.h:620
uint32_t uint32
Definition c.h:624
float float4
Definition c.h:713
#define MemSet(start, val, len)
Definition c.h:1107
#define ARRPTR(x)
Definition cube.c:28
struct cursor * cur
Definition ecpg.c:29
Datum arg
Definition elog.c:1323
int errcode(int sqlerrcode)
Definition elog.c:875
#define ERROR
Definition elog.h:40
#define ereport(elevel,...)
Definition elog.h:152
#define palloc_array(type, count)
Definition fe_memutils.h:91
#define palloc0_array(type, count)
Definition fe_memutils.h:92
#define PG_FREE_IF_COPY(ptr, n)
Definition fmgr.h:260
#define PG_GETARG_DATUM(n)
Definition fmgr.h:268
#define PG_DETOAST_DATUM(datum)
Definition fmgr.h:240
#define PG_GETARG_INT32(n)
Definition fmgr.h:269
#define PG_RETURN_FLOAT4(x)
Definition fmgr.h:368
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
Datum difference(PG_FUNCTION_ARGS)
#define STRPTR(x)
Definition hstore.h:76
#define storage
long val
Definition informix.c:689
int b
Definition isn.c:74
int a
Definition isn.c:73
int j
Definition isn.c:78
int i
Definition isn.c:77
#define GETOPERAND(x)
Definition ltree.h:165
void * repalloc(void *pointer, Size size)
Definition mcxt.c:1635
void pfree(void *pointer)
Definition mcxt.c:1619
static char * errmsg
const void size_t len
const void * data
void qsort_arg(void *base, size_t nel, size_t elsize, qsort_arg_comparator cmp, void *arg)
#define qsort(a, b, c, d)
Definition port.h:496
uint64_t Datum
Definition postgres.h:70
static int fb(int x)
void check_stack_depth(void)
Definition stack_depth.c:95
int pos
Definition tsrank.c:613
int p
Definition tsrank.c:614
DocRepresentation * begin
Definition tsrank.c:616
DocRepresentation * end
Definition tsrank.c:617
int q
Definition tsrank.c:615
QueryItem ** items
Definition tsrank.c:533
WordEntryPos pos
Definition tsrank.c:543
WordEntry * entry
Definition tsrank.c:540
QueryItem * item
Definition tsrank.c:539
struct DocRepresentation::@33::@34 query
union DocRepresentation::@33 data
bool prefix
Definition ts_type.h:163
uint8 weight
Definition ts_type.h:159
QueryRepresentationOperand * operandData
Definition tsrank.c:581
int32 size
Definition ts_type.h:221
int32 size
Definition ts_type.h:93
WordEntryPos pos[FLEXIBLE_ARRAY_MEMBER]
Definition ts_type.h:68
uint32 pos
Definition ts_type.h:46
uint32 haspos
Definition ts_type.h:44
#define PG_GETARG_TSVECTOR(n)
Definition ts_type.h:135
#define WEP_GETPOS(x)
Definition ts_type.h:80
#define _POSVECPTR(x, e)
Definition ts_type.h:109
#define MAXENTRYPOS
Definition ts_type.h:85
#define WEP_SETPOS(x, v)
Definition ts_type.h:83
#define POSDATALEN(x, e)
Definition ts_type.h:110
#define PG_GETARG_TSQUERY(n)
Definition ts_type.h:267
uint16 WordEntryPos
Definition ts_type.h:63
#define QI_OPR
Definition ts_type.h:150
#define QI_VAL
Definition ts_type.h:149
#define OP_AND
Definition ts_type.h:180
#define OP_PHRASE
Definition ts_type.h:182
#define POSDATAPTR(x, e)
Definition ts_type.h:111
#define WEP_GETWEIGHT(x)
Definition ts_type.h:79
TSTernaryValue
Definition ts_utils.h:131
@ TS_NO
Definition ts_utils.h:132
@ TS_YES
Definition ts_utils.h:133
#define TS_EXEC_EMPTY
Definition ts_utils.h:186
#define RANK_NORM_RDIVRPLUS1
Definition tsrank.c:35
Datum ts_rankcd_wtt(PG_FUNCTION_ARGS)
Definition tsrank.c:999
static DocRepresentation * get_docrep(TSVector txt, QueryRepresentation *qr, int *doclen)
Definition tsrank.c:755
Datum ts_rankcd_wttf(PG_FUNCTION_ARGS)
Definition tsrank.c:980
#define WordECompareQueryItem(e, q, p, i, m)
Definition tsrank.c:76
static int compareDocR(const void *va, const void *vb)
Definition tsrank.c:547
#define RANK_NORM_UNIQ
Definition tsrank.c:33
#define RANK_NORM_LOGLENGTH
Definition tsrank.c:30
static TSTernaryValue checkcondition_QueryOperand(void *checkval, QueryOperand *val, ExecPhraseData *data)
Definition tsrank.c:591
#define RANK_NORM_LENGTH
Definition tsrank.c:31
static void resetQueryRepresentation(QueryRepresentation *qr, bool reverseinsert)
Definition tsrank.c:621
static float4 calc_rank_cd(const float4 *arrdata, TSVector txt, TSQuery query, int method)
Definition tsrank.c:878
static float calc_rank(const float *w, TSVector t, TSQuery q, int32 method)
Definition tsrank.c:381
static int cnt_length(TSVector t)
Definition tsrank.c:54
#define wpos(wep)
Definition tsrank.c:27
static WordEntry * find_wordentry(TSVector t, TSQuery q, QueryOperand *item, int32 *nitem)
Definition tsrank.c:87
static float4 word_distance(int32 w)
Definition tsrank.c:45
#define MAXQROPOS
Definition tsrank.c:568
static int compareQueryOperand(const void *a, const void *b, void *arg)
Definition tsrank.c:136
Datum ts_rank_ttf(PG_FUNCTION_ARGS)
Definition tsrank.c:499
Datum ts_rank_wttf(PG_FUNCTION_ARGS)
Definition tsrank.c:462
Datum ts_rank_tt(PG_FUNCTION_ARGS)
Definition tsrank.c:514
static QueryOperand ** SortAndUniqItems(TSQuery q, int *size)
Definition tsrank.c:155
#define DEF_NORM_METHOD
Definition tsrank.c:36
static void getWeights(ArrayType *win, float *ws)
Definition tsrank.c:428
static float calc_rank_or(const float *w, TSVector t, TSQuery q)
Definition tsrank.c:284
static void fillQueryRepresentationData(QueryRepresentation *qr, DocRepresentation *entry)
Definition tsrank.c:634
static const float default_weights[NUM_WEIGHTS]
Definition tsrank.c:25
#define NUM_WEIGHTS
Definition tsrank.c:24
Datum ts_rank_wtt(PG_FUNCTION_ARGS)
Definition tsrank.c:481
#define QR_GET_OPERAND_DATA(q, v)
Definition tsrank.c:584
Datum ts_rankcd_ttf(PG_FUNCTION_ARGS)
Definition tsrank.c:1017
Datum ts_rankcd_tt(PG_FUNCTION_ARGS)
Definition tsrank.c:1032
#define RANK_NORM_EXTDIST
Definition tsrank.c:32
static float calc_rank_and(const float *w, TSVector t, TSQuery q)
Definition tsrank.c:201
static bool Cover(DocRepresentation *doc, int len, QueryRepresentation *qr, CoverExt *ext)
Definition tsrank.c:674
#define RANK_NORM_LOGUNIQ
Definition tsrank.c:34
bool TS_execute(QueryItem *curitem, void *arg, uint32 flags, TSExecuteCallback chkcond)
int32 tsCompareString(char *a, int lena, char *b, int lenb, bool prefix)
QueryOperator qoperator
Definition ts_type.h:209
QueryOperand qoperand
Definition ts_type.h:210
QueryItemType type
Definition ts_type.h:208
const char * type