Subject | UDF for GUID Works! |
---|---|
Author | Ritchie Annand |
Post date | 2007-05-04T16:11:49Z |
I wrote together a UDF to get binary data... well, specifically GUIDs,
in and out of the database, by thieving some of the functions Borland
wrote for Linux.
You register this by sticking GUIDUDF.DLL in the UDF directory of
Firebird and running these two statements on that database:
declare external function KeyToUUID char(16) returns cstring(38)
free_it entry_point 'KeyToUUID' module_name 'GUIDUDF';
declare external function UUIDToKey cstring(38) returns char(16)
free_it entry_point 'UUIDToKey' module_name 'GUIDUDF';
You can then use it like this
SELECT * FROM MY_TABLE WHERE MY_PRIME=
UUIDToKey('{513C5459-F170-4474-9536-AC703E45B2B7}')
SELECT KeyToUUID(MY_PRIME),DESCRIPTION FROM MY_TABLE;
... enjoy!
library GUIDUDF;
uses
SysUtils,
Classes,
GUIDUDFFunctions in 'GUIDUDFFunctions.pas';
exports
UUIDToKey,
KeyToUUID;
{$R *.res}
begin
end.
{--------------------------------}
unit GUIDUDFFunctions;
interface
function ib_util_malloc(l: integer): pointer; cdecl; external
'ib_util.dll';
function UUIDToKey(AText: PChar): PChar; cdecl; export;
function KeyToUUID(AKey: PChar): PChar; cdecl; export;
implementation
uses
SysUtils;
procedure ConvertTextToGUID(AText: PChar; AResult: PChar);
procedure InvalidGUID;
begin
raise Exception.Create('Invalid GUID');
end;
function HexChar(c: Char): Byte;
begin
case c of
'0'..'9': Result := Byte(c) - Byte('0');
'a'..'f': Result := (Byte(c) - Byte('a')) + 10;
'A'..'F': Result := (Byte(c) - Byte('A')) + 10;
else
InvalidGUID;
Result := 0;
end;
end;
function HexByte(p: PChar): Char;
begin
Result := Char((HexChar(p[0]) shl 4) + HexChar(p[1]));
end;
var
i: Integer;
begin
if ((StrLen(AText) <> 38) or (AText[0] <> '{')) then InvalidGUID;
Inc(AText);
for i := 0 to 3 do
AResult[i] := HexByte(AText+(3-i)*2);
Inc(AText, 8);
Inc(AResult, 4);
if AText[0] <> '-' then InvalidGUID;
Inc(AText);
for i := 0 to 1 do
begin
AResult^ := HexByte(AText+2);
Inc(AResult);
AResult^ := HexByte(AText);
Inc(AResult);
Inc(AText, 4);
if AText[0] <> '-' then InvalidGUID;
inc(AText);
end;
AResult^ := HexByte(AText);
Inc(AResult);
Inc(AText, 2);
AResult^ := HexByte(AText);
Inc(AResult);
Inc(AText, 2);
if AText[0] <> '-' then InvalidGUID;
Inc(AText);
for i := 0 to 5 do
begin
AResult^ := HexByte(AText);
Inc(AResult);
Inc(AText, 2);
end;
end;
function UUIDToKey(AText: PChar): PChar;
begin
Result := ib_util_malloc(16);
try
ConvertTextToGUID(AText,Result);
except
Result[0] := #0;
end;
end;
function KeyToUUID(AKey: PChar): PChar;
var
GUID : TGUID;
begin
Move(AKey^,GUID,SizeOf(GUID));
Result := ib_util_malloc(38+1);
StrLFmt(PChar(Result),
38,'{%.8x-%.4x-%.4x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x}', // do not
localize
[GUID.D1, GUID.D2, GUID.D3, GUID.D4[0], GUID.D4[1], GUID.D4[2],
GUID.D4[3],
GUID.D4[4], GUID.D4[5], GUID.D4[6], GUID.D4[7]]);
end;
end.
in and out of the database, by thieving some of the functions Borland
wrote for Linux.
You register this by sticking GUIDUDF.DLL in the UDF directory of
Firebird and running these two statements on that database:
declare external function KeyToUUID char(16) returns cstring(38)
free_it entry_point 'KeyToUUID' module_name 'GUIDUDF';
declare external function UUIDToKey cstring(38) returns char(16)
free_it entry_point 'UUIDToKey' module_name 'GUIDUDF';
You can then use it like this
SELECT * FROM MY_TABLE WHERE MY_PRIME=
UUIDToKey('{513C5459-F170-4474-9536-AC703E45B2B7}')
SELECT KeyToUUID(MY_PRIME),DESCRIPTION FROM MY_TABLE;
... enjoy!
library GUIDUDF;
uses
SysUtils,
Classes,
GUIDUDFFunctions in 'GUIDUDFFunctions.pas';
exports
UUIDToKey,
KeyToUUID;
{$R *.res}
begin
end.
{--------------------------------}
unit GUIDUDFFunctions;
interface
function ib_util_malloc(l: integer): pointer; cdecl; external
'ib_util.dll';
function UUIDToKey(AText: PChar): PChar; cdecl; export;
function KeyToUUID(AKey: PChar): PChar; cdecl; export;
implementation
uses
SysUtils;
procedure ConvertTextToGUID(AText: PChar; AResult: PChar);
procedure InvalidGUID;
begin
raise Exception.Create('Invalid GUID');
end;
function HexChar(c: Char): Byte;
begin
case c of
'0'..'9': Result := Byte(c) - Byte('0');
'a'..'f': Result := (Byte(c) - Byte('a')) + 10;
'A'..'F': Result := (Byte(c) - Byte('A')) + 10;
else
InvalidGUID;
Result := 0;
end;
end;
function HexByte(p: PChar): Char;
begin
Result := Char((HexChar(p[0]) shl 4) + HexChar(p[1]));
end;
var
i: Integer;
begin
if ((StrLen(AText) <> 38) or (AText[0] <> '{')) then InvalidGUID;
Inc(AText);
for i := 0 to 3 do
AResult[i] := HexByte(AText+(3-i)*2);
Inc(AText, 8);
Inc(AResult, 4);
if AText[0] <> '-' then InvalidGUID;
Inc(AText);
for i := 0 to 1 do
begin
AResult^ := HexByte(AText+2);
Inc(AResult);
AResult^ := HexByte(AText);
Inc(AResult);
Inc(AText, 4);
if AText[0] <> '-' then InvalidGUID;
inc(AText);
end;
AResult^ := HexByte(AText);
Inc(AResult);
Inc(AText, 2);
AResult^ := HexByte(AText);
Inc(AResult);
Inc(AText, 2);
if AText[0] <> '-' then InvalidGUID;
Inc(AText);
for i := 0 to 5 do
begin
AResult^ := HexByte(AText);
Inc(AResult);
Inc(AText, 2);
end;
end;
function UUIDToKey(AText: PChar): PChar;
begin
Result := ib_util_malloc(16);
try
ConvertTextToGUID(AText,Result);
except
Result[0] := #0;
end;
end;
function KeyToUUID(AKey: PChar): PChar;
var
GUID : TGUID;
begin
Move(AKey^,GUID,SizeOf(GUID));
Result := ib_util_malloc(38+1);
StrLFmt(PChar(Result),
38,'{%.8x-%.4x-%.4x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x}', // do not
localize
[GUID.D1, GUID.D2, GUID.D3, GUID.D4[0], GUID.D4[1], GUID.D4[2],
GUID.D4[3],
GUID.D4[4], GUID.D4[5], GUID.D4[6], GUID.D4[7]]);
end;
end.