Entw.: RESTServer-Optimierung (02)

Neben den üblichen Optimierungen bei den Datenbankzugriffen läßt sich ein RESTServer, der eine Oracle-Datenbank verwendet, noch viel weitergehender optimieren. Hier wird gezeigt, wie man aus einem Programm heraus ein Oracle-Packages direkt verwendet.

Diese Technik läßt sich ebenfalls für alle Anwendungsfälle im Oracle-Umfeld nutzen, wo schnelle Ausführungszeiten gefordert werden. Dies sind u.A.:

  • → Migrationen von unterschiedlichen Datenbankmodellen (Oracle-to-Oracle). Dabei wird PL/SQL als Script-Sprache verwendet.
  • → Pflege von Datenmodellen mit einfacher Update-Möglichkeit von unterschiedlichen Versionen eines Datenbankmodells. Besonders interessant ist, dass man den Benutzer bzw. Administrator durch graphische Komponenten unterstützen kann.
  • → Durchführen von Datenbank-Backups durch die Applikationen selber.

Als Beispiel-Package wird PLSQL-Utils verwendet. Speziell sollen die PL/SQL-Prozeduren eingesetzt werden, die frei definierbare Select's ausführen und direkt JSON-Ergebnisse liefern.

Oracle Package Wizard - Step 1Oracle Package Wizard 1

Nach dem Aufruf des Oracle Package Wizard's aus dem Tool-Menü heraus wird folgende Seite als erstes angezeigt.

Oracle Package Wizard - Step 2Oracle Package Wizard 2

Im zweiten Schritt werden alle verfügbaren Packages angezeigt. Durch Setzen von Checkbox-Hacken wird bestimmt, welche Prozeduren bzw. Funktionen eines Packages zu verwenden sind. Zu diesen Prozeduren bzw. Funktionen wird später Source-Code erzeugt, der die Verwendung aus Delphi-Programmen heraus ermöglicht.

Oracle Package Wizard - Step 3Oracle Package Wizard 3

Zum Abschluss können noch einige spezielle Eigenschaften zur Source-Code-Erzeugung gesetzt werden.

Der Package-Wizard von ODAC der Firma devart liefert abschliessend folgenden Code:

// This unit was generated by Oracle Package Wizard and
// contains wrapper class for PL/SQL Package FMS.JSON_UTIL_PKG
//
// Changes to this file may cause incorrect behavior and
// will be lost if the code is regenerated.
 
unit JsonUtilPkg;
 
interface
 
uses
  Windows, SysUtils, Classes, DB, DBAccess, Ora, OraPackage,
  FMTBcd, OraClasses, OraObjects, OraCall;
 
type
  TFmsJsonUtilPkg = class(TCustomOraPackage)
  public
    constructor Create(AOwner: TComponent); override;
    function RefCursorToJson(const PRefCursor: TOraCursor; const PMaxRows: double; const PSkipRows: double): TOraLob;
    function SqlToJsonSimple(const PSql: string; const PMaxRows: double; const PSkipRows: double): TOraLob;
    function SqlToJson(const PSql: string; const PParamNames: TOraNestTable; const PParamValues: TOraNestTable; const PMaxRows: double; const PSkipRows: double): TOraLob;
  end;
 
implementation
 
{ TFmsJsonUtilPkg }
 
constructor TFmsJsonUtilPkg.Create(AOwner: TComponent);
begin
  inherited;
  PackageName := 'FMS.JSON_UTIL_PKG';
end;
 
function TFmsJsonUtilPkg.RefCursorToJson(const PRefCursor: TOraCursor; const PMaxRows: double; const PSkipRows: double): TOraLob;
var
  ResultParam, PrefcursorParam, PmaxrowsParam, PskiprowsParam: TOraParam;
begin
  BeginExecPLSQL;
  try
    ResultParam := AddParam('RESULT', ftOraClob, ptOutput);
    PrefcursorParam := AddParam('P_REF_CURSOR', ftCursor, ptInput);
 
    PrefcursorParam.AsCursor := PRefCursor;
 
    PmaxrowsParam := AddParam('P_MAX_ROWS', ftFloat, ptInput);
    PmaxrowsParam.AsFloat := PMaxRows;
    PskiprowsParam := AddParam('P_SKIP_ROWS', ftFloat, ptInput);
    PskiprowsParam.AsFloat := PSkipRows;
    ExecProc('REF_CURSOR_TO_JSON');
    Result := ResultParam.AsOraClob;
    //-- PRefCursor := PrefcursorParam.AsCursor;
  finally
    EndExecPLSQL;
  end;
end;
 
function TFmsJsonUtilPkg.SqlToJsonSimple(const PSql: string; const PMaxRows: double; const PSkipRows: double): TOraLob;
var
  ResultParam, PsqlParam, PmaxrowsParam, PskiprowsParam: TOraParam;
begin
  BeginExecPLSQL;
  try
    ResultParam := AddParam('RESULT', ftOraClob, ptOutput);
    PsqlParam := AddParam('P_SQL', ftString, ptInput);
    PsqlParam.AsString := PSql;
    PmaxrowsParam := AddParam('P_MAX_ROWS', ftFloat, ptInput);
    PmaxrowsParam.AsFloat := PMaxRows;
    PskiprowsParam := AddParam('P_SKIP_ROWS', ftFloat, ptInput);
    PskiprowsParam.AsFloat := PSkipRows;
    ExecProc('SQL_TO_JSON_SIMPLE');
    Result := ResultParam.AsOraClob;
  finally
    EndExecPLSQL;
  end;
end;
 
function TFmsJsonUtilPkg.SqlToJson(const PSql: string; const PParamNames: TOraNestTable; const PParamValues: TOraNestTable; const PMaxRows: double; const PSkipRows: double): TOraLob;
var
  ResultParam, PsqlParam, PparamnamesParam, PparamvaluesParam, PmaxrowsParam, PskiprowsParam: TOraParam;
begin
  BeginExecPLSQL;
  try
    ResultParam := AddParam('RESULT', ftOraClob, ptOutput);
    PsqlParam := AddParam('P_SQL', ftString, ptInput);
    PsqlParam.AsString := PSql;
    PparamnamesParam := AddParam('P_PARAM_NAMES', ftDataSet, ptInput);
    PparamnamesParam.AsTable := PParamNames;
    PparamvaluesParam := AddParam('P_PARAM_VALUES', ftDataSet, ptInput);
    PparamvaluesParam.AsTable := PParamValues;
    PmaxrowsParam := AddParam('P_MAX_ROWS', ftFloat, ptInput);
    PmaxrowsParam.AsFloat := PMaxRows;
    PskiprowsParam := AddParam('P_SKIP_ROWS', ftFloat, ptInput);
    PskiprowsParam.AsFloat := PSkipRows;
    ExecProc('SQL_TO_JSON');
    Result := ResultParam.AsOraClob;
  finally
    EndExecPLSQL;
  end;
end;
 
end.