移植PG对tsquery显示的优化到openGauss中
This commit is contained in:
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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";
|
||||||
|
@ -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');
|
||||||
|
@ -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";
|
||||||
|
Reference in New Issue
Block a user