Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 2cdd6d2

Browse files
author
Alexander Korotkov
committed
Fin bug in inverted fulltext search
Array of operands in QueryItemWrap was reallocated when overflow. However, during that QueryItemWrap's changes their location. And parent pointer might become invalid. Fixed by moving operands from array to list.
1 parent 3f8e58b commit 2cdd6d2

File tree

3 files changed

+53
-52
lines changed

3 files changed

+53
-52
lines changed

expected/ruminv.out

+17-12
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ INSERT INTO test_invrum VALUES ('(a|b)&c'::tsquery);
99
INSERT INTO test_invrum VALUES ('(!(a|b))&c'::tsquery);
1010
INSERT INTO test_invrum VALUES ('(a|b)&(c|d)'::tsquery);
1111
INSERT INTO test_invrum VALUES ('!a'::tsquery);
12+
INSERT INTO test_invrum VALUES ('(a|a1|a2|a3|a4|a5)&(b|b1|b2|b3|b4|b5|b6)&!(c|c1|c2|c3)'::tsquery);
1213
SELECT * FROM test_invrum WHERE q @@ ''::tsvector;
1314
q
1415
----------------
@@ -36,12 +37,13 @@ SELECT * FROM test_invrum WHERE q @@ 'b'::tsvector;
3637
(4 rows)
3738

3839
SELECT * FROM test_invrum WHERE q @@ 'a b'::tsvector;
39-
q
40-
------------
40+
q
41+
--------------------------------------------------------------------------------------------------------------------------------
4142
'a' | 'b'
4243
'a' & 'b'
4344
!'a' | 'b'
44-
(3 rows)
45+
( 'a' | 'a1' | 'a2' | 'a3' | 'a4' | 'a5' ) & ( 'b' | 'b1' | 'b2' | 'b3' | 'b4' | 'b5' | 'b6' ) & !( 'c' | 'c1' | 'c2' | 'c3' )
46+
(4 rows)
4547

4648
SELECT * FROM test_invrum WHERE q @@ 'c'::tsvector;
4749
q
@@ -113,13 +115,14 @@ SELECT * FROM test_invrum WHERE q @@ 'b d'::tsvector;
113115
(5 rows)
114116

115117
SELECT * FROM test_invrum WHERE q @@ 'a b d'::tsvector;
116-
q
117-
-------------------------------
118+
q
119+
--------------------------------------------------------------------------------------------------------------------------------
118120
'a' | 'b'
119121
'a' & 'b'
120122
!'a' | 'b'
121123
( 'a' | 'b' ) & ( 'c' | 'd' )
122-
(4 rows)
124+
( 'a' | 'a1' | 'a2' | 'a3' | 'a4' | 'a5' ) & ( 'b' | 'b1' | 'b2' | 'b3' | 'b4' | 'b5' | 'b6' ) & !( 'c' | 'c1' | 'c2' | 'c3' )
125+
(5 rows)
123126

124127
SELECT * FROM test_invrum WHERE q @@ 'c d'::tsvector;
125128
q
@@ -166,12 +169,13 @@ SELECT * FROM test_invrum WHERE q @@ 'b'::tsvector;
166169
(4 rows)
167170

168171
SELECT * FROM test_invrum WHERE q @@ 'a b'::tsvector;
169-
q
170-
------------
172+
q
173+
--------------------------------------------------------------------------------------------------------------------------------
171174
'a' | 'b'
172175
'a' & 'b'
173176
!'a' | 'b'
174-
(3 rows)
177+
( 'a' | 'a1' | 'a2' | 'a3' | 'a4' | 'a5' ) & ( 'b' | 'b1' | 'b2' | 'b3' | 'b4' | 'b5' | 'b6' ) & !( 'c' | 'c1' | 'c2' | 'c3' )
178+
(4 rows)
175179

176180
SELECT * FROM test_invrum WHERE q @@ 'c'::tsvector;
177181
q
@@ -243,13 +247,14 @@ SELECT * FROM test_invrum WHERE q @@ 'b d'::tsvector;
243247
(5 rows)
244248

245249
SELECT * FROM test_invrum WHERE q @@ 'a b d'::tsvector;
246-
q
247-
-------------------------------
250+
q
251+
--------------------------------------------------------------------------------------------------------------------------------
248252
'a' | 'b'
249253
'a' & 'b'
250254
!'a' | 'b'
251255
( 'a' | 'b' ) & ( 'c' | 'd' )
252-
(4 rows)
256+
( 'a' | 'a1' | 'a2' | 'a3' | 'a4' | 'a5' ) & ( 'b' | 'b1' | 'b2' | 'b3' | 'b4' | 'b5' | 'b6' ) & !( 'c' | 'c1' | 'c2' | 'c3' )
257+
(5 rows)
253258

254259
SELECT * FROM test_invrum WHERE q @@ 'c d'::tsvector;
255260
q

sql/ruminv.sql

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ INSERT INTO test_invrum VALUES ('(a|b)&c'::tsquery);
1010
INSERT INTO test_invrum VALUES ('(!(a|b))&c'::tsquery);
1111
INSERT INTO test_invrum VALUES ('(a|b)&(c|d)'::tsquery);
1212
INSERT INTO test_invrum VALUES ('!a'::tsquery);
13+
INSERT INTO test_invrum VALUES ('(a|a1|a2|a3|a4|a5)&(b|b1|b2|b3|b4|b5|b6)&!(c|c1|c2|c3)'::tsquery);
1314

