Menu
Simba Technologies
Simba Technologies

SimbaEngine X SDK 10.1.3
Developing Drivers for Data Stores Without SQL

SimbaEngine X SDK Documentation > SQL Engine Features > Sample Index Implementation

Sample Index Implementation

This section provides an example of how you can implement your indexes.

//====================================================================

/// @file DBIndexMetadata.h

///

/// Definition of the Class DBIndexMetadata

///

/// Copyright (C) 2013-2014 Simba Technologies Incorporated.

//====================================================================

#ifndef _SIMBA_SQLENGINE_DBINDEXMETADATA_H_

#define _SIMBA_SQLENGINE_DBINDEXMETADATA_H_

#include "IUseableIndexMetadata.h"

#include "DB.h"

#include "AutoPtr.h"

#include <vector>

namespace Simba

{

namespace DBDSII

{

/// @brief Represents the metadata for a single index.

class DBIndexMetadata : public Simba::SQLEngine::IUseableIndexMetadata

{

//Public=========================================================

public:

/// @brief Factory method.

///

/// @param in_name The name of the index.

/// @param in_indexID The ID of the index.

/// @param in_tableColumns The columns in the table this is an index for.

/// @param in_indexColumns The columns this is an index on. These indices index

/// in_tableColumns.

static AutoPtr<DBIndexMetadata> CreatePrimaryKeyInstance(

const simba_wstring& in_name,

db_id_t in_indexID,

Simba::DSI::IColumns& in_tableColumns,

const std::vector<simba_uint16>& in_indexColumns);

/// @brief Factory method.

///

/// @param in_name The name of the index.

/// @param in_indexID The ID of the index.

/// @param in_tableColumns The columns in the table this is an index for.

/// @param in_indexColumns The columns this is an index on. These indices index

/// in_tableColumns.

/// @param in_primaryKeyColumns The columns this primary key is on. These indices index

/// in_tableColumns.

/// @param in_usUnique Whether this is a unique index.

static AutoPtr<DBIndexMetadata> CreateIndexInstance(

const simba_wstring& in_name,

db_id_t in_indexID,

Simba::DSI::IColumns& in_tableColumns,

const std::vector<simba_uint16>& in_indexColumns,

const std::vector<simba_uint16>& in_primaryKeyColumns,

bool in_isUnique);

/// @brief Return whether the associated index supports indexing on IS NULL for

/// the given column.

///

/// @param in_column The column of interest.

///

/// @return True if the associated index supports indexing IS NULL on the given column,

/// False otherwise.

virtual bool CanIndexOnNull(simba_uint16 in_column) const;

/// @brief Return whether the associated DSIExtIndex object can produce table bookmarks.

///

/// Whether GetTableBookmark() can be called on the associated DSIExtIndex to

/// produce a bookmark

/// for the row in the table referred to by the current row in the DSIExtIndex.

///

/// If false, this index can only be used for 'index only scans'.

///

/// @return Whether the associated DSIExtIndex object can produce table bookmarks.

virtual bool CanProduceTableBookmarks() const;

/// @brief Get the name of the index.

///

/// @return The name of the index.

virtual const simba_wstring& GetName() const;

/// @brief Get the indexed columns.

///

/// @return The columns involved in the index.

virtual const Simba::SQLEngine::IndexColumns& GetIndexColumns() const;

/// @brief Get the indices (into the parent table) of columns

/// whose data is retrievable via the associated index.

///

/// These are the columns whose data may be retrieved using

/// RetrieveData() on the associated DSIExtIndex object.

///

/// @return The indices of columns whose data is retrievable via the associated index.

virtual const std::set<simba_uint16>& GetIncludedColumns() const;

/// @brief Get a map from column indices in the parent relation

/// to column indices in this index.

///

/// Specifically, this is a map from column indices from columns retrievable

/// from the parent relation (for example, in the case of a table, the

/// columns returned from DSIExtResultSet::GetSelectColumns() ) to

/// columns retrievable in the associated DSIExtIndex object (in other words,

/// from this->GetIncludedColumns() ).

///

/// @return A map from column indices in the parent relation

/// to column indices in this index.

virtual const Simba::SQLEngine::ColumnIndexMap& GetTableColumnToIndexColumnMap() const;

/// @brief Get the type of the index.

///

/// @return The type of the index.

virtual Simba::SQLEngine::DSIExtIndexType GetType() const;

/// @brief Get if the indicated condition type is supported

/// for the given column of the index.

///

/// @param in_type The condition type of interest.

/// @param in_column The column of interest.

///

/// @return True if the condition type is supported for the given column;

/// false otherwise.

virtual bool IsConditionTypeSupported(

Simba::SQLEngine::DSIExtColumnConditionType in_type,

simba_uint16 in_column) const;

/// @brief Get if the index is the primary key.

///

/// Note that only one index should be the primary key for any table.

///

/// @return True if the index is the primary key; false otherwise.

virtual bool IsPrimaryKey() const;

/// @brief Get if the index traverses its rows in the order defined by the bookmark

/// comparator.

///

/// For example, this will be true if the bookmark comparator for the parent table is

/// based on the row's location on disk, and this index is clustered.

///

/// If this returns true, the SQLEngine will not attempt to sort the stream of

/// bookmarks produced by this index with the table's bookmark comparator. This

/// will cause incorrect results if the index does not actually follow that order.

///

/// @return True the index traverses its rows in the order defined by the bookmark

/// comparator, False otherwise.

virtual bool IsInBookmarkComparatorOrder() const;

/// @brief Get if the index is a sorted index.

///

/// @return True if the index is a sorted index; false otherwise.

virtual bool IsSorted() const;

/// @brief Get if the index is a unique index.

///

/// @return True if the index is a unique index; false otherwise.

virtual bool IsUnique() const;

/// @brief Get the ID for this index.

///

/// @return The ID for this index.

db_id_t GetIndexID() const;

 

// Private ==================================================================================

private:

/// @brief Private constructor so that consumers must use factory method.

///

/// @param in_name The name of the index.

/// @param in_columns The columns involved in the index, in the order

/// they appear

/// in the index. Takes ownership of the objects held.

/// (in_columns will be empty after the constructor returns)

/// @param in_includedColumns Metadata for all columns included in this index,

/// including ones which cannot be SEEKed on.

/// @param in_columnIndexMap A map from table column indices to column indices

/// in this index.

/// @param in_isInBookmarkComparatorOrder Indicate if the index order respect the one

/// of the bokmark comparator.

/// @param in_isUnique Indicate if the index is unique.

/// @param in_indexID The DB internal index identifier.

DBIndexMetadata(

const simba_wstring& in_name,

Simba::SQLEngine::IndexColumns& in_columns,

const std::set<simba_uint16>& in_includedColumns,

const Simba::SQLEngine::ColumnIndexMap& in_columnIndexMap,

bool in_isInBookmarkComparatorOrder,

bool in_isUnique,

db_id_t in_indexID);

simba_wstring m_name;

Simba::SQLEngine::IndexColumns m_indexColumns;

std::set<simba_uint16> m_includedColumns;

Simba::SQLEngine::ColumnIndexMap m_columnIndexMap;

bool m_isUnique;

bool m_isInBookmarkComparatorOrder;

// The ID for this index.

db_id_t m_indexID;

};

}

}

