*** pgsql/src/backend/access/gist/gistproc.c 2010/01/02 16:57:34 1.19 --- pgsql/src/backend/access/gist/gistproc.c 2010/01/14 16:31:09 1.20 *************** *** 10,16 **** * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/access/gist/gistproc.c,v 1.18 2009/09/18 14:01:56 teodor Exp $ * *------------------------------------------------------------------------- */ --- 10,16 ---- * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/access/gist/gistproc.c,v 1.19 2010/01/02 16:57:34 momjian Exp $ * *------------------------------------------------------------------------- */ *************** gist_box_compress(PG_FUNCTION_ARGS) *** 165,171 **** } /* ! * GiST DeCompress method for boxes (also used for polygons and circles) * * do not do anything --- we just use the stored box as is. */ --- 165,172 ---- } /* ! * GiST DeCompress method for boxes (also used for points, polygons ! * and circles) * * do not do anything --- we just use the stored box as is. */ *************** gist_box_decompress(PG_FUNCTION_ARGS) *** 176,182 **** } /* ! * The GiST Penalty method for boxes * * As in the R-tree paper, we use change in area as our penalty metric */ --- 177,183 ---- } /* ! * The GiST Penalty method for boxes (also used for points) * * As in the R-tree paper, we use change in area as our penalty metric */ *************** fallbackSplit(GistEntryVector *entryvec, *** 341,346 **** --- 342,349 ---- * * New linear algorithm, see 'New Linear Node Splitting Algorithm for R-tree', * C.H.Ang and T.C.Tan + * + * This is used for both boxes and points. */ Datum gist_box_picksplit(PG_FUNCTION_ARGS) *************** gist_box_picksplit(PG_FUNCTION_ARGS) *** 533,538 **** --- 536,543 ---- /* * Equality method + * + * This is used for both boxes and points. */ Datum gist_box_same(PG_FUNCTION_ARGS) *************** gist_circle_consistent(PG_FUNCTION_ARGS) *** 872,874 **** --- 877,1042 ---- PG_RETURN_BOOL(result); } + + /************************************************** + * Point ops + **************************************************/ + + Datum + gist_point_compress(PG_FUNCTION_ARGS) + { + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + + if (entry->leafkey) /* Point, actually */ + { + BOX *box = palloc(sizeof(BOX)); + Point *point = DatumGetPointP(entry->key); + GISTENTRY *retval = palloc(sizeof(GISTENTRY)); + + box->high = box->low = *point; + + gistentryinit(*retval, BoxPGetDatum(box), + entry->rel, entry->page, entry->offset, FALSE); + + PG_RETURN_POINTER(retval); + } + + PG_RETURN_POINTER(entry); + } + + static bool + gist_point_consistent_internal(StrategyNumber strategy, + bool isLeaf, BOX *key, Point *query) + { + bool result = false; + + switch (strategy) + { + case RTLeftStrategyNumber: + result = FPlt(key->low.x, query->x); + break; + case RTRightStrategyNumber: + result = FPgt(key->high.x, query->x); + break; + case RTAboveStrategyNumber: + result = FPgt(key->high.y, query->y); + break; + case RTBelowStrategyNumber: + result = FPlt(key->low.y, query->y); + break; + case RTSameStrategyNumber: + if (isLeaf) + { + result = FPeq(key->low.x, query->x) + && FPeq(key->low.y, query->y); + } + else + { + result = (query->x <= key->high.x && query->x >= key->low.x && + query->y <= key->high.y && query->y >= key->low.y); + } + break; + default: + elog(ERROR, "unknown strategy number: %d", strategy); + } + + return result; + } + + #define GeoStrategyNumberOffset 20 + #define PointStrategyNumberGroup 0 + #define BoxStrategyNumberGroup 1 + #define PolygonStrategyNumberGroup 2 + #define CircleStrategyNumberGroup 3 + + Datum + gist_point_consistent(PG_FUNCTION_ARGS) + { + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); + bool result; + bool *recheck = (bool *) PG_GETARG_POINTER(4); + StrategyNumber strategyGroup = strategy / GeoStrategyNumberOffset; + + switch (strategyGroup) + { + case PointStrategyNumberGroup: + result = gist_point_consistent_internal(strategy % GeoStrategyNumberOffset, + GIST_LEAF(entry), + DatumGetBoxP(entry->key), + PG_GETARG_POINT_P(1)); + *recheck = false; + break; + case BoxStrategyNumberGroup: + result = DatumGetBool(DirectFunctionCall5( + gist_box_consistent, + PointerGetDatum(entry), + PG_GETARG_DATUM(1), + Int16GetDatum(RTOverlapStrategyNumber), + 0, PointerGetDatum(recheck))); + break; + case PolygonStrategyNumberGroup: + { + POLYGON *query = PG_GETARG_POLYGON_P(1); + + result = DatumGetBool(DirectFunctionCall5( + gist_poly_consistent, + PointerGetDatum(entry), + PolygonPGetDatum(query), + Int16GetDatum(RTOverlapStrategyNumber), + 0, PointerGetDatum(recheck))); + + if (GIST_LEAF(entry) && result) + { + /* + * We are on leaf page and quick check shows overlapping + * of polygon's bounding box and point + */ + BOX *box = DatumGetBoxP(entry->key); + + Assert(box->high.x == box->low.x + && box->high.y == box->low.y); + result = DatumGetBool(DirectFunctionCall2( + poly_contain_pt, + PolygonPGetDatum(query), + PointPGetDatum(&box->high))); + *recheck = false; + } + } + break; + case CircleStrategyNumberGroup: + { + CIRCLE *query = PG_GETARG_CIRCLE_P(1); + + result = DatumGetBool(DirectFunctionCall5( + gist_circle_consistent, + PointerGetDatum(entry), + CirclePGetDatum(query), + Int16GetDatum(RTOverlapStrategyNumber), + 0, PointerGetDatum(recheck))); + + if (GIST_LEAF(entry) && result) + { + /* + * We are on leaf page and quick check shows overlapping + * of polygon's bounding box and point + */ + BOX *box = DatumGetBoxP(entry->key); + + Assert(box->high.x == box->low.x + && box->high.y == box->low.y); + result = DatumGetBool(DirectFunctionCall2( + circle_contain_pt, + CirclePGetDatum(query), + PointPGetDatum(&box->high))); + *recheck = false; + } + } + break; + default: + result = false; /* silence compiler warning */ + elog(ERROR, "unknown strategy number: %d", strategy); + } + + PG_RETURN_BOOL(result); + }