ver12.htmTEXTBlWd0-JNJN Version 1.2 notes

Back to index


OOFILE Version 1.2 Release Notes

A little bit of Grievous History:

v1.1 of OOFILE was supposedly ready for release in mid-January and was announced as such. Unfortunately, within a couple of days of the announcement, one of our beta testers unearthed a couple of deep bugs in the very heart of the database. (If you weren't cloning selections you wouldn't have found them.)

At the same time we became involved in a major contract for a local developer, in an Apple-sponsored project to rewrite a Windows program for the Macintosh. I'm very happy to say that a tough steering committee agreed with our recommendation of OOFILE as the only viable solution for this C++ development.

The v1.1 bugs, and the subsequent re-architecting of some of the internals, have taken most of the last two months to track down. In the process, OOFILE has also been thoroughly checked for memory leaks, using SmartHeap. (This is in addition to the memory overwrite checking of SmartHeap that we use regularly.)

As part of the fixes to these deep bugs, the new architecture for relationships was rolled in. This removes the parentheses at the end of related fields and gave a much cleaner model for propagating relationships.

Finally, whilst all this was going on, our new staff completed a number of major features includng wildcard searches, non-indexed searches and multiple-field sorts.

Thus, after a couple of very arduous months I'm extremely delighted to present OOFILE v1.2.

CHANGES REQUIRED TO YOUR CODE FROM b1.05

1) The dbTable function "sortBy" has been renamed "setSortOrder"

2) Related fields no longer use parentheses, eg:
People.Visits->Why() = "Flu";
is now
People.Visits->Why = "Flu";

3) Expressions on related tables now also use the pointer notation to bring them into line with the fields. (You have a real dbTable* returned by the operator-> expression):
People.Visits.newRecord();
is now
People.Visits->newRecord();


NEW FEATURES

MACROS RENAMED & ALLOWING INHERITANCE

