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$ 00027 00028 #ifndef TABLES_TABLEROW_H 00029 #define TABLES_TABLEROW_H 00030 00031 //# Includes 00032 #include <casacore/casa/aips.h> 00033 #include <casacore/tables/Tables/Table.h> 00034 #include <casacore/tables/Tables/TableRecord.h> 00035 #include <casacore/casa/Containers/Block.h> 00036 #include <casacore/casa/BasicSL/String.h> 00037 00038 namespace casacore { //# NAMESPACE CASACORE - 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 Int64 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 mutable Int64 itsLastRow; 00266 //# A switch to indicate that the last row has to be reread. 00267 //# This is the case when it has been put after being read. 00268 mutable Bool itsReread; 00269 00270 private: 00271 // Initialize the object. 00272 void init(); 00273 00274 // Make a RecordDesc from the table with some excluded column names. 00275 void makeDescExclude (RecordDesc& description, 00276 const Vector<String>& columnNames, 00277 Bool writable); 00278 00279 // Add a column to the record. 00280 // When skipOther is True, columns with a non-standard data type 00281 // will be silently skipped. 00282 void addColumnToDesc (RecordDesc& description, 00283 const TableColumn& column, Bool skipOther); 00284 00285 // Make the required objects. These are the TableRecord and for 00286 // each column a TableColumn and RecordFieldPtr. 00287 void makeObjects (const RecordDesc& description); 00288 00289 // Delete all objects. 00290 void deleteObjects(); 00291 }; 00292 00293 00294 00295 00296 // <summary> 00297 // Read/write access to a table row 00298 // </summary> 00299 00300 // <use visibility=export> 00301 00302 // <reviewed reviewer="Paul Shannon" date="1995/05/10" tests="tTableRow.cc"> 00303 // </reviewed> 00304 00305 // <prerequisite> 00306 // <li> <linkto class=ROTableRow>ROTableRow</linkto> 00307 // </prerequisite> 00308 00309 // <synopsis> 00310 // The class TableRow is derived from ROTableRow and as an extra it 00311 // provides write-access to a row in a table. 00312 // With the put function, all values in the TableRecord object will 00313 // be put in the corresponding columns in the table row. 00314 // There is, however, an extra consideration: 00315 // <ul> 00316 // <li> Constructing a TableRow object fails if the table is not 00317 // writable. Non-writable columns will not be part of the object. 00318 // If an explicitly given column is non-writable, the construction 00319 // will also fail. 00320 // </ul> 00321 // There are effectively 3 ways of writing data. 00322 // <ol> 00323 // <li> The function 00324 // <srcblock> 00325 // put (rownr, tableRecord); 00326 // </srcblock> 00327 // can be used to put all values from the given TableRecord, 00328 // which has to be conforming (i.e. matching order and names). 00329 // Optionally the conformance is checked. 00330 // This put function is capable of data type promotion. 00331 // For instance, if column COL1 is float, the corresponding 00332 // field in the TableRecord can be Int. 00333 // <li> A faster way is using the functions <src>record</src> 00334 // and <src>put</src>. It is possible to use <linkto class=RecordFieldPtr> 00335 // RecordFieldPtr</linkto> objects to get direct access to the 00336 // fields in the record (provided the structure of the record 00337 // is known). 00338 // E.g. 00339 // <srcblock> 00340 // TableRow row (someTable, stringToVector("col1,col2,col3")); 00341 // RecordFieldPtr<String> col1(row.record(), "col1"); 00342 // RecordFieldPtr<double> col2(row.record(), "col2"); 00343 // RecordFieldPtr<Array<Int> > col3(row.record(), "col3"); 00344 // for (uInt i=0; i<n; i++) { 00345 // *col1 = someString; 00346 // *col2 = somedouble; 00347 // *col3 = someArrayInt; 00348 // row.put (i); 00349 // } 00350 // </srcblock> 00351 // <li> 00352 // <li> The function 00353 // <srcblock> 00354 // putMatchingFields (rownr, tableRecord); 00355 // </srcblock> 00356 // can be used to put some fields from the given TableRecord. 00357 // Only fields having a corresponding name in the TableRow object 00358 // will be put. Similar to the first way data type promotion will 00359 // be applied for numeric values. 00360 // <br>E.g.: Suppose the TableRow object has columns A, C, and B, 00361 // and the given TableRecord has fields B, D, and C. Only fields B and C 00362 // will be put. As the example shows, the order of the fields is not 00363 // important. 00364 // <br> 00365 // This way is (much) slower than the other 2, because a name 00366 // lookup is involved for each field. It can, however, be more 00367 // convenient to use. 00368 // </ol> 00369 // </synopsis> 00370 00371 // <example> 00372 // <srcblock> 00373 // // Open the new table (with 10 rows) and define a row object containing 00374 // // values from the given column. 00375 // // Note that the function stringToVector is a very convenient 00376 // // way to construct a Vector<String>. 00377 // SetupNewTable newtab(tableDesc, Table::new); 00378 // Table table(newtab, 10); 00379 // TableRow row (table, stringToVector("col1,col2,col3,col4")); 00380 // // Loop through all rows and get their values. 00381 // for (uInt i=0; i<table.nrow(); i++) { 00382 // // Some magic filler function returns a filled TableRecord 00383 // // (with the correct fields in the correct order). 00384 // TableRecord record = fillerFunction(); 00385 // row.put (i, record); 00386 // } 00387 // </srcblock> 00388 // </example> 00389 00390 class TableRow : public ROTableRow 00391 { 00392 public: 00393 // Create a detached TableRow object. 00394 // This means that no Table, etc. is contained in it. 00395 // Function isAttached (in the base class) will return False for it. 00396 // <br> 00397 // This constructor should normally not be used, because it does not 00398 // result in a valid object. It should only be used when really needed 00399 // (e.g. when an array of objects has to be used). 00400 TableRow(); 00401 00402 // Create a TableRow object for the given Table. 00403 // Its TableRecord will contain all columns except columns with 00404 // datatype TpOther and columns which are not writable. 00405 // <br> 00406 // If the flag <src>storedColumnsOnly</src> is True, only the 00407 // columns actually stored by a storage manager will be selected. 00408 // This is useful when the contents of an entire row have to be copied. 00409 // Virtual columns are calculated on-the-fly (often using stored columns), 00410 // thus it makes no sense to copy their data. 00411 // <note role=caution> 00412 // If the table contains columns with large arrays, it may 00413 // be better not to use this constructor. Each get will read in 00414 // all data in the row, thus also the large data array(s). 00415 // In that case it is better to use the next constructor which 00416 // works selectively. 00417 // </note> 00418 explicit TableRow (const Table& table, Bool storedColumnsOnly = True); 00419 00420 // Create a TableRow object for the given Table. 00421 // Its TableRecord will contain all columns given in the Vector. 00422 // An exception is thrown if an unknown column name is given 00423 // or if a column is given which is not writable. 00424 // <br> 00425 // When exclude=True, all columns except the given columns are taken. 00426 // In that case an unknown name does not result in an exception 00427 // and non-writable columns are simply skipped. 00428 TableRow (const Table& table, const Vector<String>& columnNames, 00429 Bool exclude = False); 00430 00431 // Copy constructor (copy semantics). 00432 TableRow (const TableRow&); 00433 00434 ~TableRow(); 00435 00436 // Assignment (copy semantics). 00437 TableRow& operator= (const TableRow&); 00438 00439 // Get non-const access to the TableRecord in this object. 00440 // This can be used to change values in it which can thereafter 00441 // be put using the function <src>put(rownr)</src>. 00442 // <note> The returned TableRecord has a fixed structure, so it is 00443 // not possible to add or remove fields. It is only possible 00444 // to change values. 00445 // </note> 00446 TableRecord& record(); 00447 00448 // Put into the last row read. 00449 // An exception is thrown if no row has been read yet. 00450 // The values in the TableRecord contained in this object are put. 00451 // This TableRecord can be accessed and updated using the 00452 // function <src>record</src>. 00453 void put(); 00454 00455 // Put into the given row. 00456 // The values in the TableRecord contained in this object are put. 00457 // This TableRecord can be accessed and updated using the 00458 // function <src>record</src>. 00459 void put (uInt rownr); 00460 00461 // Put the values found in the TableRecord in the appropriate columns 00462 // in the given row. 00463 // The names and order of the fields in the TableRecord must conform 00464 // those of the description of the TableRow. The data types of numeric 00465 // values do not need to conform exactly; they can be promoted 00466 // (e.g. an Int value in the record may correspond to a float column). 00467 // If not conforming, an exception is thrown. 00468 // <note> For performance reasons it is optional to check 00469 // the name order conformance. 00470 // </note> 00471 // The <src>valuesDefined</src> block tells if the value in the 00472 // corresponding field in the record is actually defined. 00473 // If not, nothing will be written. 00474 // It is meant for array values which might be undefined in a table. 00475 // <group> 00476 void put (uInt rownr, const TableRecord& record, 00477 Bool checkConformance = True); 00478 void put (uInt rownr, const TableRecord& record, 00479 const Block<Bool>& valuesDefined, 00480 Bool checkConformance = True); 00481 // </group> 00482 00483 // Put the values found in the TableRecord. Only fields with a matching 00484 // name in the TableRow object will be put. 00485 // This makes it possible to put fields in a selective way. 00486 // <br>E.g.: If the TableRow contains columns A and B, and the 00487 // record contains fields B and C, only field B will be put. 00488 // <br>In principle the data types of the matching fields must match, 00489 // but data type promotion of numeric values will be applied. 00490 void putMatchingFields (uInt rownr, const TableRecord& record); 00491 00492 private: 00493 // Check if the names of the given record match this row. 00494 Bool namesConform (const TableRecord& that) const; 00495 }; 00496 00497 00498 inline Bool ROTableRow::isAttached() const 00499 { 00500 return (itsRecord != 0); 00501 } 00502 inline const Table& ROTableRow::table() const 00503 { 00504 return itsTable; 00505 } 00506 inline Int64 ROTableRow::rowNumber() const 00507 { 00508 return itsLastRow; 00509 } 00510 inline const TableRecord& ROTableRow::record() const 00511 { 00512 return *itsRecord; 00513 } 00514 inline const Block<Bool>& ROTableRow::getDefined() const 00515 { 00516 return itsDefined; 00517 } 00518 inline TableRecord& TableRow::record() 00519 { 00520 return *itsRecord; 00521 } 00522 inline void TableRow::put (uInt rownr) 00523 { 00524 putRecord (rownr); 00525 } 00526 00527 00528 00529 } //# NAMESPACE CASACORE - END 00530 00531 #endif