Loading...
Searching...
No Matches
ColumnsIndexArray.h
Go to the documentation of this file.
//# ColumnsIndexArray.h: Index to an array column in a table
//# Copyright (C) 2001,2002
//# Associated Universities, Inc. Washington DC, USA.
//#
//# This library is free software; you can redistribute it and/or modify it
//# under the terms of the GNU Library General Public License as published by
//# the Free Software Foundation; either version 2 of the License, or (at your
//# option) any later version.
//#
//# This library is distributed in the hope that it will be useful, but WITHOUT
//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
//# License for more details.
//#
//# You should have received a copy of the GNU Library General Public License
//# along with this library; if not, write to the Free Software Foundation,
//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
//#
//# Correspondence concerning AIPS++ should be addressed as follows:
//# Internet email: casa-feedback@nrao.edu.
//# Postal address: AIPS++ Project Office
//# National Radio Astronomy Observatory
//# 520 Edgemont Road
//# Charlottesville, VA 22903-2475 USA
#ifndef TABLES_COLUMNSINDEXARRAY_H
#define TABLES_COLUMNSINDEXARRAY_H
//# Includes
#include <casacore/casa/aips.h>
#include <casacore/tables/Tables/Table.h>
#include <casacore/casa/Arrays/Vector.h>
#include <casacore/casa/Containers/Block.h>
#include <casacore/casa/Containers/Record.h>
namespace casacore { //# NAMESPACE CASACORE - BEGIN
//# Forward Declarations
class String;
class TableColumn;
// <summary>
// Index to an array column in a table.
// </summary>
// <use visibility=export>
// <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="tColumnsIndexArray.cc" demos="">
// </reviewed>
// <prerequisite>
// <li> <linkto class=Table>Table</linkto>
// <li> <linkto class=Record>Record</linkto>
// <li> <linkto class=RecordFieldPtr>RecordFieldPtr</linkto>
// </prerequisite>
// <synopsis>
// This class makes it possible to use transient indices on top
// of an array column in a table in order to speed up the process of
// finding rows based on a given key or key range.
// It is similar to class <linkto class=ColumnsIndex>ColumnsIndex</linkto>
// which is meant for one or more scalar columns.
// <p>
// When constructing a <src>ColumnsIndexArray</src> object, one has to define
// which column forms the key for this index on the given
// <src>table</src> object.
// Not every data type is supported; only uChar, Short, Int, uInt, Int64 and
// String array columns are supported.
// The column can contain arrays of any shape and it can also contain
// empty cells. The class will probably mostly be used for vectors, as
// they seem to be the most logical way to hold multiple keys.
// <br>The data in the given column will be read, sorted,
// and stored in memory. When looking up a key or key range, the class
// will use a fast binary search on the data held in memory.
// <p>
// The <src>ColumnsIndexArray</src> object contains a
// <linkto class=Record>Record</linkto> object which can be used
// to define the key to be looked up. The record contains a field for
// the column in the index (with the same name and data type).
// The fastest way to fill the key is by creating a
// <linkto class=RecordFieldPtr>RecordFieldPtr</linkto> object for
// the field in the record (see the example) and fill it as needed.
// However, one can also use the <src>Record::define</src> function,
// but that is slower.
// <br>
// A second record is available to define the upper key
// in case a key range has to be looked up. The keys can be accessed
// using the various <src>accessKey</src> functions.
// <p>
// When a key is defined, the <src>getRowNumbers</src> function can be
// used to find the table rows containing the given key (range).
// Function <src>getRowNumber</src> can be used to lookup a single key
// if all keys in the index are unique (which can be tested with the
// <src>isUnique</src> function).
// <p>
// Instead of using the internal records holding the keys, one can also
// pass its own Record object to <src>getRowNumbers</src>.
// However, it will be slower.
// <p>
// After an index is created, it is possible to change the data
// in the underlying columns. However, the <src>ColumnsIndexArray</src> can
// not detect if the column data have changed. It can only detect if
// the number of rows has changed. If the column data have changed,
// the user has to use the <src>setChanged</src> function to indicate
// that the column has changed.
// <br>If data have changed, the entire index will be recreated by
// rereading and resorting the data. This will be deferred
// until the next key lookup.
// </synopsis>
// <example>
// Suppose one has table with a column NAME containing vectors.
// <srcblock>
// // Open the table and make an index for the column.
// Table tab("my.tab")
// ColumnsIndexArray colInx(tab, "NAME");
// // Make a RecordFieldPtr for the NAME field in the index key record.
// // Its data type has to match the data type of the column.
// RecordFieldPtr<String> nameFld(colInx.accessKey(), "NAME");
// // Find the row for a given name.
// Bool found;
// // Fill the key field and get the row number.
// // NAME is a unique key, so only one row number matches.
// // Otherwise function getRowNumbers had to be used.
// *nameFld = "MYNAME";
// rownr_t rownr = colInx.getRowNumber (found);
// if (!found) {
// cout << "Name MYNAME is unknown" << endl;
// }
// // Now get a range of names and return the row numbers in ascending order.
// // This uses the fact that the 'unique' argument also sorts the data.
// RecordFieldPtr<String> nameUpp(colInx.accessUpperKey(), "NAME");
// *nameFld = "LOWER";
// *nameUpp = "UPPER";
// RowNumbers rownrs = colInx.getRowNumbers (True, True, True);
// </srcblock>
// <motivation>
// Bob Garwood needed such a class.
// </motivation>
class ColumnsIndexArray
{
public:
// Create an index on the given table for the given column.
// The column can be a scalar or an array column.
// If <src>noSort==True</src>, the table is already in order of that
// column and the sort step will not be done.
// It only supports String and integer columns.
ColumnsIndexArray (const Table&, const String& columnName);
// Copy constructor (copy semantics).
ColumnsIndexArray (const ColumnsIndexArray& that);
~ColumnsIndexArray();
// Assignment (copy semantics).
ColumnsIndexArray& operator= (const ColumnsIndexArray& that);
// Are all keys in the index unique?
Bool isUnique() const;
// Return the names of the columns forming the index.
const String& columnName() const;
// Get the table for which this index is created.
const Table& table() const;
// Something has changed in the table, so the index has to be recreated.
// The 2nd version indicates that a specific column has changed,
// so only that column might need to be reread. If that column is not
// part of the index, nothing will be done.
// <br>Note that the class itself is keeping track if the number of
// rows in the table changes.
// <group>
void setChanged();
void setChanged (const String& columnName);
// </group>
// Access the key values.
// These functions allow you to create RecordFieldPtr<T> objects
// for each field in the key. In this way you can quickly fill in
// the key.
// <br>The records have a fixed type, so you cannot add or delete fields.
// <br>Note that <src>accessKey</src> and <src>accessLowerKey</src>
// are synonyms; they return the same underlying record.
// <group>
Record& accessKey();
Record& accessLowerKey();
Record& accessUpperKey();
// </group>
// Find the row number matching the key. All keys have to be unique,
// otherwise an exception is thrown.
// If no match is found, <src>found</src> is set to False.
// The 2nd version makes it possible to pass in your own Record
// instead of using the internal record via the <src>accessKey</src>
// functions. Note that the given Record will be copied to the internal
// record, thus overwrites it.
// <group>
rownr_t getRowNumber (Bool& found);
rownr_t getRowNumber (Bool& found, const Record& key);
// </group>
// Find the row numbers matching the key. It should be used instead
// of <src>getRowNumber</src> if the same key can exist multiple times.
// The 2nd version makes it possible to pass in your own Record
// instead of using the internal record via the <src>accessKey</src>
// functions. Note that the given Record will be copied to the internal
// record, thus overwrites it.
// <br>A row can contain multiple equal values. In such a case the
// same row number can occur multiple times in the output vector,
// unless <src>unique</src> is set to True. Note that making the row
// numbers unique implies a sort, so it can also be used to get the
// row numbers in ascending order.
// <group>
RowNumbers getRowNumbers (Bool unique=False);
RowNumbers getRowNumbers (const Record& key, Bool unique=False);
// </group>
// Find the row numbers matching the key range. The boolean arguments
// tell if the lower and upper key are part of the range.
// The 2nd version makes it possible to pass in your own Records
// instead of using the internal records via the
// <src>accessLower/UpperKey</src> functions.
// Note that the given Records will be copied to the internal
// records, thus overwrite them.
// <br>A row can contain multiple matching values. In such a case the
// same row number can occur multiple times in the output vector,
// unless <src>unique</src> is set to True. Note that making the row
// numbers unique implies a sort, so it can also be used to get the
// row numbers in ascending order.
// <group>
RowNumbers getRowNumbers (Bool lowerInclusive, Bool upperInclusive,
Bool unique=False);
RowNumbers getRowNumbers (const Record& lower, const Record& upper,
Bool lowerInclusive, Bool upperInclusive,
Bool unique=False);
// </group>
protected:
// Copy that object to this.
void copy (const ColumnsIndexArray& that);
// Delete all data in the object.
void deleteObjects();
// Add a column to the record description for the keys.
// If the switch <src>arrayPossible</src> is True, the column can
// be an array. Otherwise it has to be a scalar.
void addColumnToDesc (RecordDesc& description,
const TableColumn& column);
// Make the various internal <src>RecordFieldPtr</src> objects.
void makeObjects (const RecordDesc& description);
// Read the data of the columns forming the index, sort them and
// form the index.
void readData();
// Do a binary search on <src>itsUniqueIndexArray</src> for the key in
// <src>fieldPtrs</src>.
// If the key is found, <src>found</src> is set to True and the index
// in <src>itsUniqueIndexArray</src> is returned.
// If not found, <src>found</src> is set to False and the index
// of the next higher key is returned.
rownr_t bsearch (Bool& found, void* fieldPtr) const;
// Compare the key in <src>fieldPtr</src> with the given index entry.
// -1 is returned when less, 0 when equal, 1 when greater.
static Int compare (void* fieldPtr,
void* dataPtr,
Int dataType,
rownr_t index);
// Fill the row numbers vector for the given start till end in the
// <src>itsUniqueIndexArray</src> vector (end is not inclusive).
// If <src>unique</src> is True, the row numbers will be made unique.
void fillRowNumbers (Vector<rownr_t>& rows, rownr_t start, rownr_t end,
Bool unique) const;
// Get the data if the column is an array.
// <group>
void getArray (Vector<uChar>& result, const String& name);
void getArray (Vector<Short>& result, const String& name);
void getArray (Vector<Int>& result, const String& name);
void getArray (Vector<uInt>& result, const String& name);
void getArray (Vector<Int64>& result, const String& name);
void getArray (Vector<String>& result, const String& name);
// </group>
// Fill the rownrs belonging to each array value.
void fillRownrs (rownr_t npts, const Block<rownr_t>& nrel);
private:
Table itsTable;
rownr_t itsNrrow;
Record* itsLowerKeyPtr;
Record* itsUpperKeyPtr;
Int itsDataType;
void* itsDataVector;
void* itsData; //# pointer to data in itsDataVector
//# The following 2 blocks are actually blocks of RecordFieldPtr<T>*.
//# They are used for fast access to the records.
void* itsLowerField;
void* itsUpperField;
Bool itsChanged;
Vector<rownr_t> itsDataIndex; //# Row numbers of all keys
//# Indices in itsDataIndex for each unique key
Vector<rownr_t> itsUniqueIndex;
Block<rownr_t> itsRownrs; //# rownr for each value
rownr_t* itsDataInx; //# pointer to data in itsDataIndex
rownr_t* itsUniqueInx; //# pointer to data in itsUniqueIndex
};
inline Bool ColumnsIndexArray::isUnique() const
{
return (itsDataIndex.nelements() == itsUniqueIndex.nelements());
}
inline const Table& ColumnsIndexArray::table() const
{
return itsTable;
}
inline Record& ColumnsIndexArray::accessKey()
{
return *itsLowerKeyPtr;
}
inline Record& ColumnsIndexArray::accessLowerKey()
{
return *itsLowerKeyPtr;
}
inline Record& ColumnsIndexArray::accessUpperKey()
{
return *itsUpperKeyPtr;
}
} //# NAMESPACE CASACORE - END
#endif
casacore::Block
simple 1-D array
Definition Block.h:198
casacore::ColumnsIndexArray::itsDataType
Int itsDataType
Definition ColumnsIndexArray.h:303
casacore::ColumnsIndexArray::ColumnsIndexArray
ColumnsIndexArray(const Table &, const String &columnName)
Create an index on the given table for the given column.
casacore::ColumnsIndexArray::itsChanged
Bool itsChanged
Definition ColumnsIndexArray.h:310
casacore::ColumnsIndexArray::table
const Table & table() const
Get the table for which this index is created.
Definition ColumnsIndexArray.h:324
casacore::ColumnsIndexArray::setChanged
void setChanged()
Something has changed in the table, so the index has to be recreated.
casacore::ColumnsIndexArray::getArray
void getArray(Vector< Int > &result, const String &name)
casacore::ColumnsIndexArray::isUnique
Bool isUnique() const
Are all keys in the index unique?
Definition ColumnsIndexArray.h:320
casacore::ColumnsIndexArray::operator=
ColumnsIndexArray & operator=(const ColumnsIndexArray &that)
Assignment (copy semantics).
casacore::ColumnsIndexArray::addColumnToDesc
void addColumnToDesc(RecordDesc &description, const TableColumn &column)
Add a column to the record description for the keys.
casacore::ColumnsIndexArray::ColumnsIndexArray
ColumnsIndexArray(const ColumnsIndexArray &that)
Copy constructor (copy semantics).
casacore::ColumnsIndexArray::itsLowerKeyPtr
Record * itsLowerKeyPtr
Definition ColumnsIndexArray.h:301
casacore::ColumnsIndexArray::readData
void readData()
Read the data of the columns forming the index, sort them and form the index.
casacore::ColumnsIndexArray::itsDataInx
rownr_t * itsDataInx
Definition ColumnsIndexArray.h:315
casacore::ColumnsIndexArray::getArray
void getArray(Vector< String > &result, const String &name)
casacore::ColumnsIndexArray::makeObjects
void makeObjects(const RecordDesc &description)
Make the various internal RecordFieldPtr objects.
casacore::ColumnsIndexArray::copy
void copy(const ColumnsIndexArray &that)
Copy that object to this.
casacore::ColumnsIndexArray::getRowNumbers
RowNumbers getRowNumbers(const Record &lower, const Record &upper, Bool lowerInclusive, Bool upperInclusive, Bool unique=False)
casacore::ColumnsIndexArray::itsUniqueIndex
Vector< rownr_t > itsUniqueIndex
Definition ColumnsIndexArray.h:313
casacore::ColumnsIndexArray::itsDataVector
void * itsDataVector
Definition ColumnsIndexArray.h:304
casacore::ColumnsIndexArray::accessUpperKey
Record & accessUpperKey()
Definition ColumnsIndexArray.h:336
casacore::ColumnsIndexArray::fillRownrs
void fillRownrs(rownr_t npts, const Block< rownr_t > &nrel)
Fill the rownrs belonging to each array value.
casacore::ColumnsIndexArray::bsearch
rownr_t bsearch(Bool &found, void *fieldPtr) const
Do a binary search on itsUniqueIndexArray for the key in fieldPtrs.
casacore::ColumnsIndexArray::getRowNumbers
RowNumbers getRowNumbers(Bool unique=False)
Find the row numbers matching the key.
casacore::ColumnsIndexArray::itsUniqueInx
rownr_t * itsUniqueInx
Definition ColumnsIndexArray.h:316
casacore::ColumnsIndexArray::itsDataIndex
Vector< rownr_t > itsDataIndex
Definition ColumnsIndexArray.h:311
casacore::ColumnsIndexArray::itsData
void * itsData
Definition ColumnsIndexArray.h:305
casacore::ColumnsIndexArray::compare
static Int compare(void *fieldPtr, void *dataPtr, Int dataType, rownr_t index)
Compare the key in fieldPtr with the given index entry.
casacore::ColumnsIndexArray::getArray
void getArray(Vector< uInt > &result, const String &name)
casacore::ColumnsIndexArray::getRowNumbers
RowNumbers getRowNumbers(const Record &key, Bool unique=False)
casacore::ColumnsIndexArray::setChanged
void setChanged(const String &columnName)
casacore::ColumnsIndexArray::itsUpperField
void * itsUpperField
Definition ColumnsIndexArray.h:309
casacore::ColumnsIndexArray::getRowNumber
rownr_t getRowNumber(Bool &found)
Find the row number matching the key.
casacore::ColumnsIndexArray::fillRowNumbers
void fillRowNumbers(Vector< rownr_t > &rows, rownr_t start, rownr_t end, Bool unique) const
Fill the row numbers vector for the given start till end in the itsUniqueIndexArray vector (end is no...
casacore::ColumnsIndexArray::accessLowerKey
Record & accessLowerKey()
Definition ColumnsIndexArray.h:332
casacore::ColumnsIndexArray::itsNrrow
rownr_t itsNrrow
Definition ColumnsIndexArray.h:300
casacore::ColumnsIndexArray::itsRownrs
Block< rownr_t > itsRownrs
Definition ColumnsIndexArray.h:314
casacore::ColumnsIndexArray::itsUpperKeyPtr
Record * itsUpperKeyPtr
Definition ColumnsIndexArray.h:302
casacore::ColumnsIndexArray::getArray
void getArray(Vector< uChar > &result, const String &name)
Get the data if the column is an array.
casacore::ColumnsIndexArray::accessKey
Record & accessKey()
Access the key values.
Definition ColumnsIndexArray.h:328
casacore::ColumnsIndexArray::itsLowerField
void * itsLowerField
Definition ColumnsIndexArray.h:308
casacore::ColumnsIndexArray::itsTable
Table itsTable
Definition ColumnsIndexArray.h:299
casacore::ColumnsIndexArray::deleteObjects
void deleteObjects()
Delete all data in the object.
casacore::ColumnsIndexArray::~ColumnsIndexArray
~ColumnsIndexArray()
casacore::ColumnsIndexArray::getArray
void getArray(Vector< Short > &result, const String &name)
casacore::ColumnsIndexArray::columnName
const String & columnName() const
Return the names of the columns forming the index.
casacore::ColumnsIndexArray::getRowNumbers
RowNumbers getRowNumbers(Bool lowerInclusive, Bool upperInclusive, Bool unique=False)
Find the row numbers matching the key range.
casacore::ColumnsIndexArray::getRowNumber
rownr_t getRowNumber(Bool &found, const Record &key)
casacore::ColumnsIndexArray::getArray
void getArray(Vector< Int64 > &result, const String &name)
casacore::RecordDesc
Definition RecordDesc.h:103
casacore::RowNumbers
Definition RowNumbers.h:36
casacore::String
String: the storage and methods of handling collections of characters.
Definition String.h:223
casacore::TableColumn
Definition TableColumn.h:97
casacore::Table
Definition Table.h:157
casacore::Vector
Definition Vector.h:82
casacore::Record
Record()
casacore
this file contains all the compiler specific defines
Definition mainpage.dox:28
casacore::False
const Bool False
Definition aipstype.h:42
casacore::description
const RecordDesc & description() const
Describes the current structure of this Record.
casacore::name
String name() const
Return the name of the field.
Definition RecordField.h:163
casacore::Int
int Int
Definition aipstype.h:48
casacore::Bool
bool Bool
Define the standard types used by Casacore.
Definition aipstype.h:40
casacore::rownr_t
uInt64 rownr_t
Define the type of a row number in a table.
Definition aipsxtype.h:44
casacore::dataType
DataType dataType(const RecordFieldId &) const