To make declarations more readable, the macros have been renamed as follows (the original forms are still available, so you don't have to change your code).
CLASS_TABLE -> DECLARE_CLASS
REF_TABLE -> DECLARE_REF
SET_TABLE -> DECLARE_SET

In addition, you can declare classes using normal class syntax, providing you include the OOFILE_METHODS macro.

class dbPeople : public dbTable {
OOFILE_METHODS(dbPeople)
dbChar LastName...

See ooftst19.cpp for an example using this as well as the other variation required for mixin inheritance.

SORTING

A number of new functions have been added to control sorting and re-sorting is now (lazily) automatic. This means, if you change a selection then the next access to a field will trigger a re-sort. eg: searching, adding a record or deleting a record all make the sort "dirty".

The lazy evaluation means it is safe to perform a sequence like:
People.setSortOrder(People.OtherNames);
People.search(People.salary > 50000);
cout << People.count() << " people earn over $50,000" << endl;
People.searchSelection(People.LastName == "Dent");
if (People.count())
cout << "Dent family high-earners are: " << endl << People << endl;

The only re-sort that occurs is on the final cout ... << People. The count() function has no need to access any data so does not trigger a re-sort.

You can control sorting with People.suspendSorting(), resumeSorting() and unSorted().

Suspends and resumes are nested, and it is safe to call resumeSorting more times than a suspension has occurred.

Multiple field sorts use a dbSorter (see ooftst12 and 21) which has very similar syntax to compound fields. You can use a dbSorter on the fly, eg:

People.setSortOrder(dbSorter() << People.LastName << reverse(People.Salary));

SEARCHING

New search syntax has been added - you can now use searchSelection() to narrow your search. This is functionally equivalent to using the && operator to combine expressions.
People.search(People.salary > 50000);
People.searchSelection(People.LastName == "Dent");

is the same as
People.search(People.salary > 50000 && People.LastName == "Dent");

The wildcards * and ? can now be used in strings for 0-n and exactly 1 character matches.

For multiple fragment searches, four new calls have been added that perform a single pass over the database. You would often perform a selectAll() beforehand unless you desire their searchSelection behaviour:
searchSelContainsAllDelimited(field, string, char)
searchSelContainsAllOf(field, array, count)
searchSelContainsAnyDelimited(field, string, char)
searchSelContainsAnyOf(field, array, count)

eg, passing in a comma-delimited list:
People.selectAll();
People.searchSelContainsAnyDelimited(People.LastName, "ta,en,wood",',');

NON-INDEXED SEARCHES

All search expressions can now be performed regardless of an index on the fields.

OPTIMISED COMBINATORIAL SEARCHES

Combinatorial searches with an And expression (&&) will now do a searchSelection on the right-hand-side expression instead of searching the whole database and intersecting results. The exception is where the rhs is an indexed field and the lhs selection is very large, where the indexed search and intersect would still be faster.

NON-JOIN RELATIONSHIPS

Relationships are by default without a join field and make use of direct pointers, or at most a single indexed search (for 1-N relationships). For 1-1 or traversing N-1 relationships this is a lot faster as it avoids a search altogether.

MULTIPLE OPENS (SEQUENTIALLY)

You can now open a connection, close it (eg: theDB.close()) and open another one in the same program run.

DEFAULT NAMES FOR TABLES

You no longer need to pass in the table name as part of the constructor. The default name of the file will be the name of the class.

DECLARE_CLASS(dbPeople)
dbChar LastName;
dbPeople() : LastName(80, "Last Name") {};
};

previously you would have had to specify the dbTable argument
dbPeople() : dbTable("People"), LastName(80, "Last Name") {};

NOTE: if you rely on these default names, you may have different names to original tables, eg: dbPeople instead of People. This happens with some of the OOFILE samples and will cause errors on opening the database.

STANDALONE FIELDS

All field classes now have a standalone subclass starting with 'oof', eg: oofDate.

This is most valuable with the date classes, eg:
oofDate myDate = dbDate::currentDate();
cout << "Tomorrow is " << myDate + 1;
myDate = "7th May 1963";


OTHER CHANGES

g++ 2.7 WARNING-FREE

Apart from one sample program (20) all OOFILE samples and core code compiles without warning under g++ v2.7.

ALL READ ACCESS IS CONST-CLEAN

All read operations on field types are const clean. This includes operator char*, stream output etc.

COMPOUND FIELDS CAN HAVE PORTIONS REVERSE-INDEXED

Making use of the c-tree segment options, the different segments in a compound index can now be indexed in reverse order. Note that this is only of benefit when using a compound index to sort all records. Sorting a selection of records doesn't use the index.

There are two syntaxes for setting reverse fields, using operator>> or reverse():
MyField >> Date << Name;
MyField << reverse(Date) << Name;

DATE ARITHMETIC

See fields.txt for a comprehensive description. The dbDate type has been extended considerably to allow for arithmethic adding and deleting counts of days, getting the gap between dates (in days) and general addition and subtraction as standalone types.

DATE INPUT

The dbDate input from a string is now extremely flexible in handling most expressions that would be expected, eg: "1st March" as shown in ooftst05.

dbChar EXTRAS FOR STRING MANIPULATION

A length() function has been added as well as operator[] which lets you directly access characters in a dbChar field, eg: Stock.JobCode[0] = "X";

C-TREE HIDDEN

The ctree includes have been totally hidden from your program - just include oofile.hpp. This should help speed compilation and avoids clashes with c-tree global names (the main complaint from one beta tester).

BACKWARD ITERATION IMPROVED

The backward iteration using prev() or gotoRecord(), as commonly called from a GUI browser, is now smarter about using the index.

IMPORTING WORKS FOR ALL TYPES

insert() functions have been added for all field types, as demonstrated in sample ooftst10, so they can read from an istream.

NEW SYNTAX FOR DECLARING JOIN RELATIONSHIPS

Join relationships are declared with a separate joinField call, most probably in the constructor. (Note: that you can now use relationships without joins, just by omitting the joinField call). However, you can still use the old 4-parameter form of dbRelationship.

OLD

CLASS_TABLE(dbVisits)
dbPatientsRef Patient;
dbLong PatientNo;
dbDate VisitDate;
dbText Why;
dbVisits() :
dbTable("Visits"),
PatientNo("PatientNo", kIndexed),
VisitDate("VisitDate", kIndexed),
Why("Reason for Visit")
{};

};

dbRelationship PatientVisits(Patients.Visits, Visits.Patient,
Patients.PatientNo, Visits.PatientNo);

NEW

DECLARE_CLASS(dbVisits)
dbPatientsRef Patient;
dbLong PatientNo;
dbDate VisitDate;
dbText Why;
dbVisits() :
dbTable("Visits"),
PatientNo("PatientNo", kIndexed),
VisitDate("VisitDate", kIndexed),
Why("Reason for Visit")

