Our SQLite3/mORMot Framework has 100% UNICODE compatibility, that is compilation under Delphi 2009/2010/XE/XE2. The code has been deeply rewritten and tested, in order to provide compatibility with the String=UnicodeString paradigm of these compilers. But the code will also handle safely Unicode for older version, i.e. from Delphi 6 up to Delphi 2007.

Since our framework is natively UTF-8 (this is the better character encoding for fast text - JSON - streaming/parsing and it is natively supported by the SQLite3 engine), we had to establish a secure way our framework used strings, in order to handle all versions of Delphi (even pre-Unicode versions, especially the Delphi 7 version we like so much), and provide compatibility with the Free Pascal Compiler.

Some string types have been defined, and used in the code for best cross-compiler efficiency (avoiding most conversion between formats):
- RawUTF8 is used for every internal data usage, since both SQLite3 and JSON do expect UTF-8 encoding;
- WinAnsiString where WinAnsi-encoded AnsiString (code page 1252) are needed;
- Generic string for i18n (e.g. in unit SQLite3i18n), i.e. text ready to be used within the VCL, as either AnsiString (for Delphi 2 to 2007) or UnicodeString (for Delphi 2009/2010/XE/XE2);
- RawUnicode in some technical places (e.g. direct Win32 *W() API call in Delphi 7) - note: this type is NOT compatible with Delphi 2009/2010/XE/XE2 UnicodeString;
- RawByteString for byte storage (e.g. for FileFromString() function);
- SynUnicode is the fastest available Unicode native string type, depending on the compiler used (i.e. WideString before Delphi 2009, and UnicodeString since);
- Some special conversion functions to be used for Delphi 2009/2010/XE/XE2 UnicodeString (defined inside $ifdef UNICODE...$endif blocks);
- Never use AnsiString directly, but one of the types above.

Note that RawUTF8 is the preferred string type to be used in our framework when defining textual properties in a TSQLRecord and for all internal data processing. It's only when you're reaching the User Interface layer that you may convert explicitly the RawUTF8 content into the generic VCL string type, using either the Language. UTF8ToString method (from SQLite3i18n.pas unit) or the following function from SynCommons.pas:

/// convert any UTF-8 encoded String into a generic VCL Text
// - it's prefered to use TLanguageFile.UTF8ToString() in SQLite3i18n,
// which will handle full i18n of your application
// - it will work as is with Delphi 2009/2010/XE/XE2 (direct unicode conversion)
// - under older version of Delphi (no unicode), it will use the
// current RTL codepage, as with WideString conversion (but without slow
// WideString usage)
function UTF8ToString(const Text: RawUTF8): string;

Of course, the StringToUTF8 method or function are available to send back some text to the ORM layer.
A lot of dedicated conversion functions (including to/from numerical values) are included in SynCommons.pas. Those were optimized for speed and multi-thread capabilities, and to avoid implicit conversions involving a temporary string variable.

In fact, this enforce the n-tier layered architecture of the project:

  • RawUTF8 is to be used at Storage and Business layers;
  • string type for the User Interface (at the VCL level). 

Warnings during the compilation process are not allowed, especially under Unicode version of Delphi (e.g. Delphi 2010): all string conversion from the types above are made explicitly in the framework's code, to avoid any unattended data loss.

With such an implementation pattern, we keep all our code benefit from the strong typing feature of Delphi, whereas we can handle safely Unicode content even with older Ansi versions of Delphi.

Comments are welcome on our forum.