Home | Previous Page | Next Page   Developing DataBlade Modules That Use the R-Tree Secondary Access Method > Setting Up Nearest-Neighbor Searching >

Setting Up a Strategy Function for Nearest-Neighbor Searching

For each nearest-neighbor strategy function, there must exist a separate distance-measuring function of the same name but with a different signature. The R-tree access method calls only the distance-measuring function associated with the strategy function; the strategy function itself should not be called directly. The appearance of the strategy function in a query allows the query planner to set up a scan using the related R-tree index. You must raise an error if a user calls the strategy function directly, with a message such as, "An attempt was made to use the nearest-neighbor function name as a filter during a non-index table scan. Nearest-neighbor queries require an index scan."

You must also set up the RtreeInfo support function (described in Support Functions) to indicate that the strategy function is for nearest-neighbor searches, as Setting RtreeInfo to Indicate Nearest-Neighbor Functions shows.

The Distance-Measuring Function

The distance measuring function is not itself a part of the operator class.

The first and second arguments of the distance function must be the same as the first and second arguments of the strategy function. The third argument must be INTEGER and the return value DOUBLE PRECISION. For example, for the strategy function Nearest, created by the following SQL statement:

CREATE FUNCTION Nearest(UDT, UDT) 
  RETURNS BOOLEAN 
  WITH (NOT VARIANT);

The associated distance function, Nearest, looks like this:

CREATE FUNCTION Nearest(UDT, UDT, INTEGER) 
  RETURNS DOUBLE PRECISION 
  WITH (NOT VARIANT);

where UDT is a user-defined data type, such as the point data type, ST_Point, from the IBM Informix Spatial DataBlade module.

In C, the distance function declaration looks like this:

mi_double_precision *Nearest(UDT *x1, 
                             UDT *x2, 
                             mi_integer flags, 
                             MI_FPARAM *fp);

The first two arguments are the objects or locations between which the function calculates the distance (or the bounding-boxes of the objects, as Distance Function: Using Bounding Boxes describes).

The third argument is not used in this version of the R-tree access method.

The DOUBLE PRECISION return value is not interpreted by the R-tree access method.

Distance Function: Using Bounding Boxes

Optionally, you can provide a distance function (paired with a strategy function) that calculates distances between bounding boxes rather than exact distances between objects. The distances calculated this way are imprecise, but the function runs more quickly. For example, the IBM Informix Spatial DataBlade module provides the SE_Nearest and SE_NearestBBox functions so that the users can choose whether to run searches using precise or estimated distances.

In this case, set the RtreeInfo support function to match the strategy function with the operation key bbox_only_distance as the following section, Setting RtreeInfo to Indicate Nearest-Neighbor Functions shows.

Setting RtreeInfo to Indicate Nearest-Neighbor Functions

This C code fragment shows how to set the RtreeInfo support function to indicate that a strategy function is a nearest-neighbor function, and that a nearest-neighbor function exists that makes approximate distance calculations. To do this, use the operation keys (operation_ptr arguments), nearest_neighbor_functions, and bbox_only_distance, respectively. You can combine this fragment with the example shown in C Code Example for the RtreeInfo Support Function.

For each operation (nearest_neighbor_functions and bbox_only_distance), if the answer_ptr argument is NULL, the function should return either MI_OK or RLT_OP_UNSUPPORTED, depending whether that operation is supported.

If the answer_ptr argument is not NULL, it is a pointer to a pointer to an MI_LVARCHAR containing an array of 64 MI_BOOLEANS, one for each strategy function slot (allocated by the caller). For the nearest_neighbor_functions operation, the RtreeInfo function should fill in either MI_TRUE or MI_FALSE for each entry corresponding to a nearest-neighbor strategy function. For the bbox_only_distance operation, the RtreeInfo function should fill in MI_TRUE to indicate that the distance function uses bounding-box measurements only or MI_FALSE to indicate that exact calculation distance calculations are required. If the bbox_only_distance operation is not supported, the R-tree access method assumes that exact distance calculations are required.

...
else if (matches(operation, "nearest_neighbor_functions"))
  {
  /*
  ** Indicate which strategy functions are nearest-neighbor
  ** functions. In this case, the 6th strategy function.
  */
  mi_boolean *answer = NULL;

  if (answer_ptr == NULL)
      goto done; /* Operation is supported */

  /* Memory for 64 booleans is allocated by R-tree */
  answer = (mi_boolean*) mi_get_vardata((mi_lvarchar*)
           mi_get_vardata(answer_ptr));

  answer[0] = MI_FALSE; /* intersect */
  answer[1] = MI_FALSE; /* equal     */
  answer[2] = MI_FALSE; /* contains  */
  answer[3] = MI_FALSE; /* inside    */
  answer[4] = MI_FALSE; /* outside   */
  answer[5] = MI_TRUE;  /* nearest   */

  }

else if (matches(operation, "bbox_only_distance"))
  {
  /*
  ** Indicate which nearest-neighbor distance functions
  ** do their calculation using only bounding box information,
  ** giving an approximate distance. In this case, the 7th 
  ** strategy function.
  */
  mi_boolean *answer = NULL;

  if (answer_ptr == NULL)
      goto done; /* Operation is supported */

  /* Memory for 64 booleans is allocated by R-tree */
  answer = (mi_boolean*) mi_get_vardata((mi_lvarchar*)
  (mi_get_vardata(answer_ptr));

  if (answer == NULL)
      {
       status = MI_ERROR;
       goto bad;
      }

  answer[0] = MI_FALSE; /* intersect   */
  answer[1] = MI_FALSE; /* equal       */
  answer[2] = MI_FALSE; /* contains    */
  answer[3] = MI_FALSE; /* inside      */
  answer[4] = MI_FALSE; /* outside     */
  answer[5] = MI_FALSE; /* nearest     */
  answer[6] = MI_TRUE;  /* nearest_bbox*/


  }
Home | [ Top of Page | Previous Page | Next Page | Contents | Index ]