{
Patient.joinField(PatientNo);
};
};

dbRelationship PatientVisits(Patients.Visits, Visits.Patient);

SUPPRESSING DELETE PROPAGATION FOR RELATED RECORDS

As before Relationships automatically propagate deletes. A separate call can to be made in the constructor to suppress this. eg: (showing a non-join relationship):

DECLARE_CLASS(dbPatients)
dbChar LastName, Othernames;
dbVisitsSet Visits;
dbLong Salary;

dbPatients() :
LastName(40, "Last Name", kIndexed),
Othernames(80, "Other names", kIndexed),
Salary("Salary", kIndexed)

{
Visits.propagateRelatedDeletes(false);

};
};


FIXES

CLONING

Cloning a table, as occurs in ooftst01, was broken if you inherited tables, due to the way copy constructors worked.

You can now also explicitly use clone, eg: dbPeople* newPeople = People->cloneWithoutSelection();

COPY-ON-WRITE SELECTIONS

When you copy a selection (see ooftst01) you get a reference to the original, not a copy. This is only made into an actual copy if you change the selection. If your next operation on one of the tables is a search, then a new selection is constructed.

The bug affected simple operations such as deleting or adding a record - the original as well as the copied selection were affected.

A side-effect is now that if you have copied a large selection and make changes you may notice an initial performance hit as the selection is really copied. This is unlikely to affect most users (nobody had noticed the bug!).

JOINS OVER OTHER THAN dbLong FIELD TYPES

Relationships using a join over field types such as dbChar just crashed. They have now been fixed - a virtual function had to be implemented for each field type.


NOTE: a full diary of all changes since b1.05 is in changes.txt.


Back to index


-F,FZColorSync Profiles ver12.htmPartSIT!PartSIT!u-%Embedding Preferences% Fetch Prefs%FileMaker Prefs,:6  w%w%w%    w%w%w%  "a/Q%  w%w%w%-  .  w%w%w%5  6  w%w%w%A  B  w%w%w%y   w%w%w%   w%w%w%  w%w%w%   w%w%w%   w%w%w%   w%w%w%   w%w%w%  +  w%w%w%.  a  w%w%w%d    w%w%w%  y  w%w%w%|  "  w%w%w%%    w%w%w%    w%w%w%    w%w%w%   w%w%w%    w%w%w%    w%w%w%  6  w%w%w%:  X  w%w%w%\  c  w%w%w%g    w%w%w%  5  w%w%w%9  T  w%w%w%X  `  w%w%w%d    w%w%w%    w%w%w%    w%w%w%    w%w%w%  w%w%w%    w%w%w%    w%w%w%   w%w%w%    w%w%w%  w  w%w%w% {   w%w%w%    w%w%w%    w%w%w%   P  w%w%w% Y  z  w%w%w% ~    w%w%w%    w%w%w%    w%w%w%    w%w%w%   1  w%w%w% 4  5  w%w%w% 9  @  w%w%w% E  F  w%w%w% I  ^  w%w%w% a   w%w%w%    w%w%w%    w%w%w%   O  w%w%w% S   w%w%w%    w%w%w%     w%w%w%     w%w%w%    w%w%w%  t  w%w%w%w    w%w%w%  k  w%w%w%n  o  w%w%w%s |  w%w%w%    w%w%w%  3  w%w%w%7  ]  w%w%w%a    w%w%w%    w%w%w%    w%w%w%  M  w%w%w%P  !  w%w%w%%  X  w%w%w%\    w%w%w%    w%w%w%    w%w%w%    w%w%w%    w%w%w%"  6  w%w%w%:    w%w%w%    w%w%w%   w%w%w%    w%w%w%    w%w%w%    w%w%w% $  w%w%w%)  *  w%w%w%-  y  w%w%w%|  }  w%w%w%   w%w%w%    w%w%w%    w%w%w%    w%w%w%   w%w%w%    w%w%w%  )  w%w%w%,  -  w%w%w%1 I  w%w%w%N  O  w%w%w%R    w%w%w%    w%w%w%    w%w%w%    w%w%w%    w%w%w%    w%w%w%  J  w%w%w%N  Q  w%w%w%Z    w%w%w%    w%w%w%    w%w%w%    w%w%w%   w%w%w%    w%w%w%  /  w%w%w%2  c  w%w%w%g    w%w%w%    w%w%w%    w%w%w%    w%w%w%    w%w%w%    w%w%w%  w%w%w%    w%w%w%     w%w%w% %  w%w%w%*  +  w%w%w%.    w%w%w%    w%w%w%   w%w%w%    w%w%w%  1  w%w%w%4  5  w%w%w%9 j  w%w%w%o  p  w%w%w%s  w  w%w%w%z    w%w%w%    w%w%w%  %  w%w%w%(  )  w%w%w%- <  w%w%w%A  B  w%w%w%E  D  w%w%w% G  H  w%w%w% L  V  w%w%w% [  \  w%w%w% _   w%w%w%    w%w%w%  !!  w%w%w%!&  !'  w%w%w%!*  !  w%w%w%!  !  w%w%w%! !  w%w%w%!  !  w%w%w%!  "  w%w%w%"  "  w%w%w%" "  w%w%w%"  "  w%w%w%"  #_  w%w%w%#b  #c  w%w%w%#g #  w%w%w%#  #  w%w%w%#  $  w%w%w%$  $  w%w%w%$ $?  w%w%w%$D  $E  w%w%w%$H  %Q  w%w%w%%T  %U  w%w%w%%X  %[  w%w%w%%c  %d  w%w%w%%h  %}  w%w%w%%  %  w%w%w%%  %  w%w%w%%  %  w%w%w%%  %  w%w%w%%  %  w%w%w%%  %  w%w%w%%  %  w%w%w%%  %  w%w%w%%  %  w%w%w%%  &  w%w%w%&   &  w%w%w%&  &%  w%w%w%&)  &*  w%w%w%&.  &S  w%w%w%&W  &X  w%w%w%&\  &  w%w%w%&  &  w%w%w%&  &  w%w%w%&  &  w%w%w%&  &  w%w%w%&  &  w%w%w%&  &  w%w%w%&  '  w%w%w%'  '  w%w%w%'  'Y  w%w%w%'b  'c  w%w%w%'f  'i  w%w%w%'q  'r  w%w%w%'v  '  w%w%w%'  '  w%w%w%'  '  w%w%w%'  '  w%w%w%'  '  w%w%w%'  '  w%w%w%'  '  w%w%w%'  '  w%w%w%'  '  w%w%w%'  (  w%w%w%(  (  w%w%w%(  (  w%w%w%(  (5  w%w%w%(9  (:  w%w%w%(>  (c  w%w%w%(g  (h  w%w%w%(l  (  w%w%w%(  (  w%w%w%(  (  w%w%w%(  (  w%w%w%(  (  w%w%w%(  (  w%w%w%(  (  w%w%w%(  (  w%w%w%(  (  w%w%w%(  )  w%w%w%)   )J  w%w%w%)M  )N  w%w%w%)R )  w%w%w%)  )  w%w%w%)  *4  w%w%w%*7  *8  w%w%w%*<  *U  w%w%w%*Y  *Z  w%w%w%*^  *|  w%w%w%*  *  w%w%w%*  *  w%w%w%*  *  w%w%w%*  *  w%w%w%*  *  w%w%w%*  *  w%w%w%*  *  w%w%w%*  *  w%w%w%*  +  w%w%w%+  +  w%w%w%+   +9  w%w%w%+=  +>  w%w%w%+B  +`  w%w%w%+i  +j  w%w%w%+n  +p  w%w%w%+t  +v  w%w%w%+  +  w%w%w%+  +  w%w%w%+  +  w%w%w%+  +  w%w%w%+  +  w%w%w%+  +  w%w%w%++  w%w%w%+  +  w%w%w%+  +  w%w%w%+ +  w%w%w%+  +  w%w%w%+  ,m  w%w%w%,p  ,  w%w%w%,  ,  w%w%w%, ,  w%w%w%,  ,  w%w%w%,  -  w%w%w%-  .  w%w%w%.  /g  w%w%w%/j  /k  w%w%w%/o /  w%w%w%/  /  w%w%w%/  0C  w%w%w%0F  0G  w%w%w%0P  0  w%w%w%0  0  w%w%w%0  0  w%w%w%0  0  w%w%w%0  0  w%w%w%0  -F,FZ0rZstylsoup&8859222P