Back to index


OOFILE Version 1.3b2 Release Notes

The State of the Beta:

This beta is for the core OOFILE database only, and introduces many new features as well as the RAM backend.

Another beta due shortly will include the dBase backend. These new database backends provide the same OOFILE features and use the same syntax, but lack indexing. The dBase backend includes a utility to generate the c++ source for an OOFILE database to read a given dBase file, making it easy for you to write import code for other databases.

With the release of the dBase backend we will also be releasing 'Personal OOFILE' which includes the dBase and RAM backends but no c-tree facilities.

The report-writer and GUI integration classes, including AppMaker templates, will be released in beta in a few weeks time. Reports are being extended to provide much more formatting control and break levels and include an RTF version, as well as the long-awaited full GUI version.

The Windows versions of reports and GUI integration have unfortunately been delayed due to the demands of a local contract, and the time spent on the core OOFILE features. All Windows package owners will receive an extension to their subscription - the 12 months will date from the first shipment of the Windows GUI tools.

In this beta the documentation has mainly only been updated in the index files that refer to the sample programs, and this release note. The other documentation will be updated in future betas.

CHANGES REQUIRED TO YOUR PROJECTS FROM 1.2

The files oofctre5.cpp and oofctre6.cpp no longer exist.

You need to add the following to your project:

from the Core directory
oofrec1.cpp
oofrec2.cpp
oofrec3.cpp
oofrec4.cpp
oofram.cpp

from the Utils directory

oofwords.cpp


NEW FEATURES since 1.2

New connection Features....................

Provided you build your c-tree libraries with ctNOGLOBALS defined (in ctoptn.h) you can open multiple dbConnect_ctree databases simultaneously. OOFILE operations will automatically switch the c-tree contexts as required.

willTruncateTrailingSpaces method added to govern insert behaviour. The default is for trailing spaces to be retained, but you need to be careful when importing fields used as join keys, eg: from an MS Access database (which allows spaces on join keys).

stats dumps simple statistics on each table in the connection (number of records)

setFileExtensions allows you to set the extensions used instead of .dat and .idx when you create c-tree files with useSeparateFiles. Note that .wrd and .wdx are used by the keyword index feature.



New Table Features....................

insert on tables now copes with empty date and numeric fields

a dbDate of 0/0/0 has been made the official 'null' date and will not be output

date importing can now skip over trailing times, as exported from MS Access or the Visual BASIC Jet engine. (Note: a dbDateTime type is coming soon.)

the .inl files have been eliminated in the OOFILE source and the .inc files renamed as .hpp in the samples. For compatability with Visual C++ 1.52, the .hpp files now all have 2 blanks lines at the end.

isEmpty provides faster test to see if the current selection of records is empty, than testing count.

isNewRecord provides a public interface to let your code vary behaviour depending on whether the current record is an unsaved new record.

addOIDtoSelection adds the specified record to the selection. It can be used if you have complex filtering logic building up a selection.

dropRecordFromSelection takes a relative record number within the selection and removes that record from the selection. It does not delete the record or modify it in any way.

dbSelection class has been added as a lightweight way to contain a selection. You can get and set the selection of a table with currentSelection and setSelection. Selections support a number of operators such as contains and operator+= as well as set manipulation with difference_with etc.

makeEmptySelection is another way to create a selection for a given table, creating an empty selection you might then use as the basis for a looping union_with

stSaveSelection is a stack-based class designed to wrap a segment of code that changes the selection of a table. On destruction, the object will restore the original selection, eg:

{
stSaveSelection savePeople(People);
People.search(...); // some search
...// some other processing
}; // savePeople is destroyed on exit from this context, restoring the People selection

Assigning a record from one table to another (of the same type) is now possible using operator= or copyRecFrom. An entire selection can be copied with copyAllFrom. These are most useful when operating with two databases open, or possibly when setting up a temporary RAM-based table as a subset of a main database.

cloneRecord makes a duplicate in the current database of the current record, and makes the new record current. Regard it as like a newRecord followed by setting all the fields. You still have to issue an explicit saveRecord.

revertRecord added to reload the record from disk.

cloneSharingSelection added to create a dbTable to iterate independently over the current selection.

oidOfRecord returns the OID (may be a physical disk offset) of the Nth relative record in the current selection

Indexing can be suppressed and the indices rebuilt. See ooftst23 for detailed example. The current limitation is that this only works for useSeparateFiles.

allSelected added to enable your code to test the state of the database, in case you want to vary behaviour if the selection of records is the entire database. (eg: changing a window title to say 'all records' instead of '5 of 10 records').

