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
{
@@ -131,12 +141,19 @@ QTNodeCompare(QTNode *an, QTNode *bn)
131
141
}
132
142
}
133
143
144
+ /*
145
+ * qsort comparator for QTNode pointers.
146
+ */
134
147
static int
135
148
cmpQTN (const void * a , const void * b )
136
149
{
137
150
return QTNodeCompare (* (QTNode * const * ) a , * (QTNode * const * ) b );
138
151
}
139
152
153
+ /*
154
+ * Canonicalize a QTNode tree by sorting the children of AND/OR nodes
155
+ * into an arbitrary but well-defined order.
156
+ */
140
157
void
141
158
QTNSort (QTNode * in )
142
159
{
@@ -154,13 +171,16 @@ QTNSort(QTNode *in)
154
171
qsort ((void * ) in -> child , in -> nchild , sizeof (QTNode * ), cmpQTN );
155
172
}
156
173
174
+ /*
175
+ * Are two QTNode trees equal according to QTNodeCompare?
176
+ */
157
177
bool
158
178
QTNEq (QTNode * a , QTNode * b )
159
179
{
160
180
uint32 sign = a -> sign & b -> sign ;
161
181
162
182
if (!(sign == a -> sign && sign == b -> sign ))
163
- return 0 ;
183
+ return false ;
164
184
165
185
return (QTNodeCompare (a , b ) == 0 ) ? true : false;
166
186
}
@@ -186,11 +206,17 @@ QTNTernary(QTNode *in)
186
206
for (i = 0 ; i < in -> nchild ; i ++ )
187
207
QTNTernary (in -> child [i ]);
188
208
209
+ /* Only AND and OR are associative, so don't flatten other node types */
210
+ if (in -> valnode -> qoperator .oper != OP_AND &&
211
+ in -> valnode -> qoperator .oper != OP_OR )
212
+ return ;
213
+
189
214
for (i = 0 ; i < in -> nchild ; i ++ )
190
215
{
191
216
QTNode * cc = in -> child [i ];
192
217
193
- if (cc -> valnode -> type == QI_OPR && in -> valnode -> qoperator .oper == cc -> valnode -> qoperator .oper )
218
+ if (cc -> valnode -> type == QI_OPR &&
219
+ in -> valnode -> qoperator .oper == cc -> valnode -> qoperator .oper )
194
220
{
195
221
int oldnchild = in -> nchild ;
196
222
@@ -229,9 +255,6 @@ QTNBinary(QTNode *in)
229
255
for (i = 0 ; i < in -> nchild ; i ++ )
230
256
QTNBinary (in -> child [i ]);
231
257
232
- if (in -> nchild <= 2 )
233
- return ;
234
-
235
258
while (in -> nchild > 2 )
236
259
{
237
260
QTNode * nn = (QTNode * ) palloc0 (sizeof (QTNode ));
@@ -256,8 +279,9 @@ QTNBinary(QTNode *in)
256
279
}
257
280
258
281
/*
259
- * Count the total length of operand string in tree, including '\0'-
260
- * terminators.
282
+ * Count the total length of operand strings in tree (including '\0'-
283
+ * terminators) and the total number of nodes.
284
+ * Caller must initialize *sumlen and *nnode to zeroes.
261
285
*/
262
286
static void
263
287
cntsize (QTNode * in , int * sumlen , int * nnode )
@@ -286,6 +310,10 @@ typedef struct
286
310
char * curoperand ;
287
311
} QTN2QTState ;
288
312
313
+ /*
314
+ * Recursively convert a QTNode tree into flat tsquery format.
315
+ * Caller must have allocated arrays of the correct size.
316
+ */
289
317
static void
290
318
fillQT (QTN2QTState * state , QTNode * in )
291
319
{
@@ -323,6 +351,9 @@ fillQT(QTN2QTState *state, QTNode *in)
323
351
}
324
352
}
325
353
354
+ /*
355
+ * Build flat tsquery from a QTNode tree.
356
+ */
326
357
TSQuery
327
358
QTN2QT (QTNode * in )
328
359
{
@@ -351,6 +382,11 @@ QTN2QT(QTNode *in)
351
382
return out ;
352
383
}
353
384
385
+ /*
386
+ * Copy a QTNode tree.
387
+ *
388
+ * Modifiable copies of the words and valnodes are made, too.
389
+ */
354
390
QTNode *
355
391
QTNCopy (QTNode * in )
356
392
{
@@ -386,6 +422,9 @@ QTNCopy(QTNode *in)
386
422
return out ;
387
423
}
388
424
425
+ /*
426
+ * Clear the specified flag bit(s) in all nodes of a QTNode tree.
427
+ */
389
428
void
390
429
QTNClearFlags (QTNode * in , uint32 flags )
391
430
{
0 commit comments