REST easy with kbmMW #9 – Database 4 – Data augmentation and XML

This blog post will focus on one way of augmenting data returned from a database using the ORM, serving this as a wellformed XML result to REST client’s using as little code as possible.

kbmMW’s ORM is pretty good at fetching data from a database based on a class.

Sometimes we want to augment the class with additional data, before returning the data to a client.

This we can use the virtual table attribute for.

An example.

We have a class TPerson, which is used by the ORM to persist and retrieve persons from the person database table.

The person might refer to a company, via a companyId which is a GUID. This is all straight forward.

  TPerson = class
     [kbmMW_Field('name:id, primary:true, generator:shortGUID',ftString,40)]
     property ID:kbmMWNullable<string> read FID write FID;

     property Name:kbmMWNullable<string> read FName write FName;

     property CompanyID:kbmMWNullable<string> read FCompanyID write FCompanyID;

However lets say we want to provide an augmented REST interface to the person information, where we want to add additional fields, like company name.

  TAugmentedPerson = class
     property ID:kbmMWNullable<string> read FID write FID;

     property Name:kbmMWNullable<string> read FName write FName;

     property CompanyID:kbmMWNullable<string> read FCompanyID write FCompanyID;

     property CompanyName:kbmMWNullable<string> read FCompanyName write FCompanyName;

What you can see is that an additional class is defined, which purpose primarely is to marshal augmented TPerson data to REST clients.

We have told that the TAugmentedPerson (which by outset has no relation to TPerson class wise), is a virtual table, which means it does in fact not live in any databases, but it can still be used as the output for queries.

So lets put together an augmented query:

[kbmMW_Service('name:REST, flags:[listed]')]
TsvcRest = class(TkbmMWCustomHTTPSmartService)
   [kbmMW_Rest('method:get, path:persons')]
   function GetPersons:TObjectList<TAugmentedPerson>;
// Return augmented persons.
function TsvcRest.GetPersons:TObjectList<TAugmentedPerson>;
 Result:=dmMain.ORM.QueryList<TAugmentedPerson>('SELECT p.ID as ID, p.Name as Name, '+
           ' CompanyID, c.Name as CompanyName '+
           'FROM uData.TPerson p, uData.TCompany c '+
           'WHERE c.ID=p.Company');

This will make a query, augmenting the person data with a company name and returning it as a JSON object to the REST client.

This is all well and fine.

But lets say that the REST interface wants to return this list of TAugmentedPerson’s as XML?

This is now easily done in kbmMW by adding a responseMimeType to the kbmMW_Rest attribute of the GetPersons method.

[kbmMW_Service('name:REST, flags:[listed]')]
TsvcRest = class(TkbmMWCustomHTTPSmartService)
   [kbmMW_Rest('method:get, path:persons, responseMimeType:application/xml')]
   function GetPersons:TObjectList<TAugmentedPerson>;

This will result in simple XML document representing the resulting list of TAugmentedPerson’s. You can ask kbmMW to add XML declarations, namespaces and types if you want to by adding the properties declared:true, typed:true to the kbmMW_Rest method attribute.

But looking at the XML, it is still not perfect. It’s outer node is called TObjectList<person>, which is not a terribly nice tag name for an XML node. We are missing a way to redefine how kbmMW is to name the TObjectList<TAugmentedPerson> class.

Usually one would use the kbmMW_Root attribute in combination with our own class definition, to specify any name changes to root elements when marshalling data into or out from object instances, similarly to how TAugmentedPerson was defined.