#endif

 

// =================================================================================================

/// @file DBIndexMetadata.cpp

///

/// Implementation of the Class DBIndexMetadata

///

/// Copyright (C) 2013 Simba Technologies Incorporated.

// =================================================================================================

#include "DBIndexMetadata.h"

#include "DSIColumnMetadata.h"

#include "DSIExtIndexColumn.h"

#include "DSIResultSetColumn.h"

#include "DSIResultSetColumns.h"

#include "SqlTypeMetadata.h"

#include <algorithm>

using namespace Simba::DBDBDSII;

using namespace Simba::DSI;

using namespace Simba::SQLEngine;

using namespace std;

// Public=======================================================================================

AutoPtr<DBIndexMetadata> DBIndexMetadata::CreatePrimaryKeyInstance(

const simba_wstring& in_name,

db_id_t in_indexID,

Simba::DSI::IColumns& in_tableColumns,

const std::vector<simba_uint16>& in_indexColumns)

{

IndexColumns indexColumns;

indexColumns.reserve(in_indexColumns.size());

// Create the list of the columns that are part of the primary index.

vector<simba_uint16>::const_iterator it = in_indexColumns.begin();

const vector<simba_uint16>::const_iterator end = in_indexColumns.end();

for (; it != end; ++it)

{

indexColumns.push_back(

new DSIExtIndexColumn(in_tableColumns.GetColumn(*it), DSIEXT_SORT_ASCENDING));

}

// Create a map between the columns of the table and the corresponding

// column in the index. We do this for all columns in the index (key of

// the map=column index in table, value=column index in tuple).

ColumnIndexMap columnIndexMap;

set<simba_uint16> includedColumns;

for (simba_uint16 i = 0; i < in_indexColumns.size(); ++i)

{

columnIndexMap[in_indexColumns[i]] = i;

includedColumns.insert(in_indexColumns[i]);

}

// A primary index is clustered and unique.

AutoPtr<DBIndexMetadata> result(new DBIndexMetadata(

in_name,

indexColumns,

includedColumns,

columnIndexMap,

true,

true,

in_indexID));

return result;

}

/////////////////////////////////////////////////////////////////////////////////////////////////

AutoPtr<DBIndexMetadata> DBIndexMetadata::CreateIndexInstance(

const simba_wstring& in_name,

db_id_t in_indexID,

IColumns& in_tableColumns,

const vector<simba_uint16>& in_indexColumns,

const std::vector<simba_uint16>& in_primaryKeyColumns,

bool in_isUnique)

