88 * Portions Copyright (c) 1994, Regents of the University of California
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/access/gist/gistsplit.c,v 1.7 2009/01/01 17:23:35 momjian Exp $
11+ * $PostgreSQL: pgsql/src/backend/access/gist/gistsplit.c,v 1.8 2009/04/06 14:27:27 teodor Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -280,6 +280,63 @@ supportSecondarySplit(Relation r, GISTSTATE *giststate, int attno, GIST_SPLITVEC
280280sv -> spl_ldatum_exists = sv -> spl_rdatum_exists = false;
281281}
282282
283+ /*
284+ * Trivial picksplit implementaion. Function called only
285+ * if user-defined picksplit puts all keys to the one page.
286+ * That is a bug of user-defined picksplit but we'd like
287+ * to "fix" that.
288+ */
289+ static void
290+ genericPickSplit (GISTSTATE * giststate ,GistEntryVector * entryvec ,GIST_SPLITVEC * v ,int attno )
291+ {
292+ OffsetNumber i ,
293+ maxoff ;
294+ int nbytes ;
295+ GistEntryVector * evec ;
296+
297+ maxoff = entryvec -> n - 1 ;
298+
299+ nbytes = (maxoff + 2 )* sizeof (OffsetNumber );
300+
301+ v -> spl_left = (OffsetNumber * )palloc (nbytes );
302+ v -> spl_right = (OffsetNumber * )palloc (nbytes );
303+ v -> spl_nleft = v -> spl_nright = 0 ;
304+
305+ for (i = FirstOffsetNumber ;i <=maxoff ;i = OffsetNumberNext (i ))
306+ {
307+ if (i <= (maxoff - FirstOffsetNumber + 1 ) /2 )
308+ {
309+ v -> spl_left [v -> spl_nleft ]= i ;
310+ v -> spl_nleft ++ ;
311+ }
312+ else
313+ {
314+ v -> spl_right [v -> spl_nright ]= i ;
315+ v -> spl_nright ++ ;
316+ }
317+ }
318+
319+ /*
320+ * Form unions of each page
321+ */
322+
323+ evec = palloc (sizeof (GISTENTRY )* entryvec -> n + GEVHDRSZ );
324+
325+ evec -> n = v -> spl_nleft ;
326+ memcpy (evec -> vector ,entryvec -> vector + FirstOffsetNumber ,
327+ sizeof (GISTENTRY )* evec -> n );
328+ v -> spl_ldatum = FunctionCall2 (& giststate -> unionFn [attno ],
329+ PointerGetDatum (evec ),
330+ PointerGetDatum (& nbytes ));
331+
332+ evec -> n = v -> spl_nright ;
333+ memcpy (evec -> vector ,entryvec -> vector + FirstOffsetNumber + v -> spl_nleft ,
334+ sizeof (GISTENTRY )* evec -> n );
335+ v -> spl_rdatum = FunctionCall2 (& giststate -> unionFn [attno ],
336+ PointerGetDatum (evec ),
337+ PointerGetDatum (& nbytes ));
338+ }
339+
283340/*
284341 * Calls user picksplit method for attno columns to split vector to
285342 * two vectors. May use attno+n columns data to
@@ -296,7 +353,7 @@ gistUserPicksplit(Relation r, GistEntryVector *entryvec, int attno, GistSplitVec
296353
297354/*
298355 * now let the user-defined picksplit function set up the split vector; in
299- * entryvechave no null value!!
356+ * entryvecthere is no null value!!
300357 */
301358
302359sv -> spl_ldatum_exists = (v -> spl_lisnull [attno ]) ? false : true;
@@ -308,18 +365,43 @@ gistUserPicksplit(Relation r, GistEntryVector *entryvec, int attno, GistSplitVec
308365PointerGetDatum (entryvec ),
309366PointerGetDatum (sv ));
310367
311- /* compatibility with old code */
312- if (sv -> spl_left [sv -> spl_nleft - 1 ]== InvalidOffsetNumber )
313- sv -> spl_left [sv -> spl_nleft - 1 ]= (OffsetNumber ) (entryvec -> n - 1 );
314- if (sv -> spl_right [sv -> spl_nright - 1 ]== InvalidOffsetNumber )
315- sv -> spl_right [sv -> spl_nright - 1 ]= (OffsetNumber ) (entryvec -> n - 1 );
368+ if (sv -> spl_nleft == 0 || sv -> spl_nright == 0 )
369+ {
370+ ereport (DEBUG1 ,
371+ (errcode (ERRCODE_INTERNAL_ERROR ),
372+ errmsg ("Picksplit method for %d column of index \"%s\" failed" ,
373+ attno + 1 ,RelationGetRelationName (r )),
374+ errhint ("Index is not optimal, to optimize it contact developer or try to use the column as a second one in create index command" )));
316375
317- if (sv -> spl_ldatum_exists || sv -> spl_rdatum_exists )
376+ /*
377+ * Reinit GIST_SPLITVEC. Although that fields are not used
378+ * by genericPickSplit(), let us set up it for further processing
379+ */
380+ sv -> spl_ldatum_exists = (v -> spl_lisnull [attno ]) ? false : true;
381+ sv -> spl_rdatum_exists = (v -> spl_risnull [attno ]) ? false : true;
382+ sv -> spl_ldatum = v -> spl_lattr [attno ];
383+ sv -> spl_rdatum = v -> spl_rattr [attno ];
384+
385+ genericPickSplit (giststate ,entryvec ,sv ,attno );
386+
387+ if (sv -> spl_ldatum_exists || sv -> spl_rdatum_exists )
388+ supportSecondarySplit (r ,giststate ,attno ,sv ,v -> spl_lattr [attno ],v -> spl_rattr [attno ]);
389+ }
390+ else
318391{
319- elog (LOG ,"PickSplit method of %d columns of index '%s' doesn't support secondary split" ,
320- attno + 1 ,RelationGetRelationName (r ));
392+ /* compatibility with old code */
393+ if (sv -> spl_left [sv -> spl_nleft - 1 ]== InvalidOffsetNumber )
394+ sv -> spl_left [sv -> spl_nleft - 1 ]= (OffsetNumber ) (entryvec -> n - 1 );
395+ if (sv -> spl_right [sv -> spl_nright - 1 ]== InvalidOffsetNumber )
396+ sv -> spl_right [sv -> spl_nright - 1 ]= (OffsetNumber ) (entryvec -> n - 1 );
321397
322- supportSecondarySplit (r ,giststate ,attno ,sv ,v -> spl_lattr [attno ],v -> spl_rattr [attno ]);
398+ if (sv -> spl_ldatum_exists || sv -> spl_rdatum_exists )
399+ {
400+ elog (LOG ,"PickSplit method of %d columns of index '%s' doesn't support secondary split" ,
401+ attno + 1 ,RelationGetRelationName (r ));
402+
403+ supportSecondarySplit (r ,giststate ,attno ,sv ,v -> spl_lattr [attno ],v -> spl_rattr [attno ]);
404+ }
323405}
324406
325407v -> spl_lattr [attno ]= sv -> spl_ldatum ;