@@ -67,21 +67,6 @@ typedef struct
6767iptr2 ;
6868}ResultPair ;
6969
70- /*
71- * Context of crossmatch: represents data which are persistent across SRF calls.
72- */
73- typedef struct
74- {
75- MemoryContext context ;
76- Relation indexes [2 ];
77- List * pendingPairs ;
78- List * resultsPairs ;
79- float8 pointThreshold ;
80- int box3dThreshold ;
81- SBOX * box ;
82- int32 boxkey [6 ];
83- }CrossmatchContext ;
84-
8570/*
8671 * Point information for line sweep algorithm.
8772 */
@@ -101,28 +86,6 @@ typedef struct
10186GistNSN parentlsn ;
10287}Box3DInfo ;
10388
104- PG_FUNCTION_INFO_V1 (crossmatch );
105-
106- /*
107- * Check if relation is index and has specified am oid. Trigger error if not
108- */
109- static Relation
110- checkOpenedRelation (Relation r ,Oid PgAmOid )
111- {
112- #if PG_VERSION_NUM >=90600
113- if (r -> rd_amroutine == NULL )
114- #else
115- if (r -> rd_am == NULL )
116- #endif
117- elog (ERROR ,"Relation %s.%s is not an index" ,
118- get_namespace_name (RelationGetNamespace (r )),
119- RelationGetRelationName (r ));
120- if (r -> rd_rel -> relam != PgAmOid )
121- elog (ERROR ,"Index %s.%s has wrong type" ,
122- get_namespace_name (RelationGetNamespace (r )),
123- RelationGetRelationName (r ));
124- return r ;
125- }
12689
12790/*
12891 * Add pending pages pair to context.
@@ -132,10 +95,6 @@ addPendingPair(CrossmatchContext *ctx, BlockNumber blk1, BlockNumber blk2,
13295GistNSN parentlsn1 ,GistNSN parentlsn2 )
13396{
13497PendingPair * blockNumberPair ;
135- MemoryContext oldcontext ;
136-
137- /* Switch to persistent memory context */
138- oldcontext = MemoryContextSwitchTo (ctx -> context );
13998
14099/* Add pending pair */
141100blockNumberPair = (PendingPair * )palloc (sizeof (PendingPair ));
@@ -144,9 +103,6 @@ addPendingPair(CrossmatchContext *ctx, BlockNumber blk1, BlockNumber blk2,
144103blockNumberPair -> parentlsn1 = parentlsn1 ;
145104blockNumberPair -> parentlsn2 = parentlsn2 ;
146105ctx -> pendingPairs = lcons (blockNumberPair ,ctx -> pendingPairs );
147-
148- /* Return old memory context */
149- MemoryContextSwitchTo (oldcontext );
150106}
151107
152108/*
@@ -156,35 +112,13 @@ static void
156112addResultPair (CrossmatchContext * ctx ,ItemPointer iptr1 ,ItemPointer iptr2 )
157113{
158114ResultPair * itemPointerPair ;
159- MemoryContext oldcontext ;
160-
161- /* Switch to persistent memory context */
162- oldcontext = MemoryContextSwitchTo (ctx -> context );
163115
164116/* Add result pair */
165117itemPointerPair = (ResultPair * )
166118palloc (sizeof (ResultPair ));
167119itemPointerPair -> iptr1 = * iptr1 ;
168120itemPointerPair -> iptr2 = * iptr2 ;
169121ctx -> resultsPairs = lappend (ctx -> resultsPairs ,itemPointerPair );
170-
171- /* Return old memory context */
172- MemoryContextSwitchTo (oldcontext );
173- }
174-
175- /*
176- * Open index relation with AccessShareLock.
177- */
178- static Relation
179- indexOpen (RangeVar * relvar )
180- {
181- #if PG_VERSION_NUM < 90200
182- Oid relOid = RangeVarGetRelid (relvar , false);
183- #else
184- Oid relOid = RangeVarGetRelid (relvar ,NoLock , false);
185- #endif
186- return checkOpenedRelation (
187- index_open (relOid ,AccessShareLock ),GIST_AM_OID );
188122}
189123
190124/*
@@ -199,69 +133,32 @@ indexClose(Relation r)
199133/*
200134 * Do necessary initialization for first SRF call.
201135 */
202- static void
203- setupFirstcall (FuncCallContext * funcctx , text * names [ 2 ] ,
204- float8 threshold , SBOX * box )
136+ void
137+ setupFirstcall (CrossmatchContext * ctx , Oid idx1 , Oid idx2 ,
138+ float8 threshold )
205139{
206- MemoryContext oldcontext ;
207- CrossmatchContext * ctx ;
208- TupleDesc tupdesc ;
209140GistNSN parentnsn = InvalidNSN ;
210- int i ;
211141
212- /* Switch to persistent memory context */
213- oldcontext = MemoryContextSwitchTo (funcctx -> multi_call_memory_ctx );
142+ ctx -> box = NULL ;
143+
144+ Assert (idx1 != idx2 );
145+
146+ ctx -> indexes [0 ]= index_open (idx1 ,AccessShareLock );
147+ ctx -> indexes [1 ]= index_open (idx2 ,AccessShareLock );
214148
215- /* Allocate crossmarch context and fill it with scan parameters */
216- ctx = (CrossmatchContext * )palloc0 (sizeof (CrossmatchContext ));
217- ctx -> context = funcctx -> multi_call_memory_ctx ;
218- ctx -> box = box ;
219- if (box )
220- spherebox_gen_key (ctx -> boxkey ,box );
221149ctx -> pointThreshold = 2.0 * sin (0.5 * threshold );
222150ctx -> box3dThreshold = MAXCVALUE * ctx -> pointThreshold ;
223- funcctx -> user_fctx = (void * )ctx ;
224-
225- /* Open both indexes */
226- for (i = 0 ;i < 2 ;i ++ )
227- {
228- char * relname = text_to_cstring (names [i ]);
229- List * relname_list ;
230- RangeVar * relvar ;
231-
232- relname_list = stringToQualifiedNameList (relname );
233- relvar = makeRangeVarFromNameList (relname_list );
234- ctx -> indexes [i ]= indexOpen (relvar );
235- pfree (relname );
236- }
237151
238152/*
239153 * Add first pending pair of pages: we start scan both indexes from their
240154 * roots.
241155 */
242156addPendingPair (ctx ,GIST_ROOT_BLKNO ,GIST_ROOT_BLKNO ,
243157parentnsn ,parentnsn );
244-
245- /* Describe structure of resulting tuples */
246- tupdesc = CreateTemplateTupleDesc (2 , false);
247- TupleDescInitEntry (tupdesc ,1 ,"ctid1" ,TIDOID ,-1 ,0 );
248- TupleDescInitEntry (tupdesc ,2 ,"ctid2" ,TIDOID ,-1 ,0 );
249- funcctx -> slot = TupleDescGetSlot (tupdesc );
250- funcctx -> attinmeta = TupleDescGetAttInMetadata (tupdesc );
251-
252- /* Return old memory context */
253- MemoryContextSwitchTo (oldcontext );
254158}
255159
256- /*
257- * Close SRF call: free occupied resources.
258- */
259- static void
260- closeCall (FuncCallContext * funcctx )
160+ void endCall (CrossmatchContext * ctx )
261161{
262- CrossmatchContext * ctx = (CrossmatchContext * ) (funcctx -> user_fctx );
263-
264- /* Close indexes */
265162indexClose (ctx -> indexes [0 ]);
266163indexClose (ctx -> indexes [1 ]);
267164}
@@ -969,39 +866,9 @@ processPendingPair(CrossmatchContext *ctx, BlockNumber blk1, BlockNumber blk2,
969866/*
970867 * Crossmatch SRF
971868 */
972- Datum
973- crossmatch (PG_FUNCTION_ARGS )
869+ void
870+ crossmatch (CrossmatchContext * ctx , ItemPointer values )
974871{
975- FuncCallContext * funcctx ;
976- CrossmatchContext * ctx ;
977-
978- /*
979- * Initialize crossmatch context if first call of SRF.
980- */
981- if (SRF_IS_FIRSTCALL ())
982- {
983- SBOX * box ;
984- text * names [2 ];
985- float8 threshold = PG_GETARG_FLOAT8 (2 );
986-
987- names [0 ]= PG_GETARG_TEXT_P (0 );
988- names [1 ]= PG_GETARG_TEXT_P (1 );
989- funcctx = SRF_FIRSTCALL_INIT ();
990-
991- /* Assume no restriction on first dataset if less than 3 args */
992- if (PG_NARGS ()< 4 )
993- box = NULL ;
994- else
995- box = (SBOX * )PG_GETARG_POINTER (3 );
996-
997- setupFirstcall (funcctx ,names ,threshold ,box );
998- PG_FREE_IF_COPY (names [0 ],0 );
999- PG_FREE_IF_COPY (names [1 ],0 );
1000- }
1001-
1002- funcctx = SRF_PERCALL_SETUP ();
1003- ctx = (CrossmatchContext * )funcctx -> user_fctx ;
1004-
1005872/* Scan pending pairs until we have some result pairs */
1006873while (ctx -> resultsPairs == NIL && ctx -> pendingPairs != NIL )
1007874{
@@ -1018,27 +885,18 @@ crossmatch(PG_FUNCTION_ARGS)
1018885/* Return next result pair if any. Otherwise close SRF. */
1019886if (ctx -> resultsPairs != NIL )
1020887{
1021- Datum datums [2 ],
1022- result ;
1023- bool nulls [2 ];
1024888ResultPair * itemPointerPair = (ResultPair * )palloc (sizeof (ResultPair ));
1025- HeapTuple htuple ;
1026889
1027890* itemPointerPair = * ((ResultPair * )linitial (ctx -> resultsPairs ));
1028891pfree (linitial (ctx -> resultsPairs ));
1029892ctx -> resultsPairs = list_delete_first (ctx -> resultsPairs );
1030- datums [0 ]= PointerGetDatum (& itemPointerPair -> iptr1 );
1031- datums [1 ]= PointerGetDatum (& itemPointerPair -> iptr2 );
1032- nulls [0 ]= false;
1033- nulls [1 ]= false;
1034-
1035- htuple = heap_formtuple (funcctx -> attinmeta -> tupdesc ,datums ,nulls );
1036- result = TupleGetDatum (funcctx -> slot ,htuple );
1037- SRF_RETURN_NEXT (funcctx ,result );
893+
894+ values [0 ]= itemPointerPair -> iptr1 ;
895+ values [1 ]= itemPointerPair -> iptr2 ;
1038896}
1039897else
1040898{
1041- closeCall ( funcctx );
1042- SRF_RETURN_DONE ( funcctx );
899+ ItemPointerSetInvalid ( & values [ 0 ] );
900+ ItemPointerSetInvalid ( & values [ 1 ] );
1043901}
1044902}