{

IndexColumns indexColumns;

indexColumns.reserve(in_indexColumns.size());

// Create the list of the columns that are directly part of the index.

// NOTE: A DBDB tuple on a secondary index includes the columns of the

// primary index, but these columns are not included here except for

// the ones that are in both indexes.

vector<simba_uint16>::const_iterator it = in_indexColumns.begin();

const vector<simba_uint16>::const_iterator end = in_indexColumns.end();

for (; it != end; ++it)

{

indexColumns.push_back(

new DSIExtIndexColumn(in_tableColumns.GetColumn(*it), DSIEXT_SORT_ASCENDING));

}

// Create a map between the columns of the table and the corresponding

// column in the index. We do this for all columns in the index (key of

// the map=column index in table, value=column index in tuple).

ColumnIndexMap columnIndexMap;

set<simba_uint16> includedColumns;

for (simba_uint16 i = 0; i < in_indexColumns.size(); ++i)

{

columnIndexMap[in_indexColumns[i]] = i;

includedColumns.insert(in_indexColumns[i]);

}

// As an DBDB tuple on a secondary index contains also the columns of the

// primary index, we add the mapping between the column of the table and the

// corresponding column in the primary index. In case the primary and secondary

// index have one or more columns in common, the DBDB tuple won't duplicate

// them.

// The tuple columns are then built as follows: put the columns of the

// secondary index in the order they were created in the secondary index

// followed by the columns of the primary index that have not yet been included

// in the order they were created in the primary index.

simba_uint16 numberPKIncluded = 0;

for (simba_uint16 i = 0; i < in_primaryKeyColumns.size(); ++i)

{

if (columnIndexMap.end() == columnIndexMap.find(in_primaryKeyColumns[i]))

{

columnIndexMap[in_primaryKeyColumns[i]] = in_indexColumns.size() +

(numberPKIncluded++);

includedColumns.insert(in_primaryKeyColumns[i]);

}

}

// A secondary index is not clustered.

AutoPtr<DBIndexMetadata> result(new DBIndexMetadata(

in_name,

indexColumns,

includedColumns,

columnIndexMap,

false,

in_isUnique,

in_indexID));

return result;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

bool DBIndexMetadata::CanIndexOnNull(simba_uint16 in_column) const

{

UNUSED(in_column);

return false;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

bool DBIndexMetadata::CanProduceTableBookmarks() const

{

return true;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

const simba_wstring& DBIndexMetadata::GetName() const

{

return m_name;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

const IndexColumns& DBIndexMetadata::GetIndexColumns() const

{

return m_indexColumns;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

const std::set<simba_uint16>& DBIndexMetadata::GetIncludedColumns() const

{

return m_includedColumns;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

const ColumnIndexMap& DBIndexMetadata::GetTableColumnToIndexColumnMap() const

{

return m_columnIndexMap;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

DSIExtIndexType DBIndexMetadata::GetType() const

{

return m_isInBookmarkComparatorOrder ? INDEX_CLUSTERED : INDEX_BTREE;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

bool DBIndexMetadata::IsConditionTypeSupported(

DSIExtColumnConditionType in_type,

simba_uint16 in_column) const

{

UNUSED(in_column);

return (COLUMN_CONDITION_IS_NOT_NULL == in_type) || (COLUMN_CONDITION_IS_IN_RANGE == in_type);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

bool DBIndexMetadata::IsPrimaryKey() const

{

return m_isInBookmarkComparatorOrder;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

bool DBIndexMetadata::IsInBookmarkComparatorOrder() const

{

return m_isInBookmarkComparatorOrder;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

bool DBIndexMetadata::IsSorted() const

{

return true;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

bool DBIndexMetadata::IsUnique() const

{

return m_isUnique;

}

////////////////////////////////////////////////////////////////////////////////////////////////////

ib_id_t DBIndexMetadata::GetIndexID() const

{

return m_indexID;

}

// Private =========================================================================================

////////////////////////////////////////////////////////////////////////////////////////////////////

DBIndexMetadata::DBIndexMetadata(

const simba_wstring& in_name,

Simba::SQLEngine::IndexColumns& in_columns,

const std::set<simba_uint16>& in_includedColumns,

const Simba::SQLEngine::ColumnIndexMap& in_columnIndexMap,

bool in_isInBookmarkComparatorOrder,

bool in_isUnique,

ib_id_t in_indexID) :

m_name(in_name),

m_includedColumns(in_includedColumns),

m_columnIndexMap(in_columnIndexMap),

m_isInBookmarkComparatorOrder(in_isInBookmarkComparatorOrder),

m_isUnique(in_isUnique),

m_indexID(in_indexID)

{

m_indexColumns.swap(in_columns);

}

 

Related Links

Support for Indexes