[yunqa.de] Re: Help recompile NOCASE collation as loadable extension

  • From: Delphi Inspiration <delphi@xxxxxxxx>
  • To: yunqa@xxxxxxxxxxxxx
  • Date: Thu, 15 Dec 2011 10:21:14 +0100

On 14.12.2011 21:52, Tom Holden wrote:

> I just don't have the gray matter or the software to do this. Can
> somebody help? I would like the NOCASE collation in a loadable extension
> for SQLiteSpy but given the name RMNOCASE.

Below (and attached) is a simple Delphi project that implements a
DISQLite3 extension with a NOCASE collation. You can rename the
collation as you like by changing the 'RMNOCASE' string.

Use DISQLite3 Pro and the Delphi version of your choice to compile it
into a Win32 DLL and register it with SQLiteSpy.

Ralf

----------------------

{ Simple loadable extension project for DISQLite3. It implements
  a single collation sequence which mimics the built-in NOSORT order.

  Note that extensiona muar use the "DISQLite3Ext" unit instead of
  "DISQLite3Api". This is an important difference. Dynamically loaded
  extensions should always use "DISQLite3Ext". Only statically linked
  additions to an application should use "DISQLite3Api".

  If you want your code to work as either a statically linked or a
  dynamically loaded module, the you will need to use $IFDEFS to use the
  appropriate unit.

  http://www.yunqa.de }
library DISQLite3_Extension_Collate_NOCASE;

{$I DI.inc}
{$I DISQLite3.inc}

uses
  {$IFDEF FastMM}{$I FastMM_uses.inc}{$ENDIF}
  DISystemCompat, SysUtils,
  DISQLite3Ext; // Use the extension type definitions.

{ This variable stores the set of DISQLite3 API functions and
  procedures. The variable name "DISQLite3Api" is choosen on purpose
  so it is easier to reuse this code inside a regular, non-extension
  project. }
var
  DISQLite3Api: sqlite3_api_routines_ptr;


//----------------------------------------------------------------------------

{ This "nocase" compare function is a copy of SQLite's built-in
  function. }
function CompareNoCase_func(
  UserData: Pointer;
  l1: Integer;
  const s1: Pointer;
  l2: Integer;
  const s2: Pointer): Integer;
begin
  if l1 > l2 then
    l1 := l2;
  Result := DISQLite3Api^.sqlite3_strnicmp(s1, s2, l1);
  if Result = 0 then
    Result := l1 - l2;
end;

//------------------------------------------------------------------------------

{ This is the extension entry point and is usually the only exported
  function in a DISQLite3 loadable library. DISQLite3 invokes this
  function once when it loads the extension.

  Use this function to create new functions, collating sequences, and
  virtual table modules. }
function sqlite3_extension_init(
  DB: sqlite3_ptr;
  pzErrMsg: PPAnsiChar;
  pApi: sqlite3_api_routines_ptr): Integer;
begin
  { Store the set of published API functions and procedures to the
    "DISQLite3Api" variable. }
  DISQLite3Api := pApi;
  { Register the "reverse" collation sequence. }
  DISQLite3Api.sqlite3_create_collation_v2(
    DB, 'RMNOCASE', SQLITE_UTF8, nil, CompareNoCase_func, nil);
  { Return success. }
  Result := SQLITE_OK;
end;

exports
  sqlite3_extension_init;

begin
  {$IFDEF FastMM}{$I FastMM_init.inc}{$ENDIF}
  // Nothing to initialize here.
end.

{ Simple loadable extension project for DISQLite3. It implements
  a single collation sequence which mimics the built-in NOSORT order.

  Note that extensiona muar use the "DISQLite3Ext" unit instead of
  "DISQLite3Api". This is an important difference. Dynamically loaded
  extensions should always use "DISQLite3Ext". Only statically linked
  additions to an application should use "DISQLite3Api".

  If you want your code to work as either a statically linked or a
  dynamically loaded module, the you will need to use $IFDEFS to use the
  appropriate unit.

  http://www.yunqa.de }
library DISQLite3_Extension_Collate_NOCASE;

{$I DI.inc}
{$I DISQLite3.inc}

uses
  {$IFDEF FastMM}{$I FastMM_uses.inc}{$ENDIF}
  DISystemCompat, SysUtils,
  DISQLite3Ext; // Use the extension type definitions.

{ This variable stores the set of DISQLite3 API functions and
  procedures. The variable name "DISQLite3Api" is choosen on purpose
  so it is easier to reuse this code inside a regular, non-extension
  project. }
var
  DISQLite3Api: sqlite3_api_routines_ptr;

  //----------------------------------------------------------------------------

{ This "nocase" compare function is a copy of SQLite's built-in
  function. }
function CompareNoCase_func(
  UserData: Pointer;
  l1: Integer;
  const s1: Pointer;
  l2: Integer;
  const s2: Pointer): Integer;
begin
  if l1 > l2 then
    l1 := l2;
  Result := DISQLite3Api^.sqlite3_strnicmp(s1, s2, l1);
  if Result = 0 then
    Result := l1 - l2;
end;

//------------------------------------------------------------------------------

{ This is the extension entry point and is usually the only exported
  function in a DISQLite3 loadable library. DISQLite3 invokes this
  function once when it loads the extension.

  Use this function to create new functions, collating sequences, and
  virtual table modules. }
function sqlite3_extension_init(
  DB: sqlite3_ptr;
  pzErrMsg: PPAnsiChar;
  pApi: sqlite3_api_routines_ptr): Integer;
begin
  { Store the set of published API functions and procedures to the
    "DISQLite3Api" variable. }
  DISQLite3Api := pApi;
  { Register the "reverse" collation sequence. }
  DISQLite3Api.sqlite3_create_collation_v2(
    DB, 'RMNOCASE', SQLITE_UTF8, nil, CompareNoCase_func, nil);
  { Return success. }
  Result := SQLITE_OK;
end;

exports
  sqlite3_extension_init;

begin
  {$IFDEF FastMM}{$I FastMM_init.inc}{$ENDIF}
  // Nothing to initialize here.
end.

Other related posts: