How to use Knarvik
Command line usage
In order to use source files autogenerated by Knarvik, the Knarvik runtime must be added to your project. The Knarvik runtime consists of several C++ source files included into the Knarvik distribution in the Runtime/Knarvik directory.
Adding Knarvik databases to your project
One XML file with a schema corresponds to one Knarvik database. There can be several different databases in one program. Each database has only one global instance. Knarvik databases are not thread-safe, so it is up to the programmer to organize thread synchronization.
If the schema file contains any types in the Types section, do not forget to include the header files that declare those types into the Includes section
Using the database
Initialize the database before using it by calling its Init() method. After you are done with the database, do not forget to call its Shutdown() method. Shutdown() destroys all data. It is okay to initialize the database again after it has been shut down.
The Save() method must be called only in the initialized state and the Load() method can only be invoked on an uninitialized database because Load() initializes the database and populates it with deserialized data. Do not call any methods besides Init() and Load() while the database is not initialized.
Ownership and memory management
The database owns all objects it contains. This applies to tables, indices, rows, string fields and class fields. Do not delete any of these manually. There is a way to delete the object that a class field contains - just assign a null pointer to that field.
The database does not manage ptr fields.
There is a difference in how ownership is dealt with when database methods receive pointers as arguments. Normally, the ownership is not transferred and remains on the caller side. When a string field gets a new value, a copy of that value is created and managed by the database. But in the case of a class field, the ownership is transferred. Such a transfer happens in two places: in Create methods and in field setters.
There are restrictions on how links can be manipulated.
One-way single links consist of only one pointer which can be changed freely, provided that its value is either a valid pointer to a row or null.
The integrity of two-way links is managed automatically: when the field on one side of the link is set to point to a row, the field in that row on the other side of the link is updated accordingly. If a link field is set to null, the field on the other side is assigned the null value too. If two rows are connected by a two-way one-to-one link, they may be re-linked to other rows using this link only after it is set to null.
One-to-many links that involve a collection of pointers cannot be changed once created. Such links, however, do not need to be created when the rows are first inserted, they may be added later.
Knarvik never throws exceptions. If a runtime error is detected, the whole program is aborted. Where it is appropriate, add your own checks to make sure you don't try to force Knarvik to do something illegal. Checks that Knarvik provides are a kind of asserts.
When an index lookup fails, null is returned. Failing to find a row using an index is not considered an error, but be careful to check the pointer received from the index.
The current version of Knarvik does not support deleting of rows from tables. The absence of deletes simplifies integrity checks and memory management significantly. Although in some scenarios the lack of deletes may be considered a major problem, in surprisingly many cases this is not an issue at all. In real-time applications, for instance, heap allocations are avoided by all means after the system has been initialized. Manually managed object pools are used for fast object creation and destruction and Knarvik tables make very good object pools.