NAME

Dimedis::Ddl - Modul zur datenbankunabhängigen Erzeugung von DDL Code

SYNOPSIS

use Dimedis::Ddl;

# Konstruktor mit oder ohne Initialisierung
$ddl = Dimedis::Ddl->new ( ... );

# Nachträgliche Initialisierung
$ddl->init_from_config ( ... );

# Spezielle Einstellungen vornehmen
$ddl->set_hint ( name => $value );

# Löschen von im Objekt gespeicherten DDL Code
$ddl->clear;

# Generierung von DDL Code mit Speicherung im $ddl Objekt
$ddl->generate ( ... )

# Ausgabe von im Objekt gespeicherten DDL Code
$ddl->print ( ... )

# Ausführung von im Objekt gespeicherten oder übergebenen DDL Code
$ddl->execute ( ... )

# Zugriff auf im Objekt gespeicherten DDL Code
$ddl_llref = $ddl->get_ddl_llref;

# Generierung des Dimedis::Sql Type Hashes
$ddl->generate_type_hash;

# Ausgabe des Dimedis::Sql Type Hashes
$ddl->print_type_hash ( ... )

# Zugriff auf das im Objekt gespeicherte Dimedis::Sql Type Hash
$type_href = $ddl->get_type_hash_ref;
$type_href_lref = $ddl->get_type_hash_lref;

# Rückgabe von DDL Code zur Erstellung von Tabellen etc.
$ddl_lref = $ddl->get_create_tables;
$ddl_lref = $ddl->get_create_indices;
$ddl_lref = $ddl->get_create_references;
$ddl_lref = $ddl->get_create_constraints;

# Rückgabe von DDL Code zur Löschung von Tabellen etc.
$ddl_lref = $ddl->get_drop_tables;
$ddl_lref = $ddl->get_drop_indices;
$ddl_lref = $ddl->get_drop_references;
$ddl_lref = $ddl->get_drop_constraints;

# Prüfen ob bei der Generierung Fehler aufgetreten sind
$has_errors = $ddl->has_errors;

# Fehlermeldungen formatieren
$errors_sref = $ddl->get_formatted_errors_sref;

# croak Modus für Konfigurationsfehler abschalten
$ddl->set_croak_config_errors ( 0 );

# Fehler ausgeben
$ddl->print_errors ( ... );

# DDL Objekte ermitteln
my $objects = $ddl->query ( ... );

DESCRIPTION

Dieses Modul korrespondiert mit dem Dimedis::Sql Modul und dient der Generierung von DDL Code zur Erzeugung von Datenbankobjekten (Tabellen, Indizies etc.). Dabei wird das Datenmodell anhand einer datenbankunabhängigigen Perl Datenstruktur beschrieben. Aus dieser wird dann der datenbankspezifische Code generiert.

Es gibt ein Kommandozeilen-Interface des Moduls namens dddl. Eine Kurzdokumentation wird bei Aufruf von dddl ohne Parameter angezeigt, eine ausführliche manpage kann mit "perldoc dddl" aufgerufen werden.

Die Manpage des Moduls Dimedis::Ddl::Config beschreibt die Datenstruktur, mit der das Datenmodell definiert wird.

Diese Dokumentation beschreibt die Perl API, mit der die Dimedis::Ddl Funktionen direkt in Perl Programme eingebunden werden können.

METHODEN ZUR INITIALISIERUNG

Der Konstruktor der Dimedis::Ddl Klasse lautet:

$ddl = Dimedis::Ddl->new (
  [ db_type             => $db_type, ]
  [ dbh                 => $dbh      ],
  [ dir                 => $config_directory, |
  [ croak_config_errors => 0 | 1, ]
    filename            => $config_filename,  |
    config              => $config_object ]
);

Es muß min. db_type oder dbh angegeben werden. Wenn dbh angegeben wird, aber kein db_type, ermittelt Dimedis::Ddl den Datenbanktyp selbständig (Achtung: es gibt keine "Magie" bezüglich ODBC und MS-SQL o.ä. an dieser Stelle). Mit db_type kann der Typ selbst angegeben werden, welcher aus einer bestehenden Datenbankverbindung wie folgt ermittelt werden kann:

$dbh->{Driver}->{Name}

Hinweis: für MySQL muß ein dbh angegeben werden, wenn Referenzen unterstüzt werden sollen.

Mit croak_config_errors kann gesteuert werden, ob Dimedis::Ddl bei Konfigurationsfehlern eine Exception werfen soll. Näheres dazu steht im Kapitel zur Fehlerbehandlung weiter unten.

