移植PG对tsquery显示的优化到openGauss中

This commit is contained in:
luozihao
2022-09-24 14:25:08 +08:00
parent 3d913100e2
commit 7b34631c80
5 changed files with 61 additions and 49 deletions

View File

@ -22,6 +22,10 @@
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/memutils.h" #include "utils/memutils.h"
/* FTS operator priorities, see ts_type.h */
const int tsearch_op_priority[OP_COUNT] = {3, 2, 1};
struct TSQueryParserStateData { struct TSQueryParserStateData {
/* State for gettoken_query */ /* State for gettoken_query */
char* buffer; /* entire string we are scanning */ char* buffer; /* entire string we are scanning */
@ -533,7 +537,7 @@ typedef struct {
* recursive walk on tree and print it in * recursive walk on tree and print it in
* infix (human-readable) view * infix (human-readable) view
*/ */
static void infix(INFIX* in, bool first) static void infix(INFIX *in, int parentPriority, bool rightPhraseOp)
{ {
/* since this function recurses, it could be driven to stack overflow. */ /* since this function recurses, it could be driven to stack overflow. */
check_stack_depth(); check_stack_depth();
@ -591,35 +595,35 @@ static void infix(INFIX* in, bool first)
*(in->cur) = '\0'; *(in->cur) = '\0';
in->curpol++; in->curpol++;
} else if (in->curpol->qoperator.oper == OP_NOT) { } else if (in->curpol->qoperator.oper == OP_NOT) {
bool isopr = false; int priority = QO_PRIORITY(in->curpol);
if (priority < parentPriority) {
RESIZEBUF(in, 2);
sprintf(in->cur, "( ");
in->cur = strchr(in->cur, '\0');
}
RESIZEBUF(in, 1); RESIZEBUF(in, 1);
*(in->cur) = '!'; *(in->cur) = '!';
in->cur++; in->cur++;
*(in->cur) = '\0'; *(in->cur) = '\0';
in->curpol++; in->curpol++;
if (in->curpol->type == QI_OPR) { infix(in, priority, false);
isopr = true; if (priority < parentPriority) {
RESIZEBUF(in, 2);
rc = sprintf_s(in->cur, in->buflen - (in->cur - in->buf), "( ");
securec_check_ss(rc, "\0", "\0");
in->cur = strchr(in->cur, '\0');
}
infix(in, isopr);
if (isopr) {
RESIZEBUF(in, 2); RESIZEBUF(in, 2);
rc = sprintf_s(in->cur, in->buflen - (in->cur - in->buf), " )"); rc = sprintf_s(in->cur, in->buflen - (in->cur - in->buf), " )");
securec_check_ss(rc, "\0", "\0"); securec_check_ss(rc, "\0", "\0");
in->cur = strchr(in->cur, '\0'); in->cur = strchr(in->cur, '\0');
} }
} else { } else {
int8 op = in->curpol->qoperator.oper; int8 op = in->curpol->qoperator.oper;
int priority = QO_PRIORITY(in->curpol);
INFIX nrm; INFIX nrm;
bool needParenthesis = false;
in->curpol++; in->curpol++;
if (op == OP_OR && !first) { if (priority < parentPriority || rightPhraseOp) {
needParenthesis = true;
RESIZEBUF(in, 2); RESIZEBUF(in, 2);
rc = sprintf_s(in->cur, in->buflen - (in->cur - in->buf), "( "); rc = sprintf_s(in->cur, in->buflen - (in->cur - in->buf), "( ");
securec_check_ss(rc, "\0", "\0"); securec_check_ss(rc, "\0", "\0");
@ -632,11 +636,11 @@ static void infix(INFIX* in, bool first)
nrm.cur = nrm.buf = (char*)palloc(sizeof(char) * nrm.buflen); nrm.cur = nrm.buf = (char*)palloc(sizeof(char) * nrm.buflen);
/* get right operand */ /* get right operand */
infix(&nrm, false); infix(&nrm, priority, false);
/* get & print left operand */ /* get & print left operand */
in->curpol = nrm.curpol; in->curpol = nrm.curpol;
infix(in, false); infix(in, priority, false);
/* print operator & right operand */ /* print operator & right operand */
RESIZEBUF(in, 3 + (nrm.cur - nrm.buf)); RESIZEBUF(in, 3 + (nrm.cur - nrm.buf));
@ -656,7 +660,7 @@ static void infix(INFIX* in, bool first)
in->cur = strchr(in->cur, '\0'); in->cur = strchr(in->cur, '\0');
pfree_ext(nrm.buf); pfree_ext(nrm.buf);
if (op == OP_OR && !first) { if (needParenthesis) {
RESIZEBUF(in, 2); RESIZEBUF(in, 2);
rc = sprintf_s(in->cur, in->buflen - (in->cur - in->buf), " )"); rc = sprintf_s(in->cur, in->buflen - (in->cur - in->buf), " )");
securec_check_ss(rc, "\0", "\0"); securec_check_ss(rc, "\0", "\0");
@ -681,7 +685,7 @@ Datum tsqueryout(PG_FUNCTION_ARGS)
nrm.cur = nrm.buf = (char*)palloc(sizeof(char) * nrm.buflen); nrm.cur = nrm.buf = (char*)palloc(sizeof(char) * nrm.buflen);
*(nrm.cur) = '\0'; *(nrm.cur) = '\0';
nrm.op = GETOPERAND(query); nrm.op = GETOPERAND(query);
infix(&nrm, true); infix(&nrm, -1, false);
PG_FREE_IF_COPY(query, 0); PG_FREE_IF_COPY(query, 0);
PG_RETURN_CSTRING(nrm.buf); PG_RETURN_CSTRING(nrm.buf);
@ -900,7 +904,7 @@ Datum tsquerytree(PG_FUNCTION_ARGS)
nrm.cur = nrm.buf = (char*)palloc(sizeof(char) * nrm.buflen); nrm.cur = nrm.buf = (char*)palloc(sizeof(char) * nrm.buflen);
*(nrm.cur) = '\0'; *(nrm.cur) = '\0';
nrm.op = GETOPERAND(query); nrm.op = GETOPERAND(query);
infix(&nrm, true); infix(&nrm, -1, false);
res = cstring_to_text_with_len(nrm.buf, nrm.cur - nrm.buf); res = cstring_to_text_with_len(nrm.buf, nrm.cur - nrm.buf);
pfree_ext(nrm.buf); pfree_ext(nrm.buf);
pfree_ext(q); pfree_ext(q);

View File

@ -186,6 +186,14 @@ typedef struct {
#define OP_NOT 1 #define OP_NOT 1
#define OP_AND 2 #define OP_AND 2
#define OP_OR 3 #define OP_OR 3
#define OP_COUNT 3
extern PGDLLIMPORT const int tsearch_op_priority[OP_COUNT];
/* get operation priority by its code */
#define OP_PRIORITY(x) ( tsearch_op_priority[(x) - 1] )
/* get QueryOperator priority */
#define QO_PRIORITY(x) OP_PRIORITY(((QueryOperator *) (x))->oper)
typedef struct { typedef struct {
QueryItemType type; QueryItemType type;

View File

@ -289,15 +289,15 @@ SELECT '(!1|2)&3'::tsquery;
(1 row) (1 row)
SELECT '1|(2|(4|(5|6)))'::tsquery; SELECT '1|(2|(4|(5|6)))'::tsquery;
tsquery tsquery
----------------------------------------- -----------------------------
'1' | ( '2' | ( '4' | ( '5' | '6' ) ) ) '1' | '2' | '4' | '5' | '6'
(1 row) (1 row)
SELECT '1|2|4|5|6'::tsquery; SELECT '1|2|4|5|6'::tsquery;
tsquery tsquery
----------------------------------------- -----------------------------
( ( ( '1' | '2' ) | '4' ) | '5' ) | '6' '1' | '2' | '4' | '5' | '6'
(1 row) (1 row)
SELECT '1&(2&(4&(5&6)))'::tsquery; SELECT '1&(2&(4&(5&6)))'::tsquery;
@ -337,9 +337,9 @@ SELECT $$'\\as'$$::tsquery;
(1 row) (1 row)
SELECT 'a:* & nbb:*ac | doo:a* | goo'::tsquery; SELECT 'a:* & nbb:*ac | doo:a* | goo'::tsquery;
tsquery tsquery
------------------------------------------ --------------------------------------
( 'a':* & 'nbb':*AC | 'doo':*A ) | 'goo' 'a':* & 'nbb':*AC | 'doo':*A | 'goo'
(1 row) (1 row)
SELECT 'a' < 'b & c'::tsquery as "true"; SELECT 'a' < 'b & c'::tsquery as "true";

View File

@ -464,9 +464,9 @@ SELECT to_tsvector('ispell_tst', 'Booking the skies after rebookings for footbal
(1 row) (1 row)
SELECT to_tsquery('ispell_tst', 'footballklubber'); SELECT to_tsquery('ispell_tst', 'footballklubber');
to_tsquery to_tsquery
------------------------------------------------------------------------------ --------------------------------------------------------------------------
( 'footballklubber' | 'foot' & 'ball' & 'klubber' ) | 'football' & 'klubber' 'footballklubber' | 'foot' & 'ball' & 'klubber' | 'football' & 'klubber'
(1 row) (1 row)
SELECT to_tsquery('ispell_tst', 'footballyklubber:b & rebookings:A & sky'); SELECT to_tsquery('ispell_tst', 'footballyklubber:b & rebookings:A & sky');
@ -488,9 +488,9 @@ SELECT to_tsvector('hunspell_tst', 'Booking the skies after rebookings for footb
(1 row) (1 row)
SELECT to_tsquery('hunspell_tst', 'footballklubber'); SELECT to_tsquery('hunspell_tst', 'footballklubber');
to_tsquery to_tsquery
------------------------------------------------------------------------------ --------------------------------------------------------------------------
( 'footballklubber' | 'foot' & 'ball' & 'klubber' ) | 'football' & 'klubber' 'footballklubber' | 'foot' & 'ball' & 'klubber' | 'football' & 'klubber'
(1 row) (1 row)
SELECT to_tsquery('hunspell_tst', 'footballyklubber:b & rebookings:A & sky'); SELECT to_tsquery('hunspell_tst', 'footballyklubber:b & rebookings:A & sky');
@ -509,9 +509,9 @@ SELECT to_tsvector('hunspell_tst', 'Booking the skies after rebookings for footb
(1 row) (1 row)
SELECT to_tsquery('hunspell_tst', 'footballklubber'); SELECT to_tsquery('hunspell_tst', 'footballklubber');
to_tsquery to_tsquery
------------------------------------------------------------------------------ --------------------------------------------------------------------------
( 'footballklubber' | 'foot' & 'ball' & 'klubber' ) | 'football' & 'klubber' 'footballklubber' | 'foot' & 'ball' & 'klubber' | 'football' & 'klubber'
(1 row) (1 row)
SELECT to_tsquery('hunspell_tst', 'footballyklubber:b & rebookings:A & sky'); SELECT to_tsquery('hunspell_tst', 'footballyklubber:b & rebookings:A & sky');
@ -530,9 +530,9 @@ SELECT to_tsvector('hunspell_tst', 'Booking the skies after rebookings for footb
(1 row) (1 row)
SELECT to_tsquery('hunspell_tst', 'footballklubber'); SELECT to_tsquery('hunspell_tst', 'footballklubber');
to_tsquery to_tsquery
------------------------------------------------------------------------------ --------------------------------------------------------------------------
( 'footballklubber' | 'foot' & 'ball' & 'klubber' ) | 'football' & 'klubber' 'footballklubber' | 'foot' & 'ball' & 'klubber' | 'football' & 'klubber'
(1 row) (1 row)
SELECT to_tsquery('hunspell_tst', 'footballyklubber:b & rebookings:A & sky'); SELECT to_tsquery('hunspell_tst', 'footballyklubber:b & rebookings:A & sky');

View File

@ -289,15 +289,15 @@ SELECT '(!1|2)&3'::tsquery;
(1 row) (1 row)
SELECT '1|(2|(4|(5|6)))'::tsquery; SELECT '1|(2|(4|(5|6)))'::tsquery;
tsquery tsquery
----------------------------------------- -----------------------------
'1' | ( '2' | ( '4' | ( '5' | '6' ) ) ) '1' | '2' | '4' | '5' | '6'
(1 row) (1 row)
SELECT '1|2|4|5|6'::tsquery; SELECT '1|2|4|5|6'::tsquery;
tsquery tsquery
----------------------------------------- -----------------------------
( ( ( '1' | '2' ) | '4' ) | '5' ) | '6' '1' | '2' | '4' | '5' | '6'
(1 row) (1 row)
SELECT '1&(2&(4&(5&6)))'::tsquery; SELECT '1&(2&(4&(5&6)))'::tsquery;
@ -337,9 +337,9 @@ SELECT $$'\\as'$$::tsquery;
(1 row) (1 row)
SELECT 'a:* & nbb:*ac | doo:a* | goo'::tsquery; SELECT 'a:* & nbb:*ac | doo:a* | goo'::tsquery;
tsquery tsquery
------------------------------------------ --------------------------------------
( 'a':* & 'nbb':*AC | 'doo':*A ) | 'goo' 'a':* & 'nbb':*AC | 'doo':*A | 'goo'
(1 row) (1 row)
SELECT 'a' < 'b & c'::tsquery as "true"; SELECT 'a' < 'b & c'::tsquery as "true";