table_prefix = (string) $config['table_prefix']; $this->schema = ( isset($config['schema']) )? $config['schema']: 'public'; $this->_open_db($config['host'], $config['database'], $config['user'], $config['pass']); } /** * Datenbankeintrag erzeugen * * Die create-Methode bietet eine Schnittstelle, um Daten zur Datenbank * hinzuzufügen. * * @param string $table Tabellenname * @param array $data assoziatives Array, das die Daten enthält. * @param string $type Art der Einfügeoperation (INSERT, INSERT IGNORE, REPLACE) * @return string Ergebnis der Datenbankoperation */ public function create($table, array $data) { $rows = array_keys($data); $values = array(); foreach( array_values($data) as $value ) { $values[] = $this->_secureFieldContent($value); } $sql = 'INSERT INTO '. $this->_tableName($table); $sql .= ' ( ' . implode(', ', $rows) . ' ) '; $sql .= " VALUES ( '". implode("', '", $values) . "' );"; return ( $this->query($sql) )? $this->last_insert_id($table): false; } /** * Datenbankeintrag holen * * Die retrieve-Methode bietet eine Schnittstelle, um Daten aus der * Datenbank zu lesen. * * @param string $table Tabellenname * @param string $field Feldnamen, die abgefragt werden * @param string $condition Bedigungen, nach denen die Tabellenzeilen ausgewählt werden * @param string $order Sortierungsreihenfolge * @param string $limit maximale Anzahl von Zeilen * @return array Assoziatives Array mit den Daten. */ public function retrieve($table, $field='*', $condition='', $order='', $limit='') { if ( $limit == '') { $sql_limit = false; } elseif ( strpos($limit, ',') === false ) { $sql_limit = '0,' . $limit; } else { $sql_limit = $limit; } $sql = 'SELECT '.$field.' FROM '.$this->schema.'.'.$this->table_prefix.$table; if ( !empty($condition) ) $sql .= ' WHERE '.$condition; if ( !empty($order) ) $sql .= ' ORDER BY '.$order; if ( $sql_limit !== false ) { list($offset, $sql_limit) = explode(',', $sql_limit); $sql .= ' LIMIT '.$sql_limit . ' OFFSET '. $offset; } $sql .= ';'; $result = $this->query($sql); if ( $result === false ) { $result = array(); } return $result; } /** * Datenbankeintrag aktualisieren * * Die update-Methode bietet eine Schnittstelle, um Daten in der Datenbank * zu aktualisieren. Dies ist die vermutlich die häufigste Form der * Speicherung. * * @param string $table Tabellenname * @param array $data assoziatives Array, das die Daten enthält. * @param int $id id des Datenbankeintrages * @param string $id_field Feldname des id-Feldes * @param boolean $all Alle Zeilen verändern * * @return string Ergebnis der Datenbankoperation */ public function update($table, array $data, $id, $id_field='id', $all=FALSE) { $data_length = count($data); $i = 0; $sql = "UPDATE ".$this->table_prefix.$table." SET".PHP_EOL; foreach ($data as $field=>$content) { $this->_secureFieldContent($content); $sql .= " ".$field."='".$content."'"; if ( ( $data_length - 1 ) > $i++ ) $sql .= ","; } if ( !$all ) { $sql .= " WHERE ".$id_field."='".$id."' ;"; } else { $sql .= ';'; } $result = $this->query($sql); return $result; } /** * Datenbankeintrag löschen * * Die del-Methode bietet eine Schnittstelle, um Daten aus der Datenbank * zu löschen. * * @param string $table Tabellenname * @param int $id id des Datenbankeintrages * @return boolean Ergebnis der Datenbankoperation */ public function del($table, $id) { if ( !is_numeric($id) ) { return FALSE; } $sql = "DELETE FROM $this->table_prefix.$table WHERE id=$id;"; $result = $this->query($sql); return $result; } /** * Datenbank-Ergebnisse in richtige Typen umwandeln * * Es werden die Datentypen boolean, integer und numeric ausgewertet. * String-Datentypen muessen nicht ausgewertet werden, da PHP diesen * Datentype automatisch annimmt. * * @param string table * @param array $result * @return array */ public function convert_result($table, $result) { $table = $this->table_prefix . $table; $converted = $result; $sql = <<query($sql); foreach ( $types as $type ) { foreach ( $result as $row_num => $rows ) { $col = $type['col']; $new_type = $type['type']; if ( $new_type == 'boolean' ) { $converted[$row_num][$col] = ( $converted[$row_num][$col] == 't' )? (boolean) true: (boolean) false; } else { settype($converted[$row_num][$col], $new_type); } } } return $converted; } /** * Tabelle leeren * * @param string $table Tabellennname * @return boolean * @todo Funktion fuer PostgreSQL umarbeiten */ public function clear_table($table) { return false; $sql = 'TRUNCATE TABLE '.$this->table_prefix.$table; $result = (boolean) $this->query($sql); return $result; } /** * Tabelle optimieren * * @param string $table Tabellenname * @return boolean * @todo Funktion fuer PostgreSQL umarbeiten, VACCUUM */ public function optimize_table($table) { return false; $sql = 'OPTIMIZE TABLE ' . $this->table_prefix.$table; $result = (boolean) $this->query($sql); return $result; } /** * Zuletzt einfügte ID zurückgeben * * @param string $table * @return integer */ public function last_insert_id($table) { $result = $this->query('SELECT last_value FROM '.$this->_tableName($table).'_id_seq;'); return $result[0]['last_value']; } /** * Datenbankabfrage als SQL abgeben * * @param string $sql * @return mixed */ public function query($sql) { return $this->_query_db($sql); } // interne Funktionen /** * Datenbankverbindung öffnen * * @param string $host * @param string $db * @param string $user * @param string $pass */ private function _open_db($host, $db, $user, $pass) { if ( !extension_loaded('pgsql') ) { die("PHP-Erweiterung 'pgsql' nicht geladen"); } $conn_str = "host='$host' user='$user' password='$pass' dbname='$db'"; if ( !($this->connection = pg_connect($conn_str)) ) { die('Keine Verbindung zur Datenbank möglich. (Fehlermeldung: '.pg_last_error().')'); } pg_set_client_encoding($this->connection, 'utf8'); } /** * Datenbank abfragen * * @param mixed $sql String oder Array, das die SQL-Abfragen enthält * @return mixed */ private function _query_db($sql) { if ( is_array($sql) ) { foreach ( $sql as $nr => $query ) { $output[$nr] = $this->query( $query ); } } else { $this->log_query($sql); $output = array(); $abfrage = is_string($sql) ? trim($sql) : $this->error('Fehlerhafte Daten', $sql); $abfragetyp = strtoupper(substr($abfrage,0,6)); /* Asynchrone Abfrage if (!pg_connection_busy($this->connection)) { pg_send_query($this->connection, $abfrage); } else { $this->_error('Verbindung ausgelastet'); } $result = pg_get_result($this->connection); // pg_result_error gibt einen String zurück, wenn ein Fehler // vorliegt und FALSE, wenn kein Fehler vorliegt. // Es scheint aber auch einen leeren String zurückzugeben, wenn // kein Fehler vorliegt. $error = pg_result_error($result); if( is_string($error) AND trim($error) !== '' ) { $this->_error($error, $abfrage); } else { $this->query_count++; $result_status = pg_result_status($result); } */ /* Einzelne, synchrone Abfrage */ if ( ($result = pg_query($this->connection, $abfrage)) === false ) { $this->error(pg_last_error($this->connection), $abfrage); } else { $result_status = pg_result_status($result); } if ( $abfragetyp !== 'SELECT' ) { $output = ( $result_status === PGSQL_COMMAND_OK )? true: false; } else { $output = pg_fetch_all($result); if ( count($output) > 100 ) { pg_free_result($result); } } unset($abfragetyp); } return $output; } /** * Tabellenbezeichner herstellen * * @param string $table * @return string */ protected function _tableName($table) { return $this->schema . '.' . $this->table_prefix . $table; } public function get_table_name($table) { return $this->_tableName($table); } /** * Feldinhalte gegen Hackingversuche schützen * * Dies sind nur grundlegende Schutzmaßnahmen * * @param mixed &$var */ protected function _secureFieldContent(&$var){ if ( is_array($var) ) { $varvalue = var_export($var, TRUE); $this->error('Array wurde uebergeben, kann aber nicht gespeichert werden.', $varvalue ); } return $var = pg_escape_string($var); } } ?>