1415
SELECT * FROM test_invrum WHERE q @@ ''::tsvector;
1516
SELECT * FROM test_invrum WHERE q @@ 'a'::tsvector;

src/rumtsquery.c

+35-40
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@ typedef struct QueryItemWrap
2525
QueryItemType type;
2626
int8 oper;
2727
bool not;
28-
int operandsCount,
29-
operandsAllocated;
30-
struct QueryItemWrap *operands;
28+
List *operands;
3129
struct QueryItemWrap *parent;
3230
int distance,
3331
length;
@@ -40,29 +38,12 @@ add_child(QueryItemWrap * parent)
4038
{
4139
QueryItemWrap *result;
4240

43-
if (!parent)
44-
{
45-
result = (QueryItemWrap *) palloc0(sizeof(QueryItemWrap));
46-
}
47-
else
41+
result = (QueryItemWrap *) palloc0(sizeof(QueryItemWrap));
42+
43+
if (parent)
4844
{
49-
parent->operandsCount++;
50-
while (parent->operandsCount > parent->operandsAllocated)
51-
{
52-
if (parent->operandsAllocated > 0)
53-
{
54-
parent->operandsAllocated *= 2;
55-
parent->operands = (QueryItemWrap *) repalloc(parent->operands, parent->operandsAllocated * sizeof(*parent->operands));
56-
}
57-
else
58-
{
59-
parent->operandsAllocated = 4;
60-
parent->operands = (QueryItemWrap *) palloc(parent->operandsAllocated * sizeof(*parent->operands));
61-
}
62-
}
63-
result = &parent->operands[parent->operandsCount - 1];
64-
memset(result, 0, sizeof(*result));
6545
result->parent = parent;
46+
parent->operands = lappend(parent->operands, result);
6647
}
6748
return result;
6849
}
@@ -129,21 +110,23 @@ make_query_item_wrap(QueryItem *item, QueryItemWrap * parent, bool not)
129110
static int
130111
calc_wraps(QueryItemWrap * wrap, int *num)
131112
{
132-
int i,
133-
notCount = 0,
113+
int notCount = 0,
134114
result;
115+
ListCell *lc;
135116

136-
for (i = 0; i < wrap->operandsCount; i++)
117+
foreach(lc, wrap->operands)
137118
{
138-
if (wrap->operands[i].not)
119+
QueryItemWrap *item = (QueryItemWrap *) lfirst(lc);
120+
121+
if (item->not)
139122
notCount++;
140123
}
141124

142125
if (wrap->type == QI_OPR)
143126
{
144127
wrap->num = (*num)++;
145128
if (wrap->oper == OP_AND)
146-
wrap->sum = notCount + 1 - wrap->operandsCount;
129+
wrap->sum = notCount + 1 - list_length(wrap->operands);
147130
if (wrap->oper == OP_OR)
148131
wrap->sum = notCount;
149132
}
@@ -153,8 +136,12 @@ calc_wraps(QueryItemWrap * wrap, int *num)
153136
}
154137

155138
result = 0;
156-
for (i = 0; i < wrap->operandsCount; i++)
157-
result += calc_wraps(&wrap->operands[i], num);
139+
foreach(lc, wrap->operands)
140+
{
141+
QueryItemWrap *item = (QueryItemWrap *) lfirst(lc);
142+
143+
result += calc_wraps(item, num);
144+
}
158145
return result;
159146
}
160147

@@ -167,22 +154,26 @@ check_allnegative(QueryItemWrap * wrap)
167154
}
168155
else if (wrap->oper == OP_AND)
169156
{
170-
int i;
157+
ListCell *lc;
171158

172-
for (i = 0; i < wrap->operandsCount; i++)
159+
foreach(lc, wrap->operands)
173160
{
174-
if (!check_allnegative(&wrap->operands[i]))
161+
QueryItemWrap *item = (QueryItemWrap *) lfirst(lc);
162+
163+
if (!check_allnegative(item))
175164
return false;
176165
}
177166
return true;
178167
}
179168
else if (wrap->oper == OP_OR)
180169
{
181-
int i;
170+
ListCell *lc;
182171

183-
for (i = 0; i < wrap->operandsCount; i++)
172+
foreach(lc, wrap->operands)
184173
{
185-
if (check_allnegative(&wrap->operands[i]))
174+
QueryItemWrap *item = (QueryItemWrap *) lfirst(lc);
175+
176+
if (check_allnegative(item))
186177
return true;
187178
}
188179
return false;
@@ -348,10 +339,14 @@ extract_wraps(QueryItemWrap * wrap, ExtractContext * context, int level)
348339
}
349340
else if (wrap->type == QI_OPR)
350341
{
351-
int i;
342+
ListCell *lc;
352343

353-
for (i = 0; i < wrap->operandsCount; i++)
354-
extract_wraps(&wrap->operands[i], context, level + 1);
344+
foreach(lc, wrap->operands)
345+
{
346+
QueryItemWrap *item = (QueryItemWrap *) lfirst(lc);
347+
348+
extract_wraps(item, context, level + 1);
349+
}
355350
}
356351
}
357352

0 commit comments

Comments
 (0)