Weiterhin kann optional einer der anderen oben genannten Parameter angegeben werden, mit denen die Dimedis::Ddl Konfiguration übergeben wird.

Wenn dir angegeben ist, werden alle Konfigurationsdateien dieses Verzeichnisses eingelesen. filename gibt den Dateinamen genau einer zu ladenden Konfigurationsdatei an. Alternativ kann auch mit config ein Dimedis::Ddl::Config Objekt übergeben werden, das vorher entsprechend initialisiert wurde (siehe nächster Abschnitt).

Wenn keiner der zusätzlichen Parameter angegeben wurde, ist das Objekt noch nicht initialisiert. In diesem Fall muß vor Aufruf der Generierungsmethoden die Initialisierung mit der init_from_config Methode nachgeholt werden. Diese erwartet ein Dimedis::Ddl::Config Objekt als Parameter:

$ddl->init_from_config (
    config => $config_object
);

Andernfalls wird eine Exception geworfen, wenn anderweitig auf ein nicht initialisiertes Objekt zugegeriffen wird.

Wichtige Hinweise zu MySQL

Es muß MySQL Version 4.0.12 oder höher verwendet werden.

Die Angabe des DBI Handles ist zwingend. Es muß eine Verbindung zur aktuellen Datenbank hergestellt werden, da der MySQL DDL Treiber die existierende Datenbank analysiert. Nur mit dieser Information ist es möglich Referenzen anzulegen oder zu ändern.

WARNUNG:

DROP/MODIFY REFERENCE bewirkt ein Neuerstellen aller Tabellen, die selbst eine Referenz auf die aktuelle Tabelle haben. Das Verändern einer Referenz an einer zentralen Tabelle ist also u.U. sehr zeitaufwändig und insbesondere nicht transaktionssicher. Während eines solchen Update Vorgangs sollten also keine anderen Benutzer auf die Datenbank Zugriff haben.

Erzeugung eines Dimedis::Ddl::Config Objektes

Es gibt drei Möglichkeiten ein Dimedis::Ddl::Config Objekt zu erzeugen bzw. zu initialisieren:

$config = Dimedis::Ddl::Config->new ( [ data => $data ] );
$config->add_file ( filename => $filename );
$config->add_directory ( dir => $dir, filter_regex => '\.conf$' );

Der data Parameter der new Methode erwartet die verschachtelte Listenstruktur die weiter oben beschrieben ist. add_file erwartet den Dateinamen einer Konfigurationsdatei und add_directory den Namen des Verzeichnisses, dessen Dateien als Konfigurationsdateien eingelesen werden und der internen Konfiguration hinzugefügt werden sollen.

Wenn beim Einlesen der Dateien ein Fehler auftritt, wird eine Exception geworfen.

Optional kann mit filter_regex ein regulärer Ausdruck angegeben werden, auf den die zu ladenden Dateinamen in dem Verzeichnis passen müssen. Unterverzeichnisse werden automatisch ausgeschlossen, hierfür muß filter_regex also nicht herangezogen werden.

SPEZIELLE EINSTELLUNGEN VORNEHMEN

Um datenbankspezifisch flexibel Code generieren zu können, ohne dafür datenbankspezifische Methoden einzuführen, gibt es die set_hint Methode. Mit dieser können optionale Parameter gesetzt werden, die von den Datenbanktreibern verwendet werden, die das entsprechende Feature unterstützen.

Derzeibt gibt es hier folgende Parameter:

create_oracle_sequence=1 CREATE und DROP SEQUENCE Befehle werden für Oracle beim Tabellen anlegen/löschen mit erzeugt. Default ist hier 0.

METHODEN ZUR DDL CODE GENERIERUNG

Dimedis::Ddl hat Methoden zur Generierung von DDL Code, der im Dimedis::Ddl Objekt gespeichert wird und mit weiteren Methoden ausgegeben oder ausgeführt werden kann.

Gespeicherten DDL Code löschen

$ddl->clear;

Die clear Methode löscht im Objekt gespeicherten DDL Code.

DDL Code generieren

$ddl->generate ( [ what => $what ] );

Diese Methode ist ein Frontend gegen die zahlreichen einzelnen Methoden zur Generierung von speziellem DDL Code. Über den what Parameter wird gesteuert, welcher Code generiert werden soll, Default ist 'create_all'. Dieser Parameter entspricht exakt der -w Option des dddl Kommandos:

create_all		alles anlegen
create_tables		Tabellen anlegen
create_references	Referenzen anlegen
create_constraints	Constraints anlegen
create_indices	Indices anlegen

drop_all		alles löschen
drop_tables		Tabellen löschen
drop_references	Referenzen löschen
drop_constraints	Constraints löschen
drop_indices          Indices löschen

Der DDL Code wird generiert und im Dimedis::Ddl Objekt gespeichert.

DDL Code ausgeben

$ddl->print ( [ filename => $filename ] );

Die print Methode gibt den generierten DDL Code aus bzw. schreibt ihn in die mit filename angegebene Datei. Wenn als Dateiname ein - übergeben wird, so werden die Daten auf STDOUT ausgegeben. Wird der filename Parameter weggelassen, so wird auf STDOUT geschrieben. Als Dateiname kann auch eine Pipe (z.B. "| grep foo") angegeben werden, dann werden die Daten entsprechend in diese Pipe geschrieben.

DDL Code ausführen

$ddl->execute (
  dbh => $dbh,
  [ sql_code_lref => $sql_code_lref ]
);

Diese Methode führt SQL bzw. DDL Code aus, wobei der auszuführende Code mit dem sql_code_lref Parameter als Listenreferenz übergeben werden kann. In der Liste darf jedes Element nur genau einen SQL Befehl enthalten.

Wenn der sql_code_lref Parameter weggelassen wird, wird der intern gespeicherte bzw. vorher generierte Code ausgeführt.

Die Angabe von dbh ist zwingend und muß ein verbundenes DBI Connection Objekt enthalten.

Wenn bei der Ausführung der Befehle ein Fehler auftritt, so bricht die Methode die Ausführung mit einer entsprechenden Exception ab.

Wenn also eine feinere Fehlerkontrolle gewünscht wird, so sollte mit $ddl->get_ddl_llref (siehe unten) der DDL Code abgerufen werden, um diesen dann selbst mit DBI->do auszuführen.

Zugriff auf im Dimedis::Ddl Objekt gespeicherten Code

$ddl_llref = $ddl->get_ddl_llref;

Die get_ddl_llref Methode gibt eine Liste von Listen zurück, die den generierten DDL Code enthalten. Es folgt ein kurzes Beispiel zum Zugriff auf die gelieferten Daten:

$ddl_llref = $ddl->get_ddl_llref;

foreach my $ddl_lref ( @{$ddl_llref} ) {
    foreach my $ddl_code ( @{$ddl_lref} ) {
        $dbi->do ( $ddl_code );
    }
}

Dimedis::Sql Type Hash generieren

$ddl->generate_type_hash ( [ full => 0 | 1 ] );

Die generate_type_hash Methode generiert den Dimedis::Sql Type Hash und speichert ihn im Objekt. Dabei gibt es zwei Varianten, die über die Option full unterschieden werden. Ein eventuell im Objekt schon vorhandenes Type Hash wird überschrieben.

Per Default (full => 0) wird ein minimales Type Hash ausgegeben, das für die Verwendung mit Dimedis::Sql ausreicht. Hier sind nur 'serial', 'blob', 'clob' und 'native_date' Spalten enthalten. Alle anderen Typen werden von Dimedis::Sql auch ohne Angabe im Type Hash korrekt verarbeitet.

Mit full => 1 werden alle Spalten ausgegeben. Das Import/Export Programm von Dimedis::Sql benötigt ein vollständiges Type Hash.

Dimedis::Sql Type Hash ausgeben

$ddl->print_type_hash ( [ filename => $filename ] [, var => $var ] );

Diese Methode gibt den mit generate_type_hash generierten Type Hash aus. Für filename gilt dasselbe wie bei der print Methode: ein - Zeichen signalisiert die Ausgabe auf STDOUT, für andere Werte wird das Ergebnis in die entsprechende Datei geschrieben. Wird der filename Parameter weggelassen, so wird auf STDOUT geschrieben. Als Dateiname kann auch eine Pipe (z.B. "| grep foo") angegeben werden, dann werden die Daten entsprechend in diese Pipe geschrieben.

Der var Parameter gibt den Namen der Variablen an (ohne das $ Zeichen), die für die Zuweisung in dem Dump des Type Hashs verwendet werden soll. Wenn var fehlt, wird eine anonyme Hash Referenz ausgegeben.

Die Ausgabe erfolgt in der Reihenfolge, in der die Tabellen in der Konfiguration definiert wurden.