However since we do not define TObjectList<TAugmentedPerson> anywhere (it is implicitely being defined as the result from our ORM.QueryList call, we have no place to specify our settings/attributes for that particular class.

Next version of kbmMW provides a new kbmMW_Alias attribute which handles this issue.

Basically what it does is to declare any class as an attribute wise alias to any other class/classes, like this

TAugmentedPersonList = class(TObjectList<TAugmentedPerson>);

The kbmMW_Alias can have zero or one argument. If an argument is given, it can be a class reference, or an array of class references. If no argument is given, kbmMW automaticallyh defines TAugmentedPersonList to be an alias to TObjectList<TAugmentedPerson> due to the class inheritance.

As we never define TObjectList<TAugmentedPerson> anywhere, we can not refer to it as a class reference, why we use kbmMW’s way to implicitely determine the class by not providing any arguments for the kbmMW_Alias attribute.

In reality we will usually never instantiate any TAugmentedPersonList instances. It is only being used as a “placeholder” for defining attributes (on the class level) on types we don’t directly declare ourselves, like the TObjectList<TAughmentedPerson>.

Now the xml will look pretty, with the outer node named <persons> containing a number of inner nodes named <person> which each of them includes the companyName in addition to other TPerson related data.

As a side note, the  [kbmMW_VirtualTable] attribute can now also take an argument, namely the actual database class for which this class is a virtual class for.

It would be possible to define  [kbmMW_VirtualTable(TPerson)]

It informs kbmMW about that any queries made for TAugmentedPerson (which is not really a table found in the database), where the ORM can not deduce from any kbmMW SQL query statement, where to pickup data from, then it should use TPerson as the goto data table.

So this is now legal:


It will return first found record in the person table, which matches the person named Kim and return that as a TAugmentedPerson instance.

Only fields matching will be filled. Hence in this case the CompanyName value is null since we did not provide any value for it via the query.

But we are getting an object instance which allows us to add our own value for CompanyName, thus in practice augmenting the TPerson look alike object with additional information.


REST easy with kbmMW #8 – Database 3

In previous articles we have seen how easy it is to use kbmMW’s ORM to maintain database structures and access and manipulate data.

Next release of kbmMW continues to extend on the ORM with additional features designed to make typical chores easy.

Most often, you want records to disappear from a table the moment you call ORM’s delete methods.

But sometimes, for example when you are referencing the record from other tables, it would be nice to retain the record silently, but keep it out of the result set of most queries.

Some databases supports this the hard way by using referential integrity, which means you will simply not be allowed to delete the record if some other table reference it.

That leaves it entirely up to the developer to manually manage when to show the record and when not to.

kbmMW’s ORM takes a slightly different approach to the problem. What if you define a field in the class that will flag if the record is to be considered deleted or not, and tell kbmMW that it should take that field into account when operating that particular class?

Next version will allow you to do just that. So instead of actually deleting the record, kbmMW will automatically flag it as deleted, AND automatically keep the record out of the queries result sets, regardless if you use higher level methods to operate the data, or lowerlevel kbmMW SQL statements.

The following is a sample class holding images and other stuff. Notice the kbmMW_Table attribute. It now also contains some new settings:


[kbmMW_Table('name:image, defaultDeleteMethod:mark, deleteMarkProperty:Deleted, deleteMarkValue:true')]
TImage = class // this unit is called uData
   procedure SetBlob(AValue:TMemoryStream); virtual;
   constructor Create; virtual;
   destructor Destroy; override;

   [kbmMW_Field('name:id, primary:true, generator:shortGuid',ftString,40)]
   property ID:kbmMWNullable read FID write FID;

   property PID:string read FPersonID write FPersonID;

   property Description:kbmMWNullable read FDescription write FDescription;

   property Blob:TMemoryStream read FBlob write SetBlob;

   property Deleted:boolean read FDeleted write FDeleted;

Default value for defaultDeleteMethod is delete or default which means the same… just delete the record (the usual way).

However when setting it to mark, we tell kbmMW that we want kbmMW to mark the deletion of records by setting the value of a specific field to a specific value. Basically it can be most (non blob) types of field, and the value can also be chosen at will. In our case, we indicates that we want the Deleted boolean property to be the one that indicates if a record is deleted or not.

The moment we use ORM.Delete(…) on an TImage instance, the corresponding record will be marked as deleted, and if we search for TImage instances in the database using ORM, the deleted ones will not be returned to us.

So from the perspective of the developer, the delete seems to operate exactly the same as before, with the big exception, that the records are in fact still available in the table. The ORM just hides the deleted ones from us.

In other situations, you might actually want to delete the record the old fashioned way, but you would like also to have a copy of the deleted record in a backup or audit table.

This can also easily be done in kbmMW by setting defaultDeleteMethod to move.

[kbmMW_Table('name:image, defaultDeleteMethod:move, deleteMoveToTable:uData.TBackupImage')]
TImage = class

   [kbmMW_Field('name:id, primary:true',ftString,40)]
   property ID:kbmMWNullable read FID write FID;

Notice that we also provide a deleteMoveToTable setting, which points to the fully qualified name of the class that should act as the backup/audit table.

Each time we use kbmMW to delete a record, it will first be inserted into the database table named backupImage, and only then be deleted from the image table. All this will run in a single transaction, and if things goes wrong, a rollback will be forced to ensure the consistency between the backup table and the actual table is not violated during the insert/delete operation.

In the above example we have redefined the id field’s attributes, to ensure that there is no generators defined on it. The reason is that using kbmMW’s SQL statements to delete a record will automatically be rewritten to select into and delete. If any generator fields were defined, those would not be populated in such scenario, why kbmMW would raise an exception if generator fields were found. However if you do not use kbmMW’s SQL statements to delete records, its perfectly legal to have additional generator fields in the backup table. Those will then be populated automatically the usual way.

If you really really want to delete a record on a table where the class are using one of these alternative delete methods, you can add an option to make kbmMW just delete the record.



Assuming o is an instance of uData.TImage, and o is actually to be found in the table, then the record corresponding to o will be deleted from the table the old fashioned way.

The same option can be given to the Query methods, to allow showing a record that otherwise would not be returned, because it was marked as deleted.

If the move method was used, then you will have to query using the TBackupImage class to get to the deleted (but backed up) records.

ANN: kbmMW Professional and Enterprise Edition v. 5.03.00 released!

We are happy to announce v5.03 of our popular middleware for Delphi and C++Builder.

If you like kbmMW, please let others know! Share the word!

We strive hard to ensure kbmMW continues to set the bar for what an n-tier product must be capable of in the real world!

This release is fairly large and brings several new features:

  • Automatic database upgrade to match your ORM classes (please test carefully before deploying to production environments containing existing data!)
  • New! Template based binary parser for advanced bit fiddling
  • New! Detailed metadata extraction and creation on many supported databases, including SQLite, MSSQL, Oracle, PostgreSQL, MySQL, Interbase, Firebird
  • New! Virtual fields and tables in ORM
  • New! Thread safe configuration system for easy one style read/write access to configuration files and registry.
  • New! Debug visualizers for kbmMWNullable and kbmMWDateTime values.
  • New! CHM help files with 24800+ topics.
  • + Many many more additions and improvements and bugfixes for reported bugs

Please look in the end of this post for a detailed change list.

Professional and Enterprise Edition is available for all with a current active SAU. If your SAU has run out, please visit our shop to extend it with another 12 months.

CodeGear Edition is available for free, but only supports a specific Delphi/Win32 SKU, contains a limited feature set and do not include source.

Please visit to download.


kbmMW is the premiere n-tier product for Delphi, C++Builder and FPC on .Net, Win32, Win64, Linux, Java, PHP, Android, IOS, embedded devices, websites, mainframes and more.

Please visit for more information about kbmMW.


Components4Developers is a company established in 1999 with the purpose of providing high quality development tools for developers and enterprises. The primary focus is on SOA, EAI and systems integration via our flagship product kbmMW.

kbmMW is a portable, highly scalable, high end application server and enterprise architecture integration (EAI) development framework for Win32, ..Net and Linux with clients residing on Win32, .Net, Linux, Unix, Mainframes, Minis, Embedded and many other places. It is currently used as the backbone in hundreds of central systems, in
hospitals, courts, private, industries, offshore industry, finance, telecom, governements, schools, laboratories, rentals, culture institutions, FDA approved medical devices, military and more.


5.03.00 Sep 16 2017

Important notes (changes that may break existing code)
* Fixed Delphi C++ HPP generator errors related to kbmMWNullable.pas and kbmMWDateTime.pas
The changes needed to fix it for kbmMWNullable.pas unfortunately require
us to default unsupporting assigning of a variant directly to a kbmMWNullable.
However if you are using Delphi ONLY and will never use the C++Builder header files
you can add {$DEFINE KBMMW_DELPHI_ONLY} in
Then you can still assign a variant directly to a kbmMWNullable in Delphi.
The changes in kbmMWDateTime is using overloaded versions of methods
instead of using default value Math.NaN which is translated incorrectly
by the HPP emitter.
* Removed PrependTableName from all metadata classes and thus it may
error with missing property on opening forms/datamodules containing
metadata components. Ignore that specific property missing error and save.

New stuff
– Added support for defining root type for marshalled objects. Array or Object.
– Added support for using nth next best marshalling type if primary is not registered in known types.
– Added log to AutoRegisterServices in kbmMWServer.pas
– Added support for bit values in YAML. A bit value starts with b or B and contains only 0 or 1’s
– Added support for default metadata class for database adapters. It will be used when
no explicit metadata component has been linked to the connection pool.
– Added OnLoginSuccess and OnLoginFail events to TkbmMWAuthorizationManager.
– Added support for understanding bit values in TkbmMWObjectNotation.
– Added Path method to TkbmMWONCustomObject which will take a delimited path and
traverse the tree optionally adding needed objects on the way.
– Added support for custom properties and basic properties in AMQP.
– Added support for Default date/time in TkbmMWDateTime.
– Added Reset method to TkbmMWDateTime, completely clearing its value.
– Added additional constructors to TkbmMWDateTime allowing direct timezone information.
– Added Memory2Binary and a number of BitCount methods to TkbmMWPlatformMarshal.
– Added support for reference counted data in TkbmMWAutoValue.
– Added kbmMWGetApplicationVersionInfoAsString and kbmMWBackupFile global methods to kbmMWGlobal.pas.
– Added support for specifying quote in kbmMWQuoteString and kbmMWUnquoteString.
– Added support for different start and endquote in kbmMWImplode.
– Added kbmMWDigitCount2Multiplier, kbmMWUnsignedDigitCount, kbmMWSignedDigitCount and
kbmMWExplodeFloat to kbmMWGlobal.pas, which determines metadata of a float value.
– Added kbmMWBitStringToInteger and kbmMWIntegerToBitString to kbmMWGlobal.pas
– Added overloaded Get method to TkbmMWSmartClientORM requesting dataset from server,
returned as an object/list, and providing custom arguments.
– Added overloaded RunSQL methods to TkbmMWMemSQL allowing executing SQL directly on
one or more provided TDataset sources.
– Added support for multistatement execution in TkbmMWMemSQL. Statements are separated by semicolon.
– Added support for salting initial string or byte keys in kbmMWCipherHash.pas.
– Added Clone method to TkbmMWCustomDef in kbmMWConnectionPool.pas
– Added support for detecting deleted fields in TkbmMWFieldDefs.
– Added MetaGetDef and MetaRename functions to TkbmMWCustomMetaData.
– Added significant changes to TkbmMWCustomSQLRewriter, including datatype mapping
and rewriting of numerous statement types.
– Added DefaultMetaData and CurrentMetaData properties to TkbmMWCustomConnectionPool to
allow for using kbmMW specified default metadata, alternative specific assigned on.
– Added support for piping outcome of query thru internal SQL statement as postprocessing
in TkbmMWCustomPooledDataset. Syntax: somequery <!PIPE!> somepipestatement
somequery is the query sent to the backend database. The resultset from that
is the piped thri the kbmMW SQL type somepipestatement.
Use constant KBMMW_QUERYPIPE to add pipe statement.
– Added support for mwfdctStrictPrecision and mwfdctStrictSize in TkbmMWFieldDefs.ChangedFields.
Strict indicates values must match exactly.
– Added DeletedFields, DeleteByFieldName and GetByFieldName to TkbmMWFieldDefs.
– Added additional overloaded Rewrite methods to TkbmMWCustomSQLRewriter.
– Added Terminate to TkbmMWScheduledEvent to prematurely terminate ongoing execution.
– Added Delay method to IkbmMWScheduledEvent which can be called at any time
including during execution of the said event to add additional delay to the
coming run’s of the event.
– Added support for multistatements in kbmMWSQLite.pas
– Vastly expanded TkbmMWCustomSQLMetaData.
– Added support for readonly and virtual field attribute in TkbmMW_FieldAttribute (kbmMW_Field)
– Added new TkbmMW_VirtualFieldAttribute (kbmMW_VirtualField) to indicate field
which will show up in resultset but do not exist in datastore.
– Added CreateDBDataset to TkbmMWORM which will generate a TDataset
matching the referenced TkbmMWORMTable.
– Added CompatibleTable, GetUpgradeTableStatements, UpgradeTable to TkbmMWORM which
are used for checking if a class is compatible with the underlying datastore,
and which can either directly upgrade the underlying datastore or suggest
statements to make the upgrade happen. Use with caution on production systems!
– Vastly expanded kbmSQLRewriter.pas to support metadata, indexes, new statements etc.
– Added Reset method to kbmMWNullable to reset its contents.
– Added PrettyChar to TkbmMWCustomLogFormatter to be able to selectively
choose what each byte value should display in the log.
– Added additional Warning, Error and Fatal overloaded methods to TkbmMWLog.
– Added support for property AutoSplitLines in TkbmMWStringsLogManager.
– Added support for providing HTTP related values (mwatURL, mwatHost, mwatUserAgent,
mwatHeader (named item), mwatCookie (named item) as argument in smart services.
– Added support for new kbmMWConfiguration unit which provides access to automatically
load and optionally save configurations to various storages.
Either use Config.As…. methods directly, or specify attribute
[kbmMW_Config(‘path:a.b.c.value, direction:rw’)] on any
property or field in a class.
If the class descends from TkbmMWConfigurableObject, the field/property
will automatically receive the value as defined in the Config object,
when the class is instantiated, and similarly store the value back
to the Config object when the class instance is destroyed.
Classes not descending from TkbmMWConfigurableObject can also
take advantage of the attribute. Just make sure to
call Config.ReadConfig(TValue.From(self)); or Config.WriteConfig(TValue.From(self));
for example in AfterContruction and BeforeDestruction methods of your class.
Also register your class as a kbmMW known class.
– Added support for using kbmMW_Config attribute for arguments in smart services.
– Added new unit kbmMWBinaryParser which can be used for parsing binary data
according to a custom template. Check the blogs on
for info.
– Added new debug visualizers for kbmMWDateTime, kbmMWNullable,
kbmMWDuration and TkbmMWAutoValue values during debug.
– Added Object Notation based stats (kbmMWONStats) unit for
registering statistics in object notation format, which
hence can be saved and loaded as any of the object notation
streaming formats.

– Fixed scheduler so exceptions will not stop execution threads.
– Fixed incorrect Args[0] in REST transport stream. Now correctly contains called URL.
– Fixed detection of added and changed fields in TkbmMWFieldsList, and added detailed info about differences.
– Fixed XML namespace crash issue.
– Fixed REST streamformat incorrectly double translating UTF8
– Fixed deletemessage and rejectmessage when provinding a message already tentatively
popped resulted in message not being deleted/rejected, but instead leaked.
– Fixed TkbmMWDynamicLockFreeHashArray and siblings related to deadlock (due to using
locking without escalation support for performance reasons) and due to incorrect
management of capacity of GC generations.
– Fixed potential leaks happening on exceptions in certain places in kbmMWORM.
– Fixed occational A/V due to reporting triggering memory logging.
– Fixed REST handling of returned objects (bug introduced in 5.0.2)
– Fixed DOA adapter related to LOB
– Fixed TkbmMWStringBuilder.GetLastChar which amongst others affected YAML parsing.
– Fixed scheduler clean shutdown of defined events when removing them.
– Fixed initialdelay not respected in Scheduler.
– Fixed destruction shutdown bugs in Scheduler.
– Fixed YAML null parsing bug (hazeltine).
– Fixed various parsing bugs in YAML.
– Fixed time to execute calculation in kbmMWScheduler.pas.
– Fixed string offset issues for Linux.
– Fixed IOS TkbmMWTiming timebase issues.
– Fixed A/V bug in TkbmMWDOMXMLNameSpaceList during destruction, due to
non owned namespaces.
– Fixed IBO adapter compile errors.
– Fixed Delphi C++ HPP generator errors related to kbmMWNullable.pas and kbmMWDateTime.pas
The changes needed to fix it for kbmMWNullable.pas unfortunately require
us to default unsupporting assigning of a variant directly to a kbmMWNullable.
However if you are using Delphi ONLY and will never use the C++Builder header files
you can add {$DEFINE KBMMW_DELPHI_ONLY} in
Then you can still assign a variant directly to a kbmMWNullable in Delphi.
The changes in kbmMWDateTime is using overloaded versions of methods
instead of using default value Math.NaN which is translated incorrectly
by the HPP emitter.
– Removed PrependTableName from all metadata classes and thus it may
error with missing property on opening forms/datamodules containing
metadata components. Ignore that specific property missing error and save.
– Fixed some TkbmMWORM.ExistsTable overloads incorrectly calling CreateTable.
– Fixed TkbmMWORM.ListFromDataset returning undefined value upon error.
– Added UTCAsVariant, LocalAsVariant, LocalDateAsVariant and LocalTimeAsVariant
properties to TkbmMWDateTime.
– Fixed warning at installation of designtime package related to smart service setup.

Changes/minor additions
– Improved shutdown of transport, and scheduled events.
– Checked encryption and updated SQLite Server/Client demoes to support compression.
– Updated AMQPClient demo with sending with properties sample.
– Set AnonymousResult to default true for REST attributes.
– Improved kbmMWGetFileVersionInfoAsString to also support Android.
– Improved server side ForwardMessage, ForwardRequest, ForwardResponse when original message comes from client messaging transport.
– Improved client transport disconnect.
– Updated Metaxxxx methods on database adapters to take AOwner argument.
Typically it will be empty, but with index relations, it will hold table name.
– Improved support for providing NodeID in server side messaging transport, even
though contents is encrypted.
– Cleaned up kbmMWGlobal.pas by grouping all kbmMWTextxxxx methods as class methods in TkbmMWTextPChar,
and added similar set handling bytes as class methods in TkbmMWTextPByte.
– Improved kbmMWGetComputerName and kbmMWGetComputerModel to support additional platforms.
– Changed Save and Load methods of TkbmMWCustomStat to not take any field names.
Specialized versions of TkbmMWCustomStat will handle that.
– Improved REST streamformat marshalling.
– Improved TkbmMWClientTransactionResolver.
– Renamed TkbmMWCustomRewriter to TkbmMWCustomSQLRewriter.
– Improved stability of event execution in kbmMWScheduler.pas during exceptions.
– Optimized TkbmMWLockFreeHashArray to use generational garbage collection for
higher performance and concurrency.
– Starting to converting some utility threads (garbage collection and such) to
use be kbmMWScheduledEvent instead.
– Improved object marshalling.
– Changed default log level filter in TkbmMWCustomLogManager to [mwllBasic,mwllNormal].
– Changed default flush value in TkbmMWStreamLogManager to 0 (force each write to disk)
– Improvements added to kbmMWRTTI.pas
– Improved kbmMWDebugMemory.pas to detect when reporting is happening to avoid deadlocks.
– Enhanced TkbmMW_ArgAttribute (kbmMW_Arg) to allow for referencing specific argument index alternatively specific named argument.

ANN: kbmMemTable v. 7.77.10 Standard and Professional Edition released!

We are happy to announce the latest and greatest release of our memory table.

Whats new in 7.77.10 September 16 2017

  • Added support for SQL DDL statements:
    and some variations (ON instead of FOR, TABLE keyword
    optional in INDEX statement).
  • Added support for CASE WHEN THEN ELSE END in both forms.
  • Added support for NOT IN, NOT BETWEEN, NOT LIKE
  • Fixed CREATE TABLE issues.
  • Added support for SELECT INTO
  • Added support for SQL multistatements. Statements separated
    by ; (semicolon)
  • Added support for EXISTS TABLE and EXISTS INDEX
  • Added support for DEFAULT value in CREATE TABLE
  • Added support for UNIQUE constraint in CREATE TABLE
  • Improved SQL field datatype parsing.
  • Added support for OUT parameters in SQL custom functions.
  • Fixed SQLReplace (Replace) incorrect argument index.
  • Added SQLSplit (Split) custom SQL function to split strings.
  • Added SQLRegExp (RegExp) custom SQL function for pattern
    matching and splitting
  • Added SQLDataType (DataType) custom SQL function for splitting
    SQL datatype declaration.
  • Added Options:TkbmSQLOptions property to TkbmMemSQL.
    soOrderByNullFirst – Default Null orders last in comparison
    soOldFieldNamingSyntax – Revert to old field naming syntax
    soOldLikeSyntax – Revert to old wildcard style like syntax
    else use true SQL style format using % and ?.
  • Added multiple overloaded ExecSQL functions to TkbmMemSQL to
    allow easy one line calls. If source table names are not provided
    they will be named T1..Tn.
  • Changed to support multiple SQL parsing errors before erroring out.

Professional Edition is released with source and additional performance enhancement features to holders of an active kbmMW Pro/Ent Service and Update subscription (SAU).

A free CodeGear Edition can be found bundled with kbmMW CodeGear Edition
for specific Delphi versions.

kbmMemTable supports the following development environments:

  • RAD Studio Delphi/C++ 10.2 Tokyo
  • RAD Studio Delphi/C++ 10.1 Berlin
  • RAD Studio Delphi/C++ 10 Seattle
  • RAD Studio Delphi/C++ XE8
  • RAD Studio Delphi/C++ XE7
  • RAD Studio Delphi/C++ XE6
  • RAD Studio Delphi/C++ XE5
  • RAD Studio Delphi/C++ XE4
  • RAD Studio Delphi/C++ XE3
  • RAD Studio Delphi/C++ XE2
  • Lazarus 1.2.4 with FPC 2.6.4

And can be used on Android, IOS, Linux, OSX and Windows 32/64 bit platforms.

kbmMemTable is the premier high performance, high functionality in memory dataset for Delphi and C++Builder with kbmMemTable Professional topping the scales as being the worlds fastest!

If you have an up to date Service and Update (SAU) subscription, then you can immediately visit to download the latest kbmMemTable release.

If not, please visit our shop at and extend your SAU with another 12 months.

Im only half as wise as I were yesterday…

I had to tell my day job employer last week, that he should expect me to be only half as wise from this Wednesday and in all future.

Obviously that got some attention. The potential issues with employing a previously “full wit” but now halfwit, who expect no change in the salary, the potential issues with the planned applications to be made… do we now requite an additional halfwit to solve the same amount of work, or can the current halfwit work double shifts to make up for the loss of wisdom?

Actually the day was less than perfect.. and the night worse. It was one of those days that you just want to forget about as soon as possible.

So what is it all about?

Well… I’m nearing 50 years old, and all my years, I have had my good looks (according to myself), my healthy teeth s, and all of my wisdom that my 4 wisdom teeth s provide me with.

Then on one Wednesday I visited my dentist, and in absolutely no time, my wisdom was half ed. He pulled my two top dear and beloved wisdom teeth s, that has followed me for better and worse, without asking for much!

That was the beginning of a bad day.

We have a saying here in Denmark… bad things happens in streams. So obviously more had to happen.

Back at the office again, with a whole days of planned coding work in front of me, a bottle of coke zero ready, and the keyboard just waiting with excitement for my gentle touch, I decided to start with rescuing an ailing gaming laptop which is used for some specialized programming, but which motherboard is starting to make problems and refusing to start unless retried many times. I wanted to virtualize it using VMWare to my main development machine and then move it to some NAS drives.

Logging in, Microsoft told me that there were some updates for me, and VMWare also wanted to do some minor updates. Since my computers mostly run 24×7, and only fairly rarely are rebooted, I decided… ok.. let the update happen.

So reboot and update…. and reboot again….. and waiting… and waiting… and waiting…. while my blood pressure began to rise alarmingly for someone who couldn’t control his lips and who was drooling like a newborn baby. due to the anesthetic, but being a patriot, of course in the  Danish national colors… mostly red… and some white.

On top of it all, I of some reason has become allergic in the middle of everything… so my nose was playing catch with my mouth… about which one could produce most uncontrolled and unwanted fluids.

So sniffing, cursing and damning everything Microsoft, I sat there and waited and waited… until at some point I decided… it should have booted by now. But alas only a spinning wheel, which indicates that it is working on something. I know what it was working on… to make my day worse!

Ok… annoying… but relax maestro… you are the champ…. the computer champ. You can easily fix this little issue. That thought was the first sign of my lost wisdom.

Reboot… ….. ….. …….. ok.. that didn’t work.

Reset while rebooting…… Ahh… there is the nice advanced startup menu…. it has all sorts of tools to make my life easier and my computer work.

Lets first let it attempt to repair my startup problems.

Reboot….. Checking disk….. 1 hour later… done checking disk. No problems…. MS: “I think I have fixed your startup problem…. please try to reboot”… so… Reboot……waiting… waiting… waiting…. …. …. Argh… still not working.

Ok.. reboot twice with reset in between to access the advanced startup menu again. Next step… Start in safe mode…..Reboot…. Waiting… waiting… waiting………:ARRRGHHH.

And so my night continued. Then enabled boot log files to see what was causing the problem. Then spend countless of hours analyzing the situation. I didn’t really want to reinstall Windows from scratch again… it would take days to get all reinstalled again. Remember I have some 10-12 development environments and versions installed on it.

In late evening I started to panic… Ok… Ill go to the nearest open hypermarket and buy a new computer. Browsing what was available… and decided not to. If to buy something I like to buy something substantially better… not just more of the same… and basically… doing that would absolutely hurt my computer champ pride.

Then it was late dinner time, and it was my turn to put the plates on the table and serve the food made by my wife. Obviously one shouldn’t give such an amount of responsibility to someone like me, that was influenced in more than one way.

That resulted in loss of china. Dropped on the tile floor.

What I did get more wise about, was that mood do not improve in such situations. I learned that the hard way.

After dinner and cleaning up and trying to forget about it all for just a moment, back on death row with my stubborn computer.

Going thru all well meaning guides about the topic on the internet, and waiting… wai…wa… w…. zzzzzz…. F…. is it still not working!!!!

I gave up. I decided to reinstall Windows by issuing a fresh install, but keeping my so called “personal files”. I was worrying about the not so personal files more!

Whoaa… it has installed… let it …. Reboot!…… and waiting….waiting…. F.. F… SAKE!

It STILL DO NOT get past the spinning wheel!

To wrap the story up, I ended ripping the SSD drive from an external casing, and installing it into the computer, reinstalling a completely fresh Windows, hoping that tools like Laplink PCmover would make my life less miserable afterwards by moving applications over from my 2TB half full disk…to my….ehh…. that is gonna be a tight fit…. 256GB  SSD drive.

Darned… it was not going to be able to work the night (well now it was morning) over. I need a bigger disk to restore to.

And that is just about where I am right now. A 4TB disk richer, but probably around 10 years older and with only half my wisdom left.

So dear Components4Developer friends, dear Danvægt friends and dear family… please bear with me!