casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
TableRow.h
Go to the documentation of this file.
00001 //# TableRow.h: Access to a table row
00002 //# Copyright (C) 1996,1999,2001
00003 //# Associated Universities, Inc. Washington DC, USA.
00004 //#
00005 //# This library is free software; you can redistribute it and/or modify it
00006 //# under the terms of the GNU Library General Public License as published by
00007 //# the Free Software Foundation; either version 2 of the License, or (at your
00008 //# option) any later version.
00009 //#
00010 //# This library is distributed in the hope that it will be useful, but WITHOUT
00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013 //# License for more details.
00014 //#
00015 //# You should have received a copy of the GNU Library General Public License
00016 //# along with this library; if not, write to the Free Software Foundation,
00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00018 //#
00019 //# Correspondence concerning AIPS++ should be addressed as follows:
00020 //#        Internet email: aips2-request@nrao.edu.
00021 //#        Postal address: AIPS++ Project Office
00022 //#                        National Radio Astronomy Observatory
00023 //#                        520 Edgemont Road
00024 //#                        Charlottesville, VA 22903-2475 USA
00025 //#
00026 //# $Id: TableRow.h 21298 2012-12-07 14:53:03Z gervandiepen $
00027 
00028 #ifndef TABLES_TABLEROW_H
00029 #define TABLES_TABLEROW_H
00030 
00031 //# Includes
00032 #include <casa/aips.h>
00033 #include <tables/Tables/Table.h>
00034 #include <tables/Tables/TableRecord.h>
00035 #include <casa/Containers/Block.h>
00036 #include <casa/BasicSL/String.h>
00037 
00038 namespace casa { //# NAMESPACE CASA - BEGIN
00039 
00040 //# Forward Declarations
00041 class TableColumn;
00042 template<class T> class Vector;
00043 
00044 
00045 // <summary>
00046 // Readonly access to a table row
00047 // </summary>
00048 
00049 // <use visibility=export>
00050 
00051 // <reviewed reviewer="Paul Shannon" date="1996/05/10" tests="tTableRow.cc">
00052 // </reviewed>
00053 
00054 // <prerequisite>
00055 //   <li> <linkto class=Table>Table</linkto>
00056 //   <li> <linkto class=TableRecord>TableRecord</linkto>
00057 // </prerequisite>
00058 
00059 // <synopsis>
00060 // This class provides easy access to the contents of a table,
00061 // one row at a time. 'Normal' access to a table is by columns, each of
00062 // which contains values of the same type.
00063 // A table row, by contrast, will be a collection
00064 // of heterogeneous data, similar to a C struct. For
00065 // this reason, the TableRow classes (ROTableRow and TableRow) are built
00066 // around and provide access to the class
00067 // <linkto class=TableRecord> TableRecord </linkto>.
00068 // The TableRow delegates much of its behaviour to the TableRecord class.
00069 // For example: 
00070 // <srcblock>
00071 //   Table table ("some.table");
00072 //   ROTableRow row (table);                 // construct TableRow object
00073 //   cout << row.record().description();     // show its description
00074 //   // Get the values in row 17.
00075 //   const TableRecord& record = row.get (17);
00076 //   // column name is "Title", and automatically becomes the record
00077 //   // key for this field of the record:
00078 //   String row17title = record.asString ("Title");  
00079 //   Int    row17count = record.asInt ("Count");
00080 // </srcblock>
00081 // The simplest constructor will include all columns in the TableRow object
00082 // (although columns with a non-standard data type will be excluded,
00083 // because they cannot be represented in a TableRecord).
00084 // However, it is possible to be more selective and to include only
00085 // some columns in the TableRow object. The various constructors show
00086 // how this can be done.
00087 // <p>
00088 // It is possible to have multiple TableRow objects for the same table.
00089 // They can contain different columns or they can share columns.
00090 // 
00091 // <p>
00092 // On construction an internal <linkto class=TableRecord>TableRecord</linkto>
00093 // object is created containing the required fields. The contents of this
00094 // record will be changed with each get call, but the structure of it is
00095 // fixed. This means that <linkto class=RORecordFieldPtr>RORecordFieldPtr
00096 // </linkto> objects can be constructed once and used many times.
00097 // This results in potentially faster access to the record, because it avoids
00098 // unnecessary name lookups.
00099 // </synopsis>
00100 
00101 // <example>
00102 // <srcblock>
00103 // // Open the table as readonly and define a row object containing
00104 // // the given columns.
00105 // // Note that the function stringToVector is a very convenient
00106 // // way to construct a Vector<String>.
00107 // // Show the description of the fields in the row.
00108 // Table table("Some.table");
00109 // ROTableRow row (table, stringToVector("col1,col2,col3"));
00110 // cout << row.record().description();
00111 // // Loop through all rows and get their values.
00112 // for (uInt i=0; i<table.nrow(); i++) {
00113 //     const TableRecord& values = row.get (i);
00114 //     someString = values.asString ("col1");
00115 //     somedouble = values.asdouble ("col2");
00116 //     someArrayInt = values.asArrayInt ("col3");
00117 // }
00118 //
00119 // // Provided the structure of the record is known, the RecordFieldPtr
00120 // // objects could be used as follows.
00121 // // This is faster than the previous method, because it avoids a name
00122 // // lookup for each iteration.
00123 // RORecordFieldPtr<String> col1(row.record(), "col1");
00124 // RORecordFieldPtr<double> col2(row.record(), "col2");
00125 // RORecordFieldPtr<Array<Int> > col3(row.record(), "col3");
00126 // for (uInt i=0; i<table.nrow(); i++) {
00127 //     row.get (i);
00128 //     someString = *col1;
00129 //     somedouble = *col2;
00130 //     someArrayInt = *col3;
00131 // }
00132 // </srcblock>
00133 // Please note that the TableRecord& returned by the get() function is the
00134 // same as returned by the record() function. Therefore the RORecordField
00135 // objects can be created in advance.
00136 // </example>
00137 
00138 class ROTableRow
00139 {
00140 public:
00141     // Create a detached ROTableRow object.
00142     // This means that no Table, etc. is contained in it.
00143     // Function isAttached will return False for it.
00144     // <br>
00145     // This constructor should normally not be used, because it does not
00146     // result in a valid object. It should only be used when really needed
00147     // (e.g. when an array of objects has to be used).
00148     ROTableRow();
00149 
00150     // Create a ROTableRow object for the given Table.
00151     // Its TableRecord will contain all columns except columns with
00152     // datatype TpOther (i.e. non-standard data types).
00153     // <br>
00154     // If the flag <src>storedColumnsOnly</src> is True, only the
00155     // columns actually stored by a storage manager will be selected.
00156     // This is useful when the contents of an entire row have to be copied.
00157     // Virtual columns are calculated on-the-fly (often using stored columns),
00158     // thus it makes no sense to copy their data.
00159     // <note role=caution>
00160     //  If the table contains columns with large arrays, it may
00161     //  be better not to use this constructor. Each get will read in
00162     //  all data in the row, thus also the large data array(s).
00163     //  In that case it is better to use the constructor which
00164     //  includes selected columns only.
00165     // </note>
00166     explicit ROTableRow (const Table& table, Bool storedColumnsOnly = True);
00167 
00168     // Create a ROTableRow object for the given Table.
00169     // Its TableRecord will contain all columns given in the Vector.
00170     // An exception is thrown if an unknown column name is given.
00171     // <br>
00172     // When exclude=True, all columns except the given columns are taken.
00173     // In that case an unknown name does not result in an exception.
00174     ROTableRow (const Table& table, const Vector<String>& columnNames,
00175                 Bool exclude = False);
00176 
00177     // Copy constructor (copy semantics).
00178     ROTableRow (const ROTableRow&);
00179 
00180     ~ROTableRow();
00181 
00182     // Assignment (copy semantics).
00183     ROTableRow& operator= (const ROTableRow&);
00184 
00185     // Test if a Table is attached to this object.
00186     Bool isAttached() const;
00187 
00188     // Get the Table used for this object.
00189     const Table& table() const;
00190 
00191     // Get the record containing all fields.
00192     const TableRecord& record() const;
00193 
00194     // Get the number of the last row read.
00195     // -1 is returned when no Table is attached or no row has been read yet.
00196     Int rowNumber() const;
00197 
00198     // Get a vector consisting of all columns names.
00199     // This can, for instance, be used to construct a TableRow object
00200     // with the same columns in another table.
00201     Vector<String> columnNames() const;
00202 
00203     // Get the values of all columns used from the given row.
00204     // When the given row number equals the current one, nothing
00205     // will be read unless the alwaysRead flag is set to True.
00206     // <br>The TableRecord& returned is the same one as returned by the
00207     // record() function. So one can ignore the return value of get().
00208     const TableRecord& get (uInt rownr, Bool alwaysRead = False) const;
00209 
00210     // Get the block telling for each column if its value in the row
00211     // was indefined in the table.
00212     // Note that array values might be undefined in the table, but in
00213     // the record they will be represented as empty arrays.
00214     const Block<Bool>& getDefined() const;
00215 
00216 protected:
00217     // Copy that object to this object.
00218     // The writable flag determines if writable or readonly
00219     // TableColumn objects will be created.
00220     void copy (const ROTableRow& that);
00221 
00222     // Create the record, column, and field objects
00223     // for all columns in the table.
00224     // The writable flag determines if writable or readonly
00225     // TableColumn objects will be created.
00226     void create (const Table& table, Bool storedColumnsOnly, Bool writable);
00227 
00228     // Create the record, column, and field objects for the given columns.
00229     // The writable flag determines if writable or readonly
00230     // TableColumn objects will be created.
00231     void create (const Table& table, const Vector<String>& columnNames,
00232                  Bool exclude, Bool writable);
00233 
00234     // Put the values found in the internal TableRecord at the given row.
00235     // This is a helper function for class TableRow.
00236     void putRecord (uInt rownr);
00237 
00238     // Put a value in the given field in the TableRecord into the
00239     // given row and column.
00240     // This is a helper function for class TableRow.
00241     void putField (uInt rownr, const TableRecord& record,
00242                    Int whichColumn, Int whichField);
00243 
00244     // Set the switch to reread when the current row has been put.
00245     void setReread (uInt rownr);
00246 
00247     //# The record of all fields.
00248     TableRecord* itsRecord;
00249     //# The table used.
00250     Table        itsTable;
00251     //# The following block is actually a Block<TableColumn*>.
00252     //# However, using void* (and appropriate casts) saves on template
00253     //# instantiations.
00254     Block<void*> itsTabCols;
00255     //# The following block is actually a Block<Scalar/ArrayColumn<T>>.
00256     Block<void*> itsColumns;
00257     //# The following block is actually a block of RecordFieldPtr<T>*.
00258     //# These are used for fast access to the record.
00259     Block<void*> itsFields;
00260     //# Block to tell if the corresponding column value is defined.
00261     mutable Block<Bool> itsDefined;
00262     //# A cache for itsRecord.nfields()
00263     uInt         itsNrused;
00264     //# The last rownr read (-1 is nothing read yet).
00265     //# This is via a pointer to keep the get function const.
00266     Int*         itsLastRow;
00267     //# A switch to indicate that the last row has to be reread.
00268     //# This is the case when it has been put after being read.
00269     Bool*        itsReread;
00270 
00271 private:
00272     // Initialize the object.
00273     void init();
00274 
00275     // Make a RecordDesc from the table with some excluded column names.
00276     void makeDescExclude (RecordDesc& description,
00277                           const Vector<String>& columnNames,
00278                           Bool writable);
00279 
00280     // Add a column to the record.
00281     // When skipOther is True, columns with a non-standard data type
00282     // will be silently skipped.
00283     void addColumnToDesc (RecordDesc& description,
00284                           const TableColumn& column, Bool skipOther);
00285 
00286     // Make the required objects. These are the TableRecord and for
00287     // each column a TableColumn and RecordFieldPtr.
00288     void makeObjects (const RecordDesc& description);
00289 
00290     // Delete all objects.
00291     void deleteObjects();
00292 };
00293 
00294 
00295 
00296 
00297 // <summary>
00298 // Read/write access to a table row
00299 // </summary>
00300 
00301 // <use visibility=export>
00302 
00303 // <reviewed reviewer="Paul Shannon" date="1995/05/10" tests="tTableRow.cc">
00304 // </reviewed>
00305 
00306 // <prerequisite>
00307 //   <li> <linkto class=ROTableRow>ROTableRow</linkto>
00308 // </prerequisite>
00309 
00310 // <synopsis>
00311 // The class TableRow is derived from ROTableRow and as an extra it
00312 // provides write-access to a row in a table.
00313 // With the put function, all values in the TableRecord object will
00314 // be put in the corresponding columns in the table row.
00315 // There is, however, an extra consideration:
00316 // <ul>
00317 // <li> Constructing a TableRow object fails if the table is not
00318 //      writable. Non-writable columns will not be part of the object.
00319 //      If an explicitly given column is non-writable, the construction
00320 //      will also fail.
00321 // </ul>
00322 // There are effectively 3 ways of writing data.
00323 // <ol>
00324 // <li> The function
00325 //      <srcblock>
00326 //          put (rownr, tableRecord);
00327 //      </srcblock>
00328 //      can be used to put all values from the given TableRecord,
00329 //      which has to be conforming (i.e. matching order and names).
00330 //      Optionally the conformance is checked.
00331 //      This put function is capable of data type promotion.
00332 //      For instance, if column COL1 is float, the corresponding
00333 //      field in the TableRecord can be Int.
00334 // <li> A faster way is using the functions <src>record</src>
00335 //      and <src>put</src>. It is possible to use <linkto class=RecordFieldPtr>
00336 //      RecordFieldPtr</linkto> objects to get direct access to the
00337 //      fields in the record (provided the structure of the record
00338 //      is known).
00339 //      E.g.
00340 //      <srcblock>
00341 //         TableRow row (someTable, stringToVector("col1,col2,col3"));
00342 //         RecordFieldPtr<String> col1(row.record(), "col1");
00343 //         RecordFieldPtr<double> col2(row.record(), "col2");
00344 //         RecordFieldPtr<Array<Int> > col3(row.record(), "col3");
00345 //         for (uInt i=0; i<n; i++) {
00346 //             *col1 = someString;
00347 //             *col2 = somedouble;
00348 //             *col3 = someArrayInt;
00349 //             row.put (i);
00350 //         }
00351 //      </srcblock>
00352 // <li>
00353 // <li> The function
00354 //      <srcblock>
00355 //          putMatchingFields (rownr, tableRecord);
00356 //      </srcblock>
00357 //      can be used to put some fields from the given TableRecord.
00358 //      Only fields having a corresponding name in the TableRow object
00359 //      will be put. Similar to the first way data type promotion will
00360 //      be applied for numeric scalars.
00361 //      <br>E.g.: Suppose the TableRow object has columns A, C, and B,
00362 //      and the given TableRecord has fields B, D, and C. Only fields B and C
00363 //      will be put. As the example shows, the order of the fields is not
00364 //      important.
00365 //      <br>
00366 //      This way is (much) slower than the other 2, because a name
00367 //      lookup is involved for each field. It can, however, be more
00368 //      convenient to use.
00369 // </ol>
00370 // </synopsis>
00371 
00372 // <example>
00373 // <srcblock>
00374 // // Open the new table (with 10 rows) and define a row object containing
00375 // // values from the given column.
00376 // // Note that the function stringToVector is a very convenient
00377 // // way to construct a Vector<String>.
00378 // SetupNewTable newtab(tableDesc, Table::new);
00379 // Table table(newtab, 10);
00380 // TableRow row (table, stringToVector("col1,col2,col3,col4"));
00381 // // Loop through all rows and get their values.
00382 // for (uInt i=0; i<table.nrow(); i++) {
00383 //     // Some magic filler function returns a filled TableRecord
00384 //     // (with the correct fields in the correct order).
00385 //     TableRecord record = fillerFunction();
00386 //     row.put (i, record);
00387 // }
00388 // </srcblock>
00389 // </example>
00390 
00391 class TableRow : public ROTableRow
00392 {
00393 public:
00394     // Create a detached TableRow object.
00395     // This means that no Table, etc. is contained in it.
00396     // Function isAttached (in the base class) will return False for it.
00397     // <br>
00398     // This constructor should normally not be used, because it does not
00399     // result in a valid object. It should only be used when really needed
00400     // (e.g. when an array of objects has to be used).
00401     TableRow();
00402 
00403     // Create a TableRow object for the given Table.
00404     // Its TableRecord will contain all columns except columns with
00405     // datatype TpOther and columns which are not writable.
00406     // <br>
00407     // If the flag <src>storedColumnsOnly</src> is True, only the
00408     // columns actually stored by a storage manager will be selected.
00409     // This is useful when the contents of an entire row have to be copied.
00410     // Virtual columns are calculated on-the-fly (often using stored columns),
00411     // thus it makes no sense to copy their data.
00412     // <note role=caution>
00413     //  If the table contains columns with large arrays, it may
00414     //  be better not to use this constructor. Each get will read in
00415     //  all data in the row, thus also the large data array(s).
00416     //  In that case it is better to use the next constructor which
00417     //  works selectively.
00418     // </note>
00419     explicit TableRow (const Table& table, Bool storedColumnsOnly = True);
00420 
00421     // Create a TableRow object for the given Table.
00422     // Its TableRecord will contain all columns given in the Vector.
00423     // An exception is thrown if an unknown column name is given
00424     // or if a column is given which is not writable.
00425     // <br>
00426     // When exclude=True, all columns except the given columns are taken.
00427     // In that case an unknown name does not result in an exception
00428     // and non-writable columns are simply skipped.
00429     TableRow (const Table& table, const Vector<String>& columnNames,
00430               Bool exclude = False);
00431 
00432     // Copy constructor (copy semantics).
00433     TableRow (const TableRow&);
00434 
00435     ~TableRow();
00436 
00437     // Assignment (copy semantics).
00438     TableRow& operator= (const TableRow&);
00439 
00440     // Get non-const access to the TableRecord in this object.
00441     // This can be used to change values in it which can thereafter
00442     // be put using the function <src>put(rownr)</src>.
00443     // <note> The returned TableRecord has a fixed structure, so it is
00444     //        not possible to add or remove fields. It is only possible
00445     //        to change values.
00446     // </note>
00447     TableRecord& record();
00448 
00449     // Put into the last row read.
00450     // An exception is thrown if no row has been read yet.
00451     // The values in the TableRecord contained in this object are put.
00452     // This TableRecord can be accessed and updated using the
00453     // function <src>record</src>.
00454     void put();
00455 
00456     // Put into the given row.
00457     // The values in the TableRecord contained in this object are put.
00458     // This TableRecord can be accessed and updated using the
00459     // function <src>record</src>.
00460     void put (uInt rownr);
00461 
00462     // Put the values found in the TableRecord in the appropriate columns
00463     // in the given row.
00464     // The names and order of the fields in the TableRecord must conform
00465     // those of the description of the TableRow. The data types of numeric
00466     // scalars do not need to conform exactly; they can be promoted
00467     // (e.g. an Int value in the record may correspond to a float column).
00468     // If not conforming, an exception is thrown.
00469     // <note> For performance reasons it is optional to check
00470     //        the name order conformance.
00471     // </note>
00472     // The <src>valuesDefined</src> block tells if the value in the
00473     // corresponding field in the record is actually defined.
00474     // If not, nothing will be written.
00475     // It is meant for array values which might be undefined in a table.
00476     // <group>
00477     void put (uInt rownr, const TableRecord& record,
00478               Bool checkConformance = True);
00479     void put (uInt rownr, const TableRecord& record,
00480               const Block<Bool>& valuesDefined,
00481               Bool checkConformance = True);
00482     // </group>
00483 
00484     // Put the values found in the TableRecord. Only fields with a matching
00485     // name in the TableRow object will be put.
00486     // This makes it possible to put fields in a selective way.
00487     // <br>E.g.: If the TableRow contains columns A and B, and the
00488     // record contains fields B and C, only field B will be put.
00489     // <br>In principle the data types of the matching fields must match,
00490     // but data type promotion of numeric scalars will be applied.
00491     void putMatchingFields (uInt rownr, const TableRecord& record);
00492 
00493 private:
00494     // Check if the names of the given record match this row.
00495     Bool namesConform (const TableRecord& that) const;
00496 };
00497 
00498 
00499 inline Bool ROTableRow::isAttached() const
00500 {
00501     return  (itsRecord != 0);
00502 }
00503 inline const Table& ROTableRow::table() const
00504 {
00505     return itsTable;
00506 }
00507 inline Int ROTableRow::rowNumber() const
00508 {
00509     return *itsLastRow;
00510 }
00511 inline const TableRecord& ROTableRow::record() const
00512 {
00513     return *itsRecord;
00514 }
00515 inline const Block<Bool>& ROTableRow::getDefined() const
00516 {
00517     return itsDefined;
00518 }
00519 inline TableRecord& TableRow::record()
00520 {
00521     return *itsRecord;
00522 }
00523 inline void TableRow::put (uInt rownr)
00524 {
00525     putRecord (rownr);
00526 }
00527 
00528 
00529 
00530 } //# NAMESPACE CASA - END
00531 
00532 #endif