8
8
* Portions Copyright (c) 1994, Regents of the University of California
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -280,6 +280,63 @@ supportSecondarySplit(Relation r, GISTSTATE *giststate, int attno, GIST_SPLITVEC
280
280
sv -> spl_ldatum_exists = sv -> spl_rdatum_exists = false;
281
281
}
282
282
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
+
283
340
/*
284
341
* Calls user picksplit method for attno columns to split vector to
285
342
* two vectors. May use attno+n columns data to
@@ -296,7 +353,7 @@ gistUserPicksplit(Relation r, GistEntryVector *entryvec, int attno, GistSplitVec
296
353
297
354
/*
298
355
* now let the user-defined picksplit function set up the split vector; in
299
- * entryvec have no null value!!
356
+ * entryvec there is no null value!!
300
357
*/
301
358
302
359
sv -> spl_ldatum_exists = (v -> spl_lisnull [attno ]) ? false : true;
@@ -308,18 +365,43 @@ gistUserPicksplit(Relation r, GistEntryVector *entryvec, int attno, GistSplitVec
308
365
PointerGetDatum (entryvec ),
309
366
PointerGetDatum (sv ));
310
367
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" )));
316
375
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
318
391
{
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 );
321
397
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
+ }
323
405
}
324
406
325
407
v -> spl_lattr [attno ] = sv -> spl_ldatum ;
0 commit comments