27
27
/* FTS operator priorities, see ts_type.h */
28
28
const int tsearch_op_priority [OP_COUNT ] =
29
29
{
30
- 3 , /* OP_NOT */
31
- 2 , /* OP_AND */
32
- 1 , /* OP_OR */
33
- 4 /* OP_PHRASE */
30
+ 4 , /* OP_NOT */
31
+ 2 , /* OP_AND */
32
+ 1 , /* OP_OR */
33
+ 3 /* OP_PHRASE */
34
34
};
35
35
36
36
struct TSQueryParserStateData
@@ -431,6 +431,40 @@ pushStop(TSQueryParserState state)
431
431
432
432
#define STACKDEPTH 32
433
433
434
+ typedef struct OperatorElement {
435
+ int8 op ;
436
+ int16 distance ;
437
+ } OperatorElement ;
438
+
439
+ static void
440
+ pushOpStack (OperatorElement * stack , int * lenstack , int8 op , int16 distance )
441
+ {
442
+ if (* lenstack == STACKDEPTH ) /* internal error */
443
+ elog (ERROR , "tsquery stack too small" );
444
+
445
+ stack [* lenstack ].op = op ;
446
+ stack [* lenstack ].distance = distance ;
447
+
448
+ (* lenstack )++ ;
449
+ }
450
+
451
+ static void
452
+ cleanOpStack (TSQueryParserState state ,
453
+ OperatorElement * stack , int * lenstack , int8 op )
454
+ {
455
+ int opPriority = OP_PRIORITY (op );
456
+
457
+ while (* lenstack )
458
+ {
459
+ if (opPriority > OP_PRIORITY (stack [* lenstack - 1 ].op ))
460
+ break ;
461
+
462
+ (* lenstack )-- ;
463
+ pushOperator (state , stack [* lenstack ].op ,
464
+ stack [* lenstack ].distance );
465
+ }
466
+ }
467
+
434
468
/*
435
469
* Make polish (prefix) notation of query.
436
470
*
@@ -441,18 +475,14 @@ makepol(TSQueryParserState state,
441
475
PushFunction pushval ,
442
476
Datum opaque )
443
477
{
444
- int8 operator = 0 ;
445
- ts_tokentype type ;
446
- int lenval = 0 ;
447
- char * strval = NULL ;
448
- struct
449
- {
450
- int8 op ;
451
- int16 distance ;
452
- } opstack [STACKDEPTH ];
453
- int lenstack = 0 ;
454
- int16 weight = 0 ;
455
- bool prefix ;
478
+ int8 operator = 0 ;
479
+ ts_tokentype type ;
480
+ int lenval = 0 ;
481
+ char * strval = NULL ;
482
+ OperatorElement opstack [STACKDEPTH ];
483
+ int lenstack = 0 ;
484
+ int16 weight = 0 ;
485
+ bool prefix ;
456
486
457
487
/* since this function recurses, it could be driven to stack overflow */
458
488
check_stack_depth ();
@@ -463,49 +493,16 @@ makepol(TSQueryParserState state,
463
493
{
464
494
case PT_VAL :
465
495
pushval (opaque , state , strval , lenval , weight , prefix );
466
- while (lenstack && (opstack [lenstack - 1 ].op == OP_AND ||
467
- opstack [lenstack - 1 ].op == OP_PHRASE ||
468
- opstack [lenstack - 1 ].op == OP_NOT ))
469
- {
470
- lenstack -- ;
471
- pushOperator (state ,
472
- opstack [lenstack ].op ,
473
- opstack [lenstack ].distance );
474
- }
475
496
break ;
476
497
case PT_OPR :
477
- if (lenstack && operator == OP_OR )
478
- pushOperator (state , OP_OR , 0 );
479
- else
480
- {
481
- if (lenstack == STACKDEPTH ) /* internal error */
482
- elog (ERROR , "tsquery stack too small" );
483
- opstack [lenstack ].op = operator ;
484
- opstack [lenstack ].distance = weight ;
485
- lenstack ++ ;
486
- }
498
+ cleanOpStack (state , opstack , & lenstack , operator );
499
+ pushOpStack (opstack , & lenstack , operator , weight );
487
500
break ;
488
501
case PT_OPEN :
489
502
makepol (state , pushval , opaque );
490
-
491
- while (lenstack && (opstack [lenstack - 1 ].op == OP_AND ||
492
- opstack [lenstack - 1 ].op == OP_PHRASE ||
493
- opstack [lenstack - 1 ].op == OP_NOT ))
494
- {
495
- lenstack -- ;
496
- pushOperator (state ,
497
- opstack [lenstack ].op ,
498
- opstack [lenstack ].distance );
499
- }
500
503
break ;
501
504
case PT_CLOSE :
502
- while (lenstack )
503
- {
504
- lenstack -- ;
505
- pushOperator (state ,
506
- opstack [lenstack ].op ,
507
- opstack [lenstack ].distance );
508
- };
505
+ cleanOpStack (state , opstack , & lenstack , OP_OR /* lowest */ );
509
506
return ;
510
507
case PT_ERR :
511
508
default :
@@ -515,13 +512,8 @@ makepol(TSQueryParserState state,
515
512
state -> buffer )));
516
513
}
517
514
}
518
- while (lenstack )
519
- {
520
- lenstack -- ;
521
- pushOperator (state ,
522
- opstack [lenstack ].op ,
523
- opstack [lenstack ].distance );
524
- }
515
+
516
+ cleanOpStack (state , opstack , & lenstack , OP_OR /* lowest */ );
525
517
}
526
518
527
519
static void
@@ -751,7 +743,7 @@ while( ( (inf)->cur - (inf)->buf ) + (addsize) + 1 >= (inf)->buflen ) \
751
743
* print it in infix (human-readable) form
752
744
*/
753
745
static void
754
- infix (INFIX * in , int parentPriority )
746
+ infix (INFIX * in , int parentPriority , bool rightPhraseOp )
755
747
{
756
748
/* since this function recurses, it could be driven to stack overflow. */
757
749
check_stack_depth ();
@@ -820,7 +812,7 @@ infix(INFIX *in, int parentPriority)
820
812
}
821
813
else if (in -> curpol -> qoperator .oper == OP_NOT )
822
814
{
823
- int priority = PRINT_PRIORITY (in -> curpol );
815
+ int priority = QO_PRIORITY (in -> curpol );
824
816
825
817
if (priority < parentPriority )
826
818
{
@@ -834,7 +826,7 @@ infix(INFIX *in, int parentPriority)
834
826
* (in -> cur ) = '\0' ;
835
827
in -> curpol ++ ;
836
828
837
- infix (in , priority );
829
+ infix (in , priority , false );
838
830
if (priority < parentPriority )
839
831
{
840
832
RESIZEBUF (in , 2 );
@@ -845,16 +837,15 @@ infix(INFIX *in, int parentPriority)
845
837
else
846
838
{
847
839
int8 op = in -> curpol -> qoperator .oper ;
848
- int priority = PRINT_PRIORITY (in -> curpol );
840
+ int priority = QO_PRIORITY (in -> curpol );
849
841
int16 distance = in -> curpol -> qoperator .distance ;
850
842
INFIX nrm ;
851
843
bool needParenthesis = false;
852
844
853
845
in -> curpol ++ ;
854
846
if (priority < parentPriority ||
855
- (op == OP_PHRASE &&
856
- (priority == parentPriority || /* phrases are not commutative! */
857
- parentPriority == OP_PRIORITY (OP_AND ))))
847
+ /* phrase operator depends on order */
848
+ (op == OP_PHRASE && rightPhraseOp ))
858
849
{
859
850
needParenthesis = true;
860
851
RESIZEBUF (in , 2 );
@@ -868,11 +859,11 @@ infix(INFIX *in, int parentPriority)
868
859
nrm .cur = nrm .buf = (char * ) palloc (sizeof (char ) * nrm .buflen );
869
860
870
861
/* get right operand */
871
- infix (& nrm , priority );
862
+ infix (& nrm , priority , ( op == OP_PHRASE ) );
872
863
873
864
/* get & print left operand */
874
865
in -> curpol = nrm .curpol ;
875
- infix (in , priority );
866
+ infix (in , priority , false );
876
867
877
868
/* print operator & right operand */
878
869
RESIZEBUF (in , 3 + (2 + 10 /* distance */ ) + (nrm .cur - nrm .buf ));
@@ -924,7 +915,7 @@ tsqueryout(PG_FUNCTION_ARGS)
924
915
nrm .cur = nrm .buf = (char * ) palloc (sizeof (char ) * nrm .buflen );
925
916
* (nrm .cur ) = '\0' ;
926
917
nrm .op = GETOPERAND (query );
927
- infix (& nrm , -1 /* lowest priority */ );
918
+ infix (& nrm , -1 /* lowest priority */ , false );
928
919
929
920
PG_FREE_IF_COPY (query , 0 );
930
921
PG_RETURN_CSTRING (nrm .buf );
@@ -1151,7 +1142,7 @@ tsquerytree(PG_FUNCTION_ARGS)
1151
1142
nrm .cur = nrm .buf = (char * ) palloc (sizeof (char ) * nrm .buflen );
1152
1143
* (nrm .cur ) = '\0' ;
1153
1144
nrm .op = GETOPERAND (query );
1154
- infix (& nrm , true );
1145
+ infix (& nrm , -1 , false );
1155
1146
res = cstring_to_text_with_len (nrm .buf , nrm .cur - nrm .buf );
1156
1147
pfree (q );
1157
1148
}
0 commit comments