diff options
Diffstat (limited to 'src/backend/utils/adt/tsquery.c')
-rw-r--r-- | src/backend/utils/adt/tsquery.c | 114 |
1 files changed, 52 insertions, 62 deletions
diff --git a/src/backend/utils/adt/tsquery.c b/src/backend/utils/adt/tsquery.c index 21a18bfbc44..72e608eb913 100644 --- a/src/backend/utils/adt/tsquery.c +++ b/src/backend/utils/adt/tsquery.c @@ -26,10 +26,10 @@ /* FTS operator priorities, see ts_type.h */ const int tsearch_op_priority[OP_COUNT] = { - 3, /* OP_NOT */ + 4, /* OP_NOT */ 2, /* OP_AND */ 1, /* OP_OR */ - 4 /* OP_PHRASE */ + 3 /* OP_PHRASE */ }; struct TSQueryParserStateData @@ -430,6 +430,40 @@ pushStop(TSQueryParserState state) #define STACKDEPTH 32 +typedef struct OperatorElement { + int8 op; + int16 distance; +} OperatorElement; + +static void +pushOpStack(OperatorElement *stack, int *lenstack, int8 op, int16 distance) +{ + if (*lenstack == STACKDEPTH) /* internal error */ + elog(ERROR, "tsquery stack too small"); + + stack[*lenstack].op = op; + stack[*lenstack].distance = distance; + + (*lenstack)++; +} + +static void +cleanOpStack(TSQueryParserState state, + OperatorElement *stack, int *lenstack, int8 op) +{ + int opPriority = OP_PRIORITY(op); + + while(*lenstack) + { + if (opPriority > OP_PRIORITY(stack[*lenstack - 1].op)) + break; + + (*lenstack)--; + pushOperator(state, stack[*lenstack].op, + stack[*lenstack].distance); + } +} + /* * Make polish (prefix) notation of query. * @@ -444,11 +478,7 @@ makepol(TSQueryParserState state, ts_tokentype type; int lenval = 0; char *strval = NULL; - struct - { - int8 op; - int16 distance; - } opstack[STACKDEPTH]; + OperatorElement opstack[STACKDEPTH]; int lenstack = 0; int16 weight = 0; bool prefix; @@ -462,49 +492,16 @@ makepol(TSQueryParserState state, { case PT_VAL: pushval(opaque, state, strval, lenval, weight, prefix); - while (lenstack && (opstack[lenstack - 1].op == OP_AND || - opstack[lenstack - 1].op == OP_PHRASE || - opstack[lenstack - 1].op == OP_NOT)) - { - lenstack--; - pushOperator(state, - opstack[lenstack].op, - opstack[lenstack].distance); - } break; case PT_OPR: - if (lenstack && operator == OP_OR) - pushOperator(state, OP_OR, 0); - else - { - if (lenstack == STACKDEPTH) /* internal error */ - elog(ERROR, "tsquery stack too small"); - opstack[lenstack].op = operator; - opstack[lenstack].distance = weight; - lenstack++; - } + cleanOpStack(state, opstack, &lenstack, operator); + pushOpStack(opstack, &lenstack, operator, weight); break; case PT_OPEN: makepol(state, pushval, opaque); - - while (lenstack && (opstack[lenstack - 1].op == OP_AND || - opstack[lenstack - 1].op == OP_PHRASE || - opstack[lenstack - 1].op == OP_NOT)) - { - lenstack--; - pushOperator(state, - opstack[lenstack].op, - opstack[lenstack].distance); - } break; case PT_CLOSE: - while (lenstack) - { - lenstack--; - pushOperator(state, - opstack[lenstack].op, - opstack[lenstack].distance); - }; + cleanOpStack(state, opstack, &lenstack, OP_OR /* lowest */); return; case PT_ERR: default: @@ -514,13 +511,8 @@ makepol(TSQueryParserState state, state->buffer))); } } - while (lenstack) - { - lenstack--; - pushOperator(state, - opstack[lenstack].op, - opstack[lenstack].distance); - } + + cleanOpStack(state, opstack, &lenstack, OP_OR /* lowest */); } static void @@ -750,7 +742,7 @@ while( ( (inf)->cur - (inf)->buf ) + (addsize) + 1 >= (inf)->buflen ) \ * print it in infix (human-readable) form */ static void -infix(INFIX *in, int parentPriority) +infix(INFIX *in, int parentPriority, bool rightPhraseOp) { /* since this function recurses, it could be driven to stack overflow. */ check_stack_depth(); @@ -819,7 +811,7 @@ infix(INFIX *in, int parentPriority) } else if (in->curpol->qoperator.oper == OP_NOT) { - int priority = PRINT_PRIORITY(in->curpol); + int priority = QO_PRIORITY(in->curpol); if (priority < parentPriority) { @@ -833,7 +825,7 @@ infix(INFIX *in, int parentPriority) *(in->cur) = '\0'; in->curpol++; - infix(in, priority); + infix(in, priority, false); if (priority < parentPriority) { RESIZEBUF(in, 2); @@ -844,17 +836,15 @@ infix(INFIX *in, int parentPriority) else { int8 op = in->curpol->qoperator.oper; - int priority = PRINT_PRIORITY(in->curpol); + int priority = QO_PRIORITY(in->curpol); int16 distance = in->curpol->qoperator.distance; INFIX nrm; bool needParenthesis = false; in->curpol++; if (priority < parentPriority || - (op == OP_PHRASE && - (priority == parentPriority || /* phrases are not - * commutative! */ - parentPriority == OP_PRIORITY(OP_AND)))) + /* phrase operator depends on order */ + (op == OP_PHRASE && rightPhraseOp)) { needParenthesis = true; RESIZEBUF(in, 2); @@ -868,11 +858,11 @@ infix(INFIX *in, int parentPriority) nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen); /* get right operand */ - infix(&nrm, priority); + infix(&nrm, priority, (op == OP_PHRASE)); /* get & print left operand */ in->curpol = nrm.curpol; - infix(in, priority); + infix(in, priority, false); /* print operator & right operand */ RESIZEBUF(in, 3 + (2 + 10 /* distance */ ) + (nrm.cur - nrm.buf)); @@ -924,7 +914,7 @@ tsqueryout(PG_FUNCTION_ARGS) nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen); *(nrm.cur) = '\0'; nrm.op = GETOPERAND(query); - infix(&nrm, -1 /* lowest priority */ ); + infix(&nrm, -1 /* lowest priority */, false); PG_FREE_IF_COPY(query, 0); PG_RETURN_CSTRING(nrm.buf); @@ -1151,7 +1141,7 @@ tsquerytree(PG_FUNCTION_ARGS) nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen); *(nrm.cur) = '\0'; nrm.op = GETOPERAND(query); - infix(&nrm, true); + infix(&nrm, -1, false); res = cstring_to_text_with_len(nrm.buf, nrm.cur - nrm.buf); pfree(q); } |