17
17
#include "tsearch/ts_utils.h"
18
18
#include "miscadmin.h"
19
19
20
+ /*
21
+ * Build QTNode tree for a tsquery given in QueryItem array format.
22
+ */
20
23
QTNode *
21
24
QT2QTN (QueryItem * in , char * operand )
22
25
{
@@ -50,6 +53,12 @@ QT2QTN(QueryItem *in, char *operand)
50
53
return node ;
51
54
}
52
55
56
+ /*
57
+ * Free a QTNode tree.
58
+ *
59
+ * Referenced "word" and "valnode" items are freed if marked as transient
60
+ * by flags.
61
+ */
53
62
void
54
63
QTNFree (QTNode * in )
55
64
{
@@ -62,26 +71,27 @@ QTNFree(QTNode *in)
62
71
if (in -> valnode -> type == QI_VAL && in -> word && (in -> flags & QTN_WORDFREE ) != 0 )
63
72
pfree (in -> word );
64
73
65
- if (in -> child )
74
+ if (in -> valnode -> type == QI_OPR )
66
75
{
67
- if (in -> valnode )
68
- {
69
- if (in -> valnode -> type == QI_OPR && in -> nchild > 0 )
70
- {
71
- int i ;
72
-
73
- for (i = 0 ; i < in -> nchild ; i ++ )
74
- QTNFree (in -> child [i ]);
75
- }
76
- if (in -> flags & QTN_NEEDFREE )
77
- pfree (in -> valnode );
78
- }
79
- pfree (in -> child );
76
+ int i ;
77
+
78
+ for (i = 0 ; i < in -> nchild ; i ++ )
79
+ QTNFree (in -> child [i ]);
80
80
}
81
+ if (in -> child )
82
+ pfree (in -> child );
83
+
84
+ if (in -> flags & QTN_NEEDFREE )
85
+ pfree (in -> valnode );
81
86
82
87
pfree (in );
83
88
}
84
89
90
+ /*
91
+ * Sort comparator for QTNodes.
92
+ *
93
+ * The sort order is somewhat arbitrary.
94
+ */
85
95
int
86
96
QTNodeCompare (QTNode * an , QTNode * bn )
87
97
{
@@ -135,12 +145,19 @@ QTNodeCompare(QTNode *an, QTNode *bn)
135
145
}
136
146
}
137
147
148
+ /*
149
+ * qsort comparator for QTNode pointers.
150
+ */
138
151
static int
139
152
cmpQTN (const void * a , const void * b )
140
153
{
141
154
return QTNodeCompare (* (QTNode * const * ) a , * (QTNode * const * ) b );
142
155
}
143
156
157
+ /*
158
+ * Canonicalize a QTNode tree by sorting the children of AND/OR nodes
159
+ * into an arbitrary but well-defined order.
160
+ */
144
161
void
145
162
QTNSort (QTNode * in )
146
163
{
@@ -158,13 +175,16 @@ QTNSort(QTNode *in)
158
175
qsort ((void * ) in -> child , in -> nchild , sizeof (QTNode * ), cmpQTN );
159
176
}
160
177
178
+ /*
179
+ * Are two QTNode trees equal according to QTNodeCompare?
180
+ */
161
181
bool
162
182
QTNEq (QTNode * a , QTNode * b )
163
183
{
164
184
uint32 sign = a -> sign & b -> sign ;
165
185
166
186
if (!(sign == a -> sign && sign == b -> sign ))
167
- return 0 ;
187
+ return false ;
168
188
169
189
return (QTNodeCompare (a , b ) == 0 ) ? true : false;
170
190
}
@@ -190,14 +210,17 @@ QTNTernary(QTNode *in)
190
210
for (i = 0 ; i < in -> nchild ; i ++ )
191
211
QTNTernary (in -> child [i ]);
192
212
213
+ /* Only AND and OR are associative, so don't flatten other node types */
214
+ if (in -> valnode -> qoperator .oper != OP_AND &&
215
+ in -> valnode -> qoperator .oper != OP_OR )
216
+ return ;
217
+
193
218
for (i = 0 ; i < in -> nchild ; i ++ )
194
219
{
195
220
QTNode * cc = in -> child [i ];
196
221
197
- /* OP_Phrase isn't associative */
198
222
if (cc -> valnode -> type == QI_OPR &&
199
- in -> valnode -> qoperator .oper == cc -> valnode -> qoperator .oper &&
200
- in -> valnode -> qoperator .oper != OP_PHRASE )
223
+ in -> valnode -> qoperator .oper == cc -> valnode -> qoperator .oper )
201
224
{
202
225
int oldnchild = in -> nchild ;
203
226
@@ -236,9 +259,6 @@ QTNBinary(QTNode *in)
236
259
for (i = 0 ; i < in -> nchild ; i ++ )
237
260
QTNBinary (in -> child [i ]);
238
261
239
- if (in -> nchild <= 2 )
240
- return ;
241
-
242
262
while (in -> nchild > 2 )
243
263
{
244
264
QTNode * nn = (QTNode * ) palloc0 (sizeof (QTNode ));
@@ -263,8 +283,9 @@ QTNBinary(QTNode *in)
263
283
}
264
284
265
285
/*
266
- * Count the total length of operand string in tree, including '\0'-
267
- * terminators.
286
+ * Count the total length of operand strings in tree (including '\0'-
287
+ * terminators) and the total number of nodes.
288
+ * Caller must initialize *sumlen and *nnode to zeroes.
268
289
*/
269
290
static void
270
291
cntsize (QTNode * in , int * sumlen , int * nnode )
@@ -293,6 +314,10 @@ typedef struct
293
314
char * curoperand ;
294
315
} QTN2QTState ;
295
316
317
+ /*
318
+ * Recursively convert a QTNode tree into flat tsquery format.
319
+ * Caller must have allocated arrays of the correct size.
320
+ */
296
321
static void
297
322
fillQT (QTN2QTState * state , QTNode * in )
298
323
{
@@ -330,6 +355,9 @@ fillQT(QTN2QTState *state, QTNode *in)
330
355
}
331
356
}
332
357
358
+ /*
359
+ * Build flat tsquery from a QTNode tree.
360
+ */
333
361
TSQuery
334
362
QTN2QT (QTNode * in )
335
363
{
@@ -358,6 +386,11 @@ QTN2QT(QTNode *in)
358
386
return out ;
359
387
}
360
388
389
+ /*
390
+ * Copy a QTNode tree.
391
+ *
392
+ * Modifiable copies of the words and valnodes are made, too.
393
+ */
361
394
QTNode *
362
395
QTNCopy (QTNode * in )
363
396
{
@@ -393,6 +426,9 @@ QTNCopy(QTNode *in)
393
426
return out ;
394
427
}
395
428
429
+ /*
430
+ * Clear the specified flag bit(s) in all nodes of a QTNode tree.
431
+ */
396
432
void
397
433
QTNClearFlags (QTNode * in , uint32 flags )
398
434
{
0 commit comments