OAUTH2 Authentifizierung für ORDS REST Services

OAUTH2 Authentifizierung für ORDS REST Services

Oracle bietet über den ORDS (Oracle REST Data Services) die Möglichkeit REST Services in der Datenbank zu erstellen.

Um diese auch entsprechend zu schützen kann man den Zugriff darauf mittels einer OAUTH2 Authentifizierung einschränken. Die Authentifizierung und Autorisierung arbeiten mit Benutzern, Rollen und Berechtigungen (Privileges).

Der Aufbau ist dabei wie folgt:

Authentifizierung und Autorisierung

Abbildung 1: Rollen

Das bedeutet, ein Benutzer kann mehrere Rollen besitzen, welche ihm wiederum jeweils mehrere Berechtigungen zuweisen. Eine Berechtigung wiederum gilt für 1 oder mehrere Module (=Services) und darin eingebettete Ressourcen. Die Einschränkung auf Ressourcen wird allerdings nicht über eine Verknüpfung festgelegt, sondern einen Textfilter, welcher mit Regular Expressions arbeitet.

Die einzelnen Elemente können folgendermaßen angelegt werden:

Rolle

  • Per PL/SQL mit einem Aufruf der Prozedur create_role im Package ords.
  • Über das entsprechende REST Service Interface in APEX

Abbildung 1: Rollen

Berechtigung

  • Per PL/SQL mit einem Aufruf der Prozedur create_privilege im Package ords. Hier wird gibt es zwei Aufrufe, entweder wird nur 1 Rolle übergeben oder ein Array an Rollen.
  • Über das entsprechende REST Service Interface in APEX

Abbildung 2: Berechtigungen

Abbildung 3: Berechtigungen Detail

Berechtigungen Details

Zuweisungen der Berechtigung zum Modul werden mittels der Prozedur set_module_privilege im Package ords erstellt oder wie in Abbildung 3 zu sehen über das REST Service Interface in APEX.

Zuweisungen der Berechtigung zur jeweiligen Ressource werden mittels der Prozedur create_privilege_mapping im Package ords erstellt oder wie in Abbildung 3 zu sehen über das REST Service Interface in APEX.

 

ACHTUNG!!!

