pgsql-5793

Version:

9.0.0

Bug Link:

http://archives.postgresql.org/pgsql-bugs/2010-12/msg00127.php

http://git.postgresql.org/gitweb?p=postgresql.git;a=commitdiff;h=abc10262696e53773c9a8c9f279bbd464b464190

Symptom:

wrong tsquery interpretation result

Failure type:

Incorrect output

Is there any log message?

No

How it is diagnosed:

Reproduced!

How to reproduce:

postgres=# select '(a & !(c | d)) | (a & b)'::tsquery;

             tsquery              

----------------------------------

 'a' & !( 'c' | 'd' ) | 'a' & 'b'

(1 row)

postgres=# select 'a & !(c | d) | a & b'::tsquery;

               tsquery                

--------------------------------------

 ( 'a' | !( 'c' | 'd' ) ) & 'a' & 'b'            <----- incorrect!!

(1 row)

postgres=# select 'a & !(c | d) | a & b'::tsquery;

             tsquery              

----------------------------------              <----- correct result!!

 'a' & !( 'c' | 'd' ) | 'a' & 'b'

(1 row)

Root Cause:

After parsidng a parenthesized subexpression, we must pop all pending

ANDs and NOTs off the stack, just like the case for a simple operand.

/ * Make polish (prefix) notation of query.*/

static void makepol(...)

{

        ...

while ((type = gettoken_query(...)...)

{

        switch (type)

        {

                case PT_OPEN:

                        makepol(state, pushval, opaque);

-               if (lenstack && (opstack[lenstack - 1] == OP_AND ||

-                                opstack[lenstack - 1] == OP_NOT))

+               while (lenstack && (opstack[lenstack - 1] == OP_AND ||

+                                   opstack[lenstack - 1] == OP_NOT))

                        {

                                        lenstack--;

                                        pushOperator(state, opstack[lenstack]);

                        }

                        break;

        }

}

while (lenstack)

{

        lenstack--;

        pushOperator(state, opstack[lenstack]);

}

}

347                while ((type = gettoken_query(state, &operator, &lenval, &strval, &weight, &prefix)) != PT_END)

(gdb)

349                        switch (type)

(gdb)

352                                        pushval(opaque, state, strval, lenval, weight, prefix);

(gdb)

353                                        while (lenstack && (opstack[lenstack - 1] == OP_AND ||

(gdb)

354                                                                                opstack[lenstack - 1] == OP_NOT))

(gdb)

353                                        while (lenstack && (opstack[lenstack - 1] == OP_AND ||

(gdb)

359                                        break;

(gdb)

347                while ((type = gettoken_query(state, &operator, &lenval, &strval, &weight, &prefix)) != PT_END)

(gdb)

349                        switch (type)

(gdb)

382                                        while (lenstack)

(gdb) p strval

$21 = 0x95f2fa0 "d"

(gdb) p *state

$22 = {buffer = 0x95f29ac "a & !(c | d) | a & b", buf = 0x95f29b8 " | a & b", state = 2, count = 0, polstr = 0x95f2fe0, op = 0x95f2edc "a", curop = 0x95f2ee2 '\177' <repeats 58 times>, lenop = 64, sumlen = 6, valstate = 0x95f2f74}

(gdb) p type

$23 = PT_CLOSE

(gdb) n

384                                                lenstack--;

(gdb)

385                                                pushOperator(state, opstack[lenstack]);

(gdb)

382                                        while (lenstack)

(gdb)

387                                        return;

(gdb) n

401        }

(gdb)

makepol (state=0xbfb93d50, pushval=0x83b0b9e <pushval_asis>, opaque=0) at tsquery.c:374

374                                        while (lenstack && (opstack[lenstack - 1] == OP_AND ||

(gdb) p lenstack

$24 = 2

Can we anticipate error?

No.