The structure of a TableRecord is defined by the
RecordDesc class.
The structure of the TableRecord can be defined at
construction time. It can thereafter be restructured. This has the
effect, however, that any existing RecordFieldPtr objects become
invalid (using the Notice classes).
It is possible to add or remove fields once a TableRecord is constructed.
However, this is not possible when the TableRecord is constructed with a
fixed structure (i.e. with the fixedStructure flag set).
A TableRecord is an hierarchical structure, because it can have fields containing TableRecord's (as layed out in the RecordDesc). A subrecord has a variable structure, when its RecordDesc is empty (i.e. contains no fields). It is fixed when its RecordDesc contains fields.
A TableRecord may be assigned to another only if they conform; that is if
their fields have the identical type in the identical order.
The field names do not need to be identical however, only the types.
That is, the structure needs to be identical, but
not the labels. Note that field order is significant,
[ifield(type=Int),ffield(type=Float)]
is not the same as [ffield(type=Float),ifield(type=Int)]
Conformance is checked recursively for fixed subrecords. That is, a
variable structured subrecord is not checked, because any record
can be assigned to it. A fixed structured subrecord has to
conform the corresponding subrecord in the source.
A Table field is conforming when the name of the table
description of the source table matches the table description name
defined in the RecordDesc field. When that name is blank, every
table matches. In fact, defining a table description name is identical
to defining an array shape..
When a TableRecord is read back, possible Tables contained in fields are only opended and read back when they are accessed for the first time. In that way no needless table opens are done. When a table has been opened, it is possible to close it. This can be useful to save memory usage.
TableRecord uses copy-on-write semantics. This means that when a TableRecord is copied, only the pointer to the underlying TableRecordRep object is copied. Only when the TableRecord gets changed (i.e. when a non-const TableRecord member function is called), the TableRecordRep object is copied. This results in a cheap copy behaviour.
{ TableDesc td ("td", TableDesc::Scratch); td.addColumn (ScalarColumnDesc<Int> ("col1")); td.addColumn (ScalarColumnDesc<float> ("col2")); SetupNewTable newtab ("tTableRecord_tmp.tab1", td1, Table::New); Table tab (newtab, 10); RecordDesc rd; rd.addTable ("tab1", "td"); // with description name rd.addField ("tab2", TpTable); // without description name TableRecord rec (rd, RecordInterface::Variable); // Both define's are possible. // The first one because the table description name matches. // The second one because that field has no table description name, // thus every table description matches. rec.defineTable (rec.fieldNumber("tab1"), tab1); rec.defineTable (rec.fieldNumber("tab2"), tab1); Table t1 = rec.asTable ("tab1"); AlwaysAssertExit (t1.nrow() == 10 && t1.tableDesc().ncolumn() == 2); Table t2 = rec.asTable ("tab2"); AlwaysAssertExit (t2.nrow() == 10 && t2.tableDesc().ncolumn() == 2); AipsIO aos ("file.name", ByteIO::New); aos << rec; } // Note that he above is put in a separate scope to be sure that // all objects are deleted and tables are written. { TableRecord rec; AipsIO aos ("file.name"); aos >> rec; // At this point the record is read back, but the tables are not opened. // The next statement accesses the table resulting in its open. Table t1 = rec.asTable ("tab1"); // The following statement closes it again. rec.closeTable ("tab1");
Create a record with no fields. The type determines if the record has a fixed or variable structure. The callback function is called when a field is added to the Record. That function can check the name and of data type of the new field (for instance, the Table system uses it to ensure that table columns and keywords have different names).
Create a record with the given description. If it is not possible to create all fields (for example, if a field with an unsupported data type is requested), an exception is thrown. The type determines if the record has a fixed or variable structure. All fields are checked by the field checking function (if defined) (for instance, the Table system uses it to ensure that table columns and keywords have different names).
Create a copy of other using copy semantics.
Create a TableRecord from another type of record. It uses copy-on-write semantics if possible (i.e. if other is a TableRecord), otherwise each field is copied. Subrecords are also copied and converted to TableRecords if needed.
Copy the data in the other record to this record. It can operate in 2 ways depending on the TableRecord structure flag.
Attributes like fixed structure flag and check function will not be copied.
Release resources associated with this object.
Make a copy of this object.
Assign that RecordInterface object to this one. If that is a TableRecord, copy-on-write is used. Otherwise each individual field is copied.
Get the comment for this field.
Set the comment for this field.
Describes the current structure of this TableRecord.
Change the structure of this TableRecord to contain the fields in
newDescription. After calling restructure, description() ==
newDescription. Any existing RecordFieldPtr objects are
invalidated (their isAttached() members return False) after
this call.
When the new description contains subrecords, those subrecords
will be restructured if recursive=True is given.
Otherwise the subrecord is a variable empty record.
Subrecords will be variable if their description is empty (i.e. does
not contain any field), otherwise they are fixed.
Restructuring is not possible and an exception is thrown
if the Record has a fixed structure.
Returns True if this and other have the same RecordDesc, other than different names for the fields. That is, the number, type and the order of the fields must be identical (recursively for fixed structured sub-Records in this).
thisRecord.conform(thatRecord) == True does not imply
thatRecord.conform(thisRecord) == True, because a variable record in one conforms a fixed record in that, but not vice-versa.
How many fields does this structure have? A convenient synonym for description().nfields().
Get the field number from the field name. -1 is returned if the field name is unknown.
Get the data type of this field.
Remove a field from the record.
Removing a field means that the field number of the fields following it will be decremented. Only the RecordFieldPtr's pointing to the removed field will be invalidated.
Rename the given field.
Define a value for the given field. When the field is unknown, it will be added to the record. The second version is meant for any type of record (e.g. Record, TableRecord, GlishRecord). It is converted to a TableRecord using the TableRecord constructor taking a RecordInterface object.
Get the subrecord or table from the given field.
Get the table from the given field.
Get the attributes of a table field.
Merge a field from another record into this record. The DuplicatesFlag (as described in RecordInterface) determines what will be done in case the field name already exists.
Merge all fields from the other record into this record. The DuplicatesFlag (as described in RecordInterface) determines what will be done in case a field name already exists. An exception will be thrown if other is the same as this (i.e. if merging the record itself).
Close the table in the given field. When accessed again, it will be opened automatically. This can be useful to save memory usage.
Close all open tables. When accessed again, it will be opened automatically. This can be useful to save memory usage.
Flush all open subtables.
Rename the subtables with a path containing the old parent table name.
Are subtables used in other processes.
Write the TableRecord to an output stream.
Read the TableRecord from an input stream.
Put the data of a record. This is used to write a subrecord, whose description has not been written.
Read a record. This is used to read a subrecord, whose description has not been read.
Put the data of a record. This is used to write a subrecord, whose description has already been written.
Read the data of a record. This is used to read a subrecord, whose description has already been read.
Reopen possible tables in keywords as read/write. Tables are not reopened if they are not writable.
Set the attributes of subtables to te ones in the other record. It is primarily a helper function for PlainTable::syncTable and ColumnSet::syncColumns.
Make a unique record representation (to do copy-on-write in RecordFieldPtr).
Return a const reference to the underlying TableRecordRep.
Return a non-const reference to the underlying TableRecordRep. When needed, the TableRecordRep will be copied and all RecordField objects will be notified.
Add a field to the record.
Define a value in the given field.
Create TableRecord as a subrecord. When the description is empty, the record has a variable structure. Otherwise it is fixed.
Set the recordtype of this record and all its subrecords (recursively).