Es scheint hier einen Bug zu geben wenn ein Universal-Model verwendet wird – sprich „/*“.

Dieser wird dann nicht modulmäßig eingeschränkt und wirkt sich dann auch auf alle APEX Applikationen aus, welche dann potentiell nicht mehr aufgerufen werden können.

Benutzer

Benutzer können AUSSCHLIESSLICH per PL/SQL mittels der Prozedur create_client im Package oauth erzeugt werden!

Die Rolle muss dann ebenfalls per PL/SQL zugewiesen werden mittels der Funktion grant_client_role im Package oauth.

Die Tatsache, dass die Benutzer nicht über das Interface angelegt werden können, muss unbedingt berücksichtig werden.

Einsatz der angelegten Objekte

Um das Service nun zu nutzen muss eine Authentifizierung durchgeführt werden. Beim Anlegen des OAUTH Clients wird ein Benutzername übergeben. Mit diesem können dann die benötigten Benutzerdaten aus der Tabelle user_ords_clients geholt werden z.B. mit folgendem Statement:

SELECT client_id, client_secret FROM user_ords_clients WHERE name = 'NAME_DES_USERS';

Die client_id und das client_secret werden dann wiederum benötigt um den OAUTH Zugriffstoken zu erhalten. Dazu wird standardmäßig ein eigenes Webservice bereitgestellt, welches mit einer speziellen URL erreicht werden kann. Die URL setzt sich aus dem Basispfad zusammen und wird am Ende mit oauth/token ergänzt – z.B. https://www.myserver.at/ords/apex/oauth/token

Dieser URL werden client_id und client_secret als HTTP-Authentifizierung mitgegeben (User:Passwort), im Payload wird „grant_type=client_credentials“ mitgegeben. Als Antwort erhält man ein JSON mit folgenden Attributen:

  • access_token: der Token selbst
  • token_type: ist immer „bearer“ – muss mit angegeben werden mit dem Token
  • expires_in: Gültigkeitsdauer in Sekunden – standardmäßig 1 Stunde (dieser Wert kann nicht individuell je Service angepasst werden, nur global für alle Services dieser ORDS Instanz)

Beim Aufruf der eigentlichen Services welches durch die OAUTH Authentifizierung geschützt wird, wird dann im Header des Requests folgendes mitgegeben:

„Authorization: Bearer [OAUTH Token]“

OAUTH Token ist der vorhin mittels Webservice generierte Token. Falls der Token nicht mehr gilt (sprich die Gültigkeit abgelaufen ist oder der Token schlicht falsch ist) – gibt das Service einen HTTP 403 Forbidden Fehler zurück.

Die SQL WITH clause (oder Subquery Refactoring)

Die SQL WITH clause (oder Subquery Refactoring) wurde mit der Oracle 9i Release 2 Database eingeführt. Deren Benutzung ist seither Standard, da sie deutliche Vorteile bietet.

Mit der WITH clause wird eine temporäre Tabelle/View erstellt, auf die im Nachhinein zugegriffen werden kann.

Dadurch spart man sich bei komplexen SQL-Statments jede Menge an Code und macht ihn in der Regel auch lesbarer. Die temporäre Tabelle/View wird nur solang innerhalb eines SQL Statements verwendet, bis die Ausführung beendet ist.

Als Beispiel nehmen wir eine Employee und Department Tabelle.

Employees:

Departments:

 

Wir wollen nun alle Employees anzeigen, deren Standort sich in New York verbindet.

Standardmäßig benutzen wir ein Subselect da sich die Location in der Departments Tabelle befindet.

SELECT *
FROM emp e
WHERE e.DEPTNO in (SELECT d.DEPTNO from dept d where d.loc = 'NEW YORK');

Jetzt benutzen wir die WITH clause und erhalten das gleiche Ergebnis.

With w_dept_ny as
(SELECT /*+ materialize */ d.deptno
FROM dept d
WHERE d.loc = 'NEW YORK')
SELECT *
FROM emp e
join w_dept_ny d on e.deptno = d.deptno;

Seit Oracle 12c ist es möglich PL/SQL Functions und Procedures in eine WITH claus zu packen.

Dazu wird es noch einen gesonderten Blog Eintrag geben.

 

 

 

 

Business Continuity Management

Business Continuity Management

Wir möchten hiermit unsere Kunden, Partner und Lieferanten über unseren Umgang mit der aktuellen Situation zum COVID-19 Ausbruch informieren.

  • Wir verfügen über einen Business Continuity Plan sowie ein aktives Krisenmanagement, um auf die gegebene Situation zu reagieren und den Fortgang unserer Geschäftstätigkeiten sicherzustellen.
  • Unsere IT Infrastruktur zur Überwachung aller Kunden-Systeme ist über zwei professionelle Rechenzentren in unterschiedlichen Wiener Bezirken gespiegelt.
  • Alle Mitarbeiter nutzen einen virtuellen Desktop via Citrix. Das bedeutet, dass jeder Mitarbeiter mit seinem Laptop über eine verschlüsselte Verbindung von überall arbeiten kann, wo eine Internet Verbindung oder ein mobiles Netz zur Verfügung steht.
  • Die gesamte Mannschaft befindet sich aktuell dauerhaft im koordinierten Homeoffice. Notwendige Meetings werden ausschließlich über Video-Konferenzen abgehalten.
  • Zusätzlich zu unseren Kollegen, die ihren Arbeitsplatz dauerhaft in Salzburg und München haben, trägt die großflächige Verteilung via Homeoffice dazu bei, die Ansteckungsgefahr so gering wie möglich zu halten und die Verfügbarkeit unserer Experten weiterhin zu gewährleisten.
  • Für jene Kollegen, die sich in unserem Büro aufhalten, wurden die Arbeitsplätze weiträumig aufgeteilt, sodass sich pro Raum nur jeweils eine Person befindet.
  • Alle Mitarbeiter wurden über die aktuellen Hygienevorsichtsmaßnahmen informiert und werden laufend auf aktuellem Stand gehalten.