search and searchSelection can now take related fields, eg:

Patients.search(Patients.Visits->Why=="Flu");

getGUI has been added to return a 'GUI Coordinator' which is used to coordinate operations, eg: being able to ask the coordinator if it's OK to leave a record and having the coordinator check with all the active editors and lists. There will be more documentation on this with the new GUI integration beta.

deletion behaviour is more consistent in making sure the selection is still valid after deletion, and that a record is loaded. Deleting the last record in the selection loads the first record, as if the selection were a circular buffer. stats dumps simple statistics for the table (number of records)



dbView Changes....................

By default, a dbView will now create an iterator sharing its selection with the dbTable on which you're creating the view. This means that views can iterate over the selection without disturbing your context - a vital part of having listboxes show the same selection as being edited on the same or another window. There is a slight performance hit to this iterator creation. If you don't mind the dbView having side-effects (the v1.2 behaviour) then pass in false as the second parameter, eg: dbView test(People, false);

An operator<<(dbView*, dbField*) has been added added to allow us to use expressions like (from ooftst01):
cout << (dbView(entrepeneurs) << entrepeneurs.LastName << entrepeneurs.OtherNames) << endl;

dbViews no longer have an abstract source object, and so the expression source()->table() can now become either just source() or table().



New Relationship behaviour....................

DEFINE_REF and DEFINE_SET also define a cast operator so the reference member can be used directly in lieu of the pointer. eg if we need to pass in a dbVisits* can use People.Visits.

relateSelection will build a selection in the target table of records related to any of the rhs table. It is mainly used inside the searching by related items.

