DataStore Library: 4 Building an Index

Up: GEOS SDK TechDocs| Up | Prev: 3 Deleting a DataStore | Next: 5 String Search
DataStoreBuildIndex()

You can create a secondary index ( i.e. , an index based on a non-key field) by calling DataStoreBuildIndex() . This routine builds an index based on a single field or on sort criteria specified in a callback function.

DataStoreBuildIndex() creates an array of RecordNum s (low word only) and stores the array in an LMem (local memory) block. The block contains an IndexArrayBlockHeader which holds data about the index (the number of records in the index, the offset to the beginning of the array, etc.). Following the block header is space for writing your own data, which is followed by the index itself. There is no limit to how much data you can write but the amount of data you write naturally decreases the amount of space available for the index. If the LMem block is too big to be allocated, the routine will return DSSE_MEMORY_FULL.

The following example shows how to build an index on a field and write data to the index's block header.

Code Display 9-4 Building a Secondary Index

	/* index parameters */
	DataStoreIndexCallbackParams	params;
	/* Building an index returns the handle of the allocated block */
	MemHandle	indexHandle;
	/* sample data to be added to the index block */
	TCHAR	indexData[]  = "Index created 7/1/96.";
	/*  Set up index parameters. */
	params.DSICP_indexField = 2; /* field on which to build index */
	params.DSICP_sortOrder = SO_DESCENDING; /* sort direction */
	params.DSICP_cbData = NULL; /* data to be passed to the callback
					function if a callback is being used */ 
	/*
	 * Open the datastore. (In this example, assume that dsToken
	 * has been declared as a global variable.)
	 */
	if(DataStoreOpen("Exchange Rates", oself, 0, &dsToken) == DSE_NO_ERROR)
	{
		/* Build the index. */
		if(DataStoreBuildIndex(dsToken, &indexHandle,
				sizeof(IndexArrayBlockHeader)+
				LocalStringSize(indexData)+sizeof(TCHAR),
				&params, NULL) == DSSE_NO_ERROR)
		{
			/* get a pointer to the block header */
			IndexArrayBlockHeader *pIndex;
			/* lock the block down */
			MemLock(indexHandle);
			/*
			 * dereference the handle to get a pointer
			 * to the block header
			 */
			pIndex = MemDeref(indexHandle);
			/* increment the pointer past the block header */
			pIndex++;
			/* now copy the sample data into the block */
			strcpy((TCHAR *) pIndex,  indexData);
			/* Now that we're through with the block,unlock it. */
			MemUnlock(indexHandle);
		}
		/* Close the datastore. */
		DataStoreClose(dsToken);
	}

You can also build an index based on a custom callback routine. The calling routine passes the DataStoreCallbackParams to the callback; the callback decides which of the two records ( DSICP_rec1 or DSICP_rec2 ) should go first. (If you use a callback, DataStoreBuildIndex() will ignore DSICP _indexField and DSICP _sortOrder .)

The callback should return:
-1 if DSICP_rec1 comes before DSICP_rec2
1 if DSICP_rec1 comes after DSICP_rec2

Code Display 9-5 Declaration of Callback Function in DataStoreBuildIndex()

sword SortCallback(word dsToken, DataStoreIndexCallbackParams *params);

DataStoreBuildIndex() works on datastores of 4,000 records or less. If you call this routine on a datastore larger than 4,000 records, the routine will return DSSE_INDEX_RECORD_NUMBER_LIMIT_EXCEEDED.

The application owns this index and is responsible for freeing the block. The DataStore Manager does not maintain the index in any way. Applications can synchronize a secondary index by rebuilding it whenever the application receives notification of a change that would affect the index.


Up: GEOS SDK TechDocs| Up | Prev: 3 Deleting a DataStore | Next: 5 String Search