casacore
Loading...
Searching...
No Matches
ColumnsIndex.h
Go to the documentation of this file.
1//# ColumnsIndex.h: Index to one or more columns in a table
2//# Copyright (C) 1998,1999,2001,2002
3//# Associated Universities, Inc. Washington DC, USA.
4//#
5//# This library is free software; you can redistribute it and/or modify it
6//# under the terms of the GNU Library General Public License as published by
7//# the Free Software Foundation; either version 2 of the License, or (at your
8//# option) any later version.
9//#
10//# This library is distributed in the hope that it will be useful, but WITHOUT
11//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13//# License for more details.
14//#
15//# You should have received a copy of the GNU Library General Public License
16//# along with this library; if not, write to the Free Software Foundation,
17//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18//#
19//# Correspondence concerning AIPS++ should be addressed as follows:
20//# Internet email: casa-feedback@nrao.edu.
21//# Postal address: AIPS++ Project Office
22//# National Radio Astronomy Observatory
23//# 520 Edgemont Road
24//# Charlottesville, VA 22903-2475 USA
25
26#ifndef TABLES_COLUMNSINDEX_H
27#define TABLES_COLUMNSINDEX_H
28
29
30//# Includes
31#include <casacore/casa/aips.h>
32#include <casacore/tables/Tables/Table.h>
33#include <casacore/casa/Arrays/Vector.h>
34#include <casacore/casa/Containers/Block.h>
35#include <casacore/casa/Containers/Record.h>
36
37namespace casacore { //# NAMESPACE CASACORE - BEGIN
38
39//# Forward Declarations
40class String;
41class TableColumn;
42template<typename T> class RecordFieldPtr;
43
44// <summary>
45// Index to one or more columns in a table.
46// </summary>
47
48// <use visibility=export>
49
50// <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="tColumnsIndex.cc" demos="">
51// </reviewed>
52
53// <prerequisite>
54// <li> <linkto class=Table>Table</linkto>
55// <li> <linkto class=Record>Record</linkto>
56// <li> <linkto class=RecordFieldPtr>RecordFieldPtr</linkto>
57// </prerequisite>
58
59// <synopsis>
60// This class makes it possible to use transient indices on top
61// of tables in order to speed up the process of finding rows
62// based on a given key or key range.
63// When constructing a <src>ColumnsIndex</src> object, one has to define
64// which columns form the key for this index on the given
65// <src>table</src> object.
66// Only scalar columns are supported. The data in the given columns
67// will be read, sorted (if needed), and stored in memory.
68// When looking up a key or key range, the class will use a fast binary
69// search on the data held in memory.
70// <p>
71// The <src>ColumnsIndex</src> object contains a
72// <linkto class=Record>Record</linkto> object which can be used
73// to define the key to be looked up. The record contains a field for
74// each column in the index (with the same name and data type).
75// The fastest way to fill the key is by creating a
76// <linkto class=RecordFieldPtr>RecordFieldPtr</linkto> object for
77// each field in the record (see the example) and fill it as needed.
78// However, one can also use the <src>Record::define</src> function,
79// but that is slower.
80// <br>
81// A second record is available to define the upper key
82// when a key range has to be looked up. The keys can be accessed
83// using the various <src>accessKey</src> functions.
84// <p>
85// When a key is defined, the <src>getRowNumbers</src> function can be
86// used to find the table rows containing the given key (range).
87// Function <src>getRowNumber</src> can be used if all keys in the index
88// are unique (which can be tested with the <src>isUnique</src> function).
89// <p>
90// Instead of using the internal records holding the keys, one can also
91// pass its own Record object to <src>getRowNumbers</src>.
92// However, it will be slower.
93// <p>
94// When constructing the object, the user can supply his own compare
95// function. The default compare function compares each field of the
96// key in the normal way. A user's compare function makes it possible
97// to compare in a special way. E.g. one could use near instead of ==
98// on floating point fields. Another example (which is shown in one
99// of the examples below) makes it possible to find a key in an
100// index consisting of a time and width.
101// <p>
102// After an index is created, it is possible to change the data
103// in the underlying columns. However, the <src>ColumnsIndex</src> can
104// not detect if the column data have changed. It can only detect if
105// the number of rows has changed. If the column data have changed,
106// the user has to use the <src>setChanged</src> function to indicate
107// that all columns or a particular column has changed.
108// <br>If data have changed, the entire index will be recreated by
109// rereading and optionally resorting the data. This will be deferred
110// until the next key lookup.
111// </synopsis>
112
113// <example>
114// Suppose one has an antenna table with key ANTENNA.
115// <srcblock>
116// // Open the table and make an index for column ANTENNA.
117// Table tab("antenna.tab")
118// ColumnsIndex colInx(tab, "ANTENNA");
119// // Make a RecordFieldPtr for the ANTENNA field in the index key record.
120// // Its data type has to match the data type of the column.
121// RecordFieldPtr<Int> antFld(colInx.accessKey(), "ANTENNA");
122// // Now loop in some way and find the row for the antenna
123// // involved in that loop.
124// Bool found;
125// while (...) {
126// // Fill the key field and get the row number.
127// // ANTENNA is a unique key, so only one row number matches.
128// // Otherwise function getRowNumbers had to be used.
129// *antFld = antenna;
130// rownr_t antRownr = colInx.getRowNumber (found);
131// if (!found) {
132// cout << "Antenna " << antenna << " is unknown" << endl;
133// } else {
134// // antRownr can now be used to get data from that row in
135// // the antenna table.
136// }
137// }
138// </srcblock>
139//
140// The following example shows how multiple keys can be used and how
141// a search on a range can be done.
142// <srcblock>
143// Table tab("sometable")
144// // Note that TIME is the main key.
145// // Also note that stringToVector (in ArrayUtil.h) is a handy
146// // way to convert a String to a Vector<String>.
147// ColumnsIndex colInx(tab, stringToVector("TIME,ANTENNA"));
148// // Make a RecordFieldPtr for the fields in lower and upper key records.
149// RecordFieldPtr<Double> timeLow(colInx.accessLowerKey(), "TIME");
150// RecordFieldPtr<Int> antLow(colInx.accessLowerKey(), "ANTENNA");
151// RecordFieldPtr<Double> timeUpp(colInx.accessUpperKey(), "TIME");
152// RecordFieldPtr<Int> antUpp(colInx.accessUpperKey(), "ANTENNA");
153// while (...) {
154// // Fill the key fields.
155// *timeLow = ...;
156// *antLow = ...;
157// *timeUpp = ...;
158// *antUpp = ...;
159// // Find the row numbers for keys between low and upp (inclusive).
160// RowNumbers rows = colInx.getRowNumbers (True, True);
161// }
162// </srcblock>
163//
164// The following example shows how a specific compare function
165// could look like. A function like this will actually be used in the
166// calibration software.
167// <br>
168// The table for which the index is built, has rows with the TIME as its key.
169// However, each row is valid for a given interval, where TIME gives
170// the middle of the interval and WIDTH the length of the interval.
171// This means that the compare function has to test whether the key
172// is part of the interval.
173// <srcblock>
174// Int myCompare (const Block<void*>& fieldPtrs,
175// const Block<void*>& dataPtrs,
176// const Block<Int>& dataTypes,
177// rownr_t index)
178// {
179// // Assert (for performance only in debug mode) that the correct
180// // fields are used.
181// DebugAssert (dataTypes.nelements() == 2, AipsError);
182// DebugAssert (dataTypes[0] == TpDouble && dataTypes[1] == TpDouble,
183// AipsError);
184// // Now get the key to be looked up
185// // (an awfully looking cast has to be used).
186// const Double key = *(*(const RecordFieldPtr<Double>*)(fieldPtrs[0]));
187// // Get the time and width of the entry to be compared.
188// const Double time = ((const Double*)(dataPtrs[0]))[index];
189// const Double width = ((const Double*)(dataPtrs[1]))[index];
190// const Double start = time - width/2;
191// const Double end = time + width/2;
192// // Test if the key is before, after, or in the interval
193// // (representing less, greater, equal).
194// if (key < start) {
195// return -1;
196// } else if (key > end) {
197// return 1;
198// }
199// return 0;
200// }
201//
202// // Now use this compare function in an actual index.
203// Table tab("sometable")
204// ColumnsIndex colInx(tab, stringToVector("TIME,WIDTH"), myCompare);
205// // Make a RecordFieldPtr for the TIME field in the key record.
206// // Note that although the WIDTH is part of the index, it is
207// // not an actual key. So it does not need to be filled in.
208// RecordFieldPtr<Double> time(colInx.accessLowerKey(), "TIME");
209// Bool found;
210// while (...) {
211// // Fill the key field.
212// *time = ...;
213// // Find the row number for this time.
214// rownr_t rownr = colInx.getRowNumber (found);
215// }
216// </srcblock>
217// </example>
218
219// <motivation>
220// The calibration software needs to lookup keys in calibration tables
221// very frequently. This class makes that process much easier and faster.
222// </motivation>
223
224
226{
227public:
228 // Define the signature of a comparison function.
229 // The first block contains pointers to <src>RecordFieldPtr<T></src>
230 // objects holding the key to be looked up.
231 // The second block contains pointers to the column data.
232 // The <src>index</src> argument gives the index in the column data.
233 // The third block contains data types of those blocks (TpBool, etc.).
234 // The function should return -1 if key is less than data,
235 // 0 if equal, 1 if greater.
236 // <br>An example above shows how a compare function can be used.
237 typedef Int Compare (const Block<void*>& fieldPtrs,
238 const Block<void*>& dataPtrs,
239 const Block<Int>& dataTypes,
240 rownr_t index);
241
242 // Create an index on the given table for the given column.
243 // The column has to be a scalar column.
244 // If <src>noSort==True</src>, the table is already in order of that
245 // column and the sort step will not be done.
246 // The default compare function is provided by this class. It simply
247 // compares each field in the key.
248 ColumnsIndex (const Table&, const String& columnName,
249 Compare* compareFunction = 0, Bool noSort = False);
250
251 // Create an index on the given table for the given columns, thus
252 // the key is formed by multiple columns.
253 // The columns have to be scalar columns.
254 // If <src>noSort==True</src>, the table is already in order of those
255 // columns and the sort step will not be done.
256 // The default compare function is provided by this class. It simply
257 // compares each field in the key.
259 Compare* compareFunction = 0, Bool noSort = False);
260
261 // Copy constructor (copy semantics).
263
265
266 // Assignment (copy semantics).
268
269 // Are all keys in the index unique?
270 Bool isUnique() const;
271
272 // Return the names of the columns forming the index.
274
275 // Get the table for which this index is created.
276 const Table& table() const;
277
278 // Something has changed in the table, so the index has to be recreated.
279 // The 2nd version indicates that a specific column has changed,
280 // so only that column is reread. If that column is not part of the
281 // index, nothing will be done.
282 // <br>Note that the class itself is keeping track if the number of
283 // rows in the table changes.
284 // <group>
286 void setChanged (const String& columnName);
287 // </group>
288
289 // Access the key values.
290 // These functions allow you to create RecordFieldPtr<T> objects
291 // for each field in the key. In this way you can quickly fill in
292 // the key.
293 // <br>The records have a fixed type, so you cannot add or delete fields.
294 // <group>
295 Record& accessKey();
298 // </group>
299
300 // Find the row number matching the key. All keys have to be unique,
301 // otherwise an exception is thrown.
302 // If no match is found, <src>found</src> is set to False.
303 // The 2nd version makes it possible to pass in your own Record
304 // instead of using the internal record via the <src>accessKey</src>
305 // functions. Note that the given Record will be copied to the internal
306 // record, thus overwrites it.
307 // <group>
309 rownr_t getRowNumber (Bool& found, const Record& key);
310 // </group>
311
312 // Find the row numbers matching the key. It should be used instead
313 // of <src>getRowNumber</src> if the same key can exist multiple times.
314 // The 2nd version makes it possible to pass in your own Record
315 // instead of using the internal record via the <src>accessKey</src>
316 // functions. Note that the given Record will be copied to the internal
317 // record, thus overwrites it.
318 // <group>
321 // </group>
322
323 // Find the row numbers matching the key range. The boolean arguments
324 // tell if the lower and upper key are part of the range.
325 // The 2nd version makes it possible to pass in your own Records
326 // instead of using the internal records via the
327 // <src>accessLower/UpperKey</src> functions.
328 // Note that the given Records will be copied to the internal
329 // records, thus overwrite them.
330 // <group>
331 RowNumbers getRowNumbers (Bool lowerInclusive, Bool upperInclusive);
332 RowNumbers getRowNumbers (const Record& lower, const Record& upper,
333 Bool lowerInclusive, Bool upperInclusive);
334 // </group>
335
336 // Fill the internal key field from the corresponding external key.
337 // The data type may differ.
338 static void copyKeyField (void* field, int dtype, const Record& key);
339
340protected:
341 // Copy that object to this.
342 void copy (const ColumnsIndex& that);
343
344 // Delete all data in the object.
346
347 // Add a column to the record description for the keys.
348 void addColumnToDesc (RecordDesc& description,
349 const TableColumn& column);
350
351 // Create the various members in the object.
353 Compare* compareFunction, Bool noSort);
354
355 // Make the various internal <src>RecordFieldPtr</src> objects.
356 void makeObjects (const RecordDesc& description);
357
358 // Read the data of the columns forming the index, sort them and
359 // form the index.
360 void readData();
361
362 // Do a binary search on <src>itsUniqueIndex</src> for the key in
363 // <src>fieldPtrs</src>.
364 // If the key is found, <src>found</src> is set to True and the index
365 // in <src>itsUniqueIndex</src> is returned.
366 // If not found, <src>found</src> is set to False and the index
367 // of the next higher key is returned.
368 rownr_t bsearch (Bool& found, const Block<void*>& fieldPtrs) const;
369
370 // Compare the key in <src>fieldPtrs</src> with the given index entry.
371 // -1 is returned when less, 0 when equal, 1 when greater.
372 static Int compare (const Block<void*>& fieldPtrs,
373 const Block<void*>& dataPtrs,
374 const Block<Int>& dataTypes,
375 rownr_t index);
376
377 // Fill the row numbers vector for the given start till end in the
378 // <src>itsUniqueIndex</src> vector (end is not inclusive).
379 void fillRowNumbers (Vector<rownr_t>& rows, rownr_t start, rownr_t end) const;
380
381private:
382 // Fill the internal key fields from the corresponding external key.
383 void copyKey (Block<void*> fields, const Record& key);
384
385 // Fill the internal key field from the corresponding external key.
386 // The data type may differ.
387 template <typename T>
388 static void copyKeyField (RecordFieldPtr<T>& field, const Record& key)
389 {
390 key.get (field.name(), *field);
391 }
392
399 Block<void*> itsData; //# pointer to data in itsDataVectors
400 //# The following 2 blocks are actually blocks of RecordFieldPtr<T>*.
401 //# They are used for fast access to the records.
406 Bool itsNoSort; //# True = sort is not needed
407 Compare* itsCompare; //# Compare function
408 Vector<rownr_t> itsDataIndex; //# Row numbers of all keys
409 //# Indices in itsDataIndex for each unique key
411 rownr_t* itsDataInx; //# pointer to data in itsDataIndex
412 rownr_t* itsUniqueInx; //# pointer to data in itsUniqueIndex
413};
414
415
417{
419}
420inline const Table& ColumnsIndex::table() const
421{
422 return itsTable;
423}
425{
426 return *itsLowerKeyPtr;
427}
429{
430 return *itsLowerKeyPtr;
431}
433{
434 return *itsUpperKeyPtr;
435}
436
437
438} //# NAMESPACE CASACORE - END
439
440#endif
size_t nelements() const
How many elements does this array have? Product of all axis lengths.
Definition ArrayBase.h:101
simple 1-D array
const Table & table() const
Get the table for which this index is created.
RowNumbers getRowNumbers()
Find the row numbers matching the key.
RowNumbers getRowNumbers(const Record &key)
RowNumbers getRowNumbers(Bool lowerInclusive, Bool upperInclusive)
Find the row numbers matching the key range.
void copy(const ColumnsIndex &that)
Copy that object to this.
Int Compare(const Block< void * > &fieldPtrs, const Block< void * > &dataPtrs, const Block< Int > &dataTypes, rownr_t index)
Define the signature of a comparison function.
void fillRowNumbers(Vector< rownr_t > &rows, rownr_t start, rownr_t end) const
Fill the row numbers vector for the given start till end in the itsUniqueIndex vector (end is not inc...
void setChanged(const String &columnName)
ColumnsIndex(const Table &, const String &columnName, Compare *compareFunction=0, Bool noSort=False)
Create an index on the given table for the given column.
Vector< rownr_t > itsDataIndex
void setChanged()
Something has changed in the table, so the index has to be recreated.
Block< void * > itsUpperFields
Block< void * > itsDataVectors
void create(const Table &table, const Vector< String > &columnNames, Compare *compareFunction, Bool noSort)
Create the various members in the object.
void readData()
Read the data of the columns forming the index, sort them and form the index.
ColumnsIndex & operator=(const ColumnsIndex &that)
Assignment (copy semantics).
ColumnsIndex(const Table &, const Vector< String > &columnNames, Compare *compareFunction=0, Bool noSort=False)
Create an index on the given table for the given columns, thus the key is formed by multiple columns.
void addColumnToDesc(RecordDesc &description, const TableColumn &column)
Add a column to the record description for the keys.
ColumnsIndex(const ColumnsIndex &that)
Copy constructor (copy semantics).
Block< Bool > itsColumnChanged
rownr_t bsearch(Bool &found, const Block< void * > &fieldPtrs) const
Do a binary search on itsUniqueIndex for the key in fieldPtrs.
Block< void * > itsLowerFields
static void copyKeyField(void *field, int dtype, const Record &key)
Fill the internal key field from the corresponding external key.
Bool isUnique() const
Are all keys in the index unique?
void deleteObjects()
Delete all data in the object.
static Int compare(const Block< void * > &fieldPtrs, const Block< void * > &dataPtrs, const Block< Int > &dataTypes, rownr_t index)
Compare the key in fieldPtrs with the given index entry.
static void copyKeyField(RecordFieldPtr< T > &field, const Record &key)
Fill the internal key field from the corresponding external key.
Record & accessKey()
Access the key values.
Vector< String > columnNames() const
Return the names of the columns forming the index.
void copyKey(Block< void * > fields, const Record &key)
Fill the internal key fields from the corresponding external key.
Block< Int > itsDataTypes
Block< void * > itsData
Vector< rownr_t > itsUniqueIndex
rownr_t getRowNumber(Bool &found, const Record &key)
rownr_t getRowNumber(Bool &found)
Find the row number matching the key.
void makeObjects(const RecordDesc &description)
Make the various internal RecordFieldPtr objects.
RowNumbers getRowNumbers(const Record &lower, const Record &upper, Bool lowerInclusive, Bool upperInclusive)
String name() const
Return the name of the field.
void get(const RecordFieldId &, Bool &value) const
Get the value of the given field.
String: the storage and methods of handling collections of characters.
Definition String.h:223
this file contains all the compiler specific defines
Definition mainpage.dox:28
const Bool False
Definition aipstype.h:42
int Int
Definition aipstype.h:48
bool Bool
Define the standard types used by Casacore.
Definition aipstype.h:40
uInt64 rownr_t
Define the type of a row number in a table.
Definition aipsxtype.h:44