linkMNvia allows you to specify an MN relationship, although requiring you to define an intermediate table. (In future an intermediate table will be automatically generated if you don't require attributes on the relationship.) For example, consider a database P linked to T by intermediate table TP:

dbRelationship(P->TP, TP->P); // lhs to intermediate
dbRelationship(T->TP, TP->T); // rhs to intermediate
// declare the MN relationship
dbRelationship P_T(P->Teachers, T->Pupils);
P_T.linkMNvia(TP->P, TP->T);

countAllRelated and countAllRelatedIn have been added to aid the specific situation of counting the unique related records for a given selection. This kind of calculation is common in databases and these methods provide an optimal way to retrieve the count. countAllRelatedIn takes a parameter of a table and effectively intersects the related records with the existing selection on that table.



RAM-based Tables....................

dbConnect_ram class has been added to allow you to declare a database totally in RAM. There are no operational differences between these and other OOFILE databases except no name is passed into newConnection (and openConnection has the same effect as newConnection).

You can also quickly define an equivalent table in RAM with cloneEmptyInRAM and cloneInRAM. The latter also copies the entire current set of records.



New Field Features....................

dbBool field type added to store boolean values as an unsigned short (0 or 1) with I/O as 'T' or 'F'.

Features for all field types
getChars allows you to pass in a buffer of known size and have the field output into that buffer. It is more efficient than the copying involved in copyAsChars.
fieldMinWrapWidth will return a size that can be used in setting up columns. In future it will take account of formatters attached to fields, so you can have wrapping of text fields but avoid wrapping dates or numbers.
constructors and operator= added for all the standalone field types (eg: oofText) with special constructors taking initial values, like the native types they represent.
value method added (non-virtual) for each field type to return the value contained in the field. This is mainly intended for use in if() expressions where you want to use a field on the lhs of the expression, which would normally produce a dbQuery object and consequent compiler error. eg:
if (People.salary.value()==9000);

dbDate Features

isLeapYear static method has been added to evaluate any year
checkDate has been made public and enhanced to properly evaluate leap years. A 'null' date of 0/0/0 will be accepted but years with 1 or 3 digits cause errors, as do incorrect day or month numbers.
oofrec3.cpp
oofrec4.cpp
oofram.cpp

dbChar & dbText Features

operator+= methods added to append a single character or string
operator= method added to set the string to a single character
length returns the length of the text contents.

Keywording Features

OOF_mixKeywordableField parent class is used to add keywordable behaviour to dbChar and dbText
words returns a pointer to an oofWordParser, or nil for non-text fields.
fieldIsKeywordIndexed indicates if a field is keywordable, and has been set to create a keyword index.
indexWords indicates that a field is keyword indexed and takes an optional parameter of a user-defined word parser. This allows you to override the default word parser, either just parameterizing it with a stop-word list and minimum word length, or specifying your own subclass with different parsing rules.
hasWord search on keywordable fields is used to perform keyword searches, eg: People.search(People.Description.hasWord("boss"));

Calculated Fields

calculateWith takes a calculator object of the appropriate type to specify that a field's value is calculated, not drawn from the database.
a calculator object can retain state (instead of a simple callback function) and thus you can write very complex calculators
a different base calculator class exists for each field type, eg: dbDateCalculator to ensure it takes the correct field parameter and returns the appropriate value.
calculated fields take up no space in the record storage and are calculated whenever the field's value is read. This enables sorting and searching by calculated fields, as shown in ooftst29
in future you will be able to specify that a calculated field is indexed. This will provide fast searches and sorts but have the tradeoff of taking up space in the database.

dbBLOB Features

operator+= added to append another blob
adoptBody added to take a block in memory directly, not copying
appendBody appends a known size block to the current blob
setBytes sets the current blob to a copy of the given block
extract produces a hexdump of the blob, on the ostream
length returns the length of the contents. (this is overriden for dbText, to return 0 if the BLOB contains either nothing or just a null string)



Utility class changes....................

dbBroadcaster has new methods askAllStoppingAtFirst and askAllReturningAny that add flexibility to the roles of broadcasters and subscribers. They are particularly useful if you have an object which can cancel a pending operation (eg: cancel leaving a record because the user clicks Cancel on a 'Yes/No/Cancel to Save' dialog.)

OOF_String constructor added to take an array with specified length, so we can build strings from a partial buffer. Methods left and right added to return portions of the string.


FIXES

Importing from streams into dbTables with relationships

If the table contained relationship fields the import would fail to skip onto the next field, and would report an error. A related bug was that, if the only fields left on the table were relationship fields, a 'short import' would incorrectly be reported, as if the import data lacked a column for a real field.

Schemas with BLOB fields sometimes gave errors

If the table contained dbBLOB or dbText fields and the pattern of preceding fields did not result in an alignment to a 4-byte boundary, then the database schema was illegal and would cause errors on creating the file. A workaround spotted by one user was to insert a dummy dbLong field in front of the BLOB, as the dbLong was aligned to 4 bytes.

Declaring a database and not opening caused a crash

If the dbConnect_ctree variable was defined along with some tables, but never opened or a new database created, a crash occurred on application exit due to uninitialised data members.

io.h not used on Solaris

To avoid errors, an #ifndef SOLARIS has been added around this include. If you are using Solaris, ensure your makefile defines SOLARIS.

Referential Integrity failed on 1:1 relationships

If you deleted one record involved in a 1:1 pointer relationship, the other side was not updated and still pointed to that address. (Join relationships use searches for all traversals and so did not suffer from this problem.)

The order of includes has been reviewed in some files, and extra #ifdef logic added to detect compiler types, to avoid errors with the streams includes and bool definitions.

Changing sort order to reverse of current field failed to resort

Changing the sort order to just the reverse of a single field sort failed to mark the sort order as dirty, and so re-sorting did not occur.

Searches by NoDups numeric indexes failed

The transformation routine was incorrectly transforming the key, so depending on your c-tree settings your key was malformed and so the record would not be found.


KNOWN BUGS

Updating indexed dbChars with smaller contents breaks NoDups searches

When a dbChar field is updated, a null is written at the end of the new contents, but the entire fixed width of the field is NOT nulled out. This affects NoDups indexes as the content of the string no longer exactly matches the key. (eg: rewriting 'JOHNSTON\0\0\0' gives 'TEST\0TON\0\0\0'). When c-tree searches a NoDups index, it checks the entire key and not just up to the terminating null. (ie: character fields are handled as if they were binary keys).

MN relationship right-to-left traversals

Traversing an MN relationship backwards (as in a related search) fails as relateFromRecord uses the prototypical OOF_RelMN pointed to by the lhs of the relationship, rather than the actual OOF_RelMN pointed to by the rhs.

Global dbViews cause errors

Creating a global dbView without specifying no shared selection (ie: don't have a second ctor param of false), before the connection is opened, causes an error as the database cannot yet be cloned.

Views with shared selections update incorrectly

(See ooftst28) Creating a view without specifying no shared selection fails to update the view selection correctly when a searchSelection is performed on the original table.


NOTE: a full diary of all changes since 1.2 is in chg13b2.txt.

Previous Version 1.2 Release Notes


Back to index


(c) Copyright A.D. Software 1994-1997 (All Rights Reserved).
Last Updated: 7th October 1996