commit 853f8211ad64ffc75a189266dedf23a89b067719
parent 0b8f700c5400321393293856c86ef21658a98e25
Author: Jan Dankert <devnull@localhost>
Date: Sun, 3 Dec 2017 03:11:38 +0100
Refactoring: Datenbank-Funktionen in ein eigenes "Modul" ausgelagert.
Diffstat:
13 files changed, 1202 insertions(+), 1196 deletions(-)
diff --git a/db/Database.class.php b/db/Database.class.php
@@ -1,208 +0,0 @@
-<?php
-// OpenRat Content Management System
-// Copyright (C) 2002-2006 Jan Dankert, jandankert@jandankert.de
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-
-/**
- * Darstellung einer Datenbank-Verbindung.
- *
- * Fuer die echten DB-Aufrufe werden die entsprechenden
- * Methoden des passenden Clients aufgerufen.
- *
- * Diese Klasse stammt urspruenglich aus dem PHP-Pear-DB-Projekt, wurde hier aber intensiv veraendert.
- *
- * @author Jan Dankert
- * @package openrat.database
- */
-class DB
-{
- /**
- * Datenbank-Id.
- *
- * @var String
- */
- var $id;
-
- /**
- * Konfiguration der Datenbank-Verbindung
- *
- * @var Array
- */
- var $conf;
-
- /**
- * Kennzeichen, ob die Datenbank verf�gbar ist.
- *
- * @var Boolean
- */
- var $available;
-
- /**
- * Enth�lt eine Fehlermeldung (sofern verf�gbar).
- *
- * @var String
- */
- var $error;
-
- /**
- * Client.
- * Enth�lt ein Objekt der Klasse db_<type>.
- *
- * @var Object
- */
- var $client;
-
- /**
- * Schalter, ob eine Transaktion begonnen wurde.
- * @var boolean
- */
- var $transactionInProgress = false;
-
-
- /**
- * Kontruktor.
- * Erwartet die Datenbank-Konfiguration als Parameter.
- *
- * @param Array Konfiguration der Verbindung
- * @param boolean admin Wenn es eine Admin-DB-Verbindung werden soll, die auch DDL ausfuehren darf
- */
- public function DB( $dbconf,$admin=false )
- {
- global $conf;
-
- $this->conf = $dbconf + $conf['database-default']['defaults']; // linksstehender Operator hat Priorität!
-
- if ( $admin )
- {
- // Bevorzugung der Unter-Konfiguration 'update'
- if ( isset($this->conf['update']) )
- $this->conf = $this->conf['update'] + $this->conf; // linksstehender Operator hat Priorität!
- }
-
- $this->connect();
- }
-
-
- /**
- * Verbindung zur Datenbank aufbauen.
- *
- * @return Status
- */
- public function connect()
- {
- // Ausfuehren des Systemkommandos vor Verbindungsaufbau
- if ( !empty($this->conf['cmd']))
- {
- $ausgabe = array();
- $rc = false;
-
- Logger::debug("Database command executing: ".$this->conf['cmd']);
- exec( $this->conf['cmd'],$ausgabe,$rc );
-
- foreach( $ausgabe as $zeile )
- Logger::debug("Database command output: ".$zeile);
-
- if ( $rc != 0 )
- {
- throw new OpenRatException( 'ERROR_DATABASE_CONNECTION','Command failed: '.implode("",$ausgabe) );
- }
- }
-
- $type = $this->conf['type'];
- $classname = 'db_'.$type;
-
- if ( ! class_exists($classname) )
- {
- $this->available = false;
- throw new OpenRatException( 'ERROR_DATABASE_CONNECTION','Database type "'.$type.'" is not available');
- }
-
- // Client instanziieren
- $this->client = new $classname;
-
-
- $this->client->connect( $this->conf );
-
- // SQL nach Verbindungsaufbau ausfuehren.
- if ( ! empty($this->conf['connection_sql']) )
- {
- $cmd = $this->conf['connection_sql'];
-
- $sql = $this->sql($cmd);
-
- $ok = $sql->execute();
-
- if ( ! $ok )
- {
- throw new OpenRatException( 'ERROR_DATABASE_CONNECTION',"Could not execute connection-query '".$cmd."'");
- }
- }
-
- Logger::debug('database connection established');
-
- $this->available = true;
- return true;
- }
-
- /**
- * Startet eine Transaktion.
- * Falls der Schalter 'transaction' nicht gesetzt ist, passiert nichts.
- */
- public function start()
- {
- $this->transactionInProgress = true;
- $this->client->start();
- }
-
-
- /**
- * Beendet und bestaetigt eine Transaktion.
- * Falls der Schalter 'transaction' nicht gesetzt ist, passiert nichts.
- */
- public function commit()
- {
- if ( $this->transactionInProgress )
- {
- $this->client->commit();
- $this->transactionInProgress = false;
- }
- }
-
-
-
- /**
- * Setzt eine Transaktion zurueck.
- * Falls der Schalter 'transaction' nicht gesetzt ist, passiert nichts.
- */
- public function rollback()
- {
- if ( $this->transactionInProgress )
- {
- $this->client->rollback();
- $this->transactionInProgress = false;
- }
- }
-
- public function sql( $sql )
- {
- return new Statement( $sql,$this->client,$this->conf);
- }
-
-}
-
-
-?>-
\ No newline at end of file
diff --git a/db/DbVersion.class.php b/db/DbVersion.class.php
@@ -1,315 +0,0 @@
-<?php
-
-define('OR_DB_INDEX_PREFIX' ,'IX');
-define('OR_DB_CONSTRAINT_PREFIX','FK');
-
-abstract class DbVersion
-{
- private $db;
- private $tablePrefix;
- private $tableSuffix;
- private $dbmsType;
-
- function DbVersion( $db )
- {
- $this->db = $db;
-
- switch( $db->conf['type'] )
- {
- case 'mysql':
- case 'mysqli':
- $this->dbmsType = 'mysql';
- break;
- case 'postgresql':
- $this->dbmsType = 'postgresql';
- break;
- case 'sqlite':
- case 'sqlite3':
- $this->dbmsType = 'sqlite';
- break;
- case 'pdo':
- $dsnParts = explode(':',$db->conf['dsn']);
- switch( $dsnParts[0] )
- {
- case 'mysql':
- $this->dbmsType = 'mysql';
- break;
- case 'pgsql':
- $this->dbmsType = 'postgresql';
- break;
- case 'sqlite':
- $this->dbmsType = 'sqlite';
- break;
- default:
- Http::serverError('Datebase Configuration Error','Unknown DBMS in PDO-DSN: '.$dsnParts[0]);
- }
- break;
- default:
- Http::serverError('Datebase Configuration Error','Unknown DBMS type: '.$db->conf['type'] );
- }
-
- $this->tablePrefix = $db->conf['prefix'];
- $this->tableSuffix = $db->conf['suffix'];
- }
-
- // Muss überschrieben werden!
- abstract function update();
-
-
-
-
-
-
-
-
- protected function getTableName( $name )
- {
- return $this->tablePrefix.$name.$this->tableSuffix;
- }
-
-
- /**
- * Erzeugt eine neue Tabelle.
- * Die neue Tabelle enthält bereits eine Spalte "id" (da eine leere Tabelle i.d.R. nicht zulässig ist).
- */
- function addTable( $tableName )
- {
- $tableName = $this->getTableName($tableName);
-
- $table_opts = $this->dbmsType=='mysql'?' ENGINE=InnoDB CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci':'';
-
- $ddl = $this->db->sql('CREATE TABLE '.$tableName.'(id INTEGER)'.$table_opts.';');
- // The syntax 'TYPE = InnoDB' was deprecated in MySQL 5.0 and was removed in MySQL 5.1 and later versions.
-
- $ddl->query();
- }
-
-
- # Creating a new column
- # param 1: column name
- # param 2: type (available are: INT,VARCHAR,TEXT,BLOB)
- # param 3: size (number value)
- # param 4: default (number value)
- # param 5: nullable (available are: J,N)
- function addColumn($tableName,$columnName,$type,$size,$default,$nullable)
- {
- $table = $this->getTableName($tableName);
-
- $type = strtoupper($type);
- switch( $type )
- {
- case 'INT':
- switch( $this->dbmsType )
- {
- case 'mysql':
- if ( $size == 1 )
- $dbmsInternalType = 'TINYINT';
- else
- $dbmsInternalType = 'INT';
- break;
-
- case 'oracle':
- $dbmsInternalType = 'NUMBER';
- break;
-
- default:
- $dbmsInternalType = 'INTEGER';
-
- }
- break;
-
- case 'VARCHAR':
- switch( $this->dbmsType )
- {
- default:
- $dbmsInternalType = 'VARCHAR';
-
- }
- break;
-
- case 'TEXT':
- switch( $this->dbmsType )
- {
- case 'mysql':
- $dbmsInternalType = 'MEDIUMTEXT';
- break;
-
- case 'oracle':
- $dbmsInternalType = 'CLOB';
- break;
-
- default:
- $dbmsInternalType = 'TEXT';
-
- }
- break;
-
- case 'BLOB':
- switch( $this->dbmsType )
- {
- case 'mysql':
- $dbmsInternalType = 'MEDIUMBLOB';
- break;
-
- case 'oracle':
- $dbmsInternalType = 'CLOB';
- break;
-
- case 'postgresql':
- $dbmsInternalType = 'TEXT';
- break;
-
- case 'sqlite':
- $dbmsInternalType = 'TEXT';
- break;
-
- default:
- $dbmsInternalType = 'BLOB';
-
- }
- break;
- default:
- Http::serverError('Datebase Configuration Error','Unknown Column type: '.$type );
- }
-
- if ( $this->dbmsType == 'oracle')
- {
- // TEXT-columns should be nullable in Oracle, because empty strings are treated as NULL
- if ( $type=='VARCHAR' || $type=='TEXT')
- $nullable = true;
-
- }
-
- $ddl = $this->db->sql('ALTER TABLE '.$table.
- ' ADD COLUMN '.$columnName.' '.$dbmsInternalType.($size!=null?'('.$size.')':'').
- ($default!==null?' DEFAULT '.(is_string($default)?"'":'').$default.(is_string($default)?"'":''):'').
- ' '.($nullable?'NULL':'NOT NULL').';'
- );
- $ddl->query();
-
- }
-
-
-
- function addPrimaryKey( $tableName,$columnNames)
- {
- $table = $this->getTableName($tableName);
-
- if ( !is_array($columnNames) )
- $columnNames = explode(',',$columnNames);
-
- $ddl = $this->db->sql('ALTER TABLE '.$table.' ADD PRIMARY KEY ('.implode(',',$columnNames).');');
- $ddl->query();
-
- }
-
-
-
- # Creating a unique key
- # param 1: name of index column. Seperate multiple columns with ','
- function addIndex($tableName,$columnNames,$unique=false)
- {
- $table = $this->getTableName($tableName);
-
- if ( !is_array($columnNames) )
- $columnNames = explode(',',$columnNames);
-
- $indexName = $this->tablePrefix.OR_DB_INDEX_PREFIX.'_'.$tableName.'_'.implode('_',$columnNames).$this->tableSuffix;
-
-// if [ "$type" == "oracle" ]; then
-// cnt=$(($cnt+1))
-// echo "CREATE UNIQUE INDEX ${prefix}uidx_${cnt}" >> $outfile
-// else
-
- $ddl = $this->db->sql('CREATE '.($unique?'UNIQUE ':'').'INDEX '.$indexName.' ON '.$table.' ('.implode(',',$columnNames).');');
- $ddl->query();
-
- }
-
-
- /**
- * Creating a unique key.
- * param 1: name of index column. Seperate multiple columns with ','
- *
- */
- function addUniqueIndex($tableName,$columnNames)
- {
- $this->addIndex( $tableName,$columnNames,true );
- }
-
-
- # Creating a foreign key
- # param 1: column name
- # param 2: target table name
- # param 3: target column name
- function addConstraint($tableName,$columnName,$targetTableName,$targetColumnName)
- {
- $table = $this->getTableName($tableName);
- $targetTable = $this->getTableName($targetTableName);
-
- $constraintName = $this->tablePrefix.OR_DB_CONSTRAINT_PREFIX.'_'.$tableName.$this->tableSuffix.'_'.$columnName;
-
- // Oracle doesn't support "ON DELETE RESTRICT"-Statements, but its the default.
-
- $ddl = $this->db->sql('ALTER TABLE '.$table.' ADD CONSTRAINT '.$constraintName.' FOREIGN KEY ('.$columnName.') REFERENCES '.$targetTable.' ('.$targetColumnName.') ON DELETE RESTRICT ON UPDATE RESTRICT;');
- $ddl->query();
- }
-
-
-
- function dropTable( $tableName)
- {
- $table = $this->getTableName($tableName);
-
- $ddl = $this->db->sql('DROP TABLE '.$table.';' );
- $ddl->query();
- }
-
- function dropColumn( $tableName,$columnName )
- {
- $table = $this->getTableName($tableName);
-
- $ddl = $this->db->sql('ALTER TABLE '.$table.' DROP COLUMN '.$columnName.';');
- $ddl->query();
-
-
- }
-
- function dropIndex( $indexName,$unique=false)
- {
- $ddl = $this->db->sql('DROP'.($unique?' UNIQUE':'').' INDEX '.$indexName.';' );
- $ddl->query();
- }
-
- function dropUniqueIndex( $indexName)
- {
- $this->dropIndex( $indexName,true );
- }
-
- function dropPrimaryKey( $tableName,$columnNames )
- {
- $table = $this->getTableName($tableName);
-
- if ( !is_array($columnNames) )
- $columnNames = explode(',',$columnNames);
-
- $ddl = $this->db->sql('ALTER TABLE '.$table.' DROP PRIMARY KEY('.implode(',',$columnNames).')');
- $ddl->query();
- }
-
-
- function dropConstraint( $constraintName)
- {
- $ddl = $this->db->sql('DROP CONSTRAINT '.$constraintName.';' );
- $ddl->query();
- }
-
-
- function getDb()
- {
- return $this->db;
- }
-
-}
-
-?>-
\ No newline at end of file
diff --git a/db/Sql.class.php b/db/Sql.class.php
@@ -1,115 +0,0 @@
-<?php
-// OpenRat Content Management System
-// Copyright (C) 2002-2006 Jan Dankert, jandankert@jandankert.de
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-
-
-/**
- * SQL-Anweisung.<br>
- * <br>
- * Darstellen eines SQL-Statements incl. Methoden zum Fuellen von
- * Platzhaltern im SQL-Befehl.<br>
- * <br>
- * Beispiel<br>
- * <pre>
- * // Neues Objekt erzeugen mit SQL-Anweisung
- * $sql = $db->sql('SELECT * FROM xy WHERE id={uid} AND name={name}');
- *
- * // Parameter f�llen
- * $sql->setInt ('uid' ,1 );
- * $sql->setString('name','peter');
- *
- * // Fertige SQL-Anweisung verwenden
- * $xy->execute( $sql->query );
- * </pre>
- * <br>
- * Ziele dieser Klasse sind:<br>
- * - Schreiben einfacher SQL-Anweisungen ohne Stringverarbeitung<br>
- * - Verhindern von SQL-Injection.<br>
- * <br>
- *
- * @author Jan Dankert, $Author$
- * @version $Revision$
- * @package openrat.services
- */
-
-class Sql
-{
- /**
- * SQL-Anweisung.
- */
- var $query;
-
- /**
- * Ein 1-dimensionales Array mit den Positionen der Parameter.<br>
- * <br>
- * Beispiel:<br>
- * <pre>
- *
- * Array
- * (
- * [lid] => 16
- * [oid] => 24
- * )
- * </pre>
- */
- var $param = array();
-
-
- /**
- * Erzeugt ein SQL-Objekt und analysiert die SQL-Anfrage.
- */
- function Sql( $query = '' )
- {
- $this->parseSourceQuery( $query );
- }
-
-
- /**
- * Die SQL-Anfrage wird auf Parameter untersucht.
- */
- function parseSourceQuery( $query )
- {
- Logger::debug( 'SQL-query: '.$query);
-
- while( true ) // Schleife wird solange durchlaufen, solange Parameter gefunden werden.
- {
- $posKlLinks = strpos($query,'{');
- $posKlRechts = strpos($query,'}');
-
- if ( $posKlLinks === false || $posKlRechts === false )
- break; // Schleife abbrechen, wenn kein Parameter mehr gefunden wird.
-
- $nameParam = substr($query,$posKlLinks+1,$posKlRechts-$posKlLinks-1); // Name Parameter
-
- if ( isset($this->param[$nameParam ]))
- throw new RuntimeException( 'Parameter '.$nameParam.' in Query mehrfach vorhanden.' );
-
- $this->param[$nameParam] = $posKlLinks;
-
- $query = substr($query,0,$posKlLinks).substr($query,$posKlRechts+1);
- }
-
- $this->query = $query;
-
- }
-
-
-}
-
-
-?>-
\ No newline at end of file
diff --git a/db/Statement.class.php b/db/Statement.class.php
@@ -1,326 +0,0 @@
-<?php
-// OpenRat Content Management System
-// Copyright (C) 2002-2006 Jan Dankert, jandankert@jandankert.de
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-
-/**
- * Darstellung einer Datenbank-Abfrage.
- *
- * @author Jan Dankert
- * @package openrat.database
- */
-class Statement
-{
-
- /**
- * SQL-Objekt.
- *
- * @var SQL
- */
- var $sql;
-
- /**
- * Client.
- * Enth�lt ein Objekt der Klasse db_<type>.
- *
- * @var Object
- */
- var $client;
-
-
- /**
- * Datenbank-Konfiguration
- * @var Array
- */
- var $conf;
-
- /**
- * Kontruktor.
- * Erwartet die Datenbank-Konfiguration als Parameter.
- *
- * @param Array Konfiguration der Verbindung
- * @return Status 'true' wenn Verbindung erfolgreich aufgebaut.
- */
- public function Statement( $sql, $client,$conf )
- {
- // Tabellen-Praefixe ergaenzen.
- $this->conf = $conf;
- $this->client = $client;
-
- $sql = str_replace('{{',$conf['prefix'],$sql);
- $sql = str_replace('}}',$conf['suffix'],$sql);
-
- $this->sql = new Sql( $sql );
-
- // Vorbereitete Datenbankabfrage ("Prepared Statement")
- $this->client->clear();
-
- // Statement an die Datenbank schicken
- $this->client->prepare( $this->sql->query,$this->sql->param );
- }
-
-
-
- /**
- * Ausfuehren einer Datenbankanfrage.
- *
- * @param SQL-Objekt
- * @return Object (Result)
- */
- public function query( )
- {
- return $this->execute();
- }
-
-
- /**
- * Ausfuehren einer Datenbankanfrage.
- *
- * @param SQL-Objekt
- * @return Object (Result)
- */
- public function execute( )
- {
- // Ausfuehren...
- $result = $this->client->query($this->sql);
-
- if ( $result === FALSE )
- {
- throw new RuntimeException( 'Database error: '.$this->client->error);
- }
-
- return $result;
- }
-
-
- /**
- * Ermittelt genau 1 Datenbankergebnis aus einer SQL-Anfrage.
- * Falls es mehrere Treffer gibt, wird die 1. Spalte aus der 1. Zeile genommen.
- *
- * @param String $this->query
- * @return String
- */
- public function &getOne()
- {
- $none = '';
- $result = $this->query();
-
- $row = $this->client->fetchRow( $result,0 );
- $this->client->freeResult($result);
-
- if ( ! is_array($row) )
- return $none;
-
- $keys = array_keys($row);
-
- return $row[ $keys[0] ];
- }
-
-
- /**
- * Ermittelt eine Zeile aus der Datenbank.
- *
- * @param String $this->query
- * @return Array
- */
- public function &getRow()
- {
- $result = $this->query();
-
- $row = $this->client->fetchRow( $result,0 );
- $this->client->freeResult($result);
-
- if ( ! is_array($row) )
- $row = array();
-
- return $row;
- }
-
-
- /**
- * Ermittelt eine (die 1.) Spalte aus dem Datenbankergebnis.
- *
- * @param String $this->query
- * @return Array
- */
- public function &getCol()
- {
- $result = $this->query();
-
- $i = 0;
- $col = array();
- while( $row = $this->client->fetchRow( $result,$i++ ) )
- {
- if ( empty($row) )
- break;
-
- $keys = array_keys($row);
- $col[] = $row[ $keys[0] ];
- }
-
- $this->client->freeResult($result);
-
- return $col;
- }
-
-
- /**
- * Ermittelt ein assoziatives Array aus der Datenbank.
- *
- * @param String $this->query
- * @param Boolean $force_array
- * @return Array
- */
- public function &getAssoc()
- {
- $force_array = false;
-
- $results = array();
- $result = $this->query();
-
- $i = 0;
-
- while( $row = $this->client->fetchRow( $result,$i++ ) )
- {
- if ( empty($row) )
- break;
-
- $keys = array_keys($row);
- $key1 = $keys[0];
- $id = $row[$key1];
-
- if ( count($row) > 2 || $force_array )
- {
- unset( $row[$key1] );
- $results[ $id ] = $row;
- }
- else
- {
- $key2 = $keys[1];
-
- $results[ $id ] = $row[$key2];
- }
- }
-
- $this->client->freeResult( $result );
-
- return $results;
- }
-
-
- /**
- * Ermittelt alle Datenbankergebniszeilen.
- *
- * @param String $this->query
- * @return Array
- */
- public function &getAll()
- {
- $result = $this->query();
-
- $results = array();
- $i = 0;
-
- while( $row = $this->client->fetchRow( $result,$i++ ) )
- {
- $results[] = $row;
- }
-
- $this->client->freeResult( $result );
-
- return $results;
- }
-
-
- /**
- * Führt eine Query aus und gibt nur zurück, ob diese funktioniert.
- *
- * @param unknown_type $this->query
- * @return boolean
- */
- public function testQuery()
- {
- try
- {
- $result = $this->query();
- return $result;
- }
- catch( Exception $e )
- {
- return false;
- }
- }
-
-
- /**
- * Setzt eine Ganzzahl als Parameter.<br>
- *
- * @param name Name des Parameters
- * @param value Inhalt
- */
- function setInt( $name,$value )
- {
- $this->client->bind( $name, (int)$value );
- }
-
-
-
- /**
- * Setzt eine Zeichenkette als Parameter.<br>
- *
- * @param name Name des Parameters
- * @param value Inhalt
- */
- function setString( $name,$value )
- {
- $this->client->bind( $name, (string)$value );
- }
-
-
-
- /**
- * Setzt einen bool'schen Wert als Parameter.<br>
- * Ist der Parameterwert wahr, dann wird eine 1 gesetzt. Sonst 0.<br>
- *
- * @param name Name des Parameters
- * @param value Inhalt
- */
- function setBoolean( $name,$value )
- {
- if ( $value )
- $this->setInt( $name,1 );
- else
- $this->setInt( $name,0 );
- }
-
-
-
- /**
- * Setzt einen Parameter auf den Wert <code>null</code>.<br>
- *
- * @param name Name des Parameters
- */
- function setNull( $name )
- {
- $this->client->bind( $name, null );
- }
-
-
-}
-
-
-?>-
\ No newline at end of file
diff --git a/db/driver/pdo.class.php b/db/driver/pdo.class.php
@@ -1,221 +0,0 @@
-<?php
-
-//
-// +----------------------------------------------------------------------+
-// | PHP version 4.0 |
-// +----------------------------------------------------------------------+
-// | Copyright (c) 1997-2001 The PHP Group |
-// +----------------------------------------------------------------------+
-// | This source file is subject to version 2.02 of the PHP license, |
-// | that is bundled with this package in the file LICENSE, and is |
-// | available at through the world-wide-web at |
-// | http://www.php.net/license/2_02.txt. |
-// | If you did not receive a copy of the PHP license and are unable to |
-// | obtain it through the world-wide-web, please send a note to |
-// | license@php.net so we can mail you a copy immediately. |
-// +----------------------------------------------------------------------+
-// | Authors: Stig Bakken <ssb@fast.no> |
-// | Jan Dankert <phpdb@jandankert.de> |
-// +----------------------------------------------------------------------+
-//
-
-/**
- * Datenbank-abhaengige Methoden fuer PDO.
- *
- * @author Jan Dankert
- * @version $Revision: 1.5 $
- * @package openrat.database
- */
-class DB_pdo
-{
- /**
- * Die PDO-Verbindung.
- *
- * @var Resource
- */
- var $connection;
-
- /**
- * Datenbank-Fehler.
- *
- * @var String
- */
- var $error;
-
- var $lowercase = false;
-
- var $params;
-
-
- function connect( $conf )
- {
- $url = $conf['dsn' ];
- $user = $conf['user' ];
- $pw = $conf['password'];
-
- if ( !empty($conf['convert_to_lowercase']) )
- $this->lowercase = true;
-
- $options = array();
- foreach( $conf as $c )
- if ( is_string($c) && substr($c,0,7) == 'option_' )
- $options[substr($c,8)] = $conf[$c];
-
- if ( $conf['persistent'])
- $options[ PDO::ATTR_PERSISTENT ] = true;
-
- if ( !$conf['prepare'])
- $options[ PDO::ATTR_EMULATE_PREPARES ] = true;
-
- $options[ PDO::ERRMODE_EXCEPTION ] = true;
- $options[ PDO::ATTR_DEFAULT_FETCH_MODE ] = PDO::FETCH_ASSOC;
-
- $this->connection = new PDO($url, $user, $pw, $options);
-
- if ( !is_object($this->connection) )
- throw new OpenRatException( 'DATABASE_ERROR_CONNECTION',"Could not connect to database on host $host. ".PDO::errorInfo() );
-
- return true;
- }
-
-
-
- function disconnect()
- {
- $this->connection = null;
- return true;
- }
-
-
-
- function query($query)
- {
- $erg = $this->stmt->execute();
-
- if ( $erg === false )
- {
- throw new RuntimeException( 'Could not execute prepared statement "'.$query->query.'": '.implode('/',$this->stmt->errorInfo()) );
- }
-
- return $this->stmt;
- }
-
-
- function fetchRow( $result, $rownum )
- {
- $row = $this->stmt->fetch( PDO::FETCH_ASSOC );
-
- if ( is_array($row) && $this->lowercase )
- $row = array_change_key_case($row);
-
- return $row;
- }
-
-
- function freeResult($result)
- {
- return true;
- }
-
-
- function prepare( $query,$param)
- {
- $this->params = $param;
- $offset = 0;
- foreach( $param as $name=>$pos)
- {
- $name = ':'.$name;
- $pos += $offset;
- $query = substr($query,0,$pos).$name.substr($query,$pos);
-
- $offset = $offset + strlen($name);
- }
-
- Logger::debug('PDO: SQL-before-preparation: '.$query);
-
- $this->stmt = $this->connection->prepare($query);
-
- if ( $this->stmt === false )
- throw new OpenRatException('ERROR_DATABASE_CONNECTION','Could not prepare statement: '.$query.' Cause: '.implode('/',$this->connection->errorInfo()) );
-
- }
-
-
-
- function bind( $param,$value )
- {
- $name = ':'.$param;
-
- if ( is_string($value) )
- $type = PDO::PARAM_STR;
- elseif( is_int($value))
- $type = PDO::PARAM_INT;
- elseif( is_null($value))
- $type = PDO::PARAM_NULL;
- else
- throw new RuntimeException( 'Unknown type' );
-
- $this->stmt->bindValue($name,$value,$type);
-
- Logger::debug('PDO: SQL-Binding of parameter '.$name);
- }
-
-
-
- /**
- * Startet eine Transaktion.
- */
- function start()
- {
- $this->connection->beginTransaction();
- }
-
-
-
- /**
- * Beendet eine Transaktion.
- */
- function commit()
- {
- $this->connection->commit();
- }
-
-
- /**
- * Bricht eine Transaktion ab.
- */
- function rollback()
- {
- try
- {
- $this->connection->rollBack();
- }
- catch ( PDOException $e )
- {
- // Kommt vor, wenn keine Transaktion existiert.
- }
- }
-
-
-
- /**
- * Setzt die letzte Abfrage zurueck.
- */
- function clear()
- {
- $this->params = array();
- }
-
-
- /**
- * Why this? See http://e-mats.org/2008/07/fatal-error-exception-thrown-without-a-stack-frame-in-unknown-on-line-0/
- *
- * @return array
- */
- function __sleep() {
- return array();
- }
-
-}
-
-?>-
\ No newline at end of file
diff --git a/db/include.inc.php b/db/include.inc.php
@@ -1,9 +1,4 @@
<?php
-require_once( OR_DBCLASSES_DIR."Database.class.php" );
-require_once( OR_DBCLASSES_DIR."Statement.class.php" );
-require_once( OR_DBCLASSES_DIR."Sql.class.php" );
-if (version_compare(PHP_VERSION, '5.1.0', '>'))
- require_once( OR_DBCLASSES_DIR."driver/pdo.class.php" );
?>
\ No newline at end of file
diff --git a/dispatcher.php b/dispatcher.php
@@ -33,7 +33,7 @@ try
require_once( OR_TEXTCLASSES_DIR ."include.inc.".PHP_EXT );
// Datenbank-Funktionen einbinden.
- require_once( OR_DBCLASSES_DIR."include.inc.".PHP_EXT );
+ require_once( OR_MODULES_DIR."database/require.".PHP_EXT );
// Jetzt erst die Sitzung starten (nachdem alle Klassen zur Verfügung stehen).
session_start();
diff --git a/modules/database/Database.class.php b/modules/database/Database.class.php
@@ -0,0 +1,208 @@
+<?php
+// OpenRat Content Management System
+// Copyright (C) 2002-2006 Jan Dankert, jandankert@jandankert.de
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+/**
+ * Darstellung einer Datenbank-Verbindung.
+ *
+ * Fuer die echten DB-Aufrufe werden die entsprechenden
+ * Methoden des passenden Clients aufgerufen.
+ *
+ * Diese Klasse stammt urspruenglich aus dem PHP-Pear-DB-Projekt, wurde hier aber intensiv veraendert.
+ *
+ * @author Jan Dankert
+ * @package openrat.database
+ */
+class DB
+{
+ /**
+ * Datenbank-Id.
+ *
+ * @var String
+ */
+ var $id;
+
+ /**
+ * Konfiguration der Datenbank-Verbindung
+ *
+ * @var Array
+ */
+ var $conf;
+
+ /**
+ * Kennzeichen, ob die Datenbank verf�gbar ist.
+ *
+ * @var Boolean
+ */
+ var $available;
+
+ /**
+ * Enth�lt eine Fehlermeldung (sofern verf�gbar).
+ *
+ * @var String
+ */
+ var $error;
+
+ /**
+ * Client.
+ * Enth�lt ein Objekt der Klasse db_<type>.
+ *
+ * @var Object
+ */
+ var $client;
+
+ /**
+ * Schalter, ob eine Transaktion begonnen wurde.
+ * @var boolean
+ */
+ var $transactionInProgress = false;
+
+
+ /**
+ * Kontruktor.
+ * Erwartet die Datenbank-Konfiguration als Parameter.
+ *
+ * @param Array Konfiguration der Verbindung
+ * @param boolean admin Wenn es eine Admin-DB-Verbindung werden soll, die auch DDL ausfuehren darf
+ */
+ public function DB( $dbconf,$admin=false )
+ {
+ global $conf;
+
+ $this->conf = $dbconf + $conf['database-default']['defaults']; // linksstehender Operator hat Priorität!
+
+ if ( $admin )
+ {
+ // Bevorzugung der Unter-Konfiguration 'update'
+ if ( isset($this->conf['update']) )
+ $this->conf = $this->conf['update'] + $this->conf; // linksstehender Operator hat Priorität!
+ }
+
+ $this->connect();
+ }
+
+
+ /**
+ * Verbindung zur Datenbank aufbauen.
+ *
+ * @return Status
+ */
+ public function connect()
+ {
+ // Ausfuehren des Systemkommandos vor Verbindungsaufbau
+ if ( !empty($this->conf['cmd']))
+ {
+ $ausgabe = array();
+ $rc = false;
+
+ Logger::debug("Database command executing: ".$this->conf['cmd']);
+ exec( $this->conf['cmd'],$ausgabe,$rc );
+
+ foreach( $ausgabe as $zeile )
+ Logger::debug("Database command output: ".$zeile);
+
+ if ( $rc != 0 )
+ {
+ throw new OpenRatException( 'ERROR_DATABASE_CONNECTION','Command failed: '.implode("",$ausgabe) );
+ }
+ }
+
+ $type = $this->conf['type'];
+ $classname = 'db_'.$type;
+
+ if ( ! class_exists($classname) )
+ {
+ $this->available = false;
+ throw new OpenRatException( 'ERROR_DATABASE_CONNECTION','Database type "'.$type.'" is not available');
+ }
+
+ // Client instanziieren
+ $this->client = new $classname;
+
+
+ $this->client->connect( $this->conf );
+
+ // SQL nach Verbindungsaufbau ausfuehren.
+ if ( ! empty($this->conf['connection_sql']) )
+ {
+ $cmd = $this->conf['connection_sql'];
+
+ $sql = $this->sql($cmd);
+
+ $ok = $sql->execute();
+
+ if ( ! $ok )
+ {
+ throw new OpenRatException( 'ERROR_DATABASE_CONNECTION',"Could not execute connection-query '".$cmd."'");
+ }
+ }
+
+ Logger::debug('database connection established');
+
+ $this->available = true;
+ return true;
+ }
+
+ /**
+ * Startet eine Transaktion.
+ * Falls der Schalter 'transaction' nicht gesetzt ist, passiert nichts.
+ */
+ public function start()
+ {
+ $this->transactionInProgress = true;
+ $this->client->start();
+ }
+
+
+ /**
+ * Beendet und bestaetigt eine Transaktion.
+ * Falls der Schalter 'transaction' nicht gesetzt ist, passiert nichts.
+ */
+ public function commit()
+ {
+ if ( $this->transactionInProgress )
+ {
+ $this->client->commit();
+ $this->transactionInProgress = false;
+ }
+ }
+
+
+
+ /**
+ * Setzt eine Transaktion zurueck.
+ * Falls der Schalter 'transaction' nicht gesetzt ist, passiert nichts.
+ */
+ public function rollback()
+ {
+ if ( $this->transactionInProgress )
+ {
+ $this->client->rollback();
+ $this->transactionInProgress = false;
+ }
+ }
+
+ public function sql( $sql )
+ {
+ return new Statement( $sql,$this->client,$this->conf);
+ }
+
+}
+
+
+?>+
\ No newline at end of file
diff --git a/modules/database/DbVersion.class.php b/modules/database/DbVersion.class.php
@@ -0,0 +1,315 @@
+<?php
+
+define('OR_DB_INDEX_PREFIX' ,'IX');
+define('OR_DB_CONSTRAINT_PREFIX','FK');
+
+abstract class DbVersion
+{
+ private $db;
+ private $tablePrefix;
+ private $tableSuffix;
+ private $dbmsType;
+
+ function DbVersion( $db )
+ {
+ $this->db = $db;
+
+ switch( $db->conf['type'] )
+ {
+ case 'mysql':
+ case 'mysqli':
+ $this->dbmsType = 'mysql';
+ break;
+ case 'postgresql':
+ $this->dbmsType = 'postgresql';
+ break;
+ case 'sqlite':
+ case 'sqlite3':
+ $this->dbmsType = 'sqlite';
+ break;
+ case 'pdo':
+ $dsnParts = explode(':',$db->conf['dsn']);
+ switch( $dsnParts[0] )
+ {
+ case 'mysql':
+ $this->dbmsType = 'mysql';
+ break;
+ case 'pgsql':
+ $this->dbmsType = 'postgresql';
+ break;
+ case 'sqlite':
+ $this->dbmsType = 'sqlite';
+ break;
+ default:
+ Http::serverError('Datebase Configuration Error','Unknown DBMS in PDO-DSN: '.$dsnParts[0]);
+ }
+ break;
+ default:
+ Http::serverError('Datebase Configuration Error','Unknown DBMS type: '.$db->conf['type'] );
+ }
+
+ $this->tablePrefix = $db->conf['prefix'];
+ $this->tableSuffix = $db->conf['suffix'];
+ }
+
+ // Muss überschrieben werden!
+ abstract function update();
+
+
+
+
+
+
+
+
+ protected function getTableName( $name )
+ {
+ return $this->tablePrefix.$name.$this->tableSuffix;
+ }
+
+
+ /**
+ * Erzeugt eine neue Tabelle.
+ * Die neue Tabelle enthält bereits eine Spalte "id" (da eine leere Tabelle i.d.R. nicht zulässig ist).
+ */
+ function addTable( $tableName )
+ {
+ $tableName = $this->getTableName($tableName);
+
+ $table_opts = $this->dbmsType=='mysql'?' ENGINE=InnoDB CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci':'';
+
+ $ddl = $this->db->sql('CREATE TABLE '.$tableName.'(id INTEGER)'.$table_opts.';');
+ // The syntax 'TYPE = InnoDB' was deprecated in MySQL 5.0 and was removed in MySQL 5.1 and later versions.
+
+ $ddl->query();
+ }
+
+
+ # Creating a new column
+ # param 1: column name
+ # param 2: type (available are: INT,VARCHAR,TEXT,BLOB)
+ # param 3: size (number value)
+ # param 4: default (number value)
+ # param 5: nullable (available are: J,N)
+ function addColumn($tableName,$columnName,$type,$size,$default,$nullable)
+ {
+ $table = $this->getTableName($tableName);
+
+ $type = strtoupper($type);
+ switch( $type )
+ {
+ case 'INT':
+ switch( $this->dbmsType )
+ {
+ case 'mysql':
+ if ( $size == 1 )
+ $dbmsInternalType = 'TINYINT';
+ else
+ $dbmsInternalType = 'INT';
+ break;
+
+ case 'oracle':
+ $dbmsInternalType = 'NUMBER';
+ break;
+
+ default:
+ $dbmsInternalType = 'INTEGER';
+
+ }
+ break;
+
+ case 'VARCHAR':
+ switch( $this->dbmsType )
+ {
+ default:
+ $dbmsInternalType = 'VARCHAR';
+
+ }
+ break;
+
+ case 'TEXT':
+ switch( $this->dbmsType )
+ {
+ case 'mysql':
+ $dbmsInternalType = 'MEDIUMTEXT';
+ break;
+
+ case 'oracle':
+ $dbmsInternalType = 'CLOB';
+ break;
+
+ default:
+ $dbmsInternalType = 'TEXT';
+
+ }
+ break;
+
+ case 'BLOB':
+ switch( $this->dbmsType )
+ {
+ case 'mysql':
+ $dbmsInternalType = 'MEDIUMBLOB';
+ break;
+
+ case 'oracle':
+ $dbmsInternalType = 'CLOB';
+ break;
+
+ case 'postgresql':
+ $dbmsInternalType = 'TEXT';
+ break;
+
+ case 'sqlite':
+ $dbmsInternalType = 'TEXT';
+ break;
+
+ default:
+ $dbmsInternalType = 'BLOB';
+
+ }
+ break;
+ default:
+ Http::serverError('Datebase Configuration Error','Unknown Column type: '.$type );
+ }
+
+ if ( $this->dbmsType == 'oracle')
+ {
+ // TEXT-columns should be nullable in Oracle, because empty strings are treated as NULL
+ if ( $type=='VARCHAR' || $type=='TEXT')
+ $nullable = true;
+
+ }
+
+ $ddl = $this->db->sql('ALTER TABLE '.$table.
+ ' ADD COLUMN '.$columnName.' '.$dbmsInternalType.($size!=null?'('.$size.')':'').
+ ($default!==null?' DEFAULT '.(is_string($default)?"'":'').$default.(is_string($default)?"'":''):'').
+ ' '.($nullable?'NULL':'NOT NULL').';'
+ );
+ $ddl->query();
+
+ }
+
+
+
+ function addPrimaryKey( $tableName,$columnNames)
+ {
+ $table = $this->getTableName($tableName);
+
+ if ( !is_array($columnNames) )
+ $columnNames = explode(',',$columnNames);
+
+ $ddl = $this->db->sql('ALTER TABLE '.$table.' ADD PRIMARY KEY ('.implode(',',$columnNames).');');
+ $ddl->query();
+
+ }
+
+
+
+ # Creating a unique key
+ # param 1: name of index column. Seperate multiple columns with ','
+ function addIndex($tableName,$columnNames,$unique=false)
+ {
+ $table = $this->getTableName($tableName);
+
+ if ( !is_array($columnNames) )
+ $columnNames = explode(',',$columnNames);
+
+ $indexName = $this->tablePrefix.OR_DB_INDEX_PREFIX.'_'.$tableName.'_'.implode('_',$columnNames).$this->tableSuffix;
+
+// if [ "$type" == "oracle" ]; then
+// cnt=$(($cnt+1))
+// echo "CREATE UNIQUE INDEX ${prefix}uidx_${cnt}" >> $outfile
+// else
+
+ $ddl = $this->db->sql('CREATE '.($unique?'UNIQUE ':'').'INDEX '.$indexName.' ON '.$table.' ('.implode(',',$columnNames).');');
+ $ddl->query();
+
+ }
+
+
+ /**
+ * Creating a unique key.
+ * param 1: name of index column. Seperate multiple columns with ','
+ *
+ */
+ function addUniqueIndex($tableName,$columnNames)
+ {
+ $this->addIndex( $tableName,$columnNames,true );
+ }
+
+
+ # Creating a foreign key
+ # param 1: column name
+ # param 2: target table name
+ # param 3: target column name
+ function addConstraint($tableName,$columnName,$targetTableName,$targetColumnName)
+ {
+ $table = $this->getTableName($tableName);
+ $targetTable = $this->getTableName($targetTableName);
+
+ $constraintName = $this->tablePrefix.OR_DB_CONSTRAINT_PREFIX.'_'.$tableName.$this->tableSuffix.'_'.$columnName;
+
+ // Oracle doesn't support "ON DELETE RESTRICT"-Statements, but its the default.
+
+ $ddl = $this->db->sql('ALTER TABLE '.$table.' ADD CONSTRAINT '.$constraintName.' FOREIGN KEY ('.$columnName.') REFERENCES '.$targetTable.' ('.$targetColumnName.') ON DELETE RESTRICT ON UPDATE RESTRICT;');
+ $ddl->query();
+ }
+
+
+
+ function dropTable( $tableName)
+ {
+ $table = $this->getTableName($tableName);
+
+ $ddl = $this->db->sql('DROP TABLE '.$table.';' );
+ $ddl->query();
+ }
+
+ function dropColumn( $tableName,$columnName )
+ {
+ $table = $this->getTableName($tableName);
+
+ $ddl = $this->db->sql('ALTER TABLE '.$table.' DROP COLUMN '.$columnName.';');
+ $ddl->query();
+
+
+ }
+
+ function dropIndex( $indexName,$unique=false)
+ {
+ $ddl = $this->db->sql('DROP'.($unique?' UNIQUE':'').' INDEX '.$indexName.';' );
+ $ddl->query();
+ }
+
+ function dropUniqueIndex( $indexName)
+ {
+ $this->dropIndex( $indexName,true );
+ }
+
+ function dropPrimaryKey( $tableName,$columnNames )
+ {
+ $table = $this->getTableName($tableName);
+
+ if ( !is_array($columnNames) )
+ $columnNames = explode(',',$columnNames);
+
+ $ddl = $this->db->sql('ALTER TABLE '.$table.' DROP PRIMARY KEY('.implode(',',$columnNames).')');
+ $ddl->query();
+ }
+
+
+ function dropConstraint( $constraintName)
+ {
+ $ddl = $this->db->sql('DROP CONSTRAINT '.$constraintName.';' );
+ $ddl->query();
+ }
+
+
+ function getDb()
+ {
+ return $this->db;
+ }
+
+}
+
+?>+
\ No newline at end of file
diff --git a/modules/database/Sql.class.php b/modules/database/Sql.class.php
@@ -0,0 +1,115 @@
+<?php
+// OpenRat Content Management System
+// Copyright (C) 2002-2006 Jan Dankert, jandankert@jandankert.de
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+
+/**
+ * SQL-Anweisung.<br>
+ * <br>
+ * Darstellen eines SQL-Statements incl. Methoden zum Fuellen von
+ * Platzhaltern im SQL-Befehl.<br>
+ * <br>
+ * Beispiel<br>
+ * <pre>
+ * // Neues Objekt erzeugen mit SQL-Anweisung
+ * $sql = $db->sql('SELECT * FROM xy WHERE id={uid} AND name={name}');
+ *
+ * // Parameter f�llen
+ * $sql->setInt ('uid' ,1 );
+ * $sql->setString('name','peter');
+ *
+ * // Fertige SQL-Anweisung verwenden
+ * $xy->execute( $sql->query );
+ * </pre>
+ * <br>
+ * Ziele dieser Klasse sind:<br>
+ * - Schreiben einfacher SQL-Anweisungen ohne Stringverarbeitung<br>
+ * - Verhindern von SQL-Injection.<br>
+ * <br>
+ *
+ * @author Jan Dankert, $Author$
+ * @version $Revision$
+ * @package openrat.services
+ */
+
+class Sql
+{
+ /**
+ * SQL-Anweisung.
+ */
+ var $query;
+
+ /**
+ * Ein 1-dimensionales Array mit den Positionen der Parameter.<br>
+ * <br>
+ * Beispiel:<br>
+ * <pre>
+ *
+ * Array
+ * (
+ * [lid] => 16
+ * [oid] => 24
+ * )
+ * </pre>
+ */
+ var $param = array();
+
+
+ /**
+ * Erzeugt ein SQL-Objekt und analysiert die SQL-Anfrage.
+ */
+ function Sql( $query = '' )
+ {
+ $this->parseSourceQuery( $query );
+ }
+
+
+ /**
+ * Die SQL-Anfrage wird auf Parameter untersucht.
+ */
+ function parseSourceQuery( $query )
+ {
+ Logger::debug( 'SQL-query: '.$query);
+
+ while( true ) // Schleife wird solange durchlaufen, solange Parameter gefunden werden.
+ {
+ $posKlLinks = strpos($query,'{');
+ $posKlRechts = strpos($query,'}');
+
+ if ( $posKlLinks === false || $posKlRechts === false )
+ break; // Schleife abbrechen, wenn kein Parameter mehr gefunden wird.
+
+ $nameParam = substr($query,$posKlLinks+1,$posKlRechts-$posKlLinks-1); // Name Parameter
+
+ if ( isset($this->param[$nameParam ]))
+ throw new RuntimeException( 'Parameter '.$nameParam.' in Query mehrfach vorhanden.' );
+
+ $this->param[$nameParam] = $posKlLinks;
+
+ $query = substr($query,0,$posKlLinks).substr($query,$posKlRechts+1);
+ }
+
+ $this->query = $query;
+
+ }
+
+
+}
+
+
+?>+
\ No newline at end of file
diff --git a/modules/database/Statement.class.php b/modules/database/Statement.class.php
@@ -0,0 +1,326 @@
+<?php
+// OpenRat Content Management System
+// Copyright (C) 2002-2006 Jan Dankert, jandankert@jandankert.de
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+/**
+ * Darstellung einer Datenbank-Abfrage.
+ *
+ * @author Jan Dankert
+ * @package openrat.database
+ */
+class Statement
+{
+
+ /**
+ * SQL-Objekt.
+ *
+ * @var SQL
+ */
+ var $sql;
+
+ /**
+ * Client.
+ * Enth�lt ein Objekt der Klasse db_<type>.
+ *
+ * @var Object
+ */
+ var $client;
+
+
+ /**
+ * Datenbank-Konfiguration
+ * @var Array
+ */
+ var $conf;
+
+ /**
+ * Kontruktor.
+ * Erwartet die Datenbank-Konfiguration als Parameter.
+ *
+ * @param Array Konfiguration der Verbindung
+ * @return Status 'true' wenn Verbindung erfolgreich aufgebaut.
+ */
+ public function Statement( $sql, $client,$conf )
+ {
+ // Tabellen-Praefixe ergaenzen.
+ $this->conf = $conf;
+ $this->client = $client;
+
+ $sql = str_replace('{{',$conf['prefix'],$sql);
+ $sql = str_replace('}}',$conf['suffix'],$sql);
+
+ $this->sql = new Sql( $sql );
+
+ // Vorbereitete Datenbankabfrage ("Prepared Statement")
+ $this->client->clear();
+
+ // Statement an die Datenbank schicken
+ $this->client->prepare( $this->sql->query,$this->sql->param );
+ }
+
+
+
+ /**
+ * Ausfuehren einer Datenbankanfrage.
+ *
+ * @param SQL-Objekt
+ * @return Object (Result)
+ */
+ public function query( )
+ {
+ return $this->execute();
+ }
+
+
+ /**
+ * Ausfuehren einer Datenbankanfrage.
+ *
+ * @param SQL-Objekt
+ * @return Object (Result)
+ */
+ public function execute( )
+ {
+ // Ausfuehren...
+ $result = $this->client->query($this->sql);
+
+ if ( $result === FALSE )
+ {
+ throw new RuntimeException( 'Database error: '.$this->client->error);
+ }
+
+ return $result;
+ }
+
+
+ /**
+ * Ermittelt genau 1 Datenbankergebnis aus einer SQL-Anfrage.
+ * Falls es mehrere Treffer gibt, wird die 1. Spalte aus der 1. Zeile genommen.
+ *
+ * @param String $this->query
+ * @return String
+ */
+ public function &getOne()
+ {
+ $none = '';
+ $result = $this->query();
+
+ $row = $this->client->fetchRow( $result,0 );
+ $this->client->freeResult($result);
+
+ if ( ! is_array($row) )
+ return $none;
+
+ $keys = array_keys($row);
+
+ return $row[ $keys[0] ];
+ }
+
+
+ /**
+ * Ermittelt eine Zeile aus der Datenbank.
+ *
+ * @param String $this->query
+ * @return Array
+ */
+ public function &getRow()
+ {
+ $result = $this->query();
+
+ $row = $this->client->fetchRow( $result,0 );
+ $this->client->freeResult($result);
+
+ if ( ! is_array($row) )
+ $row = array();
+
+ return $row;
+ }
+
+
+ /**
+ * Ermittelt eine (die 1.) Spalte aus dem Datenbankergebnis.
+ *
+ * @param String $this->query
+ * @return Array
+ */
+ public function &getCol()
+ {
+ $result = $this->query();
+
+ $i = 0;
+ $col = array();
+ while( $row = $this->client->fetchRow( $result,$i++ ) )
+ {
+ if ( empty($row) )
+ break;
+
+ $keys = array_keys($row);
+ $col[] = $row[ $keys[0] ];
+ }
+
+ $this->client->freeResult($result);
+
+ return $col;
+ }
+
+
+ /**
+ * Ermittelt ein assoziatives Array aus der Datenbank.
+ *
+ * @param String $this->query
+ * @param Boolean $force_array
+ * @return Array
+ */
+ public function &getAssoc()
+ {
+ $force_array = false;
+
+ $results = array();
+ $result = $this->query();
+
+ $i = 0;
+
+ while( $row = $this->client->fetchRow( $result,$i++ ) )
+ {
+ if ( empty($row) )
+ break;
+
+ $keys = array_keys($row);
+ $key1 = $keys[0];
+ $id = $row[$key1];
+
+ if ( count($row) > 2 || $force_array )
+ {
+ unset( $row[$key1] );
+ $results[ $id ] = $row;
+ }
+ else
+ {
+ $key2 = $keys[1];
+
+ $results[ $id ] = $row[$key2];
+ }
+ }
+
+ $this->client->freeResult( $result );
+
+ return $results;
+ }
+
+
+ /**
+ * Ermittelt alle Datenbankergebniszeilen.
+ *
+ * @param String $this->query
+ * @return Array
+ */
+ public function &getAll()
+ {
+ $result = $this->query();
+
+ $results = array();
+ $i = 0;
+
+ while( $row = $this->client->fetchRow( $result,$i++ ) )
+ {
+ $results[] = $row;
+ }
+
+ $this->client->freeResult( $result );
+
+ return $results;
+ }
+
+
+ /**
+ * Führt eine Query aus und gibt nur zurück, ob diese funktioniert.
+ *
+ * @param unknown_type $this->query
+ * @return boolean
+ */
+ public function testQuery()
+ {
+ try
+ {
+ $result = $this->query();
+ return $result;
+ }
+ catch( Exception $e )
+ {
+ return false;
+ }
+ }
+
+
+ /**
+ * Setzt eine Ganzzahl als Parameter.<br>
+ *
+ * @param name Name des Parameters
+ * @param value Inhalt
+ */
+ function setInt( $name,$value )
+ {
+ $this->client->bind( $name, (int)$value );
+ }
+
+
+
+ /**
+ * Setzt eine Zeichenkette als Parameter.<br>
+ *
+ * @param name Name des Parameters
+ * @param value Inhalt
+ */
+ function setString( $name,$value )
+ {
+ $this->client->bind( $name, (string)$value );
+ }
+
+
+
+ /**
+ * Setzt einen bool'schen Wert als Parameter.<br>
+ * Ist der Parameterwert wahr, dann wird eine 1 gesetzt. Sonst 0.<br>
+ *
+ * @param name Name des Parameters
+ * @param value Inhalt
+ */
+ function setBoolean( $name,$value )
+ {
+ if ( $value )
+ $this->setInt( $name,1 );
+ else
+ $this->setInt( $name,0 );
+ }
+
+
+
+ /**
+ * Setzt einen Parameter auf den Wert <code>null</code>.<br>
+ *
+ * @param name Name des Parameters
+ */
+ function setNull( $name )
+ {
+ $this->client->bind( $name, null );
+ }
+
+
+}
+
+
+?>+
\ No newline at end of file
diff --git a/modules/database/driver/pdo.class.php b/modules/database/driver/pdo.class.php
@@ -0,0 +1,221 @@
+<?php
+
+//
+// +----------------------------------------------------------------------+
+// | PHP version 4.0 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2001 The PHP Group |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.02 of the PHP license, |
+// | that is bundled with this package in the file LICENSE, and is |
+// | available at through the world-wide-web at |
+// | http://www.php.net/license/2_02.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +----------------------------------------------------------------------+
+// | Authors: Stig Bakken <ssb@fast.no> |
+// | Jan Dankert <phpdb@jandankert.de> |
+// +----------------------------------------------------------------------+
+//
+
+/**
+ * Datenbank-abhaengige Methoden fuer PDO.
+ *
+ * @author Jan Dankert
+ * @version $Revision: 1.5 $
+ * @package openrat.database
+ */
+class DB_pdo
+{
+ /**
+ * Die PDO-Verbindung.
+ *
+ * @var Resource
+ */
+ var $connection;
+
+ /**
+ * Datenbank-Fehler.
+ *
+ * @var String
+ */
+ var $error;
+
+ var $lowercase = false;
+
+ var $params;
+
+
+ function connect( $conf )
+ {
+ $url = $conf['dsn' ];
+ $user = $conf['user' ];
+ $pw = $conf['password'];
+
+ if ( !empty($conf['convert_to_lowercase']) )
+ $this->lowercase = true;
+
+ $options = array();
+ foreach( $conf as $c )
+ if ( is_string($c) && substr($c,0,7) == 'option_' )
+ $options[substr($c,8)] = $conf[$c];
+
+ if ( $conf['persistent'])
+ $options[ PDO::ATTR_PERSISTENT ] = true;
+
+ if ( !$conf['prepare'])
+ $options[ PDO::ATTR_EMULATE_PREPARES ] = true;
+
+ $options[ PDO::ERRMODE_EXCEPTION ] = true;
+ $options[ PDO::ATTR_DEFAULT_FETCH_MODE ] = PDO::FETCH_ASSOC;
+
+ $this->connection = new PDO($url, $user, $pw, $options);
+
+ if ( !is_object($this->connection) )
+ throw new OpenRatException( 'DATABASE_ERROR_CONNECTION',"Could not connect to database on host $host. ".PDO::errorInfo() );
+
+ return true;
+ }
+
+
+
+ function disconnect()
+ {
+ $this->connection = null;
+ return true;
+ }
+
+
+
+ function query($query)
+ {
+ $erg = $this->stmt->execute();
+
+ if ( $erg === false )
+ {
+ throw new RuntimeException( 'Could not execute prepared statement "'.$query->query.'": '.implode('/',$this->stmt->errorInfo()) );
+ }
+
+ return $this->stmt;
+ }
+
+
+ function fetchRow( $result, $rownum )
+ {
+ $row = $this->stmt->fetch( PDO::FETCH_ASSOC );
+
+ if ( is_array($row) && $this->lowercase )
+ $row = array_change_key_case($row);
+
+ return $row;
+ }
+
+
+ function freeResult($result)
+ {
+ return true;
+ }
+
+
+ function prepare( $query,$param)
+ {
+ $this->params = $param;
+ $offset = 0;
+ foreach( $param as $name=>$pos)
+ {
+ $name = ':'.$name;
+ $pos += $offset;
+ $query = substr($query,0,$pos).$name.substr($query,$pos);
+
+ $offset = $offset + strlen($name);
+ }
+
+ Logger::debug('PDO: SQL-before-preparation: '.$query);
+
+ $this->stmt = $this->connection->prepare($query);
+
+ if ( $this->stmt === false )
+ throw new OpenRatException('ERROR_DATABASE_CONNECTION','Could not prepare statement: '.$query.' Cause: '.implode('/',$this->connection->errorInfo()) );
+
+ }
+
+
+
+ function bind( $param,$value )
+ {
+ $name = ':'.$param;
+
+ if ( is_string($value) )
+ $type = PDO::PARAM_STR;
+ elseif( is_int($value))
+ $type = PDO::PARAM_INT;
+ elseif( is_null($value))
+ $type = PDO::PARAM_NULL;
+ else
+ throw new RuntimeException( 'Unknown type' );
+
+ $this->stmt->bindValue($name,$value,$type);
+
+ Logger::debug('PDO: SQL-Binding of parameter '.$name);
+ }
+
+
+
+ /**
+ * Startet eine Transaktion.
+ */
+ function start()
+ {
+ $this->connection->beginTransaction();
+ }
+
+
+
+ /**
+ * Beendet eine Transaktion.
+ */
+ function commit()
+ {
+ $this->connection->commit();
+ }
+
+
+ /**
+ * Bricht eine Transaktion ab.
+ */
+ function rollback()
+ {
+ try
+ {
+ $this->connection->rollBack();
+ }
+ catch ( PDOException $e )
+ {
+ // Kommt vor, wenn keine Transaktion existiert.
+ }
+ }
+
+
+
+ /**
+ * Setzt die letzte Abfrage zurueck.
+ */
+ function clear()
+ {
+ $this->params = array();
+ }
+
+
+ /**
+ * Why this? See http://e-mats.org/2008/07/fatal-error-exception-thrown-without-a-stack-frame-in-unknown-on-line-0/
+ *
+ * @return array
+ */
+ function __sleep() {
+ return array();
+ }
+
+}
+
+?>+
\ No newline at end of file
diff --git a/modules/database/require.php b/modules/database/require.php
@@ -0,0 +1,10 @@
+<?php
+
+include( dirname(__FILE__) . "/Database.class.php" );
+include( dirname(__FILE__) . "/Statement.class.php" );
+include( dirname(__FILE__) . "/Sql.class.php" );
+
+if (version_compare(PHP_VERSION, '5.1.0', '>'))
+ include( dirname(__FILE__) . "/driver/pdo.class.php" );
+
+?>+
\ No newline at end of file