Wir beobachten und bewerten laufend die Situation und leiten entsprechende Handlungen daraus ab.

Gemeinsam schaffen wir auch die COVID-19 Herausforderung zu meistern.

Homeworking Arbeitsplätze der Mitarbeiter

Business Breakfast 2020 auf Herbst verschoben

Aufgrund der anhaltenden Corona-Virus Krise haben wir uns entschlossen, unsere alljährlich im Frühjahr stattfindende Business Breakfast Veranstaltungreihe abzusagen.

Wir hoffen, dass sich die Lage bald entspannt und wir die Veranstaltungsreihe im Herbst nachholen können.

 

 

wir haben eine neue Adresse

Wir haben uns verpflanzt. Schon wieder.

Nachdem wir erst vor vier Jahren in unser doppelt so großes Büro gezogen sind,
ist es jetzt wieder so weit uns zu verdoppeln.

Wir haben uns daher erneut verpflanzt und schlagen im Ares Tower unsere Wurzeln,
um weiter wachsen zu können.

Unsere neue Adresse:

DBConcepts GmbH
Ares Tower, Donau-City Straße 11
1220 Wien

Wir freuen uns von Ihnen zu hören!

 

 

Intel Cascade Lake und Oracle Database SE2 ein künftiges Risiko?

Wie schon bei vielen AMD Nutzern bekannt und beliebt setzt nun auch Intel auf die technischen Vorteile, welche ein Multichip Layout bietet.

Mit den seit Q2/2019 verfügbaren und nun langsam in den Markt auftauchenden Intel-Cascade-Lake-Mikroarchitektur Familie von 64-Bit-Mikroprozessoren für Server, stellt sich in Zukunft das Problem des lizenzkonformen Betriebs von Standard Edition 2 Datenbanken.

Diese Mehrkernprozessoren mit 4 bis 28 (SP) Kernen stellen die Nachfolger der Intel-Skylake-Mikroarchitektur-basierten Intel-Xeon-Prozessoren dar.

Sie werden jedoch im Gegensatz zu Ihren Vorgängern (obwohl in einem Gehäuse vergossen) Aufgrund ihres Layouts mit mehreren Prozessor Chips auf einer Platine nicht als Multichip Prozessoren gewertet.

Das neue Prozessor Layout ist derzeit bei der „Advanced Performance“ Serie verfügbar Xeon® Platinum 9282, 9242, 9222 und 9221.

Wir gehen davon aus, dass Intel diese Technogie noch weiter verbreiten wird.

Lizenzregeln

Es gibt zu Multichip Prozessoren eine seit 2007 bestehende Definition in den Oracle Lizenzverträgen, die in diesen Fällen nun nach vielen Jahren wieder zu Tragen kommt  ( nachzulesen unter der allgemeinen Prozessordefinition):

 

Bei der Lizenzierung von Oracle Programmen mit Standard Edition 2, Standard Edition One oder Standard Edition im Produktnamen (hiervon ausgenommen sind WebCenter Enterprise Capture Standard Edition, Java SE Abonnement, Java SE Support, Java SE Advanced and Java SE Suite) wird ein Prozessor mit einem belegten Socket gleichgesetzt; bei Modulen mit mehreren Chips hingegen wird jeder Chip mit einem belegten Socket gleichgesetzt.“

 

Somit haben wir die Situation, dass bei einer Nutzung von Intel-Cascade-Lake Prozessoren aus der Advanced Perfomance Linie für EINEN belegten Sockel ZWEI Prozessorlizenzen schlagend werden.

Weiters wären bei Maschinen, welche mit zwei solcher Prozessoren bestückt sind, das erlaubte Lizenzmaxima nicht mehr gegeben und eine Lizenz der Oracle Database Enterprise Edition notwendig!

Tipp: Es ist vor jedem Hardware-Upgrade zu prüfen, ob der Prozessor zum gewählten Lizenzmodell passt.

