casacore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TableRow.h
Go to the documentation of this file.
1 //# TableRow.h: Access to a table row
2 //# Copyright (C) 1996,1999,2001
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: aips2-request@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 //# $Id$
27 
28 #ifndef TABLES_TABLEROW_H
29 #define TABLES_TABLEROW_H
30 
31 //# Includes
32 #include <casacore/casa/aips.h>
38 
39 namespace casacore { //# NAMESPACE CASACORE - BEGIN
40 
41 //# Forward Declarations
42 class TableColumn;
43 
44 // <summary>
45 // Readonly access to a table row
46 // </summary>
47 
48 // <use visibility=export>
49 
50 // <reviewed reviewer="Paul Shannon" date="1996/05/10" tests="tTableRow.cc">
51 // </reviewed>
52 
53 // <prerequisite>
54 // <li> <linkto class=Table>Table</linkto>
55 // <li> <linkto class=TableRecord>TableRecord</linkto>
56 // </prerequisite>
57 
58 // <synopsis>
59 // This class provides easy access to the contents of a table,
60 // one row at a time. 'Normal' access to a table is by columns, each of
61 // which contains values of the same type.
62 // A table row, by contrast, will be a collection
63 // of heterogeneous data, similar to a C struct. For
64 // this reason, the TableRow classes (ROTableRow and TableRow) are built
65 // around and provide access to the class
66 // <linkto class=TableRecord> TableRecord </linkto>.
67 // The TableRow delegates much of its behaviour to the TableRecord class.
68 // For example:
69 // <srcblock>
70 // Table table ("some.table");
71 // ROTableRow row (table); // construct TableRow object
72 // cout << row.record().description(); // show its description
73 // // Get the values in row 17.
74 // const TableRecord& record = row.get (17);
75 // // column name is "Title", and automatically becomes the record
76 // // key for this field of the record:
77 // String row17title = record.asString ("Title");
78 // Int row17count = record.asInt ("Count");
79 // </srcblock>
80 // The simplest constructor will include all columns in the TableRow object
81 // (although columns with a non-standard data type will be excluded,
82 // because they cannot be represented in a TableRecord).
83 // However, it is possible to be more selective and to include only
84 // some columns in the TableRow object. The various constructors show
85 // how this can be done.
86 // <p>
87 // It is possible to have multiple TableRow objects for the same table.
88 // They can contain different columns or they can share columns.
89 //
90 // <p>
91 // On construction an internal <linkto class=TableRecord>TableRecord</linkto>
92 // object is created containing the required fields. The contents of this
93 // record will be changed with each get call, but the structure of it is
94 // fixed. This means that <linkto class=RORecordFieldPtr>RORecordFieldPtr
95 // </linkto> objects can be constructed once and used many times.
96 // This results in potentially faster access to the record, because it avoids
97 // unnecessary name lookups.
98 // </synopsis>
99 
100 // <example>
101 // <srcblock>
102 // // Open the table as readonly and define a row object containing
103 // // the given columns.
104 // // Note that the function stringToVector is a very convenient
105 // // way to construct a Vector<String>.
106 // // Show the description of the fields in the row.
107 // Table table("Some.table");
108 // ROTableRow row (table, stringToVector("col1,col2,col3"));
109 // cout << row.record().description();
110 // // Loop through all rows and get their values.
111 // for (rownr_t i=0; i<table.nrow(); i++) {
112 // const TableRecord& values = row.get (i);
113 // someString = values.asString ("col1");
114 // somedouble = values.asdouble ("col2");
115 // someArrayInt = values.asArrayInt ("col3");
116 // }
117 //
118 // // Provided the structure of the record is known, the RecordFieldPtr
119 // // objects could be used as follows.
120 // // This is faster than the previous method, because it avoids a name
121 // // lookup for each iteration.
122 // RORecordFieldPtr<String> col1(row.record(), "col1");
123 // RORecordFieldPtr<double> col2(row.record(), "col2");
124 // RORecordFieldPtr<Array<Int> > col3(row.record(), "col3");
125 // for (rownr_t i=0; i<table.nrow(); i++) {
126 // row.get (i);
127 // someString = *col1;
128 // somedouble = *col2;
129 // someArrayInt = *col3;
130 // }
131 // </srcblock>
132 // Please note that the TableRecord& returned by the get() function is the
133 // same as returned by the record() function. Therefore the RORecordField
134 // objects can be created in advance.
135 // </example>
136 
138 {
139 public:
140  // Create a detached ROTableRow object.
141  // This means that no Table, etc. is contained in it.
142  // Function isAttached will return False for it.
143  // <br>
144  // This constructor should normally not be used, because it does not
145  // result in a valid object. It should only be used when really needed
146  // (e.g. when an array of objects has to be used).
147  ROTableRow();
148 
149  // Create a ROTableRow object for the given Table.
150  // Its TableRecord will contain all columns except columns with
151  // datatype TpOther (i.e. non-standard data types).
152  // <br>
153  // If the flag <src>storedColumnsOnly</src> is True, only the
154  // columns actually stored by a storage manager will be selected.
155  // This is useful when the contents of an entire row have to be copied.
156  // Virtual columns are calculated on-the-fly (often using stored columns),
157  // thus it makes no sense to copy their data.
158  // <note role=caution>
159  // If the table contains columns with large arrays, it may
160  // be better not to use this constructor. Each get will read in
161  // all data in the row, thus also the large data array(s).
162  // In that case it is better to use the constructor which
163  // includes selected columns only.
164  // </note>
165  explicit ROTableRow (const Table& table, Bool storedColumnsOnly = True);
166 
167  // Create a ROTableRow object for the given Table.
168  // Its TableRecord will contain all columns given in the Vector.
169  // An exception is thrown if an unknown column name is given.
170  // <br>
171  // When exclude=True, all columns except the given columns are taken.
172  // In that case an unknown name does not result in an exception.
173  ROTableRow (const Table& table, const Vector<String>& columnNames,
174  Bool exclude = False);
175 
176  // Copy constructor (copy semantics).
177  ROTableRow (const ROTableRow&);
178 
179  ~ROTableRow();
180 
181  // Assignment (copy semantics).
183 
184  // Test if a Table is attached to this object.
185  Bool isAttached() const;
186 
187  // Get the Table used for this object.
188  const Table& table() const;
189 
190  // Get the record containing all fields.
191  const TableRecord& record() const;
192 
193  // Get the number of the last row read.
194  // -1 is returned when no Table is attached or no row has been read yet.
195  Int64 rowNumber() const;
196 
197  // Get a vector consisting of all columns names.
198  // This can, for instance, be used to construct a TableRow object
199  // with the same columns in another table.
200  Vector<String> columnNames() const;
201 
202  // Get the values of all columns used from the given row.
203  // When the given row number equals the current one, nothing
204  // will be read unless the alwaysRead flag is set to True.
205  // <br>The TableRecord& returned is the same one as returned by the
206  // record() function. So one can ignore the return value of get().
207  const TableRecord& get (rownr_t rownr, Bool alwaysRead = False) const;
208 
209  // Get the block telling for each column if its value in the row
210  // was indefined in the table.
211  // Note that array values might be undefined in the table, but in
212  // the record they will be represented as empty arrays.
213  const Block<Bool>& getDefined() const;
214 
215 protected:
216  // Copy that object to this object.
217  // The writable flag determines if writable or readonly
218  // TableColumn objects will be created.
219  void copy (const ROTableRow& that);
220 
221  // Create the record, column, and field objects
222  // for all columns in the table.
223  // The writable flag determines if writable or readonly
224  // TableColumn objects will be created.
225  void create (const Table& table, Bool storedColumnsOnly, Bool writable);
226 
227  // Create the record, column, and field objects for the given columns.
228  // The writable flag determines if writable or readonly
229  // TableColumn objects will be created.
230  void create (const Table& table, const Vector<String>& columnNames,
231  Bool exclude, Bool writable);
232 
233  // Put the values found in the internal TableRecord at the given row.
234  // This is a helper function for class TableRow.
235  void putRecord (rownr_t rownr);
236 
237  // Put a value in the given field in the TableRecord into the
238  // given row and column.
239  // This is a helper function for class TableRow.
240  void putField (rownr_t rownr, const TableRecord& record,
241  Int whichColumn, Int whichField);
242 
243  // Set the switch to reread when the current row has been put.
244  void setReread (rownr_t rownr);
245 
246  //# The record of all fields.
248  //# The table used.
250  //# The following block is actually a Block<TableColumn*>.
251  //# However, using void* (and appropriate casts) saves on template
252  //# instantiations.
254  //# The following block is actually a Block<Scalar/ArrayColumn<T>>.
256  //# The following block is actually a block of RecordFieldPtr<T>*.
257  //# These are used for fast access to the record.
259  //# Block to tell if the corresponding column value is defined.
261  //# A cache for itsRecord.nfields()
263  //# The last rownr read (-1 is nothing read yet).
264  mutable Int64 itsLastRow;
265  //# A switch to indicate that the last row has to be reread.
266  //# This is the case when it has been put after being read.
267  mutable Bool itsReread;
268 
269 private:
270  // Initialize the object.
271  void init();
272 
273  // Make a RecordDesc from the table with some excluded column names.
274  void makeDescExclude (RecordDesc& description,
275  const Vector<String>& columnNames,
276  Bool writable);
277 
278  // Add a column to the record.
279  // When skipOther is True, columns with a non-standard data type
280  // will be silently skipped.
281  void addColumnToDesc (RecordDesc& description,
282  const TableColumn& column, Bool skipOther);
283 
284  // Make the required objects. These are the TableRecord and for
285  // each column a TableColumn and RecordFieldPtr.
286  void makeObjects (const RecordDesc& description);
287 
288  // Delete all objects.
289  void deleteObjects();
290 };
291 
292 
293 
294 
295 // <summary>
296 // Read/write access to a table row
297 // </summary>
298 
299 // <use visibility=export>
300 
301 // <reviewed reviewer="Paul Shannon" date="1995/05/10" tests="tTableRow.cc">
302 // </reviewed>
303 
304 // <prerequisite>
305 // <li> <linkto class=ROTableRow>ROTableRow</linkto>
306 // </prerequisite>
307 
308 // <synopsis>
309 // The class TableRow is derived from ROTableRow and as an extra it
310 // provides write-access to a row in a table.
311 // With the put function, all values in the TableRecord object will
312 // be put in the corresponding columns in the table row.
313 // There is, however, an extra consideration:
314 // <ul>
315 // <li> Constructing a TableRow object fails if the table is not
316 // writable. Non-writable columns will not be part of the object.
317 // If an explicitly given column is non-writable, the construction
318 // will also fail.
319 // </ul>
320 // There are effectively 3 ways of writing data.
321 // <ol>
322 // <li> The function
323 // <srcblock>
324 // put (rownr, tableRecord);
325 // </srcblock>
326 // can be used to put all values from the given TableRecord,
327 // which has to be conforming (i.e. matching order and names).
328 // Optionally the conformance is checked.
329 // This put function is capable of data type promotion.
330 // For instance, if column COL1 is float, the corresponding
331 // field in the TableRecord can be Int.
332 // <li> A faster way is using the functions <src>record</src>
333 // and <src>put</src>. It is possible to use <linkto class=RecordFieldPtr>
334 // RecordFieldPtr</linkto> objects to get direct access to the
335 // fields in the record (provided the structure of the record
336 // is known).
337 // E.g.
338 // <srcblock>
339 // TableRow row (someTable, stringToVector("col1,col2,col3"));
340 // RecordFieldPtr<String> col1(row.record(), "col1");
341 // RecordFieldPtr<double> col2(row.record(), "col2");
342 // RecordFieldPtr<Array<Int> > col3(row.record(), "col3");
343 // for (rownr_t i=0; i<n; i++) {
344 // *col1 = someString;
345 // *col2 = somedouble;
346 // *col3 = someArrayInt;
347 // row.put (i);
348 // }
349 // </srcblock>
350 // <li>
351 // <li> The function
352 // <srcblock>
353 // putMatchingFields (rownr, tableRecord);
354 // </srcblock>
355 // can be used to put some fields from the given TableRecord.
356 // Only fields having a corresponding name in the TableRow object
357 // will be put. Similar to the first way data type promotion will
358 // be applied for numeric values.
359 // <br>E.g.: Suppose the TableRow object has columns A, C, and B,
360 // and the given TableRecord has fields B, D, and C. Only fields B and C
361 // will be put. As the example shows, the order of the fields is not
362 // important.
363 // <br>
364 // This way is (much) slower than the other 2, because a name
365 // lookup is involved for each field. It can, however, be more
366 // convenient to use.
367 // </ol>
368 // </synopsis>
369 
370 // <example>
371 // <srcblock>
372 // // Open the new table (with 10 rows) and define a row object containing
373 // // values from the given column.
374 // // Note that the function stringToVector is a very convenient
375 // // way to construct a Vector<String>.
376 // SetupNewTable newtab(tableDesc, Table::new);
377 // Table table(newtab, 10);
378 // TableRow row (table, stringToVector("col1,col2,col3,col4"));
379 // // Loop through all rows and get their values.
380 // for (rownr_t i=0; i<table.nrow(); i++) {
381 // // Some magic filler function returns a filled TableRecord
382 // // (with the correct fields in the correct order).
383 // TableRecord record = fillerFunction();
384 // row.put (i, record);
385 // }
386 // </srcblock>
387 // </example>
388 
389 class TableRow : public ROTableRow
390 {
391 public:
392  // Create a detached TableRow object.
393  // This means that no Table, etc. is contained in it.
394  // Function isAttached (in the base class) will return False for it.
395  // <br>
396  // This constructor should normally not be used, because it does not
397  // result in a valid object. It should only be used when really needed
398  // (e.g. when an array of objects has to be used).
399  TableRow();
400 
401  // Create a TableRow object for the given Table.
402  // Its TableRecord will contain all columns except columns with
403  // datatype TpOther and columns which are not writable.
404  // <br>
405  // If the flag <src>storedColumnsOnly</src> is True, only the
406  // columns actually stored by a storage manager will be selected.
407  // This is useful when the contents of an entire row have to be copied.
408  // Virtual columns are calculated on-the-fly (often using stored columns),
409  // thus it makes no sense to copy their data.
410  // <note role=caution>
411  // If the table contains columns with large arrays, it may
412  // be better not to use this constructor. Each get will read in
413  // all data in the row, thus also the large data array(s).
414  // In that case it is better to use the next constructor which
415  // works selectively.
416  // </note>
417  explicit TableRow (const Table& table, Bool storedColumnsOnly = True);
418 
419  // Create a TableRow object for the given Table.
420  // Its TableRecord will contain all columns given in the Vector.
421  // An exception is thrown if an unknown column name is given
422  // or if a column is given which is not writable.
423  // <br>
424  // When exclude=True, all columns except the given columns are taken.
425  // In that case an unknown name does not result in an exception
426  // and non-writable columns are simply skipped.
427  TableRow (const Table& table, const Vector<String>& columnNames,
428  Bool exclude = False);
429 
430  // Copy constructor (copy semantics).
431  TableRow (const TableRow&);
432 
433  ~TableRow();
434 
435  // Assignment (copy semantics).
436  TableRow& operator= (const TableRow&);
437 
438  // Get non-const access to the TableRecord in this object.
439  // This can be used to change values in it which can thereafter
440  // be put using the function <src>put(rownr)</src>.
441  // <note> The returned TableRecord has a fixed structure, so it is
442  // not possible to add or remove fields. It is only possible
443  // to change values.
444  // </note>
445  TableRecord& record();
446 
447  // Put into the last row read.
448  // An exception is thrown if no row has been read yet.
449  // The values in the TableRecord contained in this object are put.
450  // This TableRecord can be accessed and updated using the
451  // function <src>record</src>.
452  void put();
453 
454  // Put into the given row.
455  // The values in the TableRecord contained in this object are put.
456  // This TableRecord can be accessed and updated using the
457  // function <src>record</src>.
458  void put (rownr_t rownr);
459 
460  // Put the values found in the TableRecord in the appropriate columns
461  // in the given row.
462  // The names and order of the fields in the TableRecord must conform
463  // those of the description of the TableRow. The data types of numeric
464  // values do not need to conform exactly; they can be promoted
465  // (e.g. an Int value in the record may correspond to a float column).
466  // If not conforming, an exception is thrown.
467  // <note> For performance reasons it is optional to check
468  // the name order conformance.
469  // </note>
470  // The <src>valuesDefined</src> block tells if the value in the
471  // corresponding field in the record is actually defined.
472  // If not, nothing will be written.
473  // It is meant for array values which might be undefined in a table.
474  // <group>
475  void put (rownr_t rownr, const TableRecord& record,
476  Bool checkConformance = True);
477  void put (rownr_t rownr, const TableRecord& record,
478  const Block<Bool>& valuesDefined,
479  Bool checkConformance = True);
480  // </group>
481 
482  // Put the values found in the TableRecord. Only fields with a matching
483  // name in the TableRow object will be put.
484  // This makes it possible to put fields in a selective way.
485  // <br>E.g.: If the TableRow contains columns A and B, and the
486  // record contains fields B and C, only field B will be put.
487  // <br>In principle the data types of the matching fields must match,
488  // but data type promotion of numeric values will be applied.
489  void putMatchingFields (rownr_t rownr, const TableRecord& record);
490 
491 private:
492  // Check if the names of the given record match this row.
493  Bool namesConform (const TableRecord& that) const;
494 };
495 
496 
498 {
499  return (itsRecord != 0);
500 }
501 inline const Table& ROTableRow::table() const
502 {
503  return itsTable;
504 }
506 {
507  return itsLastRow;
508 }
509 inline const TableRecord& ROTableRow::record() const
510 {
511  return *itsRecord;
512 }
513 inline const Block<Bool>& ROTableRow::getDefined() const
514 {
515  return itsDefined;
516 }
518 {
519  return *itsRecord;
520 }
521 inline void TableRow::put (rownr_t rownr)
522 {
523  putRecord (rownr);
524 }
525 
526 
527 
528 } //# NAMESPACE CASACORE - END
529 
530 #endif
Vector< String > columnNames() const
Get a vector consisting of all columns names.
A 1-D Specialization of the Array class.
Definition: ArrayFwd.h:9
long long Int64
Define the extra non-standard types used by Casacore (like proposed uSize, Size)
Definition: aipsxtype.h:38
int Int
Definition: aipstype.h:50
Block< void * > itsFields
Definition: TableRow.h:258
Main interface class to a read/write table.
Definition: Table.h:157
ROTableRow & operator=(const ROTableRow &)
Assignment (copy semantics).
Block< void * > itsColumns
Definition: TableRow.h:255
void setReread(rownr_t rownr)
Set the switch to reread when the current row has been put.
TableRecord & record()
Get non-const access to the TableRecord in this object.
Definition: TableRow.h:517
Read/write access to a table row.
Definition: TableRow.h:389
Block< Bool > itsDefined
Definition: TableRow.h:260
void addColumnToDesc(RecordDesc &description, const TableColumn &column, Bool skipOther)
Add a column to the record.
Bool namesConform(const TableRecord &that) const
Check if the names of the given record match this row.
void putMatchingFields(rownr_t rownr, const TableRecord &record)
Put the values found in the TableRecord.
Bool isAttached() const
Test if a Table is attached to this object.
Definition: TableRow.h:497
void copy(const ROTableRow &that)
Copy that object to this object.
void deleteObjects()
Delete all objects.
Int64 rowNumber() const
Get the number of the last row read.
Definition: TableRow.h:505
void makeDescExclude(RecordDesc &description, const Vector< String > &columnNames, Bool writable)
Make a RecordDesc from the table with some excluded column names.
Description of the fields in a record object.
Definition: RecordDesc.h:105
Readonly access to a table row.
Definition: TableRow.h:137
void create(const Table &table, Bool storedColumnsOnly, Bool writable)
Create the record, column, and field objects for all columns in the table.
bool Bool
Define the standard types used by Casacore.
Definition: aipstype.h:42
TableRow()
Create a detached TableRow object.
Read/write access to a table column.
Definition: TableColumn.h:98
const Bool False
Definition: aipstype.h:44
A hierarchical collection of named fields of various types.
Definition: TableRecord.h:185
TableRecord * itsRecord
Definition: TableRow.h:247
const TableRecord & record() const
Get the record containing all fields.
Definition: TableRow.h:509
uInt64 rownr_t
Define the type of a row number in a table.
Definition: aipsxtype.h:46
const Table & table() const
Get the Table used for this object.
Definition: TableRow.h:501
void putRecord(rownr_t rownr)
Put the values found in the internal TableRecord at the given row.
Block< void * > itsTabCols
Definition: TableRow.h:253
ROTableRow()
Create a detached ROTableRow object.
void putField(rownr_t rownr, const TableRecord &record, Int whichColumn, Int whichField)
Put a value in the given field in the TableRecord into the given row and column.
void init()
Initialize the object.
void put()
Put into the last row read.
void makeObjects(const RecordDesc &description)
Make the required objects.
const Bool True
Definition: aipstype.h:43
unsigned int uInt
Definition: aipstype.h:51
TableRow & operator=(const TableRow &)
Assignment (copy semantics).
const Block< Bool > & getDefined() const
Get the block telling for each column if its value in the row was indefined in the table...
Definition: TableRow.h:513