Logo Search packages:      
Sourcecode: webissues version File versions  Download package

tabletemplates.h

/**************************************************************************
* Generic, native, relational database
* Copyright (C) 2006 Michał Męciński
* Copyright (C) 2007 WebIssues Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
**************************************************************************/

#ifndef TABLETEMPLATES_H
#define TABLETEMPLATES_H

#include "tablecore.h"
#include "tableindexes.h"

/**
* Generic, native, relational database.
*
* RDB is a set of class templates implementing a simple and very fast relational database.
*
* A table row is an object which inherits the RowBase class template. Each row has a number
* of integer keys and any additional properties and methods.
*
* A table may inherit one of the SimpleTable, ChildTable or CrossTable class template,
* depending on the number and type of indexes. The SimpleTable has one index using a single
* primary key. The ChildTable has one index for the primary key and one for the foreign key.
* The CrossTable has two indexes for foreign keys and its primary key consist of a pair of
* both foreign keys.
*
* Each kind of table implements methods for inserting, removing and finding rows using their
* primary key (or pair of keys).
*
* Classes inheriting the table class templates may define any number of additional indexes.
* The UniqueIndex can be used to find a single row matching the given value of the key and the
* ForeignIndex can be used to iterate over all rows matching the given value of the key.
* Indexes are implemented as hash tables of fixed size with linked lists of buckets.
*
* The IndexIterator and IndexConstIterator can be used to iterate over all rows of a table
* using any of its indexes. The TableIterator and TableConstIterator are convenience iterators
* which automatically use the main index of the given table.
*
* The ForeignIterator and ForeignConstIterator can be used to efficiently find all rows with
* a given value of the foreign key using the ForeignIndex of a table.
*
* All tables and indexes are type-safe and const-safe.
*
* Tables take ownership of the inserted rows and delete them when they are removed.
*
* For efficiency reasons the RDB tables provide no constraint checking. For example
* it is possible to insert two rows with the same primary key into the SimpleTable. In that
* case the result of the find() and remove() methods becomes undefined.
*/
namespace RDB
{

/**
* Table with one index using a single primary key.
*
* It can be used to store rows which have no foreign keys.
*
* The @p ROW class must inherit the RowBase class template.
*/
template<class ROW>
00066 class SimpleTable
{
public:
    /**
    * Constructor.
    *
    * @param size The size of the hash table of the index.
    */
00074     SimpleTable( int size ) :
        m_core( m_data, ROW::Dimensions ),
        m_index( &m_data[ 0 ] )
    {
        m_data[ 0 ].initialize( 0, size );
    }

    /**
    * Destructor.
    */
00084     ~SimpleTable() { m_core.clear(); }

public:
    /**
    * Return the primary index of the table.
    */
00090     UniqueIndex<ROW>* index() { return &m_index; }

    /**
    * @overload
    */
00095     const UniqueIndex<ROW>* index() const { return &m_index; }

    /**
    * Find the row with the given primary key.
    *
    * @param key Value of the primary key.
    *
    * @return The matching row or \c NULL if it doesn't exist.
    */
00104     ROW* find( int key ) { return (ROW*)m_core.find( 0, key ); }

    /**
    * @overload
    */
00109     const ROW* find( int key ) const { return (const ROW*)m_core.find( 0, key ); }

    /**
    * Insert a row to the table.
    *
    * @param row The row to insert.
    *
    * @note The table doesn't prevent from inserting two rows with the same primary key.
    */
00118     void insert( ROW* row ) { m_core.insert( row ); }

    /**
    * Remove the row from the table.
    *
    * @param key Value of the primary key of the row to remove.
    */
00125     void remove( int key ) { m_core.remove( 0, key ); }

    /**
    * Remove all rows from the table.
    */
00130     void clear() { m_core.clear(); }

protected:
    TableData m_data[ ROW::Dimensions ];

    TableCore m_core;
    UniqueIndex<ROW> m_index;
};

/**
* Table with a primary key index and a foreign key index.
*
* It can be used to store rows with unique primary keys which also have a single foreign key
* related with a parent table.
*
* The @p ROW class must inherit the RowBase class template and must have at least two dimensions.
*/
template<class ROW>
00148 class ChildTable
{
public:
    /**
    * Constructor.
    *
    * @param size The size of the hash table of the primary index.
    *
    * @param parentSize The size of the hash table of the foreign index.
    */
00158     ChildTable( int size, int parentSize ) :
        m_core( m_data, ROW::Dimensions ),
        m_index( &m_data[ 0 ] ),
        m_parentIndex( &m_data[ 1 ] )
    {
        m_data[ 0 ].initialize( 0, size );
        m_data[ 1 ].initialize( 1, parentSize );
    }

    /**
    * Destructor.
    */
00170     ~ChildTable() { m_core.clear(); }

public:
    /**
    * Return the primary index of the table.
    */
00176     UniqueIndex<ROW>* index() { return &m_index; }

    /**
    * @overload
    */
00181     const UniqueIndex<ROW>* index() const { return &m_index; }

    /**
    * Return the foreign index of the table.
    */
00186     ForeignIndex<ROW>* parentIndex() { return &m_parentIndex; }

    /**
    * @overload
    */
00191     const ForeignIndex<ROW>* parentIndex() const { return &m_parentIndex; }

    /**
    * Find the row with the given primary key.
    *
    * @param key Value of the primary key.
    *
    * @return The matching row or \c NULL if it doesn't exist.
    */
00200     ROW* find( int key ) { return (ROW*)m_core.find( 0, key ); }

    /**
    * @overload
    */
00205     const ROW* find( int key ) const { return (const ROW*)m_core.find( 0, key ); }

    /**
    * Insert a row to the table.
    *
    * @param row The row to insert.
    *
    * @note The table doesn't prevent from inserting two rows with the same primary key.
    */
00214     void insert( ROW* row ) { m_core.insert( row ); }

    /**
    * Remove the row from the table.
    *
    * @param key Value of the primary key of the row to remove.
    */
00221     void remove( int key ) { m_core.remove( 0, key ); }

    /**
    * Remove all rows matching the given foreign key.
    *
    * @param parentKey Value of the foreign key of the rows to remove.
    */
00228     void removeChildren( int parentKey ) { m_core.removeAll( 1, parentKey ); }

    /**
    * Remove all rows from the table.
    */
00233     void clear() { m_core.clear(); }

protected:
    TableData m_data[ ROW::Dimensions ];

    TableCore m_core;
    UniqueIndex<ROW> m_index;
    ForeignIndex<ROW> m_parentIndex;
};

/**
* Table with two foreign indexes whose primary key is the pair of foreign keys.
*
* It can be used to store 'N to N' relations between two tables.
*
* The @p ROW class must inherit the RowBase class template and must have at least two dimensions.
*/
template<class ROW>
00251 class CrossTable
{
public:
    /**
    * Constructor.
    *
    * @param size The size of the hash table of the first index.
    *
    * @param otherSize The size of the hash table of the second index.
    */
00261     CrossTable( int size, int otherSize ) :
        m_core( m_data, ROW::Dimensions ),
        m_index( &m_data[ 0 ] ),
        m_otherIndex( &m_data[ 1 ] )
    {
        m_data[ 0 ].initialize( 0, size );
        m_data[ 1 ].initialize( 1, otherSize );
    }

    /**
    * Destructor.
    */
00273     ~CrossTable() { m_core.clear(); }

public:
    /**
    * Return the first foreign index of the table.
    */
00279     ForeignIndex<ROW>* index() { return &m_index; }

    /**
    * @overload
    */
00284     const ForeignIndex<ROW>* index() const { return &m_index; }

    /**
    * Return the second foreign index of the table.
    */
00289     ForeignIndex<ROW>* otherIndex() { return &m_otherIndex; }

    /**
    * @overload
    */
00294     const ForeignIndex<ROW>* otherIndex() const { return &m_otherIndex; }

    /**
    * Find the row with the given primary key.
    *
    * @param key Value of the first key of the primary key pair.
    *
    * @param otherKey Value of the second key of the primary key pair.
    *
    * @return The matching row or \c NULL if it doesn't exist.
    */
00305     ROW* find( int key, int otherKey ) { return (ROW*)m_core.find( 0, key, 1, otherKey ); }

    /**
    * @overload
    */
00310     const ROW* find( int key, int otherKey ) const { return (const ROW*)m_core.find( 0, key, 1, otherKey ); }

    /**
    * Insert a row to the table.
    *
    * @param row The row to insert.
    *
    * @note The table doesn't prevent from inserting two rows with the same primary key.
    */
00319     void insert( ROW* row ) { m_core.insert( row ); }

    /**
    * Remove the row with the given primary key.
    *
    * @param key Value of the first key of the primary key pair.
    *
    * @param otherKey Value of the second key of the primary key pair.
    */
00328     void remove( int key, int otherKey ) { m_core.remove( 0, key, 1, otherKey ); }

    /**
    * Remove all rows with the given key.
    *
    * @param index The index of the key to use.
    *
    * @param key The value of the key to match.
    */
00337     void removeAll( int index, int key ) { m_core.removeAll( index, key ); }

    /**
    * Remove all rows from the table.
    */
00342     void clear() { m_core.clear(); }

protected:
    TableData m_data[ ROW::Dimensions ];

    TableCore m_core;
    ForeignIndex<ROW> m_index;
    ForeignIndex<ROW> m_otherIndex;
};

}

#endif

Generated by  Doxygen 1.6.0   Back to index