Auch bei einem Upgrade der Infrastruktur mit den besten Absichten kann der Lizenz- und Kosteneinsatz sich um das 20-fache erhöhen, sofern man wie oben beschrieben durch das Multi-Chip Layout gezwungen ist, von Standard Edition Database Lizenzierung auf Enterprise Edition Database Lizenzierung zu migrieren.

Die Liste der betroffenen Prozessoren finden Sie hier:

https://de.wikipedia.org/wiki/Intel_Xeon_(Cascade_Lake)

oder hier:

https://www.intel.de/content/www/de/de/design/products-and-solutions/processors-and-chipsets/cascade-lake/2nd-gen-intel-xeon-scalable-processors.html

Autor: Berhard Halbetel

Oracle APEX: WWV_FLOW_FND_USER_FK-Verletzung beim Importieren von Workspaces

Ich bin jüngst im Rahmen eines APEX-Projekts auf ein Problem gestoßen, für das ich im Oracle Support Portal keinen einzigen Eintrag finden konnte – nach einigem Überlegen und Testen aber auf eine relativ einfache Lösung gekommen bin.

Ausgangslage

Das erste Arbeitspaket im Rahmen des Projektes ist fertig entwickelt und soll dem Kunden zur Abnahme in der dafür von diesem bereitgestellten Test-Umgebung deployed werden. Da es in dieser Umgebung keine APEX-Entwicklungs-Umgebung gibt, sind die Sourcen per SQLplus, PL/SQL-Developer oder mit ähnlichen Tools zu deployen.

Nach der fehlerfreien Erstellung von Schemas, Tabellen, Packages etc. folgt der Import des APEX-Workspaces; das aus APEX exportierte Script hierfür schaut sinngemäß wie folgt aus:

set define off verify off feedback off
whenever sqlerror exit sql.sqlcode rollback
--------------------------------------------------------------------------------
--
-- ORACLE Application Express (APEX) export file
--
-- You should run the script connected to SQL*Plus as the Oracle user
-- APEX_050100 or as the owner (parsing schema) of the application.
--
-- NOTE: Calls to apex_application_install override the defaults below.
--
--------------------------------------------------------------------------------
begin
wwv_flow_api.import_begin (
p_version_yyyy_mm_dd=>'[DATE]'
,p_default_workspace_id=>276...332
);
end;
/
prompt WORKSPACE 276...332
--
-- Workspace, User Group, User, and Team Development Export:
-- Date and Time: [DATE_AN_TIME]
-- Exported By: ADMIN
-- Export Type: Workspace Export
-- Version: 5.1.2.00.09
-- Instance ID: 714...698
--
-- Import:
-- Using Instance Administration / Manage Workspaces
-- or
-- Using SQL*Plus as the Oracle user APEX_050100

