3
3
#include "optimizer/pathnode.h"
4
4
#include "optimizer/restrictinfo.h"
5
5
#include "optimizer/tlist.h"
6
+ #include "optimizer/var.h"
6
7
#include "utils/tqual.h"
7
8
#include "utils/builtins.h"
8
9
#include "utils/elog.h"
@@ -172,69 +173,43 @@ get_const_val(Const *node)
172
173
* whether some partial indices may suffice
173
174
*/
174
175
static Oid
175
- pick_suitable_index (Oid relation , AttrNumber column )
176
+ pick_suitable_index (RelOptInfo * relation , AttrNumber column )
176
177
{
177
178
Oid found_index = InvalidOid ;
178
179
int64 found_index_size = 0 ;
179
- HeapTuple htup ;
180
- SysScanDesc scan ;
181
- Relation pg_index ;
182
- List * spoint2_opclass_name ;
183
- Oid spoint2_opclass ;
184
- ScanKeyData key [3 ];
185
-
186
- spoint2_opclass_name = stringToQualifiedNameList ("public.spoint2" );
187
- spoint2_opclass = get_opclass_oid (GIST_AM_OID , spoint2_opclass_name , false);
188
-
189
- ScanKeyInit (& key [0 ],
190
- Anum_pg_index_indrelid ,
191
- BTEqualStrategyNumber ,
192
- F_OIDEQ ,
193
- ObjectIdGetDatum (relation ));
194
-
195
- pg_index = heap_open (IndexRelationId , AccessShareLock );
196
- scan = systable_beginscan (pg_index , InvalidOid , false, NULL , 1 , key );
197
-
198
- while (HeapTupleIsValid (htup = systable_getnext (scan )))
199
- {
200
- Form_pg_index pg_ind = (Form_pg_index ) GETSTRUCT (htup );
201
- Relation index ;
202
- Oid index_am ;
180
+ List * spoint2_opfamily_name ;
181
+ Oid spoint2_opfamily ;
182
+ ListCell * lc ;
183
+
184
+ spoint2_opfamily_name = stringToQualifiedNameList ("public.spoint2" );
185
+ spoint2_opfamily = get_opfamily_oid (GIST_AM_OID , spoint2_opfamily_name , false);
203
186
204
- index = index_open ( pg_ind -> indexrelid , AccessShareLock );
205
- index_am = index -> rd_rel -> relam ;
206
- index_close ( index , AccessShareLock );
187
+ foreach ( lc , relation -> indexlist )
188
+ {
189
+ IndexOptInfo * index = ( IndexOptInfo * ) lfirst ( lc );
207
190
208
191
/*
209
- * check if this is a valid GIST index with no predicates and
210
- * its first column is the required spoint with opclass 'spoint2'.
192
+ * check if this is a valid GIST index and its first
193
+ * column is the required spoint with opclass 'spoint2'.
211
194
*/
212
- if (index_am == GIST_AM_OID && pg_ind -> indisvalid &&
213
- heap_attisnull ( htup , Anum_pg_index_indpred ) &&
214
- pg_ind -> indkey . dim1 >= 1 && pg_ind -> indkey . values [0 ] == column )
195
+ if (index -> relam == GIST_AM_OID &&
196
+ ( index -> indpred == NIL || index -> predOK ) &&
197
+ index -> ncolumns >= 1 && index -> indexkeys [0 ] == column )
215
198
{
216
- int64 cur_index_size = get_index_size ( pg_ind -> indexrelid ) ;
199
+ int64 cur_index_size = index -> pages ;
217
200
218
201
if (found_index == InvalidOid || cur_index_size < found_index_size )
219
202
{
220
- bool is_null ;
221
- Datum indclass = heap_getattr (htup , Anum_pg_index_indclass ,
222
- pg_index -> rd_att , & is_null );
223
- oidvector * indclasses = (oidvector * ) DatumGetPointer (indclass );
224
-
225
203
/* column must use 'spoint2' opclass */
226
- if (! is_null && indclasses -> values [0 ] == spoint2_opclass )
204
+ if (index -> opfamily [0 ] == spoint2_opfamily )
227
205
{
228
- found_index = pg_ind -> indexrelid ;
206
+ found_index = index -> indexoid ;
229
207
found_index_size = cur_index_size ;
230
208
}
231
209
}
232
210
}
233
211
}
234
212
235
- systable_endscan (scan );
236
- heap_close (pg_index , AccessShareLock );
237
-
238
213
return found_index ;
239
214
}
240
215
@@ -301,16 +276,22 @@ create_crossmatch_path(PlannerInfo *root,
301
276
{
302
277
CrossmatchJoinPath * result ;
303
278
304
- Oid outer_rel = root -> simple_rte_array [outer_path -> parent -> relid ]-> relid ;
305
- Oid inner_rel = root -> simple_rte_array [inner_path -> parent -> relid ]-> relid ;
306
- Oid outer_idx ;
307
- Oid inner_idx ;
279
+ RelOptInfo * outerrel = outer_path -> parent ;
280
+ RelOptInfo * innerrel = inner_path -> parent ;
281
+ Oid outerrelid = root -> simple_rte_array [outerrel -> relid ]-> relid ;
282
+ Oid innerrelid = root -> simple_rte_array [innerrel -> relid ]-> relid ;
283
+ Oid outer_idx ;
284
+ Oid inner_idx ;
285
+
286
+ Assert (outerrelid != InvalidOid );
287
+ Assert (innerrelid != InvalidOid );
308
288
309
- if (outer_rel == inner_rel )
289
+ /* Relations should be different */
290
+ if (outerrel -> relid == innerrel -> relid )
310
291
return ;
311
292
312
- if ((outer_idx = pick_suitable_index (outer_rel , outer_spoint )) == InvalidOid ||
313
- (inner_idx = pick_suitable_index (inner_rel , inner_spoint )) == InvalidOid )
293
+ if ((outer_idx = pick_suitable_index (outerrel , outer_spoint )) == InvalidOid ||
294
+ (inner_idx = pick_suitable_index (innerrel , inner_spoint )) == InvalidOid )
314
295
{
315
296
return ;
316
297
}
@@ -328,10 +309,10 @@ create_crossmatch_path(PlannerInfo *root,
328
309
result -> cpath .methods = & crossmatch_path_methods ;
329
310
result -> outer_path = outer_path ;
330
311
result -> outer_idx = outer_idx ;
331
- result -> outer_rel = outer_rel ;
312
+ result -> outer_rel = outerrelid ;
332
313
result -> inner_path = inner_path ;
333
314
result -> inner_idx = inner_idx ;
334
- result -> inner_rel = inner_rel ;
315
+ result -> inner_rel = innerrelid ;
335
316
result -> threshold = threshold ;
336
317
result -> joinrestrictinfo = restrict_clauses ;
337
318
@@ -468,6 +449,7 @@ create_crossmatch_plan(PlannerInfo *root,
468
449
List * joinrestrictclauses = gpath -> joinrestrictinfo ;
469
450
List * joinclauses ;
470
451
CustomScan * cscan ;
452
+ PathTarget * target ;
471
453
472
454
Assert (!IS_OUTER_JOIN (gpath -> jointype ));
473
455
joinclauses = extract_actual_clauses (joinrestrictclauses , false);
@@ -477,8 +459,12 @@ create_crossmatch_plan(PlannerInfo *root,
477
459
cscan -> scan .plan .qual = joinclauses ;
478
460
cscan -> scan .scanrelid = 0 ;
479
461
462
+ /* Add Vars needed for our extended 'joinclauses' */
463
+ target = copy_pathtarget (rel -> reltarget );
464
+ add_new_columns_to_pathtarget (target , pull_var_clause ((Node * ) joinclauses , 0 ));
465
+
480
466
/* tlist of the 'virtual' join rel we'll have to build and scan */
481
- cscan -> custom_scan_tlist = make_tlist_from_pathtarget (rel -> reltarget );
467
+ cscan -> custom_scan_tlist = make_tlist_from_pathtarget (target );
482
468
483
469
cscan -> flags = best_path -> flags ;
484
470
cscan -> methods = & crossmatch_plan_methods ;
0 commit comments