Embedded Databases NexusDB
Embedded Databases NexusDB
Abstract
NexusDB is a database engine from NexusDB, specifically designed for use in Del-
phi. It runs as an embedded database server, but can also be used as a client/server
setup; It supports a variety of client/server protocols, and can be used with or without
SQL engine. In this last article about Embedded Databases we compare it with other
engines.
1 Introduction
The NexusDB engine has it’s roots in the - discontinued - FlashFiler product from Tur-
boPower. It was designed specifically as an embedded engine, but has many powerful
options for running it as a stand-alone engine as well. It runs solely on Windows platforms,
and with any version of Delphi. It comes with it’s own memory manager, which is one of
the reasons why porting it to Free Pascal/Lazarus is not an option at this time. It would take
a huge effort to do this.
Despite the fact that it is designed specifically for Delphi, the NexusDB database engine can
also be accessed through ODBC, PHP, ADO.NET: drivers for each of these exist (although
it’s not quite clear whether they will work with the embedded version)
NexusDB has a very rich feature set: Transactional support, foreign key handling, SQL
2003 compliance, stored procedures, extensive monitoring and logging mechanisms, live
backups. The engine can be extended with custom plugins, and so is easily extendable.
NexusDB is a commercial product, but can be downloaded for free - without sourcecode -
from their website:
http://www.nexusdb.com/
The free version is usable only for embedded use: no client/server capabilities are provided.
There are 2 versions of the NexusDB engine: an older version (V1) and a newer version
(V2).
Installation is very simple, the product installs itself and provides a large number of help
files, which provided detailed information in how the product works.
In the next section, the architecture of the Nexus DB components is outlined. After that, the
SQL executor application which was coded for the other database engines will be coded for
the Nexus DB engine as well, after which performance will be tested on the Pupil Tracker
database.
1
2 Architecture
NexusDB is built very modular: the different parts of the system are quite independent of
each other. This means that it is possible to tune the application to a large degree: only the
functionality that is actually needed can be included in the final binary. No external libraries
or drivers are needed. The engine is directly included in the application executable.
Since everything is built with Delphi components, this modularity reflects itself in the com-
ponents that are installed in the component palette of Delphi by the installer program.
The main components are the following:
TnxServerEngine This is the Nexus Server engine. It is the core of the Nexus DB archi-
tecture, and contains the actual file and data management routines. It is only needed
if the application will function as a server application - which is of course the case
for any embedded application. Pure clients would not need this part.
TnxDatabase This represents a Nexus Database. It’s mainly the definition of the database,
as the actual data is handled by the server engine. It’s always needed, also on a pure
client.
TnxSqlEngine This component should be added if one wishes to execute SQL statements.
It is possible to avoid the use of SQL altogether and access the tables in a database
much as one would access DBase files. If a database should be SQL enabled, it
should point to an SQL engine component by means of it’s SQLEngine property.
TnxseAllEngines (or Tnx1xAllEngines) are 2 components that are needed to link the
various needed server engines in the executable.
This seems like a lot of components - compared to other database engines where only 1
component is needed to establish a connection, but this is a consequence of the modular
design of Nexus DB. This could be alleviated by creating some descendents which group
some of these components into a single component.
The above components are all needed to be able to connect to a Nexus DB database. The
following 2 components are the TDataset descendents which actually allow access to
the data:
TnxTable This component allows direct access to the tables of the Nexus Database. It
does not need any SQL capacities, but does allow complex filters to be built and
applied. Likewise, master-detail relationships can be built. It is the Nexus equivalent
of the BDE
TnxMemTable This component allows to create and manipulate in-memory tables. These
tables are kept in-memory, are accessible throughout simultaneous sessions: they are
handled at the server, and disappear when the server is stopped.
TnxQuery This component allows to specify an SQL statement and either directly execute
that statement, or open a dataset with the results of the statement.
2
TnxStoredProc This component allows to execute stored procedures on the server, and
possibly retrieve results generated by this procedure.
There are many other components: monitoring and logging components, server plugin
components. The help files and examples give more information about most of them.
Additionally, there are various transport mechanisms to create true client/server applica-
tions: data transport between client and server can be achieved through COM, Shared
memory, TCP/IP, named pipes and so on. All that is needed is to drop the desired transport
component on the form, set some properties, and that is it.
Remains to code the 3 routines in the SQL executor that are specific to the database engine.
The StartDatabase method is first:
procedure TMainForm.StartDatabase;
begin
SQLEngine.Active:=True;
DBExecutor.AliasPath:=ExtractFilePath(ParamStr(0))+’Data’;
DBExecutor.Active:=True;
TCExecutor.Active:=True;
TCExecutor.StartTransaction();
end;
3
As can be seen in the code above, all needed components must be activated before they can
be used. The database path is set to the Data subdirectory of the application directory.
The StopDatabase performs the inverse operation, in the reverse order:
procedure TMainForm.StopDatabase;
begin
TCExecutor.Commit;
TCExecutor.Active:=False;
DBExecutor.Active:=False;
SQLEngine.Active:=False;
end;
Note that to execute DDL statements, the transaction context should not be activated, be-
cause then the statements will fail.
Executing a statement is just as simple:
begin
Try
If (Trim(SQL)<>’’) then
begin
QExecutor.SQL.Text:=SQL;
QExecutor.ExecSQL;
end;
Except
On E: Exception do
begin
MLog.Lines.add(’Error executing SQL statement: ’+SQL);
MLog.Lines.Add(’Error message : ’+E.Message);
If Not IgnoreError then
Raise;
end;
end;
end;
And with that, the SQL executor is ready. It can be used to create the database, and populate
them.
There are 2 caveats in this:
1. The transaction must be disabled when executing the database creation scripts; DDL
statements cannot be executed in the context of a transaction.
2. The SQL syntax for DATE and Time fields is not compatible with the standards as
followed by the other database engines. It is necessary to change the scripts so a date
field is specified as follows:
DATE ’2006-01-01’
Note the DATE identifier in front of the constant. Likewise a time value must be
explicitly indicated:
TIME ’08:27:00’
4
Figure 1: The pupil trackdata browser
5
4 Performance
The performance of the Nexus DB engine is compared with the performance of the other
databases. As usual, 4 tests were run. Since the queries needed for the tests need some
date/time constants, the tests are repeated here, with corrected SQL statements.
SELECT
PU_ID,COUNT(PT_ID)
from
pupil
left join pupiltrack on (PU_ID=PT_PUPIL_FK);
SELECT
COUNT(PT_ID)
FROM
PUPILTRACK
WHERE
(PT_DATE= DATE ’2005-09-06’)
AND (PT_CODE=’I’)
AND (PT_TIME<= TIME ’08:28:00’);
4. Number of different pupils entering school on 6 september 2005, before 8:28 AM.
SELECT
COUNT(PU_ID)
FROM
PUPIL LEFT JOIN PUPILTRACK ON (PT_PUPIL_FK=PU_ID)
WHERE
(PT_DATE= DATE ’2005-09-06’)
AND (PT_CODE=’I’)
AND (PT_TIME<= TIME ’08:28:00’);
6
be remedied with some simple coding. The upside is that Nexus DB can be finely tuned
to one’s needs. It can be upscaled to full client/server, making it a safe bet for embedded
work when the application can be upscaled in the near future. The fact that no additional
files need to be deployed make it very easy to distribute an application that uses it.
The test results show engine performs very well, compliance to SQL standards is reason-
able, but has some quircks which the developer will need to get used to.
The only drawback is that it’s very Windows bound; A linux version or Lazarus/Free Pascal
would be a definite plus: Linux is, after all, a popular server platform.
All in all it would be fair to say that Nexus DB is a good choice for Embedded work, with
definite possibilities for upscaling, unless one has cross-platform development in mind.
SQLite is very easy in deployment (a single DLL) , is very fast for simple queries and
inserts. On the downside one should mention that it has issues with difficult queries,
and does no typechecking whatsoever on the data entered. In a Pascal environment,
this is not recommendable. It cannot be upscaled, so should only be used when this
is not an issue. Support for Delphi and Lazarus is good.
Firebird is easy to deploy, works fast, is feature rich. It is cross-platform, and there is no
problem upscaling to full client-server. Support for Delphi and Lazarus is very good
to excellent.
MySQL is hard to deploy as an embedded engine, is not available for all platforms in the
latest version. It’s however very fast, and is definitely upscalable. Support for Delphi
and Lazarus is medium to good: the issues with various versions are a problem; not
all components handle all versions of MySQL.
ADS - Advantage Database Server is very easy to deploy. Works fast - some quircks
aside -, is feature rich and is easily upscalable. As a commercial product, support is
readily available. Support for Delphi and Lazarus is very good to excellent, and it
works both on Windows and Linux. It’s available for embedded use for free.
Nexus is probably the easiest to deploy. Works very fast, again, some quircks aside, is
also feature rich and is easily upscalable. It is a commercial product, so support is
readily available. Support for Delphi is excellent, but support for Linux or Lazarus
is non-existent. It’s available for embedded use for free.
Which of these engines is to be recommended is hard to say, they are all closely tied. Each
has some disadvantages and advantages. It’s easier to warn that SQLite and MySQL have
some issues that make it less suitable for use with Delphi and/or Lazarus.