begin
wwv_flow_api.set_security_group_id(p_security_group_id=>276...332);
end;
/
----------------
-- W O R K S P A C E
-- Creating a workspace will not create database schemas or objects.
-- This API creates only the meta data for this APEX workspace
prompt Creating workspace LEHM...
begin
wwv_flow_fnd_user_api.create_company (
p_id => 276...354
,p_provisioning_company_id => 276...332
,p_short_name => '[SHORT_NAME]'
,p_display_name => '[DISPLAY_NAME]'
,p_first_schema_provisioned => '[SCHEMA_NAME]'
,p_company_schemas => '[SCHEMA_NAMES]'
,p_account_status => 'ASSIGNED'
,p_allow_plsql_editing => 'Y'
,p_allow_app_building_yn => 'Y'
,p_allow_packaged_app_ins_yn => 'Y'
,p_allow_sql_workshop_yn => 'Y'
,p_allow_websheet_dev_yn => 'Y'
,p_allow_team_development_yn => 'Y'
,p_allow_to_be_purged_yn => 'Y'
,p_allow_restful_services_yn => 'Y'
,p_source_identifier => '[IDENTIFIER]'
,p_path_prefix => '[PATH_PREFIX]'
,p_files_version => 1
);
end;
/
----------------
-- G R O U P S
--
prompt Creating Groups...
begin
wwv_flow_api.create_user_groups (
p_id => 927...937,
p_GROUP_NAME => 'OAuth2 Client Developer',
p_SECURITY_GROUP_ID => [ID],
p_GROUP_DESC => 'Users authorized to register OAuth2 Client Applications');
end;
/
begin
wwv_flow_api.create_user_groups (
p_id => 927...936,
p_GROUP_NAME => 'RESTful Services',
p_SECURITY_GROUP_ID => [ID],
p_GROUP_DESC => 'Users authorized to use RESTful Services with this workspace');
end;
/
begin
wwv_flow_api.create_user_groups (
p_id => 927...912,
p_GROUP_NAME => 'SQL Developer',
p_SECURITY_GROUP_ID => [ID],
p_GROUP_DESC => 'Users authorized to use SQL Developer with this workspace');
end;
/
prompt Creating group grants...
----------------
-- U S E R S
-- User repository for use with APEX cookie-based authentication.
--
prompt Creating Users...
begin
wwv_flow_fnd_user_api.create_fnd_user (
p_user_id => '276...332',
p_user_name => 'ADMIN',
p_first_name => '',
p_last_name => '',
p_description => '',
p_email_address => '[MAIL_ADDRESS]',
p_web_password => '[PASSWORD_STRING]',
p_web_password_format => '[PASSWORD_FORMAT]',
p_group_ids => '',
p_developer_privs => 'ADMIN:CREATE:DATA_LOADER:EDIT:HELP:MONITOR:SQL',
p_default_schema => '[SCHEMA_NAME]',
p_account_locked => 'N',
p_account_expiry => to_date('[DATE_AND_TIME]','YYYYMMDDHH24MI'),
p_failed_access_attempts => 0,
p_change_password_on_first_use => 'Y',
p_first_password_use_occurred => 'Y',
p_allow_app_building_yn => 'Y',
p_allow_sql_workshop_yn => 'Y',
p_allow_websheet_dev_yn => 'Y',
p_allow_team_development_yn => 'Y',
p_allow_access_to_schemas => '');
end;
/
[MORE_USER_CREATION_STEPS]
prompt Check Compatibility...
begin
-- This date identifies the minimum version required to import this file.
wwv_flow_team_api.check_version(p_version_yyyy_mm_dd=>'[DATE]');
end;
/

begin wwv_flow.g_import_in_progress := true; wwv_flow.g_user := USER; end; 
/
[SOME_EMPTY_ANONYMOUS_BLOCKS]
begin
wwv_flow_api.import_end(p_auto_install_sup_obj => nvl(wwv_flow_application_install.get_auto_install_sup_obj, false));
commit;
end;
/
set verify on feedback on define on
prompt ...done

Das Problem

An der Stelle, wo der erste User-Account erstellt werden soll, schlägt die Script-Ausführung dann fehl:

ORA-02291: Integritäts-Constraint (APEX_050100.WWV_FLOW_FND_USER_FK) verletzt – übergeordneter Schlüssel nicht gefunden

ORA-06512: in „APEX_050100.WWV_FLOW_FND_USER_INT“, Zeile 2010

ORA-06512: in „APEX_050100.WWV_FLOW_FND_USER_API“, Zeile 328

ORA-06512: in Zeile 2

 

Eine Suche im Oracle Support Portal nach WWV_FLOW_FND_USER_FK liefert (heute am 14.01.2020) exakt Null Ergebnisse – es ist also Eigeninitiative gefragt.
Eine Web-Suche offenbart recht schnell, dass der genannte Foreign Key ein Verweis auf den Workspace ist – was einigermaßen überraschend ist, da der Abschnitt der Workspace-Erstellung aus dem Script mit PL/SQL procedure successfully completed erfolgreich durchgelaufen war.

 

Die Lösung

Auf die Lösung bin ich erst gestoßen als ich im PL/SQL-Developer jeden Schritt einzeln ausgeführt habe. Bereits nach dem ersten Block erkannte der Developer eine aktive offene Transaktion – dies ist an entsprechenden Icons zu erkennen.