Zugriff auf im Dimedis::Ddl Objekt gespeichertes Type Hash

$type_href = $ddl->get_type_hash_ref;

Die get_type_hash_ref Methode gibt eine Referenz auf das zuvor generierte und im Objekt gespeicherte Dimedis::Sql Type Hash zurück.

$type_href_lref = $ddl->get_type_hash_lref;

Die get_type_hash_lref Methode gibt das Type Hash in der Reihenfolge zurück, in der die Tabellen in der Konfiguration auftraten. Ergebnis ist eine Referenz auf eine Liste von Hashes, die folgende Schlüssel definieren:

name    Name der Tabelle
hash    Type-Hash der Tabelle

RÜCKGABE VON GENERIERTEM DDL CODE

Die oben genannten Methoden generieren DDL Code und speichern diesen im Objekt bzw. greifen auf intern gespeicherten Code zu. Es ist auch möglich den Code über spezifische Methoden zu generieren und ihn sich zurückgeben zu lassen, ohne daß dieser im Objekt gespeichert wird.

Folgende Methoden stehen dafür zur Verfügung:

# Rückgabe von DDL Code zur Erstellung von Tabellen etc.
$ddl_lref = $ddl->get_create_tables;
$ddl_lref = $ddl->get_create_indices;
$ddl_lref = $ddl->get_create_references;
$ddl_lref = $ddl->get_create_constraints;

# Rückgabe von DDL Code zur Löschung von Tabellen etc.
$ddl_lref = $ddl->get_drop_tables;
$ddl_lref = $ddl->get_drop_indices;
$ddl_lref = $ddl->get_drop_references;
$ddl_lref = $ddl->get_drop_constraints;

Der Rückgabewert dieser Methoden eignet sich zur Übergabe an die execute Methode und ist eine Referenz auf eine Liste von DDL Befehlen, die z.B. auch einzeln mittels DBI->do ausgeführt werden können.

FEHLERBEHANDLUNG

Bei allen Methoden zur Generierung von DDL Code können Fehler auftreten, wenn die Konfiguration nicht korrekt ist. Mit der Methode

$ddl->set_croak_config_errors ( 0 | 1 );

kann gesteuert werden, ob Dimedis::Ddl in diesem Fall eine Exception werfen soll oder nicht. Per Default wird eine Exception geworfen, d.h. croak_config_errors ist auf 1 gesetzt.

Ob Fehler vorliegen, kann kann jederzeit abgefragt werden:

$has_errors = $ddl->has_errors;

Die Fehlermeldungen können formatiert werden:

$errors_sref = $ddl->get_formatted_errors_sref;

oder direkt formatiert ausgegeben werden (per Default auf STDERR oder auf ein gegebenes Filehandle):

$ddl->print_errors ( fh => \*STDOUT );

Weiterhin wird Dimedis::Ddl::Config Exceptions, wenn beim Einlesen von Dateien oder Directories ein Fehler auftritt.

Eine Ausgabe von generiertem Code wird generell unterbunden, sobald ein Fehler aufgetreten ist.

DDL Objekte ermitteln

[ experimentell, nicht alle Kombinationen getestet ]

Es gibt eine eingeschränkte Möglichkeit die aufgrund der Konfigurationsdatei erzeugten internen DDL Objekte zu analysieren (Dimedis::Ddl::Table, Dimedis::Ddl::Column, Dimedis::Ddl::Index, Dimedis::Ddl::PrimaryKey, Dimedis::Ddl::Constraint, Dimedis::Ddl::Reference):

$objects = $ddl->query (

  type => 'table'       | 'column'     | 'index'  |
  	    'primary_key' | 'constraint' | 'reference',

  alter_state => 'create'     | 'add'  | 'modify' |
  		   'drop_table' | 'drop'

);

Es kann also nach Datentyp unterschieden werden, sowie der Operation, die mit diesem durchgeführt wird.

Zurückgegeben werden die entsprechenden Dimedis::Ddl intern erzeugten Objekte für diesen Datentyp, die einen entsprechenden alter_state haben.

AUTOR

Joern Reder <joern@dimedis.de>

COPYRIGHT

Copyright (c) 2001-2003 dimedis GmbH, All Rights Reserved

SEE ALSO

dddl, Dimedis::Ddl::Config, Dimedis::Sql

1 POD Error

The following errors were encountered while parsing the POD:

Around line 777:

Non-ASCII character seen before =encoding in 'datenbankunabhängigen'. Assuming CP1252