Firebird 3 UDR in Pascal/Delphi

Themen rund um den praktischen Einsatz von Firebird. Fragen zu SQL, Performance, Datenbankstrukturen, etc.

Moderator: thorben.braun

Antworten
vr2
Beiträge: 49
Registriert: Fr 13. Apr 2018, 00:13

Do 26. Apr 2018, 02:13

Hallo,

hat sich jemand von euch schon mit den user defined routines (UDR) von Firebird 3 beschäftigt? Sie sollen die alten UDFs ablösen und können im Gegensatz zu diesen auch auf der Datenbank operieren, ihren Attachment-/Transaktionskontext nutzen, was eine enorme Verbesserung ist und viele spannende Möglichkeiten eröffnet.

Bspw könnte man damit eine UDF schreiben, die eine Datei oder Daten von einer URL in eine Tabelle einliest oder als Blob zurückliefert, oder umgekehrt eine Tabelle in eine Datei exportiert, aber eben *von innerhalb der Datenbank ausgelöst*. Firebird bekäme damit eine universelle Schnittstelle zu externen Daten, Aufruf zb:

select import('daten.csv', 'tbl1') from rdb$database

Leider ist die Dokumentation dünn, und Programmierbeispiele in .pas nahezu nicht vorhanden. Es gibt
https://github.com/asfernandes/fbstuff/ ... piTest.dpr
und auf stackoverflow das hier
https://stackoverflow.com/questions/371 ... d-3-oo-api

aber für UDRs kenne ich nur die cpp-Programmbeispiele im Firebird3-Installationsverzeichnis, zb in examples\udr\Functions.cpp. Meine C++-Kenntnisse sind zu schlecht, um den Code ohne weiteres nach D10 zu konvertieren.

Ist jemand von euch schon weiter?

Grüße, Volker
Benutzeravatar
martin.koeditz
Beiträge: 121
Registriert: Sa 31. Mär 2018, 14:35

Do 26. Apr 2018, 09:40

Guten Morgen Volker,

leider habe ich auch nichts im Developer's Guide gefunden. Gibt es zu den UDR überhaupt Infos? Mir war das Feature gar nicht bewusst.

Gruß
Martin
Martin Köditz
it & synergy GmbH
vr2
Beiträge: 49
Registriert: Fr 13. Apr 2018, 00:13

Do 26. Apr 2018, 17:55

Hallo Martin,

es gibt diese Beschreibung des neuen OO-APis:
https://firebirdsql.org/file/documentat ... s-api.html

Im Installationsverzeichnis von Firebird 4! stimmen die Pfade (bei Firebird 3 fehlten die teilweise noch), es gibt dort
<firebird_root>\plugins - enthält u.a. die UDR-Engine und die Konfiguration dazu (udr_engine.dll und udr_engine.conf)
<firebird_root>\plugins\udr - enthält die UDR-dlls. Das ist der default-Ort - wenn das Verzeichnis nicht existiert, einfach anlegen. Libs, die man dort reinkopiert, brauchen nicht extra konfiguriert zu werden.

Das zugehörige Registrier-SQL wird in der DB ausgeführt. Die Registrierung hat sich gegenüber den alten UDFs geändert, bspw:

create function frac (
val double precision
) returns double precision
external name 'udf_compat!UC_frac'
engine udr;

Dabei ist in diesem Fall udf_compat der Name der lib, und UC_frac der Name der UDR-Funktion in der lib, die beiden werden durch Ausrufezeichen getrennt.

<firebird_root>\examples\interfaces - enthält u.a. 01.create.pas und 01.create.cpp. Das ist Beispielcode, mit dem die Nutzung des neuen APIs erläutert wird - DB erzeugen, Tabelle anlegen, Satz einfügen. Das ist schon mal ne ganze Menge. Die unit Firebird.pas, die in 01.create.pas benutzt wird, gibt es allerdings nicht.

Rätsel über Rätsel ;-)

Gruß, Volker
Zuletzt geändert von vr2 am Mo 14. Okt 2019, 02:02, insgesamt 1-mal geändert.
vr2
Beiträge: 49
Registriert: Fr 13. Apr 2018, 00:13

Mo 30. Apr 2018, 20:12

Ich ergänze mal diesen Thread, weil es gerade auf der Firebird-devel-Liste Hinweise und eine Nachfrage nach besserer Doku gab:

Code: Alles auswählen

1. Any call to FbException.catchException(nil, e) will raise Access Violation in catchException procedure.

function IUdrPluginImpl_getMasterDispatcher(this: IUdrPlugin): IMaster; cdecl;
begin
  try
    Result := IUdrPluginImpl(this).getMaster();
  except
    on e: Exception do FbException.catchException(nil, e); // There are 299 such places in code (with first nil parameter).
  end
end;


class procedure FbException.catchException(status: IStatus; e: Exception);
var
  statusVector: array[0..4] of NativeIntPtr;
  msg: AnsiString;
begin
  if (e.inheritsFrom(FbException)) then
    status.setErrors(FbException(e).getStatus.getErrors)
  else
  begin
    msg := e.message;

    statusVector[0] := NativeIntPtr(isc_arg_gds);
    statusVector[1] := NativeIntPtr(isc_random);
    statusVector[2] := NativeIntPtr(isc_arg_string);
    statusVector[3] := NativeIntPtr(PAnsiChar(msg));
    statusVector[4] := NativeIntPtr(isc_arg_end);

    status.setErrors(@statusVector);
  end
end;


2. On "msg := e.message" all unicode characters will be lost:
- E.Message is utf-16 string for Delphi 2009 and higher
- E.Message is ansi string for Delphi 2007 and lower
- E.Message is compiler switches dependent for freepascal 3.0.0 and higher (default is utf-8)

3. Maybe we need to put a sample of firebird.pas at github. It will allow other developers to patch it in more productive way than now.
vr2
Beiträge: 49
Registriert: Fr 13. Apr 2018, 00:13

So 13. Okt 2019, 02:38

Hallo,

Hier gibt es Neuigkeiten. Norbert Saint Georges, ein Firebird-Anwender, hat zwei D10-Projekte zum Thema UDR auf github gestellt:
https://github.com/Arcantar/FirebirdSQL_Sample

Teste die und berichte. Wer sich für das Thema interessiert, nur zu.

Grüße, Volker
Antworten