Die nachfolgenden Schritte verursachten keinerlei Probleme – bis die erste User Group importiert werden sollte. Hier fiel dann auf, dass dem Developer zufolge die Transaktion verschwand. Und der nachfolgende Import von User Accounts schlug daraufhin mit der bereits beschriebenen Fehlermeldung fehl.

Als ich die User-Group-Erstellung ausließ, funktionierte auch der User-Account-Import wieder problemlos. 😊

Da die User Groups im Rahmen des genannten Projekts nicht weiter verwendet werden, ist die Lösung ausreichend: das Entfernen der Erstellung der User Groups aus dem Workspace-Erstellungs-Scripts.

Die Ursache

Die genaue Ursache lässt sich ohne den entschlüsselten Code des Packages WWV_FLOW_API nur schwer ermitteln – höchstwahrscheinlich fehlt in der Procedure CREATE_USER_GROUPS aber ein RAISE um einen auftretenden Fehler weiterzureichen…

 

Django – Part 1: Installation auf Ubuntu-Server mittels pip

Eine Möglichkeit zur Erstellung einer Webapplikation stellt unter anderem das OpenSource-Framework Django dar, welches als Grundlage die Programmiersprache Python verwendet.
Wie man dieses Framework installiert und zum Laufen bringt, soll folgender Beitrag zeigen.

Auf Ubuntu sollte Python schon installiert sein, mit folgendem Befehl kann man prüfen, welche Version konkret installiert ist:

python3 -V

Sollte Python noch nicht installiert sein, kann man dies über folgenden Befehl nachholen:

sudo apt install python3.6

Weiters benötigen wir das Paketverwaltungsprogramm von Python namens pip (akronym für pip installs packages).

sudo apt install python3-pip

Als weiteren Schritt installieren wir noch das Package python3-venv, mit dessen Hilfe eine virtuelle Python-Laufzeitumgebung erstellt werden kann.

sudo apt install python3-venv

Natürlich können alle drei Packages auf einmal installiert werden, sie wurden hier nur der Beschreibung halber aufgeteilt.

Der Befehl würde dann folgendermaßen aussehen:

sudo apt install python3.6 python3-pip python3-venv

Nachdem nun alle benötigten Ubuntu-Packages installiert sein sollten, erstellen wir nun einen Ordner, in welchem das neue Projekt angelegt werden soll:

mkdir ~/testapp

und navigieren in diesen Ordner:

cd ~/testapp

Als nächsten Schritt erstellen wir nun eine virtuelle Python-Laufzeitumgebung mit folgendem Befehl:

python3 -m venv testapp_venv

Einer der Vorteile einer virtuellen Python-Laufzeitumgebung für einzelne Projekte ist die separate Verwaltung einzelner Packages, deshalb ist dieser Schritt sehr empfohlen, aber nicht zwingend notwendig.

Um nun die virtuelle Umgebung zu aktivieren, ist folgender Befehl notwendig:

source testapp_venv/bin/activate

Der Name der virtuellen Umgebung sollte nun in runden Klammern im Terminal ersichtlich sein. Alle Aktionen, die nun ausgeführt werden, verwenden die Python-Sourcen der virtuellen Umgebung.

Als Nächstes installieren wir also die benötigten Django-Sourcen über pip in der neu erstellten virtuellen Python-Umgebung:

pip install django

Damit ist Django für diese virtuelle Umgebung installiert.

Will man die virtuelle Umgebung wieder verlassen, so kann man dies mit folgendem Befehl machen:

deactivate

Als letzten Schritt erstellen wir nun ein erstes Dummy-Projekt und nennen dieses app1.

Hat man zuvor die virtuelle Umgebung verlassen, so sollte man diese nun nochmals mittels

source ~/testapp/testapp_venv/bin/activate

aktivieren. Wurde der deactivate-Befehl nicht ausgeführt, ist man noch in der virtuellen Umgebung und kann direkt den Befehl zur Erstellung eines neuen Django-Projektes ausführen:

