Seite 1 von 3

Firebird 3 UDR in Pascal/Delphi

Verfasst: Do 26. Apr 2018, 02:13
von vr2
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

Re: Firebird 3 UDR in Pascal/Delphi

Verfasst: Do 26. Apr 2018, 09:40
von martin.koeditz
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

Re: Firebird 3 UDR in Pascal/Delphi

Verfasst: Do 26. Apr 2018, 17:55
von vr2
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

Re: Firebird 3 UDR in Pascal/Delphi

Verfasst: Mo 30. Apr 2018, 20:12
von vr2
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.

Re: Firebird 3 UDR in Pascal/Delphi

Verfasst: So 13. Okt 2019, 02:38
von vr2
Hier gibt es Neuigkeiten. Norbert SG, 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

Re: Firebird 3 UDR in Pascal/Delphi

Verfasst: Fr 1. Nov 2019, 04:41
von vr2
Eins der verlinkten D10-Projekte erzeugt eine externe SP namens gen_rows, die zwischen den beiden Eingabeparametern start_n und end_n hochzählt und zu jeder Zahl einen Satz ausgibt.

1. https://github.com/Arcantar/FirebirdSQL ... enRows.pas in D10 übersetzen.
2. Das erzeugt eine pascaludr.dll und eine "SP" gen_rows darin. Zur Nutzung kopiert man die dll ins Verzeichnis <Firebird_root>/plugins/udr des Firebird-Servers (ab Version 3). Das Verzeichnis udr gibt es nicht, muss man anlegen. Das ist der default-Ort für UDR-libs - wenn man das so macht, muss man firebirdseitig nichts weiter konfigurieren.
3. Die externe SP wird dann so in der DB registriert:

Code: Alles auswählen

create procedure gen_rows (
    start_n integer not null,
    end_n integer not null
) returns (
    result integer not null
)
    external name 'pascaludr!gen_rows'
    engine udr;
Danach kann man die SP nutzen. Bspw liefert ein

Code: Alles auswählen

select result from gen_rows(1, 10)
eine Tabelle der Zahlen von 1 bis 10. Um den Overhead zu testen, hab ich als Endwert 1 Mio angegeben, was alle Zahlen zwischen 1 und 1 Mio zurückgibt und außenrum summiert, das braucht auf einem halbwegs brauchbaren Test-Laptop 900 msek. Zum Vergleich hab ich eine native Firebird-SP geschrieben, die das gleiche macht. Die braucht reproduzierbar ~100 msek länger dafür. Overhead ist also zunächst kein Thema.

Grüße, Volker

Re: Firebird 3 UDR in Pascal/Delphi

Verfasst: Do 20. Mai 2021, 02:18
von vr2
Hi,

Es gibt ein 92-Seiten-Handbuch zum UDR-Schreiben in Pascal/Delphi in Russisch: https://www.ibase.ru/files/firebird/udr.pdf
Mäh. Seit Juli 2019. Wieso steht das nirgendwo? In der Zeit hätte ich das pdf Wort für Wort mit leo übersetzen können :D

Ich check mal, ob sich die Übersetzung sponsorn lässt.

Gruß Volker

Re: Firebird 3 UDR in Pascal/Delphi

Verfasst: Fr 28. Mai 2021, 08:05
von martin.koeditz
Hallo Volker,

bist du hier schon mit Alexey in Kontakt? Sonst hake ich mal nach, ob wir die Originale Docbook / AsciiDoc-Quellen bekommen können. Dann ist die Übersetzung vermutlich nicht allzu schwierig.

Gruß
Martin

Re: Firebird 3 UDR in Pascal/Delphi

Verfasst: Mo 31. Mai 2021, 03:50
von vr2
Hallo Martin,

Du meinst Alexey Kovyazin von IBSurgeon? Nee - betreut der das? Der Autor des Manuals ist Denis Simonov. Jedenfalls, das Ding in englisch oder deutsch, wenn das einfacher ist, wär super. Dann könnte ich hier einige UDR-Threads weiterführen ;-)

Grüße, Volker

Re: Firebird 3 UDR in Pascal/Delphi

Verfasst: Mo 31. Mai 2021, 08:43
von martin.koeditz
Moin Volker,

Alexey und Denis haben mir die Quellen zur Verfügung gestellt. Ich werde die Struktur im Laufe der Woche in das passende Format überführen.

Gruß
Martin