]> source.dussan.org Git - nextcloud-server.git/commitdiff
Refactoring of OC_DB
authorJakob Sack <kde@jakobsack.de>
Fri, 8 Apr 2011 14:53:17 +0000 (16:53 +0200)
committerJakob Sack <kde@jakobsack.de>
Fri, 8 Apr 2011 14:53:17 +0000 (16:53 +0200)
lib/base.php

index e38b76fff90ecae93c0f9f2730c40632c1193076..3bf74e233a5edb4905b361e4a72aedd658244aef 100644 (file)
@@ -350,18 +350,23 @@ class OC_HOOK{
 }
 
 /**
- * Class for database access
- *
+ * This class manages the access to the database. It basically is a wrapper for
+ * MDB2 with some adaptions.
  */
 class OC_DB {
        static private $DBConnection=false;
        static private $schema=false;
        static private $affected=0;
        static private $result=false;
+
        /**
-       * connect to the datbase if not already connected
-       */
-       public static function connect(){
+        * @brief connects to the database
+        * @returns true if connection can be established or nothing (die())
+        *
+        * Connects to the database as specified in config.php
+        */
+       static public function connect(){
+               // The global data we need
                global $CONFIG_DBNAME;
                global $CONFIG_DBHOST;
                global $CONFIG_DBUSER;
@@ -369,8 +374,13 @@ class OC_DB {
                global $CONFIG_DBTYPE;
                global $DOCUMENTROOT;
                global $SERVERROOT;
+
+               // do nothing if the connection already has been established
                if(!self::$DBConnection){
+                       // Require MDB2.php (TODO: why here not in head of file?)
                        @oc_require_once('MDB2.php');
+
+                       // Prepare options array
                        $options = array(
                                'portability' => MDB2_PORTABILITY_ALL,
                                'log_line_break' => '<br>',
@@ -378,249 +388,261 @@ class OC_DB {
                                'debug' => true,
                                'quote_identifier' => true,
                        );
+
+                       // Add the dsn according to the database type
                        if($CONFIG_DBTYPE=='sqlite'){
+                               // sqlite
                                $dsn = array(
-                                       'phptype'  => 'sqlite',
-                                       'database' => $SERVERROOT.'/'.$CONFIG_DBNAME,
-                                       'mode'   => '0644',
-                               );
-                       }elseif($CONFIG_DBTYPE=='mysql'){
+                                 'phptype'  => 'sqlite',
+                                 'database' => "$SERVERROOT/$CONFIG_DBNAME",
+                                 'mode' => '0644' );
+                       }
+                       elseif($CONFIG_DBTYPE=='mysql'){
+                               // MySQL
                                $dsn = array(
-                                       'phptype'  => 'mysql',
-                                       'username' => $CONFIG_DBUSER,
-                                       'password' => $CONFIG_DBPASSWORD,
-                                       'hostspec' => $CONFIG_DBHOST,
-                                       'database' => $CONFIG_DBNAME,
-                               );
-                       }elseif($CONFIG_DBTYPE=='pgsql'){
+                                 'phptype'  => 'mysql',
+                                 'username' => $CONFIG_DBUSER,
+                                 'password' => $CONFIG_DBPASSWORD,
+                                 'hostspec' => $CONFIG_DBHOST,
+                                 'database' => $CONFIG_DBNAME );
+                       }
+                       elseif($CONFIG_DBTYPE=='pgsql'){
+                               // PostgreSQL
                                $dsn = array(
-                                       'phptype'  => 'pgsql',
-                                       'username' => $CONFIG_DBUSER,
-                                       'password' => $CONFIG_DBPASSWORD,
-                                       'hostspec' => $CONFIG_DBHOST,
-                                       'database' => $CONFIG_DBNAME,
-                               );
+                                 'phptype'  => 'pgsql',
+                                 'username' => $CONFIG_DBUSER,
+                                 'password' => $CONFIG_DBPASSWORD,
+                                 'hostspec' => $CONFIG_DBHOST,
+                                 'database' => $CONFIG_DBNAME );
                        }
-                       self::$DBConnection=MDB2::factory($dsn,$options);
-
-                       if (PEAR::isError(self::$DBConnection)) {
-                               echo('<b>can not connect to database, using '.$CONFIG_DBTYPE.'. ('.self::$DBConnection->getUserInfo().')</center>');
-                               $error=self::$DBConnection->getMessage();
-                               error_log("$error");
-                               error_log(self::$DBConnection->getUserInfo());
-                               die($error);
+
+                       // Try to establish connection
+                       self::$DBConnection = MDB2::factory( $dsn, $options );
+
+                       // Die if we could not connect
+                       if( PEAR::isError( self::$DBConnection )){
+                               echo( '<b>can not connect to database, using '.$CONFIG_DBTYPE.'. ('.self::$DBConnection->getUserInfo().')</center>');
+                               $error = self::$DBConnection->getMessage();
+                               error_log( $error);
+                               error_log( self::$DBConnection->getUserInfo());
+                               die( $error );
                        }
+
+                       // We always, really always want associative arrays
                        self::$DBConnection->setFetchMode(MDB2_FETCHMODE_ASSOC);
                }
-       }
 
-       public static function connectScheme(){
-               self::connect();
-               if(!self::$schema){
-                       @oc_require_once('MDB2/Schema.php');
-                       self::$schema=&MDB2_Schema::factory(self::$DBConnection);
-               }
+               // we are done. great!
+               return true;
        }
 
        /**
-        * executes a query on the database
+        * @brief SQL query
+        * @param $query Query string
+        * @returns result as MDB2_Result
         *
-        * @param string $cmd
-        * @return result-set
+        * SQL query via MDB2 query()
         */
-       static function query($cmd){
-               global $CONFIG_DBTYPE;
-               if(!trim($cmd)){
-                       return false;
-               }
-               OC_DB::connect();
-               //fix differences between sql versions
+       static public function query( $query ){
+               // Optimize the query
+               $query = self::processQuery( $query );
 
-               //differences in escaping of table names (` for mysql)
-               if($CONFIG_DBTYPE=='sqlite'){
-                       $cmd=str_replace('`','\'',$cmd);
-               }elseif($CONFIG_DBTYPE=='pgsql'){
-                       $cmd=str_replace('`','"',$cmd);
-               }
-               $result=self::$DBConnection->exec($cmd);
-               if (PEAR::isError($result)) {
-                       $entry='DB Error: "'.$result->getMessage().'"<br />';
-                       $entry.='Offending command was: '.$cmd.'<br />';
-                       error_log($entry);
-                       die($entry);
-               }else{
-                       self::$affected=$result;
-               }
-               self::$result=$result;
-               return $result;
-       }
+               self::connect();
+               //fix differences between sql versions
 
-  /**
-   * executes a query on the database and returns the result in an array
-   *
-   * @param string $cmd
-   * @return result-set
-   */
-       static function select($cmd){
-               OC_DB::connect();
-               global $CONFIG_DBTYPE;
-  //fix differences between sql versions
+               // return the result
+               $result = self::$DBConnection->exec( $query );
 
-               //differences in escaping of table names (` for mysql)
-               if($CONFIG_DBTYPE=='sqlite'){
-                       $cmd=str_replace('`','\'',$cmd);
-               }elseif($CONFIG_DBTYPE=='pgsql'){
-                       $cmd=str_replace('`','"',$cmd);
-               }
-               $result=self::$DBConnection->queryAll($cmd);
-               if (PEAR::isError($result)){
-                       $entry='DB Error: "'.$result->getMessage().'"<br />';
-                       $entry.='Offending command was: '.$cmd.'<br />';
-                       die($entry);
+               // Die if we have an error (error means: bad query, not 0 results!)
+               if( PEAR::isError($result)) {
+                       $entry = 'DB Error: "'.$result->getMessage().'"<br />';
+                       $entry .= 'Offending command was: '.$cmd.'<br />';
+                       error_log( $entry );
+                       die( $entry );
                }
+
                return $result;
        }
 
        /**
-       * executes multiply queries on the database
-       *
-       * @param string $cmd
-       * @return result-set
-       */
-       static function multiquery($cmd) {
-               $queries=explode(';',$cmd);
-               foreach($queries as $query){
-                       OC_DB::query($query);
-               }
-               return true;
-       }
-
+        * @brief Prepare a SQL query
+        * @param $query Query string
+        * @returns prepared SQL query
+        *
+        * SQL query via MDB2 prepare(), needs to be execute()'d!
+        */
+       static public function prepare( $query ){
+               // Optimize the query
+               $query = self::processQuery( $query );
 
-       /**
-       * closing a db connection
-       *
-       * @return bool
-       */
-       static function close() {
-               self::$DBConnection->disconnect();
-               self::$DBConnection=false;
-       }
+               self::connect();
+               //fix differences between sql versions
 
+               // return the result
+               $result = self::$DBConnection->prepare( $query );
 
-       /**
-       * Returning primarykey if last statement was an insert.
-       *
-       * @return primarykey
-       */
-       static function insertid() {
-               $id=self::$DBConnection->lastInsertID();
-               return $id;
-       }
+               // Die if we have an error (error means: bad query, not 0 results!)
+               if( PEAR::isError($result)) {
+                       $entry = 'DB Error: "'.$result->getMessage().'"<br />';
+                       $entry .= 'Offending command was: '.$cmd.'<br />';
+                       error_log( $entry );
+                       die( $entry );
+               }
 
-       /**
-       * Returning number of rows in a result
-       *
-       * @param resultset $result
-       * @return int
-       */
-       static function numrows($result) {
-               $result->numRows();
-       }
-       /**
-       * Returning number of affected rows
-       *
-       * @return int
-       */
-       static function affected_rows() {
-               return self::$affected;
-       }
-
-        /**
-       * get a field from the resultset
-       *
-       * @param resultset $result
-       * @param int $i
-       * @param int $field
-       * @return unknown
-       */
-       static function result($result, $i, $field) {
-               $tmp=$result->fetchRow(MDB2_FETCHMODE_ASSOC,$i);
-               $tmp=$tmp[$field];
-               return($tmp);
+               return $result;
        }
 
        /**
-       * get data-array from resultset
-       *
-       * @param resultset $result
-       * @return data
-       */
-       static function fetch_assoc($result){
-               return $result->fetchRow(MDB2_FETCHMODE_ASSOC);
+        * @brief gets last value of autoincrement
+        * @returns id
+        *
+        * MDB2 lastInsertID()
+        *
+        * Call this method right after the insert command or other functions may
+        * cause trouble!
+        */
+       public static function insertid(){
+               self::connect();
+               return self::$DBConnection->lastInsertID();
        }
 
        /**
-       * Freeing resultset (performance)
-       *
-       * @param unknown_type $result
-       * @return bool
-       */
-       static function free_result() {
-               if(self::$result){
-                       self::$result->free();
-                       self::$result=false;
-               }
-       }
-
-       static public function disconnect(){
+        * @brief Disconnect
+        * @returns true/false
+        *
+        * This is good bye, good bye, yeah!
+        */
+       public static function disconnect(){
+               // Cut connection if required
                if(self::$DBConnection){
                        self::$DBConnection->disconnect();
                        self::$DBConnection=false;
                }
+
+               return true;
        }
 
        /**
-       * escape strings so they can be used in queries
-       *
-       * @param string string
-       * @return string
-       */
-       static function escape($string){
-               OC_DB::connect();
-               return self::$DBConnection->escape($string);
-       }
-
-       static function getDbStructure($file){
-               OC_DB::connectScheme();
+        * @brief Escapes bad characters
+        * @param $string string with dangerous characters
+        * @returns escaped string
+        *
+        * MDB2 escape()
+        */
+       public static function escape( $string ){
+               self::connect();
+               return self::$DBConnection->escape( $string );
+       }
+
+       /**
+        * @brief saves database scheme to xml file
+        * @param $file name of file
+        * @returns true/false
+        *
+        * TODO: write more documentation
+        */
+       public static function getDbStructure( $file ){
+               self::connectScheme();
+
+               // write the scheme
                $definition = self::$schema->getDefinitionFromDatabase();
                $dump_options = array(
                        'output_mode' => 'file',
                        'output' => $file,
                        'end_of_line' => "\n"
                );
-               self::$schema->dumpDatabase($definition, $dump_options, MDB2_SCHEMA_DUMP_STRUCTURE);
+               self::$schema->dumpDatabase( $definition, $dump_options, MDB2_SCHEMA_DUMP_STRUCTURE );
+
+               return true;
        }
 
-       static function createDbFromStructure($file){
-               OC_DB::connectScheme();
+       /**
+        * @brief Creates tables from XML file
+        * @param $file file to read structure from
+        * @returns true/false
+        *
+        * TODO: write more documentation
+        */
+       public static function createDbFromStructure( $file ){
                global $CONFIG_DBNAME;
                global $CONFIG_DBTABLEPREFIX;
-               $content=file_get_contents($file);
-               $file2=tempnam(sys_get_temp_dir(),'oc_db_scheme_');
-               $content=str_replace('*dbname*',$CONFIG_DBNAME,$content);
-               $content=str_replace('*dbprefix*',$CONFIG_DBTABLEPREFIX,$content);
-               file_put_contents($file2,$content);
-               $definition=@self::$schema->parseDatabaseDefinitionFile($file2);
-               unlink($file2);
-               if($definition instanceof MDB2_Schema_Error){
-                       die($definition->getMessage() . ': ' . $definition->getUserInfo());
+
+               self::connectScheme();
+
+               // read file
+               $content = file_get_contents( $file );
+
+               // Make changes and save them to a temporary file
+               $file2 = tempnam( sys_get_temp_dir(), 'oc_db_scheme_' );
+               $content = str_replace( '*dbname*', $CONFIG_DBNAME, $content );
+               $content = str_replace( '*dbprefix*', $CONFIG_DBTABLEPREFIX, $content );
+               file_put_contents( $file2, $content );
+
+               // Try to create tables
+               $definition = @self::$schema->parseDatabaseDefinitionFile( $file2 );
+
+               // Delete our temporary file
+               unlink( $file2 );
+
+               // Die in case something went wrong
+               if( $definition instanceof MDB2_Schema_Error ){
+                       die( $definition->getMessage().': '.$definition->getUserInfo());
                }
-               $ret=@self::$schema->createDatabase($definition);
-               if($ret instanceof MDB2_Error) {
+               $ret=@self::$schema->createDatabase( $definition );
+
+               // Die in case something went wrong
+               if( $ret instanceof MDB2_Error ){
                        die ($ret->getMessage() . ': ' . $ret->getUserInfo());
-               }else{
-                       return true;
                }
+
+               return true;
+       }
+
+       /**
+        * @brief connects to a MDB2 database scheme
+        * @returns true/false
+        *
+        * Connects to a MDB2 database scheme
+        */
+       private static function connectScheme(){
+               // We need a database connection
+               self::connect();
+
+               // Connect if this did not happen before
+               if(!self::$schema){
+                       @oc_require_once('MDB2/Schema.php');
+                       self::$schema=&MDB2_Schema::factory(self::$DBConnection);
+               }
+
+               return true;
+       }
+
+       /**
+        * @brief does minor chages to query
+        * @param $query Query string
+        * @returns corrected query string
+        *
+        * This function replaces *PREFIX* with the value of $CONFIG_DBTABLEPREFIX
+        * and replaces the ` woth ' or " according to the database driver.
+        */
+       private static function processQuery( $query ){
+               // We need Database type and table prefix
+               global $CONFIG_DBTYPE;
+               global $CONFIG_DBTABLEPREFIX;
+
+               // differences in escaping of table names (` for mysql)
+               // Problem: what if there is a ` in the value we want to insert?
+               if( $CONFIG_DBTYPE == 'sqlite' ){
+                       $query = str_replace( '`', '\'', $query );
+               }
+               elseif( $CONFIG_DBTYPE == 'pgsql' ){
+                       $query = str_replace( '`', '"', $query );
+               }
+
+               // replace table names
+               $query = str_replace( '*PREFIX*', $CONFIG_DBTABLEPREFIX, $query );
+
+               return $query;
        }
 }