cd ~/testapp

django-admin startproject app1 .

Dadurch werden im aktuellen Ordner diverse für Django benötigte Unterordner und Dateien erzeugt. Die Struktur und Funktionsweise dieser Files werden in einem zukünftigen Blogartikel näher erläutert.

Aktuell wollen wir nur noch das Projekt einmal starten, wir rufen dazu aus der virtuellen Umgebung heraus folgenden Befehl auf:

python manage.py runserver localhost:8000

Öffnet man auf der Maschine nun einen Browser, sollte mittels der URL http://localhost:8000 oder http://127.0.0.1:8000 folgende Seite aufgebaut werden:

Damit ist die erste Django-App erstellt und es kann nun begonnen werden, diese auszubauen.

Doch dazu mehr im Teil 2.

Programmgesteuertes Verschieben des ODI Load Plan in einen bestimmten Ordner

Haben Sie schon einmal erlebt, dass Ihr Load Plan nicht dort ist wo Sie ihn hinterlegt haben?

Aufgrund der manchmal schlechten Implementierung der ODI-Studio Benutzeroberfläche kommt es sehr oft vor, dass jemand anderes (oder sogar Sie selbst) einen Load Plan an einen Ort verschoben hat, an dem er nicht sein sollte.

Wenn die entsprechende Warnung in den ODI Studio Einstellungen deaktiviert ist, erkennt der Entwickler nicht einmal, dass er verschoben wurde.

Sobald Sie dann das Chaos entdeckt haben könnte es auch noch schwierig sein den Load Plan wegen Tonnen von Szenarien in der ODI-Studio Ansicht „Ladepläne und Szenarien“ zurückzusetzen.

Aus diesem Grund habe ich ein nützliches Skript geschrieben, um einen Load Plan wieder an seinen richtigen Platz zu bringen.

Viel Spaß!

import oracle.odi.core.persistence.transaction.ITransactionStatus;
import oracle.odi.core.persistence.transaction.support.DefaultTransactionDefinition;
import oracle.odi.domain.runtime.scenario.finder.IOdiScenarioFolderFinder;
import oracle.odi.domain.runtime.scenario.OdiScenarioFolder;
import oracle.odi.domain.runtime.loadplan.OdiLoadPlan;
import oracle.odi.domain.runtime.loadplan.finder.IOdiLoadPlanFinder;

//
// Find a subfolder with given folderName in parentFolder. 
// When no folder exists and creationFlag = true then the folder will be created.
//
def getScenFolder(parentFolder,folderName,creationFlag,tme) {
  def ff = (IOdiScenarioFolderFinder)tme.getFinder(OdiScenarioFolder.class);
  // There would be a findName() method in the finder class, 
  // but it delivers the first folder having the given name even if more than one exists. 
  // So here all folders have to be checked.
  def fs = ff.findAll(); 
  def folder = null;
  for (f in fs) {
    // If the folder has the same name and the parent folder is the given parentFolder then correct folder was found. 
    // The last part of the expression also checks the top level folder.
    if (f.getName()==folderName&&((f.getParentScenFolder()==parentFolder)||(!f.getParentScenFolder()&&!parentFolder))) {
      folder = f;
    }
  }
  // If the folder doesn't exist and creation is requested then it will be created´.
  if ((!folder)&&creationFlag) {
    if (parentFolder) {
      folder = new OdiScenarioFolder(parentFolder, folderName);
    }
    else {
      folder = new OdiScenarioFolder(folderName);
    }
    tme.persist(folder);
  }
  return folder;
}

//
// Find the folder represented by the full folderPath. 
// The creationFlag indicated if the path should be created if is not exists.
//
def getScenFolder(folderPath,creationFlag,tme){  
  // Split the folder path into parts based on slashes
  parts = folderPath.split("/");
  def parentFolder = null;
  // Loop through the parts to find the correct folder beginning with the root to the leaves.
  for (part in parts) {
    if (part) {
      folder = getScenFolder(parentFolder,part,creationFlag,tme);
      if (!folder) return null; // Stop when either no folder was found or no folder was created.
      parentFolder = folder; // Save found folder as parentfolder for the next level loop.
    }
  }
  return folder;
}

//
// Find the loadplan
//
def getLoadPlan(lpName,tme){
  lpf = (IOdiLoadPlanFinder)tme.getFinder(OdiLoadPlan.class);
  lp = lpf.findByName(lpName);
  return lp;
}

//
// Move the loadplan named with lpName to the folder given by the full folder path in folderPath. 
//
def fixLP(folderPath,lpName,creationFlag){
  txnDef = new DefaultTransactionDefinition();
  tm = odiInstance.getTransactionManager();
  tme = odiInstance.getTransactionalEntityManager();
  txnStatus = tm.getTransaction(txnDef);
  
  try{
    lp = getLoadPlan(lpName,tme);
    // Get the scenario folder given by the full path (creationFlag could force the creation of this path)
    scenf = getScenFolder(folderPath,creationFlag,tme);
    lp.setScenarioFolder(scenf); // Move the load plan to the scenario folder
    tme.persist(lp); // Persist the changes
    tm.commit(txnStatus); // Commit everything
  } catch (Throwable all) {
    println(all)
    tm.rollback(txnStatus); // Rollback if something went wrong
    println(all.getStackTrace());
  }
}

//
// Call the main function to move the loadplan where it should be.
//
fixLP('/ALL_LOADPLANS/MY_LOADPLANS','MY_LOADPLAN',true);
Postgresql Cheat Sheets

PostgreSQL Cheat Sheets – Sammlung

Für PostgreSQL finden sich einige sehr nützliche PostgreSQL Cheat Sheets, um im Alltag mit der Datenbank eine schnelle und nützliche Referenz zur Hand zu haben.

Die korrekte Übersetzung von Cheat-Sheet lautet „Schummelzettel“.

Allerdings zielt die Verwendung in erster Linie nicht auf das Schummeln ab, sonder es handelt sich vielmehr um eine übersichtliche Zusammenstellung von wichtigsten Details zu einem ganz bestimmten Thema.

Im Idealfall sollte die Länge von einem A4 Blatt nicht überschritten werden, aber es gibt natürlich auch umfassendere Cheat-Sheets.

Zum Thema PostgreSQL haben wir folgende nützliche Cheat-Sheets gefunden:

[Link ] PostgreSQL Cheat Sheet von postgresqltutorial.com – 3 Seiten

In diesem Cheat Sheet werden folgende PostgreSQL Themen behandelt:

  • quering data from table
  • quering from multible tables (verschiedene Joins – left join, right join, outer join, cross join, usw..)
  • SQL operatoren – union, intersect, except, like – not like, in – not in, between and, is null – is not null
  • Table Management – create, drop, alter, truncate, etc…
  • SQL Constraints – primary key, foreign key, unique, check, usw..
  • Data Modification – insert into values, insert into select * from table, update set, delete from, etc…
  • View Management – create view as select, create recursive view, create temporary view, etc…
  • Index Management – create index, create unique index, drop index
  • SQL Aggreate Functions – avg, count, sum, max, min
  • Trigger Management – create trigger when event, etc…

[ Link ] Postgresql Cheat Sheet von alberton.info – 1 Seite

In diesem Cheat-Sheet werden folgende PostgreSQL Themen behandelt:

  • Data Types
  • Internal Functions
  • Usefull Queries
  • Information Shema

[ Link ] PostgreSQL Sting Functions Cheat Sheet von SQLBackupAndFTP.com – 1 Seite

In diesem Cheat-Sheet werden PostgreSQL String Functions behandelt:

  • Conversion
  • Measurement
  • Modification

[Link ] Postgresql terminal commands – cheatography.com – 1 Seite

In diesem Cheat-Sheet werden PostgreSQL terminal commands behandelt:

  • Connecting
  • PSQL
  • Roles and database management
  • Database backup

Informationen zu unseren professionellen PostgreSQL Managed Services finden Sie hier