diff --git a/3rdparty b/3rdparty
index 217626723957161191572ea50172a3943c30696d..25e8568d41a9b9a6d1662ccf33058822a890e7f5 160000
--- a/3rdparty
+++ b/3rdparty
@@ -1 +1 @@
-Subproject commit 217626723957161191572ea50172a3943c30696d
+Subproject commit 25e8568d41a9b9a6d1662ccf33058822a890e7f5
diff --git a/db_structure.xml b/db_structure.xml
index cefb7fc52c91c31a6300d966736554936a4707bc..ef5de653033c573f69077830e5ce6a51dfb46a3f 100644
--- a/db_structure.xml
+++ b/db_structure.xml
@@ -308,7 +308,7 @@
 				<name>etag</name>
 				<type>text</type>
 				<default></default>
-				<notnull>true</notnull>
+				<notnull>false</notnull>
 				<length>40</length>
 			</field>
 
diff --git a/lib/MDB2/Driver/Datatype/sqlite3.php b/lib/MDB2/Driver/Datatype/sqlite3.php
deleted file mode 100644
index ca4c1cbceb8d3d85d651eb5656be0a1b01341fe7..0000000000000000000000000000000000000000
--- a/lib/MDB2/Driver/Datatype/sqlite3.php
+++ /dev/null
@@ -1,385 +0,0 @@
-<?php
-/**
- * ownCloud
- *
- * @author Robin Appelman
- * @copyright 2011 Robin Appelman icewind1991@gmail.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or any later version.
- *
- * This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU Affero General Public
- * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-require_once 'MDB2/Driver/Datatype/Common.php';
-
-/**
- * MDB2 SQLite driver
- *
- * @package MDB2
- * @category Database
- * @author  Lukas Smith <smith@pooteeweet.org>
- */
-class MDB2_Driver_Datatype_sqlite3 extends MDB2_Driver_Datatype_Common
-{
-    // {{{ _getCollationFieldDeclaration()
-
-    /**
-     * Obtain DBMS specific SQL code portion needed to set the COLLATION
-     * of a field declaration to be used in statements like CREATE TABLE.
-     *
-     * @param string $collation name of the collation
-     *
-     * @return string DBMS specific SQL code portion needed to set the COLLATION
-     *                of a field declaration.
-     */
-    function _getCollationFieldDeclaration($collation)
-    {
-        return 'COLLATE '.$collation;
-    }
-
-    // }}}
-    // {{{ getTypeDeclaration()
-
-    /**
-     * Obtain DBMS specific SQL code portion needed to declare an text type
-     * field to be used in statements like CREATE TABLE.
-     *
-     * @param array $field  associative array with the name of the properties
-     *      of the field being declared as array indexes. Currently, the types
-     *      of supported field properties are as follows:
-     *
-     *      length
-     *          Integer value that determines the maximum length of the text
-     *          field. If this argument is missing the field should be
-     *          declared to have the longest length allowed by the DBMS.
-     *
-     *      default
-     *          Text value to be used as default for this field.
-     *
-     *      notnull
-     *          Boolean flag that indicates whether this field is constrained
-     *          to not be set to null.
-     * @return string  DBMS specific SQL code portion that should be used to
-     *      declare the specified field.
-     * @access public
-     */
-    function getTypeDeclaration($field)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        switch ($field['type']) {
-        case 'text':
-            $length = !empty($field['length'])
-                ? $field['length'] : false;
-            $fixed = !empty($field['fixed']) ? $field['fixed'] : false;
-            return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')')
-                : ($length ? 'VARCHAR('.$length.')' : 'TEXT');
-        case 'clob':
-            if (!empty($field['length'])) {
-                $length = $field['length'];
-                if ($length <= 255) {
-                    return 'TINYTEXT';
-                } elseif ($length <= 65532) {
-                    return 'TEXT';
-                } elseif ($length <= 16777215) {
-                    return 'MEDIUMTEXT';
-                }
-            }
-            return 'LONGTEXT';
-        case 'blob':
-            if (!empty($field['length'])) {
-                $length = $field['length'];
-                if ($length <= 255) {
-                    return 'TINYBLOB';
-                } elseif ($length <= 65532) {
-                    return 'BLOB';
-                } elseif ($length <= 16777215) {
-                    return 'MEDIUMBLOB';
-                }
-            }
-            return 'LONGBLOB';
-        case 'integer':
-            if (!empty($field['length'])) {
-                $length = $field['length'];
-                if ($length <= 2) {
-                    return 'SMALLINT';
-                } elseif ($length == 3 || $length == 4) {
-                    return 'INTEGER';
-                } elseif ($length > 4) {
-                    return 'BIGINT';
-                }
-            }
-            return 'INTEGER';
-        case 'boolean':
-            return 'BOOLEAN';
-        case 'date':
-            return 'DATE';
-        case 'time':
-            return 'TIME';
-        case 'timestamp':
-            return 'DATETIME';
-        case 'float':
-            return 'DOUBLE'.($db->options['fixed_float'] ? '('.
-                ($db->options['fixed_float']+2).','.$db->options['fixed_float'].')' : '');
-        case 'decimal':
-            $length = !empty($field['length']) ? $field['length'] : 18;
-            $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
-            return 'DECIMAL('.$length.','.$scale.')';
-        }
-        return '';
-    }
-
-    // }}}
-    // {{{ _getIntegerDeclaration()
-
-    /**
-     * Obtain DBMS specific SQL code portion needed to declare an integer type
-     * field to be used in statements like CREATE TABLE.
-     *
-     * @param string  $name   name the field to be declared.
-     * @param string  $field  associative array with the name of the properties
-     *                        of the field being declared as array indexes.
-     *                        Currently, the types of supported field
-     *                        properties are as follows:
-     *
-     *                       unsigned
-     *                        Boolean flag that indicates whether the field
-     *                        should be declared as unsigned integer if
-     *                        possible.
-     *
-     *                       default
-     *                        Integer value to be used as default for this
-     *                        field.
-     *
-     *                       notnull
-     *                        Boolean flag that indicates whether this field is
-     *                        constrained to not be set to null.
-     * @return string  DBMS specific SQL code portion that should be used to
-     *                 declare the specified field.
-     * @access protected
-     */
-    function _getIntegerDeclaration($name, $field)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $default = $autoinc = '';
-        if (!empty($field['autoincrement'])) {
-            $autoinc = ' PRIMARY KEY AUTOINCREMENT';
-        } elseif (array_key_exists('default', $field)) {
-            if ($field['default'] === '') {
-                $field['default'] = empty($field['notnull']) ? null : 0;
-            }
-            $default = ' DEFAULT '.$this->quote($field['default'], 'integer');
-        }
-
-        $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
-        $unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED';
-        $name = $db->quoteIdentifier($name, true);
-        if($autoinc) {
-			return $name.' '.$this->getTypeDeclaration($field).$autoinc;
-        }else{
-			return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull.$autoinc;
-        }
-    }
-
-    // }}}
-    // {{{ matchPattern()
-
-    /**
-     * build a pattern matching string
-     *
-     * @access public
-     *
-     * @param array $pattern even keys are strings, odd are patterns (% and _)
-     * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
-     * @param string $field optional field name that is being matched against
-     *                  (might be required when emulating ILIKE)
-     *
-     * @return string SQL pattern
-     */
-    function matchPattern($pattern, $operator = null, $field = null)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $match = '';
-        if (!is_null($operator)) {
-            $field = is_null($field) ? '' : $field.' ';
-            $operator = strtoupper($operator);
-            switch ($operator) {
-            // case insensitive
-            case 'ILIKE':
-                $match = $field.'LIKE ';
-                break;
-            // case sensitive
-            case 'LIKE':
-                $match = $field.'LIKE ';
-                break;
-            default:
-                return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-                    'not a supported operator type:'. $operator, __FUNCTION__);
-            }
-        }
-        $match.= "'";
-        foreach ($pattern as $key => $value) {
-            if ($key % 2) {
-                $match.= $value;
-            } else {
-                $match.= $db->escapePattern($db->escape($value));
-            }
-        }
-        $match.= "'";
-        $match.= $this->patternEscapeString();
-        return $match;
-    }
-
-    // }}}
-    // {{{ _mapNativeDatatype()
-
-    /**
-     * Maps a native array description of a field to a MDB2 datatype and length
-     *
-     * @param array  $field native field description
-     * @return array containing the various possible types, length, sign, fixed
-     * @access public
-     */
-    function _mapNativeDatatype($field)
-    {
-        $db_type = strtolower($field['type']);
-        $length = !empty($field['length']) ? $field['length'] : null;
-        $unsigned = !empty($field['unsigned']) ? $field['unsigned'] : null;
-        $fixed = null;
-        $type = array();
-        switch ($db_type) {
-        case 'boolean':
-            $type[] = 'boolean';
-            break;
-        case 'tinyint':
-            $type[] = 'integer';
-            $type[] = 'boolean';
-            if (preg_match('/^(is|has)/', $field['name'])) {
-                $type = array_reverse($type);
-            }
-            $unsigned = preg_match('/ unsigned/i', $field['type']);
-            $length = 1;
-            break;
-        case 'smallint':
-            $type[] = 'integer';
-            $unsigned = preg_match('/ unsigned/i', $field['type']);
-            $length = 2;
-            break;
-        case 'mediumint':
-            $type[] = 'integer';
-            $unsigned = preg_match('/ unsigned/i', $field['type']);
-            $length = 3;
-            break;
-        case 'int':
-        case 'integer':
-        case 'serial':
-            $type[] = 'integer';
-            $unsigned = preg_match('/ unsigned/i', $field['type']);
-            $length = 4;
-            break;
-        case 'bigint':
-        case 'bigserial':
-            $type[] = 'integer';
-            $unsigned = preg_match('/ unsigned/i', $field['type']);
-            $length = 8;
-            break;
-        case 'clob':
-            $type[] = 'clob';
-            $fixed  = false;
-            break;
-        case 'tinytext':
-        case 'mediumtext':
-        case 'longtext':
-        case 'text':
-        case 'varchar':
-        case 'varchar2':
-            $fixed = false;
-        case 'char':
-            $type[] = 'text';
-            if ($length == '1') {
-                $type[] = 'boolean';
-                if (preg_match('/^(is|has)/', $field['name'])) {
-                    $type = array_reverse($type);
-                }
-            } elseif (strstr($db_type, 'text')) {
-                $type[] = 'clob';
-                $type = array_reverse($type);
-            }
-            if ($fixed !== false) {
-                $fixed = true;
-            }
-            break;
-        case 'date':
-            $type[] = 'date';
-            $length = null;
-            break;
-        case 'datetime':
-        case 'timestamp':
-            $type[] = 'timestamp';
-            $length = null;
-            break;
-        case 'time':
-            $type[] = 'time';
-            $length = null;
-            break;
-        case 'float':
-        case 'double':
-        case 'real':
-            $type[] = 'float';
-            break;
-        case 'decimal':
-        case 'numeric':
-            $type[] = 'decimal';
-            $length = $length.','.$field['decimal'];
-            break;
-        case 'tinyblob':
-        case 'mediumblob':
-        case 'longblob':
-        case 'blob':
-            $type[] = 'blob';
-            $length = null;
-            break;
-        case 'year':
-            $type[] = 'integer';
-            $type[] = 'date';
-            $length = null;
-            break;
-        default:
-            $db =$this->getDBInstance();
-            if (PEAR::isError($db)) {
-                return $db;
-            }
-            return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-                'unknown database attribute type: '.$db_type, __FUNCTION__);
-        }
-
-        if ((int)$length <= 0) {
-            $length = null;
-        }
-
-        return array($type, $length, $unsigned, $fixed);
-    }
-
-    // }}}
-}
diff --git a/lib/MDB2/Driver/Function/sqlite3.php b/lib/MDB2/Driver/Function/sqlite3.php
deleted file mode 100644
index 4147a48199f54e1bdb1e1f2cc939c3f83790d75e..0000000000000000000000000000000000000000
--- a/lib/MDB2/Driver/Function/sqlite3.php
+++ /dev/null
@@ -1,136 +0,0 @@
-<?php
-/**
- * ownCloud
- *
- * @author Robin Appelman
- * @copyright 2011 Robin Appelman icewind1991@gmail.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or any later version.
- *
- * This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU Affero General Public
- * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-require_once 'MDB2/Driver/Function/Common.php';
-
-/**
- * MDB2 SQLite driver for the function modules
- *
- * @package MDB2
- * @category Database
- * @author  Lukas Smith <smith@pooteeweet.org>
- */
-class MDB2_Driver_Function_sqlite3 extends MDB2_Driver_Function_Common
-{
-    // {{{ constructor
-
-    /**
-     * Constructor
-     */
-    function __construct($db_index)
-    {
-        parent::__construct($db_index);
-        // create all sorts of UDFs
-    }
-
-    // {{{ now()
-
-    /**
-     * Return string to call a variable with the current timestamp inside an SQL statement
-     * There are three special variables for current date and time.
-     *
-     * @return string to call a variable with the current timestamp
-     * @access public
-     */
-    function now($type = 'timestamp')
-    {
-        switch ($type) {
-        case 'time':
-            return 'CURRENT_TIME';
-        case 'date':
-            return 'CURRENT_DATE';
-        case 'timestamp':
-        default:
-            return 'CURRENT_TIMESTAMP';
-        }
-    }
-
-    // }}}
-    // {{{ unixtimestamp()
-
-    /**
-     * return string to call a function to get the unix timestamp from a iso timestamp
-     *
-     * @param string $expression
-     *
-     * @return string to call a variable with the timestamp
-     * @access public
-     */
-    function unixtimestamp($expression)
-    {
-        return 'strftime("%s",'. $expression.', "utc")';
-    }
-
-    // }}}
-    // {{{ substring()
-
-    /**
-     * return string to call a function to get a substring inside an SQL statement
-     *
-     * @return string to call a function to get a substring
-     * @access public
-     */
-    function substring($value, $position = 1, $length = null)
-    {
-        if (!is_null($length)) {
-            return "substr($value, $position, $length)";
-        }
-        return "substr($value, $position, length($value))";
-    }
-
-    // }}}
-    // {{{ random()
-
-    /**
-     * return string to call a function to get random value inside an SQL statement
-     *
-     * @return return string to generate float between 0 and 1
-     * @access public
-     */
-    function random()
-    {
-        return '((RANDOM()+2147483648)/4294967296)';
-    }
-
-    // }}}
-    // {{{ replace()
-
-    /**
-     * return string to call a function to get a replacement inside an SQL statement.
-     *
-     * @return string to call a function to get a replace
-     * @access public
-     */
-    function replace($str, $from_str, $to_str)
-    {
-        $db =& $this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $error =& $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-            'method not implemented', __FUNCTION__);
-        return $error;
-    }
-
-    // }}}
-}
diff --git a/lib/MDB2/Driver/Manager/sqlite3.php b/lib/MDB2/Driver/Manager/sqlite3.php
deleted file mode 100644
index 921153c17dd027f9c082caa4a6be73bba4ab7655..0000000000000000000000000000000000000000
--- a/lib/MDB2/Driver/Manager/sqlite3.php
+++ /dev/null
@@ -1,1362 +0,0 @@
-<?php
-/**
- * ownCloud
- *
- * @author Robin Appelman
- * @copyright 2011 Robin Appelman icewind1991@gmail.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or any later version.
- *
- * This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU Affero General Public
- * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-require_once 'MDB2/Driver/Manager/Common.php';
-
-/**
- * MDB2 SQLite driver for the management modules
- *
- * @package MDB2
- * @category Database
- * @author  Lukas Smith <smith@pooteeweet.org>
- * @author  Lorenzo Alberton <l.alberton@quipo.it>
- */
-class MDB2_Driver_Manager_sqlite3 extends MDB2_Driver_Manager_Common
-{
-    // {{{ createDatabase()
-
-    /**
-     * create a new database
-     *
-     * @param string $name    name of the database that should be created
-     * @param array  $options array with charset info
-     *
-     * @return mixed MDB2_OK on success, a MDB2 error on failure
-     * @access public
-     */
-    function createDatabase($name, $options = array())
-    {
-		$datadir=OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" );
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $database_file = $db->_getDatabaseFile($name);
-        if (file_exists($database_file)) {
-            return $db->raiseError(MDB2_ERROR_ALREADY_EXISTS, null, null,
-                'database already exists', __FUNCTION__);
-        }
-        $php_errormsg = '';
-        $database_file="$datadir/$database_file.db";
-        $handle=new SQLite3($database_file);
-        if (!$handle) {
-            return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null,
-                (isset($php_errormsg) ? $php_errormsg : 'could not create the database file'), __FUNCTION__);
-        }
-        //sqlite doesn't support the latin1 we use
-//         if (!empty($options['charset'])) {
-//             $query = 'PRAGMA encoding = ' . $db->quote($options['charset'], 'text');
-//             $handle->exec($query);
-//         }
-        $handle->close();
-        return MDB2_OK;
-    }
-
-    // }}}
-    // {{{ dropDatabase()
-
-    /**
-     * drop an existing database
-     *
-     * @param string $name name of the database that should be dropped
-     * @return mixed MDB2_OK on success, a MDB2 error on failure
-     * @access public
-     */
-    function dropDatabase($name)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $database_file = $db->_getDatabaseFile($name);
-        if (!@file_exists($database_file)) {
-            return $db->raiseError(MDB2_ERROR_CANNOT_DROP, null, null,
-                'database does not exist', __FUNCTION__);
-        }
-        $result = @unlink($database_file);
-        if (!$result) {
-            return $db->raiseError(MDB2_ERROR_CANNOT_DROP, null, null,
-                (isset($php_errormsg) ? $php_errormsg : 'could not remove the database file'), __FUNCTION__);
-        }
-        return MDB2_OK;
-    }
-
-    // }}}
-    // {{{ _getAdvancedFKOptions()
-
-    /**
-     * Return the FOREIGN KEY query section dealing with non-standard options
-     * as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
-     *
-     * @param array $definition
-     * @return string
-     * @access protected
-     */
-    function _getAdvancedFKOptions($definition)
-    {
-        $query = '';
-        if (!empty($definition['match'])) {
-            $query .= ' MATCH '.$definition['match'];
-        }
-        if (!empty($definition['onupdate']) && (strtoupper($definition['onupdate']) != 'NO ACTION')) {
-            $query .= ' ON UPDATE '.$definition['onupdate'];
-        }
-        if (!empty($definition['ondelete']) && (strtoupper($definition['ondelete']) != 'NO ACTION')) {
-            $query .= ' ON DELETE '.$definition['ondelete'];
-        }
-        if (!empty($definition['deferrable'])) {
-            $query .= ' DEFERRABLE';
-        } else {
-            $query .= ' NOT DEFERRABLE';
-        }
-        if (!empty($definition['initiallydeferred'])) {
-            $query .= ' INITIALLY DEFERRED';
-        } else {
-            $query .= ' INITIALLY IMMEDIATE';
-        }
-        return $query;
-    }
-
-    // }}}
-    // {{{ _getCreateTableQuery()
-
-    /**
-     * Create a basic SQL query for a new table creation
-     * @param string $name   Name of the database that should be created
-     * @param array $fields  Associative array that contains the definition of each field of the new table
-     * @param array $options  An associative array of table options
-     * @return mixed string (the SQL query) on success, a MDB2 error on failure
-     * @see createTable()
-     */
-    function _getCreateTableQuery($name, $fields, $options = array())
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        if (!$name) {
-            return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null,
-                'no valid table name specified', __FUNCTION__);
-        }
-        if (empty($fields)) {
-            return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null,
-                'no fields specified for table "'.$name.'"', __FUNCTION__);
-        }
-        $query_fields = $this->getFieldDeclarationList($fields);
-        if (PEAR::isError($query_fields)) {
-            return $query_fields;
-        }
-        if (!empty($options['foreign_keys'])) {
-            foreach ($options['foreign_keys'] as $fkname => $fkdef) {
-                if (empty($fkdef)) {
-                    continue;
-                }
-                $query_fields.= ', CONSTRAINT '.$fkname.' FOREIGN KEY ('.implode(', ', array_keys($fkdef['fields'])).')';
-                $query_fields.= ' REFERENCES '.$fkdef['references']['table'].' ('.implode(', ', array_keys($fkdef['references']['fields'])).')';
-                $query_fields.= $this->_getAdvancedFKOptions($fkdef);
-            }
-        }
-
-        $name = $db->quoteIdentifier($name, true);
-        $result = 'CREATE ';
-        if (!empty($options['temporary'])) {
-            $result .= $this->_getTemporaryTableQuery();
-        }
-        $result .= " TABLE $name ($query_fields)";
-        return $result;
-    }
-
-    // }}}
-    // {{{ createTable()
-
-    /**
-     * create a new table
-     *
-     * @param string $name    Name of the database that should be created
-     * @param array  $fields  Associative array that contains the definition
-     *                        of each field of the new table
-     * @param array  $options An associative array of table options
-     *
-     * @return mixed MDB2_OK on success, a MDB2 error on failure
-     * @access public
-     */
-    function createTable($name, $fields, $options = array())
-    {
-        $result = parent::createTable($name, $fields, $options);
-        if (PEAR::isError($result)) {
-            return $result;
-        }
-        // create triggers to enforce FOREIGN KEY constraints
-        if (!empty($options['foreign_keys'])) {
-            $db =$this->getDBInstance();
-            if (PEAR::isError($db)) {
-                return $db;
-            }
-            foreach ($options['foreign_keys'] as $fkname => $fkdef) {
-                if (empty($fkdef)) {
-                    continue;
-                }
-                //set actions to default if not set
-                $fkdef['onupdate'] = empty($fkdef['onupdate']) ? $db->options['default_fk_action_onupdate'] : strtoupper($fkdef['onupdate']);
-                $fkdef['ondelete'] = empty($fkdef['ondelete']) ? $db->options['default_fk_action_ondelete'] : strtoupper($fkdef['ondelete']);
-
-                $trigger_names = array(
-                    'insert'    => $fkname.'_insert_trg',
-                    'update'    => $fkname.'_update_trg',
-                    'pk_update' => $fkname.'_pk_update_trg',
-                    'pk_delete' => $fkname.'_pk_delete_trg',
-                );
-
-                //create the [insert|update] triggers on the FK table
-                $table_fields = array_keys($fkdef['fields']);
-                $referenced_fields = array_keys($fkdef['references']['fields']);
-                $query = 'CREATE TRIGGER %s BEFORE %s ON '.$name
-                        .' FOR EACH ROW BEGIN'
-                        .' SELECT RAISE(ROLLBACK, \'%s on table "'.$name.'" violates FOREIGN KEY constraint "'.$fkname.'"\')'
-                        .' WHERE  (SELECT ';
-                $aliased_fields = array();
-                foreach ($referenced_fields as $field) {
-                    $aliased_fields[] = $fkdef['references']['table'] .'.'.$field .' AS '.$field;
-                }
-                $query .= implode(',', $aliased_fields)
-                       .' FROM '.$fkdef['references']['table']
-                       .' WHERE ';
-                $conditions = array();
-                for ($i=0; $i<count($table_fields); $i++) {
-                    $conditions[] = $referenced_fields[$i] .' = NEW.'.$table_fields[$i];
-                }
-                $query .= implode(' AND ', $conditions).') IS NULL; END;';
-                $result = $db->exec(sprintf($query, $trigger_names['insert'], 'INSERT', 'insert'));
-                if (PEAR::isError($result)) {
-                    return $result;
-                }
-
-                $result = $db->exec(sprintf($query, $trigger_names['update'], 'UPDATE', 'update'));
-                if (PEAR::isError($result)) {
-                    return $result;
-                }
-
-                //create the ON [UPDATE|DELETE] triggers on the primary table
-                $restrict_action = 'SELECT RAISE(ROLLBACK, \'%s on table "'.$name.'" violates FOREIGN KEY constraint "'.$fkname.'"\')'
-                                  .' WHERE  (SELECT ';
-                $aliased_fields = array();
-                foreach ($table_fields as $field) {
-                    $aliased_fields[] = $name .'.'.$field .' AS '.$field;
-                }
-                $restrict_action .= implode(',', $aliased_fields)
-                       .' FROM '.$name
-                       .' WHERE ';
-                $conditions  = array();
-                $new_values  = array();
-                $null_values = array();
-                for ($i=0; $i<count($table_fields); $i++) {
-                    $conditions[]  = $table_fields[$i] .' = OLD.'.$referenced_fields[$i];
-                    $new_values[]  = $table_fields[$i] .' = NEW.'.$referenced_fields[$i];
-                    $null_values[] = $table_fields[$i] .' = NULL';
-                }
-                $conditions2 = array();
-                for ($i=0; $i<count($referenced_fields); $i++) {
-                    $conditions2[]  = 'NEW.'.$referenced_fields[$i] .' <> OLD.'.$referenced_fields[$i];
-                }
-                $restrict_action .= implode(' AND ', $conditions).') IS NOT NULL'
-                                 .' AND (' .implode(' OR ', $conditions2) .')';
-
-                $cascade_action_update = 'UPDATE '.$name.' SET '.implode(', ', $new_values) .' WHERE '.implode(' AND ', $conditions);
-                $cascade_action_delete = 'DELETE FROM '.$name.' WHERE '.implode(' AND ', $conditions);
-                $setnull_action        = 'UPDATE '.$name.' SET '.implode(', ', $null_values).' WHERE '.implode(' AND ', $conditions);
-
-                if ('SET DEFAULT' == $fkdef['onupdate'] || 'SET DEFAULT' == $fkdef['ondelete']) {
-                    $db->loadModule('Reverse', null, true);
-                    $default_values = array();
-                    foreach ($table_fields as $table_field) {
-                        $field_definition = $db->reverse->getTableFieldDefinition($name, $field);
-                        if (PEAR::isError($field_definition)) {
-                            return $field_definition;
-                        }
-                        $default_values[] = $table_field .' = '. $field_definition[0]['default'];
-                    }
-                    $setdefault_action = 'UPDATE '.$name.' SET '.implode(', ', $default_values).' WHERE '.implode(' AND ', $conditions);
-                }
-
-                $query = 'CREATE TRIGGER %s'
-                        .' %s ON '.$fkdef['references']['table']
-                        .' FOR EACH ROW BEGIN ';
-
-                if ('CASCADE' == $fkdef['onupdate']) {
-                    $sql_update = sprintf($query, $trigger_names['pk_update'], 'AFTER UPDATE',  'update') . $cascade_action_update. '; END;';
-                } elseif ('SET NULL' == $fkdef['onupdate']) {
-                    $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $setnull_action. '; END;';
-                } elseif ('SET DEFAULT' == $fkdef['onupdate']) {
-                    $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $setdefault_action. '; END;';
-                } elseif ('NO ACTION' == $fkdef['onupdate']) {
-                    $sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'AFTER UPDATE', 'update') . '; END;';
-                } elseif ('RESTRICT' == $fkdef['onupdate']) {
-                    $sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . '; END;';
-                }
-                if ('CASCADE' == $fkdef['ondelete']) {
-                    $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'AFTER DELETE',  'delete') . $cascade_action_delete. '; END;';
-                } elseif ('SET NULL' == $fkdef['ondelete']) {
-                    $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $setnull_action. '; END;';
-                } elseif ('SET DEFAULT' == $fkdef['ondelete']) {
-                    $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $setdefault_action. '; END;';
-                } elseif ('NO ACTION' == $fkdef['ondelete']) {
-                    $sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'AFTER DELETE', 'delete')  . '; END;';
-                } elseif ('RESTRICT' == $fkdef['ondelete']) {
-                    $sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . '; END;';
-                }
-
-                if (PEAR::isError($result)) {
-                    return $result;
-                }
-                $result = $db->exec($sql_delete);
-                if (PEAR::isError($result)) {
-                    return $result;
-                }
-                $result = $db->exec($sql_update);
-                if (PEAR::isError($result)) {
-                    return $result;
-                }
-            }
-        }
-        if (PEAR::isError($result)) {
-            return $result;
-        }
-        return MDB2_OK;
-    }
-
-    // }}}
-    // {{{ dropTable()
-
-    /**
-     * drop an existing table
-     *
-     * @param string $name name of the table that should be dropped
-     * @return mixed MDB2_OK on success, a MDB2 error on failure
-     * @access public
-     */
-    function dropTable($name)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        //delete the triggers associated to existing FK constraints
-        $constraints = $this->listTableConstraints($name);
-        if (!PEAR::isError($constraints) && !empty($constraints)) {
-            $db->loadModule('Reverse', null, true);
-            foreach ($constraints as $constraint) {
-                $definition = $db->reverse->getTableConstraintDefinition($name, $constraint);
-                if (!PEAR::isError($definition) && !empty($definition['foreign'])) {
-                    $result = $this->_dropFKTriggers($name, $constraint, $definition['references']['table']);
-                    if (PEAR::isError($result)) {
-                        return $result;
-                    }
-                }
-            }
-        }
-
-        $name = $db->quoteIdentifier($name, true);
-        return $db->exec("DROP TABLE $name");
-    }
-
-    // }}}
-    // {{{ vacuum()
-
-    /**
-     * Optimize (vacuum) all the tables in the db (or only the specified table)
-     * and optionally run ANALYZE.
-     *
-     * @param string $table table name (all the tables if empty)
-     * @param array  $options an array with driver-specific options:
-     *               - timeout [int] (in seconds) [mssql-only]
-     *               - analyze [boolean] [pgsql and mysql]
-     *               - full [boolean] [pgsql-only]
-     *               - freeze [boolean] [pgsql-only]
-     *
-     * @return mixed MDB2_OK success, a MDB2 error on failure
-     * @access public
-     */
-    function vacuum($table = null, $options = array())
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $query = 'VACUUM';
-        if (!empty($table)) {
-            $query .= ' '.$db->quoteIdentifier($table, true);
-        }
-        return $db->exec($query);
-    }
-
-    // }}}
-    // {{{ alterTable()
-
-    /**
-     * alter an existing table
-     *
-     * @param string $name         name of the table that is intended to be changed.
-     * @param array $changes     associative array that contains the details of each type
-     *                             of change that is intended to be performed. The types of
-     *                             changes that are currently supported are defined as follows:
-     *
-     *                             name
-     *
-     *                                New name for the table.
-     *
-     *                            add
-     *
-     *                                Associative array with the names of fields to be added as
-     *                                 indexes of the array. The value of each entry of the array
-     *                                 should be set to another associative array with the properties
-     *                                 of the fields to be added. The properties of the fields should
-     *                                 be the same as defined by the MDB2 parser.
-     *
-     *
-     *                            remove
-     *
-     *                                Associative array with the names of fields to be removed as indexes
-     *                                 of the array. Currently the values assigned to each entry are ignored.
-     *                                 An empty array should be used for future compatibility.
-     *
-     *                            rename
-     *
-     *                                Associative array with the names of fields to be renamed as indexes
-     *                                 of the array. The value of each entry of the array should be set to
-     *                                 another associative array with the entry named name with the new
-     *                                 field name and the entry named Declaration that is expected to contain
-     *                                 the portion of the field declaration already in DBMS specific SQL code
-     *                                 as it is used in the CREATE TABLE statement.
-     *
-     *                            change
-     *
-     *                                Associative array with the names of the fields to be changed as indexes
-     *                                 of the array. Keep in mind that if it is intended to change either the
-     *                                 name of a field and any other properties, the change array entries
-     *                                 should have the new names of the fields as array indexes.
-     *
-     *                                The value of each entry of the array should be set to another associative
-     *                                 array with the properties of the fields to that are meant to be changed as
-     *                                 array entries. These entries should be assigned to the new values of the
-     *                                 respective properties. The properties of the fields should be the same
-     *                                 as defined by the MDB2 parser.
-     *
-     *                            Example
-     *                                array(
-     *                                    'name' => 'userlist',
-     *                                    'add' => array(
-     *                                        'quota' => array(
-     *                                            'type' => 'integer',
-     *                                            'unsigned' => 1
-     *                                        )
-     *                                    ),
-     *                                    'remove' => array(
-     *                                        'file_limit' => array(),
-     *                                        'time_limit' => array()
-     *                                    ),
-     *                                    'change' => array(
-     *                                        'name' => array(
-     *                                            'length' => '20',
-     *                                            'definition' => array(
-     *                                                'type' => 'text',
-     *                                                'length' => 20,
-     *                                            ),
-     *                                        )
-     *                                    ),
-     *                                    'rename' => array(
-     *                                        'sex' => array(
-     *                                            'name' => 'gender',
-     *                                            'definition' => array(
-     *                                                'type' => 'text',
-     *                                                'length' => 1,
-     *                                                'default' => 'M',
-     *                                            ),
-     *                                        )
-     *                                    )
-     *                                )
-     *
-     * @param boolean $check     indicates whether the function should just check if the DBMS driver
-     *                             can perform the requested table alterations if the value is true or
-     *                             actually perform them otherwise.
-     * @access public
-     *
-      * @return mixed MDB2_OK on success, a MDB2 error on failure
-     */
-    function alterTable($name, $changes, $check, $options = array())
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        foreach ($changes as $change_name => $change) {
-            switch ($change_name) {
-            case 'add':
-            case 'remove':
-            case 'change':
-            case 'name':
-            case 'rename':
-                break;
-            default:
-                return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null,
-                    'change type "'.$change_name.'" not yet supported', __FUNCTION__);
-            }
-        }
-
-        if ($check) {
-            return MDB2_OK;
-        }
-
-        if (empty($changes['remove']) and empty($changes['rename']) and empty($changes['change']) ) {//if only rename or add changes are required, we can use ALTER TABLE
-			$query = '';
-			if (!empty($changes['name'])) {
-				$change_name = $db->quoteIdentifier($changes['name'], true);
-				$query = 'RENAME TO ' . $change_name;
-				$db->exec("ALTER TABLE $name $query");
-			}
-
-			if (!empty($changes['add']) && is_array($changes['add'])) {
-				foreach ($changes['add'] as $field_name => $field) {
-					$query= 'ADD ' . $db->getDeclaration($field['type'], $field_name, $field);
-					$db->exec("ALTER TABLE $name $query");
-				}
-			}
-			return MDB2_OK;
-        }
-
-        $db->loadModule('Reverse', null, true);
-
-        // for other operations we need to emulate them with sqlite3
-        $fields = $db->manager->listTableFields($name);
-        if (PEAR::isError($fields)) {
-            return $fields;
-        }
-
-        $fields = array_flip($fields);
-        foreach ($fields as $field => $value) {
-            $definition = $db->reverse->getTableFieldDefinition($name, $field);
-            if (PEAR::isError($definition)) {
-                return $definition;
-            }
-            $fields[$field] = $definition[0];
-        }
-
-        $indexes = $db->manager->listTableIndexes($name);
-        if (PEAR::isError($indexes)) {
-            return $indexes;
-        }
-
-        $indexes = array_flip($indexes);
-        foreach ($indexes as $index => $value) {
-            $definition = $db->reverse->getTableIndexDefinition($name, $index);
-            if (PEAR::isError($definition)) {
-                return $definition;
-            }
-            $indexes[$index] = $definition;
-        }
-
-        $constraints = $db->manager->listTableConstraints($name);
-        if (PEAR::isError($constraints)) {
-            return $constraints;
-        }
-
-        if (!array_key_exists('foreign_keys', $options)) {
-            $options['foreign_keys'] = array();
-        }
-        $constraints = array_flip($constraints);
-        foreach ($constraints as $constraint => $value) {
-            if (!empty($definition['primary'])) {
-                if (!array_key_exists('primary', $options)) {
-                    $options['primary'] = $definition['fields'];
-                    //remove from the $constraint array, it's already handled by createTable()
-                    unset($constraints[$constraint]);
-                }
-            } else {
-                $c_definition = $db->reverse->getTableConstraintDefinition($name, $constraint);
-                if (PEAR::isError($c_definition)) {
-                    return $c_definition;
-                }
-                if (!empty($c_definition['foreign'])) {
-                    if (!array_key_exists($constraint, $options['foreign_keys'])) {
-                        $options['foreign_keys'][$constraint] = $c_definition;
-                    }
-                    //remove from the $constraint array, it's already handled by createTable()
-                    unset($constraints[$constraint]);
-                } else {
-                    $constraints[$constraint] = $c_definition;
-                }
-            }
-        }
-
-        $name_new = $name;
-        $create_order = $select_fields = array_keys($fields);
-        foreach ($changes as $change_name => $change) {
-            switch ($change_name) {
-            case 'add':
-                foreach ($change as $field_name => $field) {
-                    $fields[$field_name] = $field;
-                    $create_order[] = $field_name;
-                }
-                break;
-            case 'remove':
-                foreach ($change as $field_name => $field) {
-                    unset($fields[$field_name]);
-                    $select_fields = array_diff($select_fields, array($field_name));
-                    $create_order = array_diff($create_order, array($field_name));
-                }
-                break;
-            case 'change':
-                foreach ($change as $field_name => $field) {
-                    $fields[$field_name] = $field['definition'];
-                }
-                break;
-            case 'name':
-                $name_new = $change;
-                break;
-            case 'rename':
-                foreach ($change as $field_name => $field) {
-                    unset($fields[$field_name]);
-                    $fields[$field['name']] = $field['definition'];
-                    $create_order[array_search($field_name, $create_order)] = $field['name'];
-                }
-                break;
-            default:
-                return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null,
-                    'change type "'.$change_name.'" not yet supported', __FUNCTION__);
-            }
-        }
-
-		//rename the old table so we can create the new one
-        $db->exec("ALTER TABLE $name RENAME TO __$name");
-        $data = null;
-
-
-        $result = $this->createTable($name_new, $fields, $options);
-        if (PEAR::isError($result)) {
-            return $result;
-        }
-
-        //these seem to only give errors
-
-//         foreach ($indexes as $index => $definition) {
-//             $this->createIndex($name_new, $index, $definition);
-//         }
-
-//         foreach ($constraints as $constraint => $definition) {
-//             $this->createConstraint($name_new, $constraint, $definition);
-//         }
-
-        //fill the new table with data from the old one
-        if (!empty($select_fields)) {
-			$query = 'INSERT INTO '.$db->quoteIdentifier($name_new, true);
-			$query.= '('.implode(', ', array_slice(array_keys($fields), 0, count($select_fields))).')';
-            $query .= ' SELECT '.implode(', ', $select_fields).' FROM '.$db->quoteIdentifier('__'.$name, true);
-            $db->exec($query);
-        }
-
-//         if (!empty($select_fields) && !empty($data)) {
-//             $query = 'INSERT INTO '.$db->quoteIdentifier($name_new, true);
-//             $query.= '('.implode(', ', array_slice(array_keys($fields), 0, count($select_fields))).')';
-//             $query.=' VALUES (?'.str_repeat(', ?', (count($select_fields) - 1)).')';
-//             $stmt =$db->prepare($query, null, MDB2_PREPARE_MANIP);
-//             if (PEAR::isError($stmt)) {
-//                 return $stmt;
-//             }
-//             foreach ($data as $row) {
-//                 $result = $stmt->execute($row);
-//                 if (PEAR::isError($result)) {
-//                     return $result;
-//                 }
-//             }
-//         }
-
-        //remove the old table
-        $result = $this->dropTable('__'.$name);
-        if (PEAR::isError($result)) {
-            return $result;
-        }
-        return MDB2_OK;
-    }
-
-    // }}}
-    // {{{ listDatabases()
-
-    /**
-     * list all databases
-     *
-     * @return mixed array of database names on success, a MDB2 error on failure
-     * @access public
-     */
-    function listDatabases()
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-            'list databases is not supported', __FUNCTION__);
-    }
-
-    // }}}
-    // {{{ listUsers()
-
-    /**
-     * list all users
-     *
-     * @return mixed array of user names on success, a MDB2 error on failure
-     * @access public
-     */
-    function listUsers()
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-            'list databases is not supported', __FUNCTION__);
-    }
-
-    // }}}
-    // {{{ listViews()
-
-    /**
-     * list all views in the current database
-     *
-     * @return mixed array of view names on success, a MDB2 error on failure
-     * @access public
-     */
-    function listViews($dummy=null)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $query = "SELECT name FROM sqlite_master WHERE type='view' AND sql NOT NULL";
-        $result = $db->queryCol($query);
-        if (PEAR::isError($result)) {
-            return $result;
-        }
-        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
-        }
-        return $result;
-    }
-
-    // }}}
-    // {{{ listTableViews()
-
-    /**
-     * list the views in the database that reference a given table
-     *
-     * @param string table for which all referenced views should be found
-     * @return mixed array of view names on success, a MDB2 error on failure
-     * @access public
-     */
-    function listTableViews($table)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $query = "SELECT name, sql FROM sqlite_master WHERE type='view' AND sql NOT NULL";
-        $views = $db->queryAll($query, array('text', 'text'), MDB2_FETCHMODE_ASSOC);
-        if (PEAR::isError($views)) {
-            return $views;
-        }
-        $result = array();
-        foreach ($views as $row) {
-            if (preg_match("/^create view .* \bfrom\b\s+\b{$table}\b /i", $row['sql'])) {
-                if (!empty($row['name'])) {
-                    $result[$row['name']] = true;
-                }
-            }
-        }
-
-        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-            $result = array_change_key_case($result, $db->options['field_case']);
-        }
-        return array_keys($result);
-    }
-
-    // }}}
-    // {{{ listTables()
-
-    /**
-     * list all tables in the current database
-     *
-     * @return mixed array of table names on success, a MDB2 error on failure
-     * @access public
-     */
-    function listTables($dummy=null)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $query = "SELECT name FROM sqlite_master WHERE type='table' AND sql NOT NULL AND name!='sqlite_sequence' ORDER BY name";
-        $table_names = $db->queryCol($query);
-        if (PEAR::isError($table_names)) {
-            return $table_names;
-        }
-        $result = array();
-        foreach ($table_names as $table_name) {
-            if (!$this->_fixSequenceName($table_name, true)) {
-                $result[] = $table_name;
-            }
-        }
-        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
-        }
-        return $result;
-    }
-
-    // }}}
-    // {{{ listTableFields()
-
-    /**
-     * list all fields in a table in the current database
-     *
-     * @param string $table name of table that should be used in method
-     * @return mixed array of field names on success, a MDB2 error on failure
-     * @access public
-     */
-    function listTableFields($table)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $result = $db->loadModule('Reverse', null, true);
-        if (PEAR::isError($result)) {
-            return $result;
-        }
-        $query = "SELECT sql FROM sqlite_master WHERE type='table' AND ";
-        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-            $query.= 'LOWER(name)='.$db->quote(strtolower($table), 'text');
-        } else {
-            $query.= 'name='.$db->quote($table, 'text');
-        }
-        $sql = $db->queryOne($query);
-        if (PEAR::isError($sql)) {
-            return $sql;
-        }
-        $columns = $db->reverse->_getTableColumns($sql);
-        $fields = array();
-        foreach ($columns as $column) {
-            if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-                if ($db->options['field_case'] == CASE_LOWER) {
-                    $column['name'] = strtolower($column['name']);
-                } else {
-                    $column['name'] = strtoupper($column['name']);
-                }
-            } else {
-                $column = array_change_key_case($column, $db->options['field_case']);
-            }
-            $fields[] = $column['name'];
-        }
-        return $fields;
-    }
-
-    // }}}
-    // {{{ listTableTriggers()
-
-    /**
-     * list all triggers in the database that reference a given table
-     *
-     * @param string table for which all referenced triggers should be found
-     * @return mixed array of trigger names on success, a MDB2 error on failure
-     * @access public
-     */
-    function listTableTriggers($table = null)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $query = "SELECT name FROM sqlite_master WHERE type='trigger' AND sql NOT NULL";
-        if (!is_null($table)) {
-            if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-                $query.= ' AND LOWER(tbl_name)='.$db->quote(strtolower($table), 'text');
-            } else {
-                $query.= ' AND tbl_name='.$db->quote($table, 'text');
-            }
-        }
-        $result = $db->queryCol($query);
-        if (PEAR::isError($result)) {
-            return $result;
-        }
-        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
-        }
-        return $result;
-    }
-
-    // }}}
-    // {{{ createIndex()
-
-    /**
-     * Get the stucture of a field into an array
-     *
-     * @param string    $table         name of the table on which the index is to be created
-     * @param string    $name         name of the index to be created
-     * @param array     $definition        associative array that defines properties of the index to be created.
-     *                                 Currently, only one property named FIELDS is supported. This property
-     *                                 is also an associative with the names of the index fields as array
-     *                                 indexes. Each entry of this array is set to another type of associative
-     *                                 array that specifies properties of the index that are specific to
-     *                                 each field.
-     *
-     *                                Currently, only the sorting property is supported. It should be used
-     *                                 to define the sorting direction of the index. It may be set to either
-     *                                 ascending or descending.
-     *
-     *                                Not all DBMS support index sorting direction configuration. The DBMS
-     *                                 drivers of those that do not support it ignore this property. Use the
-     *                                 function support() to determine whether the DBMS driver can manage indexes.
-
-     *                                 Example
-     *                                    array(
-     *                                        'fields' => array(
-     *                                            'user_name' => array(
-     *                                                'sorting' => 'ascending'
-     *                                            ),
-     *                                            'last_login' => array()
-     *                                        )
-     *                                    )
-     * @return mixed MDB2_OK on success, a MDB2 error on failure
-     * @access public
-     */
-    function createIndex($table, $name, $definition)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $table = $db->quoteIdentifier($table, true);
-        $name  = $db->getIndexName($name);
-        $query = "CREATE INDEX $name ON $table";
-        $fields = array();
-        foreach ($definition['fields'] as $field_name => $field) {
-            $field_string = $field_name;
-            if (!empty($field['sorting'])) {
-                switch ($field['sorting']) {
-                case 'ascending':
-                    $field_string.= ' ASC';
-                    break;
-                case 'descending':
-                    $field_string.= ' DESC';
-                    break;
-                }
-            }
-            $fields[] = $field_string;
-        }
-        $query .= ' ('.implode(', ', $fields) . ')';
-        return $db->exec($query);
-    }
-
-    // }}}
-    // {{{ dropIndex()
-
-    /**
-     * drop existing index
-     *
-     * @param string    $table         name of table that should be used in method
-     * @param string    $name         name of the index to be dropped
-     * @return mixed MDB2_OK on success, a MDB2 error on failure
-     * @access public
-     */
-    function dropIndex($table, $name)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $name = $db->getIndexName($name);
-        return $db->exec("DROP INDEX $name");
-    }
-
-    // }}}
-    // {{{ listTableIndexes()
-
-    /**
-     * list all indexes in a table
-     *
-     * @param string $table name of table that should be used in method
-     * @return mixed array of index names on success, a MDB2 error on failure
-     * @access public
-     */
-    function listTableIndexes($table)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $table = $db->quote($table, 'text');
-        $query = "SELECT sql FROM sqlite_master WHERE type='index' AND ";
-        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-            $query.= 'LOWER(tbl_name)='.strtolower($table);
-        } else {
-            $query.= "tbl_name=$table";
-        }
-        $query.= " AND sql NOT NULL ORDER BY name";
-        $indexes = $db->queryCol($query, 'text');
-        if (PEAR::isError($indexes)) {
-            return $indexes;
-        }
-
-        $result = array();
-        foreach ($indexes as $sql) {
-            if (preg_match("/^create index ([^ ]+) on /i", $sql, $tmp)) {
-                $index = $this->_fixIndexName($tmp[1]);
-                if (!empty($index)) {
-                    $result[$index] = true;
-                }
-            }
-        }
-
-        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-            $result = array_change_key_case($result, $db->options['field_case']);
-        }
-        return array_keys($result);
-    }
-
-    // }}}
-    // {{{ createConstraint()
-
-    /**
-     * create a constraint on a table
-     *
-     * @param string $table      name of the table on which the constraint is to be created
-     * @param string $name       name of the constraint to be created
-     * @param array  $definition associative array that defines properties of the constraint to be created.
-     *                           Currently, only one property named FIELDS is supported. This property
-     *                           is also an associative with the names of the constraint fields as array
-     *                           constraints. Each entry of this array is set to another type of associative
-     *                           array that specifies properties of the constraint that are specific to
-     *                           each field.
-     *
-     *                           Example
-     *                              array(
-     *                                  'fields' => array(
-     *                                      'user_name' => array(),
-     *                                      'last_login' => array()
-     *                                  )
-     *                              )
-     * @return mixed MDB2_OK on success, a MDB2 error on failure
-     * @access public
-     */
-    function createConstraint($table, $name, $definition)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        if (!empty($definition['primary'])) {
-            return $db->manager->alterTable($table, array(), false, array('primary' => $definition['fields']));
-        }
-
-        if (!empty($definition['foreign'])) {
-            return $db->manager->alterTable($table, array(), false, array('foreign_keys' => array($name => $definition)));
-        }
-
-        $table = $db->quoteIdentifier($table, true);
-        $name  = $db->getIndexName($name);
-        $query = "CREATE UNIQUE INDEX $name ON $table";
-        $fields = array();
-        foreach ($definition['fields'] as $field_name => $field) {
-            $field_string = $field_name;
-            if (!empty($field['sorting'])) {
-                switch ($field['sorting']) {
-                case 'ascending':
-                    $field_string.= ' ASC';
-                    break;
-                case 'descending':
-                    $field_string.= ' DESC';
-                    break;
-                }
-            }
-            $fields[] = $field_string;
-        }
-        $query .= ' ('.implode(', ', $fields) . ')';
-        return $db->exec($query);
-    }
-
-    // }}}
-    // {{{ dropConstraint()
-
-    /**
-     * drop existing constraint
-     *
-     * @param string    $table        name of table that should be used in method
-     * @param string    $name         name of the constraint to be dropped
-     * @param string    $primary      hint if the constraint is primary
-     * @return mixed MDB2_OK on success, a MDB2 error on failure
-     * @access public
-     */
-    function dropConstraint($table, $name, $primary = false)
-    {
-        if ($primary || $name == 'PRIMARY') {
-            return $this->alterTable($table, array(), false, array('primary' => null));
-        }
-
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        //is it a FK constraint? If so, also delete the associated triggers
-        $db->loadModule('Reverse', null, true);
-        $definition = $db->reverse->getTableConstraintDefinition($table, $name);
-        if (!PEAR::isError($definition) && !empty($definition['foreign'])) {
-            //first drop the FK enforcing triggers
-            $result = $this->_dropFKTriggers($table, $name, $definition['references']['table']);
-            if (PEAR::isError($result)) {
-                return $result;
-            }
-            //then drop the constraint itself
-            return $this->alterTable($table, array(), false, array('foreign_keys' => array($name => null)));
-        }
-
-        $name = $db->getIndexName($name);
-        return $db->exec("DROP INDEX $name");
-    }
-
-    // }}}
-    // {{{ _dropFKTriggers()
-
-    /**
-     * Drop the triggers created to enforce the FOREIGN KEY constraint on the table
-     *
-     * @param string $table  table name
-     * @param string $fkname FOREIGN KEY constraint name
-     * @param string $referenced_table  referenced table name
-     *
-     * @return mixed MDB2_OK on success, a MDB2 error on failure
-     * @access private
-     */
-    function _dropFKTriggers($table, $fkname, $referenced_table)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $triggers  = $this->listTableTriggers($table);
-        $triggers2 = $this->listTableTriggers($referenced_table);
-        if (!PEAR::isError($triggers2) && !PEAR::isError($triggers)) {
-            $triggers = array_merge($triggers, $triggers2);
-            $pattern = '/^'.$fkname.'(_pk)?_(insert|update|delete)_trg$/i';
-            foreach ($triggers as $trigger) {
-                if (preg_match($pattern, $trigger)) {
-                    $result = $db->exec('DROP TRIGGER '.$trigger);
-                    if (PEAR::isError($result)) {
-                        return $result;
-                    }
-                }
-            }
-        }
-        return MDB2_OK;
-    }
-
-    // }}}
-    // {{{ listTableConstraints()
-
-    /**
-     * list all constraints in a table
-     *
-     * @param string $table name of table that should be used in method
-     * @return mixed array of constraint names on success, a MDB2 error on failure
-     * @access public
-     */
-    function listTableConstraints($table)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $table = $db->quote($table, 'text');
-        $query = "SELECT sql FROM sqlite_master WHERE type='index' AND ";
-        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-            $query.= 'LOWER(tbl_name)='.strtolower($table);
-        } else {
-            $query.= "tbl_name=$table";
-        }
-        $query.= " AND sql NOT NULL ORDER BY name";
-        $indexes = $db->queryCol($query, 'text');
-        if (PEAR::isError($indexes)) {
-            return $indexes;
-        }
-
-        $result = array();
-        foreach ($indexes as $sql) {
-            if (preg_match("/^create unique index ([^ ]+) on /i", $sql, $tmp)) {
-                $index = $this->_fixIndexName($tmp[1]);
-                if (!empty($index)) {
-                    $result[$index] = true;
-                }
-            }
-        }
-
-        // also search in table definition for PRIMARY KEYs...
-        $query = "SELECT sql FROM sqlite_master WHERE type='table' AND ";
-        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-            $query.= 'LOWER(name)='.strtolower($table);
-        } else {
-            $query.= "name=$table";
-        }
-        $query.= " AND sql NOT NULL ORDER BY name";
-        $table_def = $db->queryOne($query, 'text');
-        if (PEAR::isError($table_def)) {
-            return $table_def;
-        }
-        if (preg_match("/\bPRIMARY\s+KEY\b/i", $table_def, $tmp)) {
-            $result['primary'] = true;
-        }
-
-        // ...and for FOREIGN KEYs
-        if (preg_match_all("/\bCONSTRAINT\b\s+([^\s]+)\s+\bFOREIGN\s+KEY/imsx", $table_def, $tmp)) {
-            foreach ($tmp[1] as $fk) {
-                $result[$fk] = true;
-            }
-        }
-
-        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-            $result = array_change_key_case($result, $db->options['field_case']);
-        }
-        return array_keys($result);
-    }
-
-    // }}}
-    // {{{ createSequence()
-
-    /**
-     * create sequence
-     *
-     * @param string    $seq_name     name of the sequence to be created
-     * @param string    $start         start value of the sequence; default is 1
-     * @return mixed MDB2_OK on success, a MDB2 error on failure
-     * @access public
-     */
-    function createSequence($seq_name, $start = 1)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
-        $seqcol_name = $db->quoteIdentifier($db->options['seqcol_name'], true);
-        $query = "CREATE TABLE $sequence_name ($seqcol_name INTEGER PRIMARY KEY DEFAULT 0 NOT NULL)";
-        $res = $db->exec($query);
-        if (PEAR::isError($res)) {
-            return $res;
-        }
-        if ($start == 1) {
-            return MDB2_OK;
-        }
-        $res = $db->exec("INSERT INTO $sequence_name ($seqcol_name) VALUES (".($start-1).')');
-        if (!PEAR::isError($res)) {
-            return MDB2_OK;
-        }
-        // Handle error
-        $result = $db->exec("DROP TABLE $sequence_name");
-        if (PEAR::isError($result)) {
-            return $db->raiseError($result, null, null,
-                'could not drop inconsistent sequence table', __FUNCTION__);
-        }
-        return $db->raiseError($res, null, null,
-            'could not create sequence table', __FUNCTION__);
-    }
-
-    // }}}
-    // {{{ dropSequence()
-
-    /**
-     * drop existing sequence
-     *
-     * @param string    $seq_name     name of the sequence to be dropped
-     * @return mixed MDB2_OK on success, a MDB2 error on failure
-     * @access public
-     */
-    function dropSequence($seq_name)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
-        return $db->exec("DROP TABLE $sequence_name");
-    }
-
-    // }}}
-    // {{{ listSequences()
-
-    /**
-     * list all sequences in the current database
-     *
-     * @return mixed array of sequence names on success, a MDB2 error on failure
-     * @access public
-     */
-    function listSequences($dummy=null)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $query = "SELECT name FROM sqlite_master WHERE type='table' AND sql NOT NULL ORDER BY name";
-        $table_names = $db->queryCol($query);
-        if (PEAR::isError($table_names)) {
-            return $table_names;
-        }
-        $result = array();
-        foreach ($table_names as $table_name) {
-            if ($sqn = $this->_fixSequenceName($table_name, true)) {
-                $result[] = $sqn;
-            }
-        }
-        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
-        }
-        return $result;
-    }
-
-    // }}}
-}
diff --git a/lib/MDB2/Driver/Native/sqlite3.php b/lib/MDB2/Driver/Native/sqlite3.php
deleted file mode 100644
index 344d523bdf3285b38e12789f1959f9a8a41199b6..0000000000000000000000000000000000000000
--- a/lib/MDB2/Driver/Native/sqlite3.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-/**
- * ownCloud
- *
- * @author Robin Appelman
- * @copyright 2011 Robin Appelman icewind1991@gmail.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or any later version.
- *
- * This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU Affero General Public
- * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-require_once 'MDB2/Driver/Native/Common.php';
-
-/**
- * MDB2 SQLite driver for the native module
- *
- * @package MDB2
- * @category Database
- * @author  Lukas Smith <smith@pooteeweet.org>
- */
-class MDB2_Driver_Native_sqlite extends MDB2_Driver_Native_Common
-{
-}
diff --git a/lib/MDB2/Driver/Reverse/sqlite3.php b/lib/MDB2/Driver/Reverse/sqlite3.php
deleted file mode 100644
index 9703780954904d49165abd82d389f847f986f4d0..0000000000000000000000000000000000000000
--- a/lib/MDB2/Driver/Reverse/sqlite3.php
+++ /dev/null
@@ -1,586 +0,0 @@
-<?php
-/**
- * ownCloud
- *
- * @author Robin Appelman
- * @copyright 2011 Robin Appelman icewind1991@gmail.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or any later version.
- *
- * This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU Affero General Public
- * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-require_once 'MDB2/Driver/Reverse/Common.php';
-
-/**
- * MDB2 SQlite driver for the schema reverse engineering module
- *
- * @package MDB2
- * @category Database
- * @author  Lukas Smith <smith@pooteeweet.org>
- */
-class MDB2_Driver_Reverse_sqlite3 extends MDB2_Driver_Reverse_Common
-{
-    /**
-     * Remove SQL comments from the field definition
-     *
-     * @access private
-     */
-    function _removeComments($sql) {
-        $lines = explode("\n", $sql);
-        foreach ($lines as $k => $line) {
-            $pieces = explode('--', $line);
-            if (count($pieces) > 1 && (substr_count($pieces[0], '\'') % 2) == 0) {
-                $lines[$k] = substr($line, 0, strpos($line, '--'));
-            }
-        }
-        return implode("\n", $lines);
-    }
-
-    /**
-     *
-     */
-    function _getTableColumns($sql)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-        $start_pos  = strpos($sql, '(');
-        $end_pos    = strrpos($sql, ')');
-        $column_def = substr($sql, $start_pos+1, $end_pos-$start_pos-1);
-        // replace the decimal length-places-separator with a colon
-        $column_def = preg_replace('/(\d),(\d)/', '\1:\2', $column_def);
-        $column_def = $this->_removeComments($column_def);
-        $column_sql = explode(',', $column_def);
-        $columns    = array();
-        $count      = count($column_sql);
-        if ($count == 0) {
-            return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-                'unexpected empty table column definition list', __FUNCTION__);
-        }
-        $regexp = '/^\s*([^\s]+) +(CHAR|VARCHAR|VARCHAR2|TEXT|BOOLEAN|SMALLINT|INT|INTEGER|DECIMAL|BIGINT|DOUBLE|FLOAT|DATETIME|DATE|TIME|LONGTEXT|LONGBLOB)( ?\(([1-9][0-9]*)(:([1-9][0-9]*))?\))?( NULL| NOT NULL)?( UNSIGNED)?( NULL| NOT NULL)?( PRIMARY KEY)?( AUTOINCREMENT)?( DEFAULT (\'[^\']*\'|[^ ]+))?( NULL| NOT NULL)?( PRIMARY KEY)?(\s*\-\-.*)?$/i';
-        $regexp2 = '/^\s*([^ ]+) +(PRIMARY|UNIQUE|CHECK)$/i';
-        for ($i=0, $j=0; $i<$count; ++$i) {
-            if (!preg_match($regexp, trim($column_sql[$i]), $matches)) {
-                if (!preg_match($regexp2, trim($column_sql[$i]))) {
-                    continue;
-                }
-                return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-                    'unexpected table column SQL definition: "'.$column_sql[$i].'"', __FUNCTION__);
-            }
-            $columns[$j]['name'] = trim($matches[1], implode('', $db->identifier_quoting));
-            $columns[$j]['type'] = strtolower($matches[2]);
-            if (isset($matches[4]) && strlen($matches[4])) {
-                $columns[$j]['length'] = $matches[4];
-            }
-            if (isset($matches[6]) && strlen($matches[6])) {
-                $columns[$j]['decimal'] = $matches[6];
-            }
-            if (isset($matches[8]) && strlen($matches[8])) {
-                $columns[$j]['unsigned'] = true;
-            }
-            if (isset($matches[10]) && strlen($matches[10])) {
-                $columns[$j]['autoincrement'] = true;
-                $columns[$j]['notnull']=true;
-            }
-            if (isset($matches[10]) && strlen($matches[10])) {
-                $columns[$j]['autoincrement'] = true;
-                $columns[$j]['notnull']=true;
-            }
-            if (isset($matches[13]) && strlen($matches[13])) {
-                $default = $matches[13];
-                if (strlen($default) && $default[0]=="'") {
-                    $default = str_replace("''", "'", substr($default, 1, strlen($default)-2));
-                }
-                if ($default === 'NULL') {
-                    $default = null;
-                }
-                $columns[$j]['default'] = $default;
-            }
-            if (isset($matches[7]) && strlen($matches[7])) {
-                $columns[$j]['notnull'] = ($matches[7] === ' NOT NULL');
-            } else if (isset($matches[9]) && strlen($matches[9])) {
-                $columns[$j]['notnull'] = ($matches[9] === ' NOT NULL');
-            } else if (isset($matches[14]) && strlen($matches[14])) {
-                $columns[$j]['notnull'] = ($matches[14] === ' NOT NULL');
-            }
-            ++$j;
-        }
-        return $columns;
-    }
-
-    // {{{ getTableFieldDefinition()
-
-    /**
-     * Get the stucture of a field into an array
-     *
-     * @param string $table_name name of table that should be used in method
-     * @param string $field_name name of field that should be used in method
-     * @return mixed data array on success, a MDB2 error on failure.
-     *          The returned array contains an array for each field definition,
-     *          with (some of) these indices:
-     *          [notnull] [nativetype] [length] [fixed] [default] [type] [mdb2type]
-     * @access public
-     */
-    function getTableFieldDefinition($table_name, $field_name)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        list($schema, $table) = $this->splitTableSchema($table_name);
-
-        $result = $db->loadModule('Datatype', null, true);
-        if (PEAR::isError($result)) {
-            return $result;
-        }
-        $query = "SELECT sql FROM sqlite_master WHERE type='table' AND ";
-        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-            $query.= 'LOWER(name)='.$db->quote(strtolower($table), 'text');
-        } else {
-            $query.= 'name='.$db->quote($table, 'text');
-        }
-        $sql = $db->queryOne($query);
-        if (PEAR::isError($sql)) {
-            return $sql;
-        }
-        $columns = $this->_getTableColumns($sql);
-        foreach ($columns as $column) {
-            if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-                if ($db->options['field_case'] == CASE_LOWER) {
-                    $column['name'] = strtolower($column['name']);
-                } else {
-                    $column['name'] = strtoupper($column['name']);
-                }
-            } else {
-                $column = array_change_key_case($column, $db->options['field_case']);
-            }
-            if ($field_name == $column['name']) {
-                $mapped_datatype = $db->datatype->mapNativeDatatype($column);
-                if (PEAR::isError($mapped_datatype)) {
-                    return $mapped_datatype;
-                }
-                list($types, $length, $unsigned, $fixed) = $mapped_datatype;
-                $notnull = false;
-                if (!empty($column['notnull'])) {
-                    $notnull = $column['notnull'];
-                }
-                $default = false;
-                if (array_key_exists('default', $column)) {
-                    $default = $column['default'];
-                    if (is_null($default) && $notnull) {
-                        $default = '';
-                    }
-                }
-                $autoincrement = false;
-                if (!empty($column['autoincrement'])) {
-                    $autoincrement = true;
-                }
-
-                $definition[0] = array(
-                    'notnull' => $notnull,
-                    'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type'])
-                );
-                if (!is_null($length)) {
-                    $definition[0]['length'] = $length;
-                }
-                if (!is_null($unsigned)) {
-                    $definition[0]['unsigned'] = $unsigned;
-                }
-                if (!is_null($fixed)) {
-                    $definition[0]['fixed'] = $fixed;
-                }
-                if ($default !== false) {
-                    $definition[0]['default'] = $default;
-                }
-                if ($autoincrement !== false) {
-                    $definition[0]['autoincrement'] = $autoincrement;
-                }
-                foreach ($types as $key => $type) {
-                    $definition[$key] = $definition[0];
-                    if ($type == 'clob' || $type == 'blob') {
-                        unset($definition[$key]['default']);
-                    }
-                    $definition[$key]['type'] = $type;
-                    $definition[$key]['mdb2type'] = $type;
-                }
-                return $definition;
-            }
-        }
-
-        return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
-            'it was not specified an existing table column', __FUNCTION__);
-    }
-
-    // }}}
-    // {{{ getTableIndexDefinition()
-
-    /**
-     * Get the stucture of an index into an array
-     *
-     * @param string $table_name name of table that should be used in method
-     * @param string $index_name name of index that should be used in method
-     * @return mixed data array on success, a MDB2 error on failure
-     * @access public
-     */
-    function getTableIndexDefinition($table_name, $index_name)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        list($schema, $table) = $this->splitTableSchema($table_name);
-
-        $query = "SELECT sql FROM sqlite_master WHERE type='index' AND ";
-        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-            $query.= 'LOWER(name)=%s AND LOWER(tbl_name)=' . $db->quote(strtolower($table), 'text');
-        } else {
-            $query.= 'name=%s AND tbl_name=' . $db->quote($table, 'text');
-        }
-        $query.= ' AND sql NOT NULL ORDER BY name';
-        $index_name_mdb2 = $db->getIndexName($index_name);
-        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-            $qry = sprintf($query, $db->quote(strtolower($index_name_mdb2), 'text'));
-        } else {
-            $qry = sprintf($query, $db->quote($index_name_mdb2, 'text'));
-        }
-        $sql = $db->queryOne($qry, 'text');
-        if (PEAR::isError($sql) || empty($sql)) {
-            // fallback to the given $index_name, without transformation
-            if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-                $qry = sprintf($query, $db->quote(strtolower($index_name), 'text'));
-            } else {
-                $qry = sprintf($query, $db->quote($index_name, 'text'));
-            }
-            $sql = $db->queryOne($qry, 'text');
-        }
-        if (PEAR::isError($sql)) {
-            return $sql;
-        }
-        if (!$sql) {
-            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
-                'it was not specified an existing table index', __FUNCTION__);
-        }
-
-        $sql = strtolower($sql);
-        $start_pos = strpos($sql, '(');
-        $end_pos = strrpos($sql, ')');
-        $column_names = substr($sql, $start_pos+1, $end_pos-$start_pos-1);
-        $column_names = explode(',', $column_names);
-
-        if (preg_match("/^create unique/", $sql)) {
-            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
-                'it was not specified an existing table index', __FUNCTION__);
-        }
-
-        $definition = array();
-        $count = count($column_names);
-        for ($i=0; $i<$count; ++$i) {
-            $column_name = strtok($column_names[$i], ' ');
-            $collation = strtok(' ');
-            $definition['fields'][$column_name] = array(
-                'position' => $i+1
-            );
-            if (!empty($collation)) {
-                $definition['fields'][$column_name]['sorting'] =
-                    ($collation=='ASC' ? 'ascending' : 'descending');
-            }
-        }
-
-        if (empty($definition['fields'])) {
-            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
-                'it was not specified an existing table index', __FUNCTION__);
-        }
-        return $definition;
-    }
-
-    // }}}
-    // {{{ getTableConstraintDefinition()
-
-    /**
-     * Get the stucture of a constraint into an array
-     *
-     * @param string $table_name      name of table that should be used in method
-     * @param string $constraint_name name of constraint that should be used in method
-     * @return mixed data array on success, a MDB2 error on failure
-     * @access public
-     */
-    function getTableConstraintDefinition($table_name, $constraint_name)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        list($schema, $table) = $this->splitTableSchema($table_name);
-
-        $query = "SELECT sql FROM sqlite_master WHERE type='index' AND ";
-        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-            $query.= 'LOWER(name)=%s AND LOWER(tbl_name)=' . $db->quote(strtolower($table), 'text');
-        } else {
-            $query.= 'name=%s AND tbl_name=' . $db->quote($table, 'text');
-        }
-        $query.= ' AND sql NOT NULL ORDER BY name';
-        $constraint_name_mdb2 = $db->getIndexName($constraint_name);
-        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-            $qry = sprintf($query, $db->quote(strtolower($constraint_name_mdb2), 'text'));
-        } else {
-            $qry = sprintf($query, $db->quote($constraint_name_mdb2, 'text'));
-        }
-        $sql = $db->queryOne($qry, 'text');
-        if (PEAR::isError($sql) || empty($sql)) {
-            // fallback to the given $index_name, without transformation
-            if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-                $qry = sprintf($query, $db->quote(strtolower($constraint_name), 'text'));
-            } else {
-                $qry = sprintf($query, $db->quote($constraint_name, 'text'));
-            }
-            $sql = $db->queryOne($qry, 'text');
-        }
-        if (PEAR::isError($sql)) {
-            return $sql;
-        }
-        //default values, eventually overridden
-        $definition = array(
-            'primary' => false,
-            'unique'  => false,
-            'foreign' => false,
-            'check'   => false,
-            'fields'  => array(),
-            'references' => array(
-                'table'  => '',
-                'fields' => array(),
-            ),
-            'onupdate'  => '',
-            'ondelete'  => '',
-            'match'     => '',
-            'deferrable'        => false,
-            'initiallydeferred' => false,
-        );
-        if (!$sql) {
-            $query = "SELECT sql FROM sqlite_master WHERE type='table' AND ";
-            if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-                $query.= 'LOWER(name)='.$db->quote(strtolower($table), 'text');
-            } else {
-                $query.= 'name='.$db->quote($table, 'text');
-            }
-            $query.= " AND sql NOT NULL ORDER BY name";
-            $sql = $db->queryOne($query, 'text');
-            if (PEAR::isError($sql)) {
-                return $sql;
-            }
-            if ($constraint_name == 'primary') {
-                // search in table definition for PRIMARY KEYs
-                if (preg_match("/\bPRIMARY\s+KEY\b\s*\(([^)]+)/i", $sql, $tmp)) {
-                    $definition['primary'] = true;
-                    $definition['fields'] = array();
-                    $column_names = explode(',', $tmp[1]);
-                    $colpos = 1;
-                    foreach ($column_names as $column_name) {
-                        $definition['fields'][trim($column_name)] = array(
-                            'position' => $colpos++
-                        );
-                    }
-                    return $definition;
-                }
-                if (preg_match("/\"([^\"]+)\"[^\,\"]+\bPRIMARY\s+KEY\b[^\,\)]*/i", $sql, $tmp)) {
-                    $definition['primary'] = true;
-                    $definition['fields'] = array();
-                    $column_names = explode(',', $tmp[1]);
-                    $colpos = 1;
-                    foreach ($column_names as $column_name) {
-                        $definition['fields'][trim($column_name)] = array(
-                            'position' => $colpos++
-                        );
-                    }
-                    return $definition;
-                }
-            } else {
-                // search in table definition for FOREIGN KEYs
-                $pattern = "/\bCONSTRAINT\b\s+%s\s+
-                    \bFOREIGN\s+KEY\b\s*\(([^\)]+)\)\s*
-                    \bREFERENCES\b\s+([^\s]+)\s*\(([^\)]+)\)\s*
-                    (?:\bMATCH\s*([^\s]+))?\s*
-                    (?:\bON\s+UPDATE\s+([^\s,\)]+))?\s*
-                    (?:\bON\s+DELETE\s+([^\s,\)]+))?\s*
-                    /imsx";
-                $found_fk = false;
-                if (preg_match(sprintf($pattern, $constraint_name_mdb2), $sql, $tmp)) {
-                    $found_fk = true;
-                } elseif (preg_match(sprintf($pattern, $constraint_name), $sql, $tmp)) {
-                    $found_fk = true;
-                }
-                if ($found_fk) {
-                    $definition['foreign'] = true;
-                    $definition['match'] = 'SIMPLE';
-                    $definition['onupdate'] = 'NO ACTION';
-                    $definition['ondelete'] = 'NO ACTION';
-                    $definition['references']['table'] = $tmp[2];
-                    $column_names = explode(',', $tmp[1]);
-                    $colpos = 1;
-                    foreach ($column_names as $column_name) {
-                        $definition['fields'][trim($column_name)] = array(
-                            'position' => $colpos++
-                        );
-                    }
-                    $referenced_cols = explode(',', $tmp[3]);
-                    $colpos = 1;
-                    foreach ($referenced_cols as $column_name) {
-                        $definition['references']['fields'][trim($column_name)] = array(
-                            'position' => $colpos++
-                        );
-                    }
-                    if (isset($tmp[4])) {
-                        $definition['match']    = $tmp[4];
-                    }
-                    if (isset($tmp[5])) {
-                        $definition['onupdate'] = $tmp[5];
-                    }
-                    if (isset($tmp[6])) {
-                        $definition['ondelete'] = $tmp[6];
-                    }
-                    return $definition;
-                }
-            }
-            $sql = false;
-        }
-        if (!$sql) {
-            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
-                $constraint_name . ' is not an existing table constraint', __FUNCTION__);
-        }
-
-        $sql = strtolower($sql);
-        $start_pos = strpos($sql, '(');
-        $end_pos   = strrpos($sql, ')');
-        $column_names = substr($sql, $start_pos+1, $end_pos-$start_pos-1);
-        $column_names = explode(',', $column_names);
-
-        if (!preg_match("/^create unique/", $sql)) {
-            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
-                $constraint_name . ' is not an existing table constraint', __FUNCTION__);
-        }
-
-        $definition['unique'] = true;
-        $count = count($column_names);
-        for ($i=0; $i<$count; ++$i) {
-            $column_name = strtok($column_names[$i], " ");
-            $collation = strtok(" ");
-            $definition['fields'][$column_name] = array(
-                'position' => $i+1
-            );
-            if (!empty($collation)) {
-                $definition['fields'][$column_name]['sorting'] =
-                    ($collation=='ASC' ? 'ascending' : 'descending');
-            }
-        }
-
-        if (empty($definition['fields'])) {
-            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
-                $constraint_name . ' is not an existing table constraint', __FUNCTION__);
-        }
-        return $definition;
-    }
-
-    // }}}
-    // {{{ getTriggerDefinition()
-
-    /**
-     * Get the structure of a trigger into an array
-     *
-     * EXPERIMENTAL
-     *
-     * WARNING: this function is experimental and may change the returned value
-     * at any time until labelled as non-experimental
-     *
-     * @param string    $trigger    name of trigger that should be used in method
-     * @return mixed data array on success, a MDB2 error on failure
-     * @access public
-     */
-    function getTriggerDefinition($trigger)
-    {
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $query = "SELECT name as trigger_name,
-                         tbl_name AS table_name,
-                         sql AS trigger_body,
-                         NULL AS trigger_type,
-                         NULL AS trigger_event,
-                         NULL AS trigger_comment,
-                         1 AS trigger_enabled
-                    FROM sqlite_master
-                   WHERE type='trigger'";
-        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-            $query.= ' AND LOWER(name)='.$db->quote(strtolower($trigger), 'text');
-        } else {
-            $query.= ' AND name='.$db->quote($trigger, 'text');
-        }
-        $types = array(
-            'trigger_name'    => 'text',
-            'table_name'      => 'text',
-            'trigger_body'    => 'text',
-            'trigger_type'    => 'text',
-            'trigger_event'   => 'text',
-            'trigger_comment' => 'text',
-            'trigger_enabled' => 'boolean',
-        );
-        $def = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC);
-        if (PEAR::isError($def)) {
-            return $def;
-        }
-        if (empty($def)) {
-            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
-                'it was not specified an existing trigger', __FUNCTION__);
-        }
-        if (preg_match("/^create\s+(?:temp|temporary)?trigger\s+(?:if\s+not\s+exists\s+)?.*(before|after)?\s+(insert|update|delete)/Uims", $def['trigger_body'], $tmp)) {
-            $def['trigger_type'] = strtoupper($tmp[1]);
-            $def['trigger_event'] = strtoupper($tmp[2]);
-        }
-        return $def;
-    }
-
-    // }}}
-    // {{{ tableInfo()
-
-    /**
-     * Returns information about a table
-     *
-     * @param string         $result  a string containing the name of a table
-     * @param int            $mode    a valid tableInfo mode
-     *
-     * @return array  an associative array with the information requested.
-     *                 A MDB2_Error object on failure.
-     *
-     * @see MDB2_Driver_Common::tableInfo()
-     * @since Method available since Release 1.7.0
-     */
-    function tableInfo($result, $mode = null)
-    {
-        if (is_string($result)) {
-           return parent::tableInfo($result, $mode);
-        }
-
-        $db =$this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        return $db->raiseError(MDB2_ERROR_NOT_CAPABLE, null, null,
-           'This DBMS can not obtain tableInfo from result sets', __FUNCTION__);
-    }
-}
diff --git a/lib/MDB2/Driver/sqlite3.php b/lib/MDB2/Driver/sqlite3.php
deleted file mode 100644
index 693ceffa01c0d22b9ef49ce5e3a6ddb5557d908d..0000000000000000000000000000000000000000
--- a/lib/MDB2/Driver/sqlite3.php
+++ /dev/null
@@ -1,1332 +0,0 @@
-<?php
-/**
- * ownCloud
- *
- * @author Robin Appelman
- * @copyright 2011 Robin Appelman icewind1991@gmail.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or any later version.
- *
- * This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU Affero General Public
- * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/**
- * MDB2 SQLite3 driver
- *
- * @package MDB2
- * @category Database
- * @author  Lukas Smith <smith@pooteeweet.org>
- */
-class MDB2_Driver_sqlite3 extends MDB2_Driver_Common
-{
-    // {{{ properties
-    public $string_quoting = array('start' => "'", 'end' => "'", 'escape' => "'", 'escape_pattern' => false);
-
-    public $identifier_quoting = array('start' => '"', 'end' => '"', 'escape' => '"');
-
-    public $_lasterror = '';
-
-    public $fix_assoc_fields_names = false;
-
-    // }}}
-    // {{{ constructor
-
-    /**
-     * Constructor
-     */
-    function __construct()
-    {
-        parent::__construct();
-
-        $this->phptype = 'sqlite3';
-        $this->dbsyntax = 'sqlite';
-
-        $this->supported['sequences'] = 'emulated';
-        $this->supported['indexes'] = true;
-        $this->supported['affected_rows'] = true;
-        $this->supported['summary_functions'] = true;
-        $this->supported['order_by_text'] = true;
-        $this->supported['current_id'] = 'emulated';
-        $this->supported['limit_queries'] = true;
-        $this->supported['LOBs'] = true;
-        $this->supported['replace'] = true;
-        $this->supported['transactions'] = false;
-        $this->supported['savepoints'] = false;
-        $this->supported['sub_selects'] = true;
-        $this->supported['triggers'] = true;
-        $this->supported['auto_increment'] = true;
-        $this->supported['primary_key'] = false; // requires alter table implementation
-        $this->supported['result_introspection'] = false; // not implemented
-        $this->supported['prepared_statements'] = true;
-        $this->supported['identifier_quoting'] = true;
-        $this->supported['pattern_escaping'] = false;
-        $this->supported['new_link'] = false;
-
-        $this->options['DBA_username'] = false;
-        $this->options['DBA_password'] = false;
-        $this->options['base_transaction_name'] = '___php_MDB2_sqlite_auto_commit_off';
-        $this->options['fixed_float'] = 0;
-        $this->options['database_path'] = '';
-        $this->options['database_extension'] = '';
-        $this->options['server_version'] = '';
-        $this->options['max_identifiers_length'] = 128; //no real limit
-    }
-
-    // }}}
-    // {{{ errorInfo()
-
-    /**
-     * This method is used to collect information about an error
-     *
-     * @param integer $error
-     * @return array
-     * @access public
-     */
-    function errorInfo($error = null)
-    {
-        $native_code = null;
-        if ($this->connection) {
-            $native_code = $this->connection->lastErrorCode();
-        }
-	$native_msg = html_entity_decode($this->_lasterror);
-
-        // PHP 5.2+ prepends the function name to $php_errormsg, so we need
-        // this hack to work around it, per bug #9599.
-        $native_msg = preg_replace('/^sqlite[a-z_]+\(\)[^:]*: /', '', $native_msg);
-
-        if (is_null($error)) {
-            static $error_regexps;
-            if (empty($error_regexps)) {
-                $error_regexps = array(
-                    '/^no such table:/' => MDB2_ERROR_NOSUCHTABLE,
-                    '/^no such index:/' => MDB2_ERROR_NOT_FOUND,
-                    '/^(table|index) .* already exists$/' => MDB2_ERROR_ALREADY_EXISTS,
-                    '/PRIMARY KEY must be unique/i' => MDB2_ERROR_CONSTRAINT,
-                    '/is not unique/' => MDB2_ERROR_CONSTRAINT,
-                    '/columns .* are not unique/i' => MDB2_ERROR_CONSTRAINT,
-                    '/uniqueness constraint failed/' => MDB2_ERROR_CONSTRAINT,
-                    '/may not be NULL/' => MDB2_ERROR_CONSTRAINT_NOT_NULL,
-                    '/^no such column:/' => MDB2_ERROR_NOSUCHFIELD,
-                    '/no column named/' => MDB2_ERROR_NOSUCHFIELD,
-                    '/column not present in both tables/i' => MDB2_ERROR_NOSUCHFIELD,
-                    '/^near ".*": syntax error$/' => MDB2_ERROR_SYNTAX,
-                    '/[0-9]+ values for [0-9]+ columns/i' => MDB2_ERROR_VALUE_COUNT_ON_ROW,
-                 );
-            }
-            foreach ($error_regexps as $regexp => $code) {
-                if (preg_match($regexp, $native_msg)) {
-                    $error = $code;
-                    break;
-                }
-            }
-        }
-        return array($error, $native_code, $native_msg);
-    }
-
-    // }}}
-    // {{{ escape()
-
-    /**
-     * Quotes a string so it can be safely used in a query. It will quote
-     * the text so it can safely be used within a query.
-     *
-     * @param   string  the input string to quote
-     * @param   bool    escape wildcards
-     *
-     * @return  string  quoted string
-     *
-     * @access  public
-     */
-    public function escape($text, $escape_wildcards = false)
-    {
-		if($this->connection) {
-			return $this->connection->escapeString($text);
-		}else{
-			return str_replace("'", "''", $text);//TODO; more
-		}
-    }
-
-    // }}}
-    // {{{ beginTransaction()
-
-    /**
-     * Start a transaction or set a savepoint.
-     *
-     * @param   string  name of a savepoint to set
-     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
-     *
-     * @access  public
-     */
-    function beginTransaction($savepoint = null)
-    {
-        $this->debug('Starting transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
-        if (!is_null($savepoint)) {
-            return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-                'savepoints are not supported', __FUNCTION__);
-        } elseif ($this->in_transaction) {
-            return MDB2_OK;  //nothing to do
-        }
-        if (!$this->destructor_registered && $this->opened_persistent) {
-            $this->destructor_registered = true;
-            register_shutdown_function('MDB2_closeOpenTransactions');
-        }
-        $query = 'BEGIN TRANSACTION '.$this->options['base_transaction_name'];
-        $result =$this->_doQuery($query, true);
-        if (PEAR::isError($result)) {
-            return $result;
-        }
-        $this->in_transaction = true;
-        return MDB2_OK;
-    }
-
-    // }}}
-    // {{{ commit()
-
-    /**
-     * Commit the database changes done during a transaction that is in
-     * progress or release a savepoint. This function may only be called when
-     * auto-committing is disabled, otherwise it will fail. Therefore, a new
-     * transaction is implicitly started after committing the pending changes.
-     *
-     * @param   string  name of a savepoint to release
-     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
-     *
-     * @access  public
-     */
-    function commit($savepoint = null)
-    {
-        $this->debug('Committing transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
-        if (!$this->in_transaction) {
-            return $this->raiseError(MDB2_ERROR_INVALID, null, null,
-                'commit/release savepoint cannot be done changes are auto committed', __FUNCTION__);
-        }
-        if (!is_null($savepoint)) {
-            return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-                'savepoints are not supported', __FUNCTION__);
-        }
-
-        $query = 'COMMIT TRANSACTION '.$this->options['base_transaction_name'];
-        $result =$this->_doQuery($query, true);
-        if (PEAR::isError($result)) {
-            return $result;
-        }
-        $this->in_transaction = false;
-        return MDB2_OK;
-    }
-
-    // }}}
-    // {{{
-
-    /**
-     * Cancel any database changes done during a transaction or since a specific
-     * savepoint that is in progress. This function may only be called when
-     * auto-committing is disabled, otherwise it will fail. Therefore, a new
-     * transaction is implicitly started after canceling the pending changes.
-     *
-     * @param   string  name of a savepoint to rollback to
-     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
-     *
-     * @access  public
-     */
-    function rollback($savepoint = null)
-    {
-        $this->debug('Rolling back transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
-        if (!$this->in_transaction) {
-            return $this->raiseError(MDB2_ERROR_INVALID, null, null,
-                'rollback cannot be done changes are auto committed', __FUNCTION__);
-        }
-        if (!is_null($savepoint)) {
-            return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-                'savepoints are not supported', __FUNCTION__);
-        }
-
-        $query = 'ROLLBACK TRANSACTION '.$this->options['base_transaction_name'];
-        $result =$this->_doQuery($query, true);
-        if (PEAR::isError($result)) {
-            return $result;
-        }
-        $this->in_transaction = false;
-        return MDB2_OK;
-    }
-
-    // }}}
-    // {{{ function setTransactionIsolation()
-
-    /**
-     * Set the transacton isolation level.
-     *
-     * @param   string  standard isolation level
-     *                  READ UNCOMMITTED (allows dirty reads)
-     *                  READ COMMITTED (prevents dirty reads)
-     *                  REPEATABLE READ (prevents nonrepeatable reads)
-     *                  SERIALIZABLE (prevents phantom reads)
-     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
-     *
-     * @access  public
-     * @since   2.1.1
-     */
-    function setTransactionIsolation($isolation, $options=array())
-    {
-        $this->debug('Setting transaction isolation level', __FUNCTION__, array('is_manip' => true));
-        switch ($isolation) {
-        case 'READ UNCOMMITTED':
-            $isolation = 0;
-            break;
-        case 'READ COMMITTED':
-        case 'REPEATABLE READ':
-        case 'SERIALIZABLE':
-            $isolation = 1;
-            break;
-        default:
-            return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-                'isolation level is not supported: '.$isolation, __FUNCTION__);
-        }
-
-        $query = "PRAGMA read_uncommitted=$isolation";
-        return $this->_doQuery($query, true);
-    }
-
-    // }}}
-    // {{{ getDatabaseFile()
-
-    /**
-     * Builds the string with path+dbname+extension
-     *
-     * @return string full database path+file
-     * @access protected
-     */
-    function _getDatabaseFile($database_name)
-    {
-        if ($database_name === '' || $database_name === ':memory:') {
-            return $database_name;
-        }
-        return $this->options['database_path'].$database_name.$this->options['database_extension'];
-    }
-
-    // }}}
-    // {{{ connect()
-
-    /**
-     * Connect to the database
-     *
-     * @return true on success, MDB2 Error Object on failure
-     **/
-    function connect()
-    {
-		if($this->connection instanceof SQLite3) {
-			return MDB2_OK;
-		}
-		$datadir=OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" );
-        $database_file = $this->_getDatabaseFile($this->database_name);
-        if (is_resource($this->connection)) {
-            //if (count(array_diff($this->connected_dsn, $this->dsn)) == 0
-            if (MDB2::areEquals($this->connected_dsn, $this->dsn)
-                && $this->connected_database_name == $database_file
-                && $this->opened_persistent == $this->options['persistent']
-            ) {
-                return MDB2_OK;
-            }
-            $this->disconnect(false);
-        }
-
-        if (!PEAR::loadExtension($this->phptype)) {
-            return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
-                'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__);
-        }
-
-        if (empty($this->database_name)) {
-            return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null,
-            'unable to establish a connection', __FUNCTION__);
-        }
-
-        if ($database_file !== ':memory:') {
-			if(!strpos($database_file, '.db')) {
-				$database_file="$datadir/$database_file.db";
-			}
-            if (!file_exists($database_file)) {
-                if (!touch($database_file)) {
-                    return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
-                        'Could not create database file', __FUNCTION__);
-                }
-                if (!isset($this->dsn['mode'])
-                    || !is_numeric($this->dsn['mode'])
-                ) {
-                    $mode = 0644;
-                } else {
-                    $mode = octdec($this->dsn['mode']);
-                }
-                if (!chmod($database_file, $mode)) {
-                    return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
-                        'Could not be chmodded database file', __FUNCTION__);
-                }
-                if (!file_exists($database_file)) {
-                    return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
-                        'Could not be found database file', __FUNCTION__);
-                }
-            }
-            if (!is_file($database_file)) {
-                return $this->raiseError(MDB2_ERROR_INVALID, null, null,
-                        'Database is a directory name', __FUNCTION__);
-            }
-            if (!is_readable($database_file)) {
-                return $this->raiseError(MDB2_ERROR_ACCESS_VIOLATION, null, null,
-                        'Could not read database file', __FUNCTION__);
-            }
-        }
-
-        $php_errormsg = '';
-		$this->connection = new SQLite3($database_file);
-		if(is_callable(array($this->connection, 'busyTimeout'))) {//busy timout is only available in php>=5.3
-			$this->connection->busyTimeout(60000);
-		}
-        $this->_lasterror = $this->connection->lastErrorMsg();
-        if (!$this->connection) {
-            return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null,
-            'unable to establish a connection', __FUNCTION__);
-        }
-
-        if ($this->fix_assoc_fields_names ||
-            $this->options['portability'] & MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES) {
-            $this->connection->exec("PRAGMA short_column_names = 1");
-            $this->fix_assoc_fields_names = true;
-        }
-
-        $this->connected_dsn = $this->dsn;
-        $this->connected_database_name = $database_file;
-        $this->opened_persistent = $this->getoption('persistent');
-        $this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype;
-
-        return MDB2_OK;
-    }
-
-    // }}}
-    // {{{ databaseExists()
-
-    /**
-     * check if given database name is exists?
-     *
-     * @param string $name    name of the database that should be checked
-     *
-     * @return mixed true/false on success, a MDB2 error on failure
-     * @access public
-     */
-    function databaseExists($name)
-    {
-        $database_file = $this->_getDatabaseFile($name);
-        $result = file_exists($database_file);
-        return $result;
-    }
-
-    // }}}
-    // {{{ disconnect()
-
-    /**
-     * Log out and disconnect from the database.
-     *
-     * @param  boolean $force if the disconnect should be forced even if the
-     *                        connection is opened persistently
-     * @return mixed true on success, false if not connected and error
-     *                object on error
-     * @access public
-     */
-    function disconnect($force = true)
-    {
-        if ($this->connection instanceof  SQLite3) {
-            if ($this->in_transaction) {
-                $dsn = $this->dsn;
-                $database_name = $this->database_name;
-                $persistent = $this->options['persistent'];
-                $this->dsn = $this->connected_dsn;
-                $this->database_name = $this->connected_database_name;
-                $this->options['persistent'] = $this->opened_persistent;
-                $this->rollback();
-                $this->dsn = $dsn;
-                $this->database_name = $database_name;
-                $this->options['persistent'] = $persistent;
-            }
-
-            if (!$this->opened_persistent || $force) {
-                $this->connection->close();
-            }
-        } else {
-            return false;
-        }
-        return parent::disconnect($force);
-    }
-
-    // }}}
-    // {{{ _doQuery()
-
-    /**
-     * Execute a query
-     * @param string $query  query
-     * @param boolean $is_manip  if the query is a manipulation query
-     * @param resource $connection
-     * @param string $database_name
-     * @return result or error object
-     * @access protected
-     */
-    function _doQuery($query, $is_manip = false, $connection = null, $database_name = null)
-    {
-        $this->last_query = $query;
-        $result = $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'pre'));
-        if ($result) {
-            if (PEAR::isError($result)) {
-                return $result;
-            }
-            $query = $result;
-        }
-        if ($this->options['disable_query']) {
-            $result = $is_manip ? 0 : null;
-            return $result;
-        }
-		$result=$this->connection->query($query.';');
-        $this->_lasterror = $this->connection->lastErrorMsg();
-
-        if (!$result) {
-            $err =$this->raiseError(null, null, null,
-                'Could not execute statement', __FUNCTION__);
-            return $err;
-        }
-
-        $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'post', 'result' => $result));
-        return $result;
-    }
-
-    // }}}
-    // {{{ _affectedRows()
-
-    /**
-     * Returns the number of rows affected
-     *
-     * @param resource $result
-     * @param resource $connection
-     * @return mixed MDB2 Error Object or the number of rows affected
-     * @access private
-     */
-    function _affectedRows($connection, $result = null)
-    {
-        return $this->connection->changes();
-    }
-
-    // }}}
-    // {{{ _modifyQuery()
-
-    /**
-     * Changes a query string for various DBMS specific reasons
-     *
-     * @param string $query  query to modify
-     * @param boolean $is_manip  if it is a DML query
-     * @param integer $limit  limit the number of rows
-     * @param integer $offset  start reading from given offset
-     * @return string modified query
-     * @access protected
-     */
-    function _modifyQuery($query, $is_manip, $limit, $offset)
-    {
-        if ($this->options['portability'] & MDB2_PORTABILITY_DELETE_COUNT) {
-            if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) {
-                $query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/',
-                                      'DELETE FROM \1 WHERE 1=1', $query);
-            }
-        }
-        if ($limit > 0
-            && !preg_match('/LIMIT\s*\d(?:\s*(?:,|OFFSET)\s*\d+)?(?:[^\)]*)?$/i', $query)
-        ) {
-            $query = rtrim($query);
-            if (substr($query, -1) == ';') {
-                $query = substr($query, 0, -1);
-            }
-            if ($is_manip) {
-                $query.= " LIMIT $limit";
-            } else {
-                $query.= " LIMIT $offset,$limit";
-            }
-        }
-        return $query;
-    }
-
-    // }}}
-    // {{{ getServerVersion()
-
-    /**
-     * return version information about the server
-     *
-     * @param bool   $native  determines if the raw version string should be returned
-     * @return mixed array/string with version information or MDB2 error object
-     * @access public
-     */
-    function getServerVersion($native = false)
-    {
-        $server_info = false;
-        if ($this->connected_server_info) {
-            $server_info = $this->connected_server_info;
-        } elseif ($this->options['server_version']) {
-            $server_info = $this->options['server_version'];
-        } elseif (function_exists('sqlite_libversion')) {
-            $server_info = @sqlite_libversion();
-        }
-        if (!$server_info) {
-            return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-                'Requires either the "server_version" option or the sqlite_libversion() function', __FUNCTION__);
-        }
-        // cache server_info
-        $this->connected_server_info = $server_info;
-        if (!$native) {
-            $tmp = explode('.', $server_info, 3);
-            $server_info = array(
-                'major' => isset($tmp[0]) ? $tmp[0] : null,
-                'minor' => isset($tmp[1]) ? $tmp[1] : null,
-                'patch' => isset($tmp[2]) ? $tmp[2] : null,
-                'extra' => null,
-                'native' => $server_info,
-            );
-        }
-        return $server_info;
-    }
-
-    // }}}
-    // {{{ replace()
-
-    /**
-     * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
-     * query, except that if there is already a row in the table with the same
-     * key field values, the old row is deleted before the new row is inserted.
-     *
-     * The REPLACE type of query does not make part of the SQL standards. Since
-     * practically only SQLite implements it natively, this type of query is
-     * emulated through this method for other DBMS using standard types of
-     * queries inside a transaction to assure the atomicity of the operation.
-     *
-     * @access public
-     *
-     * @param string $table name of the table on which the REPLACE query will
-     *  be executed.
-     * @param array $fields associative array that describes the fields and the
-     *  values that will be inserted or updated in the specified table. The
-     *  indexes of the array are the names of all the fields of the table. The
-     *  values of the array are also associative arrays that describe the
-     *  values and other properties of the table fields.
-     *
-     *  Here follows a list of field properties that need to be specified:
-     *
-     *    value:
-     *          Value to be assigned to the specified field. This value may be
-     *          of specified in database independent type format as this
-     *          function can perform the necessary datatype conversions.
-     *
-     *    Default:
-     *          this property is required unless the Null property
-     *          is set to 1.
-     *
-     *    type
-     *          Name of the type of the field. Currently, all types Metabase
-     *          are supported except for clob and blob.
-     *
-     *    Default: no type conversion
-     *
-     *    null
-     *          Boolean property that indicates that the value for this field
-     *          should be set to null.
-     *
-     *          The default value for fields missing in INSERT queries may be
-     *          specified the definition of a table. Often, the default value
-     *          is already null, but since the REPLACE may be emulated using
-     *          an UPDATE query, make sure that all fields of the table are
-     *          listed in this function argument array.
-     *
-     *    Default: 0
-     *
-     *    key
-     *          Boolean property that indicates that this field should be
-     *          handled as a primary key or at least as part of the compound
-     *          unique index of the table that will determine the row that will
-     *          updated if it exists or inserted a new row otherwise.
-     *
-     *          This function will fail if no key field is specified or if the
-     *          value of a key field is set to null because fields that are
-     *          part of unique index they may not be null.
-     *
-     *    Default: 0
-     *
-     * @return mixed MDB2_OK on success, a MDB2 error on failure
-     */
-    function replace($table, $fields)
-    {
-        $count = count($fields);
-        $query = $values = '';
-        $keys = $colnum = 0;
-        for (reset($fields); $colnum < $count; next($fields), $colnum++) {
-            $name = key($fields);
-            if ($colnum > 0) {
-                $query .= ',';
-                $values.= ',';
-            }
-            $query.= $this->quoteIdentifier($name, true);
-            if (isset($fields[$name]['null']) && $fields[$name]['null']) {
-                $value = 'NULL';
-            } else {
-                $type = isset($fields[$name]['type']) ? $fields[$name]['type'] : null;
-                $value = $this->quote($fields[$name]['value'], $type);
-                if (PEAR::isError($value)) {
-                    return $value;
-                }
-            }
-            $values.= $value;
-            if (isset($fields[$name]['key']) && $fields[$name]['key']) {
-                if ($value === 'NULL') {
-                    return $this->raiseError(MDB2_ERROR_CANNOT_REPLACE, null, null,
-                        'key value '.$name.' may not be NULL', __FUNCTION__);
-                }
-                $keys++;
-            }
-        }
-        if ($keys == 0) {
-            return $this->raiseError(MDB2_ERROR_CANNOT_REPLACE, null, null,
-                'not specified which fields are keys', __FUNCTION__);
-        }
-
-        $connection = $this->getConnection();
-        if (PEAR::isError($connection)) {
-            return $connection;
-        }
-
-        $table = $this->quoteIdentifier($table, true);
-        $query = "REPLACE INTO $table ($query) VALUES ($values)";
-        $result =$this->_doQuery($query, true, $connection);
-        if (PEAR::isError($result)) {
-            return $result;
-        }
-        return $this->_affectedRows($connection, $result);
-    }
-
-    // }}}
-    // {{{ nextID()
-
-    /**
-     * Returns the next free id of a sequence
-     *
-     * @param string $seq_name name of the sequence
-     * @param boolean $ondemand when true the sequence is
-     *                          automatic created, if it
-     *                          not exists
-     *
-     * @return mixed MDB2 Error Object or id
-     * @access public
-     */
-    function nextID($seq_name, $ondemand = true)
-    {
-        $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true);
-        $seqcol_name = $this->options['seqcol_name'];
-        $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (NULL)";
-        $this->pushErrorHandling(PEAR_ERROR_RETURN);
-        $this->expectError(MDB2_ERROR_NOSUCHTABLE);
-        $result =$this->_doQuery($query, true);
-        $this->popExpect();
-        $this->popErrorHandling();
-        if (PEAR::isError($result)) {
-            if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) {
-                $this->loadModule('Manager', null, true);
-                $result = $this->manager->createSequence($seq_name);
-                if (PEAR::isError($result)) {
-                    return $this->raiseError($result, null, null,
-                        'on demand sequence '.$seq_name.' could not be created', __FUNCTION__);
-                } else {
-                    return $this->nextID($seq_name, false);
-                }
-            }
-            return $result;
-        }
-        $value = $this->lastInsertID();
-        if (is_numeric($value)) {
-            $query = "DELETE FROM $sequence_name WHERE $seqcol_name < $value";
-            $result =$this->_doQuery($query, true);
-            if (PEAR::isError($result)) {
-                $this->warnings[] = 'nextID: could not delete previous sequence table values from '.$seq_name;
-            }
-        }
-        return $value;
-    }
-
-    // }}}
-    // {{{ lastInsertID()
-
-    /**
-     * Returns the autoincrement ID if supported or $id or fetches the current
-     * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field)
-     *
-     * @param string $table name of the table into which a new row was inserted
-     * @param string $field name of the field into which a new row was inserted
-     * @return mixed MDB2 Error Object or id
-     * @access public
-     */
-    function lastInsertID($table = null, $field = null)
-    {
-        return $this->connection->lastInsertRowID();
-    }
-
-    // }}}
-    // {{{ currID()
-
-    /**
-     * Returns the current id of a sequence
-     *
-     * @param string $seq_name name of the sequence
-     * @return mixed MDB2 Error Object or id
-     * @access public
-     */
-    function currID($seq_name)
-    {
-        $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true);
-        $seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true);
-        $query = "SELECT MAX($seqcol_name) FROM $sequence_name";
-        return $this->queryOne($query, 'integer');
-    }
-
-    /**
-     * Prepares a query for multiple execution with execute().
-     * With some database backends, this is emulated.
-     * prepare() requires a generic query as string like
-     * 'INSERT INTO numbers VALUES(?,?)' or
-     * 'INSERT INTO numbers VALUES(:foo,:bar)'.
-     * The ? and :name and are placeholders which can be set using
-     * bindParam() and the query can be sent off using the execute() method.
-     * The allowed format for :name can be set with the 'bindname_format' option.
-     *
-     * @param string $query the query to prepare
-     * @param mixed   $types  array that contains the types of the placeholders
-     * @param mixed   $result_types  array that contains the types of the columns in
-     *                        the result set or MDB2_PREPARE_RESULT, if set to
-     *                        MDB2_PREPARE_MANIP the query is handled as a manipulation query
-     * @param mixed   $lobs   key (field) value (parameter) pair for all lob placeholders
-     * @return mixed resource handle for the prepared query on success, a MDB2
-     *        error on failure
-     * @access public
-     * @see bindParam, execute
-     */
-    function prepare($query, $types = null, $result_types = null, $lobs = array())
-    {
-        if ($this->options['emulate_prepared']
-            || $this->supported['prepared_statements'] !== true
-        ) {
-            $obj =& parent::prepare($query, $types, $result_types, $lobs);
-            return $obj;
-        }
-        $this->last_query = $query;
-        $is_manip = ($result_types === MDB2_PREPARE_MANIP);
-        $offset = $this->offset;
-        $limit = $this->limit;
-        $this->offset = $this->limit = 0;
-        $query = $this->_modifyQuery($query, $is_manip, $limit, $offset);
-        $result = $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'pre'));
-        if ($result) {
-            if (PEAR::isError($result)) {
-                return $result;
-            }
-            $query = $result;
-        }
-        $placeholder_type_guess = $placeholder_type = null;
-        $question = '?';
-        $colon = ':';
-        $positions = array();
-        $position = 0;
-        while ($position < strlen($query)) {
-            $q_position = strpos($query, $question, $position);
-            $c_position = strpos($query, $colon, $position);
-            if ($q_position && $c_position) {
-                $p_position = min($q_position, $c_position);
-            } elseif ($q_position) {
-                $p_position = $q_position;
-            } elseif ($c_position) {
-                $p_position = $c_position;
-            } else {
-                break;
-            }
-            if (is_null($placeholder_type)) {
-                $placeholder_type_guess = $query[$p_position];
-            }
-
-            $new_pos = $this->_skipDelimitedStrings($query, $position, $p_position);
-            if (PEAR::isError($new_pos)) {
-                return $new_pos;
-            }
-            if ($new_pos != $position) {
-                $position = $new_pos;
-                continue; //evaluate again starting from the new position
-            }
-
-
-            if ($query[$position] == $placeholder_type_guess) {
-                if (is_null($placeholder_type)) {
-                    $placeholder_type = $query[$p_position];
-                    $question = $colon = $placeholder_type;
-                }
-                if ($placeholder_type == ':') {
-                    $regexp = '/^.{'.($position+1).'}('.$this->options['bindname_format'].').*$/s';
-                    $parameter = preg_replace($regexp, '\\1', $query);
-                    if ($parameter === '') {
-                        $err =& $this->raiseError(MDB2_ERROR_SYNTAX, null, null,
-                            'named parameter name must match "bindname_format" option', __FUNCTION__);
-                        return $err;
-                    }
-                    $positions[$p_position] = $parameter;
-                    $query = substr_replace($query, '?', $position, strlen($parameter)+1);
-                } else {
-                    $positions[$p_position] = count($positions);
-                }
-                $position = $p_position + 1;
-            } else {
-                $position = $p_position;
-            }
-        }
-        $connection = $this->getConnection();
-        if (PEAR::isError($connection)) {
-            return $connection;
-        }
-        $statement =$this->connection->prepare($query);
-        if (!$statement) {
-            return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
-                        'unable to prepare statement: '.$query);
-        }
-
-        $class_name = 'MDB2_Statement_'.$this->phptype;
-        $obj = new $class_name($this, $statement, $positions, $query, $types, $result_types, $is_manip, $limit, $offset);
-        $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'post', 'result' => $obj));
-        return $obj;
-    }
-}
-
-/**
- * MDB2 SQLite result driver
- *
- * @package MDB2
- * @category Database
- * @author  Lukas Smith <smith@pooteeweet.org>
- */
-class MDB2_Result_sqlite3 extends MDB2_Result_Common
-{
-    // }}}
-    // {{{ fetchRow()
-
-    /**
-     * Fetch a row and insert the data into an existing array.
-     *
-     * @param int       $fetchmode  how the array data should be indexed
-     * @param int    $rownum    number of the row where the data can be found
-     * @return int data array on success, a MDB2 error on failure
-     * @access public
-     */
-    function fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null)
-    {
-        if (!is_null($rownum)) {
-            $seek = $this->seek($rownum);
-            if (PEAR::isError($seek)) {
-                return $seek;
-            }
-        }
-        if ($fetchmode == MDB2_FETCHMODE_DEFAULT) {
-            $fetchmode = $this->db->fetchmode;
-        }
-        if ($fetchmode & MDB2_FETCHMODE_ASSOC) {
-            //$row = @sqlite_fetch_array($this->result, SQLITE_ASSOC);
-            $row=$this->result->fetchArray(SQLITE3_ASSOC);
-            if (is_array($row)
-                && $this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE
-            ) {
-                $row = array_change_key_case($row, $this->db->options['field_case']);
-            }
-        } else {
-           $row=$this->result->fetchArray(SQLITE3_NUM);
-        }
-        if (!$row) {
-            if ($this->result === false) {
-                $err =$this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
-                    'resultset has already been freed', __FUNCTION__);
-                return $err;
-            }
-            $null = null;
-            return $null;
-        }
-        $mode = $this->db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL;
-        $rtrim = false;
-        if ($this->db->options['portability'] & MDB2_PORTABILITY_RTRIM) {
-            if (empty($this->types)) {
-                $mode += MDB2_PORTABILITY_RTRIM;
-            } else {
-                $rtrim = true;
-            }
-        }
-        if ($mode) {
-            $this->db->_fixResultArrayValues($row, $mode);
-        }
-        if (!empty($this->types)) {
-            $row = $this->db->datatype->convertResultRow($this->types, $row, $rtrim);
-        }
-        if (!empty($this->values)) {
-            $this->_assignBindColumns($row);
-        }
-        if ($fetchmode === MDB2_FETCHMODE_OBJECT) {
-            $object_class = $this->db->options['fetch_class'];
-            if ($object_class == 'stdClass') {
-                $row = (object) $row;
-            } else {
-                $row = new $object_class($row);
-            }
-        }
-        ++$this->rownum;
-        return $row;
-    }
-
-    // }}}
-    // {{{ _getColumnNames()
-
-    /**
-     * Retrieve the names of columns returned by the DBMS in a query result.
-     *
-     * @return  mixed   Array variable that holds the names of columns as keys
-     *                  or an MDB2 error on failure.
-     *                  Some DBMS may not return any columns when the result set
-     *                  does not contain any rows.
-     * @access private
-     */
-    function _getColumnNames()
-    {
-        $columns = array();
-        $numcols = $this->numCols();
-        if (PEAR::isError($numcols)) {
-            return $numcols;
-        }
-        for ($column = 0; $column < $numcols; $column++) {
-            $column_name = $this->result->getColumnName($column);
-            $columns[$column_name] = $column;
-        }
-        if ($this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
-            $columns = array_change_key_case($columns, $this->db->options['field_case']);
-        }
-        return $columns;
-    }
-
-    // }}}
-    // {{{ numCols()
-
-    /**
-     * Count the number of columns returned by the DBMS in a query result.
-     *
-     * @access public
-     * @return mixed integer value with the number of columns, a MDB2 error
-     *                       on failure
-     */
-    function numCols()
-    {
-        $this->result->numColumns();
-    }
-}
-
-/**
- * MDB2 SQLite buffered result driver
- *
- * @package MDB2
- * @category Database
- * @author  Lukas Smith <smith@pooteeweet.org>
- */
-class MDB2_BufferedResult_sqlite3 extends MDB2_Result_sqlite3
-{
-    // {{{ seek()
-
-    /**
-     * Seek to a specific row in a result set
-     *
-     * @param int    $rownum    number of the row where the data can be found
-     * @return mixed MDB2_OK on success, a MDB2 error on failure
-     * @access public
-     */
-    function seek($rownum = 0)
-    {
-		$this->result->reset();
-		for($i=0;$i<$rownum;$i++) {
-			$this->result->fetchArray();
-		}
-        $this->rownum = $rownum - 1;
-        return MDB2_OK;
-    }
-
-    // }}}
-    // {{{ valid()
-
-    /**
-     * Check if the end of the result set has been reached
-     *
-     * @return mixed true or false on sucess, a MDB2 error on failure
-     * @access public
-     */
-    function valid()
-    {
-        $numrows = $this->numRows();
-        if (PEAR::isError($numrows)) {
-            return $numrows;
-        }
-        return $this->rownum < ($numrows - 1);
-    }
-
-    // }}}
-    // {{{ numRows()
-
-    /**
-     * Returns the number of rows in a result object
-     *
-     * @return mixed MDB2 Error Object or the number of rows
-     * @access public
-     */
-    function numRows()
-    {
-        $rows = 0;
-        $this->result->reset();
-        while($this->result->fetchArray()) {
-			$rows++;
-        }
-        $this->result->reset();
-        return $rows;
-    }
-}
-
-/**
- * MDB2 SQLite statement driver
- *
- * @package MDB2
- * @category Database
- * @author  Lukas Smith <smith@pooteeweet.org>
- */
-class MDB2_Statement_sqlite3 extends MDB2_Statement_Common
-{
-	// }}}
-    // {{{ function bindValue($parameter, &$value, $type = null)
-
-	private function getParamType($type) {
-		switch(strtolower($type)) {
-			case 'text':
-				return SQLITE3_TEXT;
-			case 'boolean':
-			case 'integer':
-				return SQLITE3_INTEGER;
-			case 'float':
-				return SQLITE3_FLOAT;
-			case 'blob':
-				return SQLITE3_BLOB;
-		}
-	}
-    /**
-     * Set the value of a parameter of a prepared query.
-     *
-     * @param   int     the order number of the parameter in the query
-     *       statement. The order number of the first parameter is 1.
-     * @param   mixed   value that is meant to be assigned to specified
-     *       parameter. The type of the value depends on the $type argument.
-     * @param   string  specifies the type of the field
-     *
-     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
-     *
-     * @access  public
-     */
-    function bindValue($parameter, $value, $type = null) {
-		if($type) {
-			$type=$this->getParamType($type);
-			$this->statement->bindValue($parameter, $value, $type);
-		}else{
-			$this->statement->bindValue($parameter, $value);
-		}
-		return MDB2_OK;
-    }
-
-	/**
-     * Bind a variable to a parameter of a prepared query.
-     *
-     * @param   int     the order number of the parameter in the query
-     *       statement. The order number of the first parameter is 1.
-     * @param   mixed   variable that is meant to be bound to specified
-     *       parameter. The type of the value depends on the $type argument.
-     * @param   string  specifies the type of the field
-     *
-     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
-     *
-     * @access  public
-     */
-    function bindParam($parameter, &$value, $type = null) {
-        if($type) {
-			$type=$this->getParamType($type);
-			$this->statement->bindParam($parameter, $value, $type);
-		}else{
-			$this->statement->bindParam($parameter, $value);
-		}
-        return MDB2_OK;
-    }
-
-    /**
-     * Release resources allocated for the specified prepared query.
-     *
-     * @return mixed MDB2_OK on success, a MDB2 error on failure
-     * @access public
-     */
-    function free()
-	{
-		$this->statement->close();
-    }
-
-    /**
-     * Execute a prepared query statement helper method.
-     *
-     * @param mixed $result_class string which specifies which result class to use
-     * @param mixed $result_wrap_class string which specifies which class to wrap results in
-     *
-     * @return mixed MDB2_Result or integer (affected rows) on success,
-     *               a MDB2 error on failure
-     * @access private
-     */
-    function _execute($result_class = true, $result_wrap_class = false) {
-		if (is_null($this->statement)) {
-            $result =& parent::_execute($result_class, $result_wrap_class);
-            return $result;
-        }
-        $this->db->last_query = $this->query;
-        $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'pre', 'parameters' => $this->values));
-        if ($this->db->getOption('disable_query')) {
-            $result = $this->is_manip ? 0 : null;
-            return $result;
-        }
-
-        $connection = $this->db->getConnection();
-        if (PEAR::isError($connection)) {
-            return $connection;
-        }
-
-        $result = $this->statement->execute();
-        if ($result==false) {
-            $err =$this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
-                    'cant execute statement', __FUNCTION__);
-        }
-
-        if ($this->is_manip) {
-            $affected_rows = $this->db->_affectedRows($connection, $result);
-            return $affected_rows;
-        }
-
-        $result = $this->db->_wrapResult($result, $this->result_types,
-            $result_class, $result_wrap_class, $this->limit, $this->offset);
-        $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'post', 'result' => $result));
-        return $result;
-    }
-
-    /**
-     * Set the values of multiple a parameter of a prepared query in bulk.
-     *
-     * @param   array   specifies all necessary information
-     *       for bindValue() the array elements must use keys corresponding to
-     *       the number of the position of the parameter.
-     * @param   array   specifies the types of the fields
-     *
-     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
-     *
-     * @access  public
-     * @see     bindParam()
-     */
-    function bindValueArray($values, $types = null)
-    {
-        $types = is_array($types) ? array_values($types) : array_fill(0, count($values), null);
-        $parameters = array_keys($values);
-        foreach ($parameters as $key => $parameter) {
-            $this->db->pushErrorHandling(PEAR_ERROR_RETURN);
-            $this->db->expectError(MDB2_ERROR_NOT_FOUND);
-            $err = $this->bindValue($parameter+1, $values[$parameter], $types[$key]);
-            $this->db->popExpect();
-            $this->db->popErrorHandling();
-            if (PEAR::isError($err)) {
-                if ($err->getCode() == MDB2_ERROR_NOT_FOUND) {
-                    //ignore (extra value for missing placeholder)
-                    continue;
-                }
-                return $err;
-            }
-        }
-        return MDB2_OK;
-    }
-    // }}}
-    // {{{ function bindParamArray(&$values, $types = null)
-
-    /**
-     * Bind the variables of multiple a parameter of a prepared query in bulk.
-     *
-     * @param   array   specifies all necessary information
-     *       for bindParam() the array elements must use keys corresponding to
-     *       the number of the position of the parameter.
-     * @param   array   specifies the types of the fields
-     *
-     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
-     *
-     * @access  public
-     * @see     bindParam()
-     */
-    function bindParamArray(&$values, $types = null)
-    {
-        $types = is_array($types) ? array_values($types) : array_fill(0, count($values), null);
-        $parameters = array_keys($values);
-        foreach ($parameters as $key => $parameter) {
-            $err = $this->bindParam($parameter+1, $values[$parameter], $types[$key]);
-            if (PEAR::isError($err)) {
-                return $err;
-            }
-        }
-        return MDB2_OK;
-    }
-
-    // }}}
-    // {{{ function &execute($values = null, $result_class = true, $result_wrap_class = false)
-
-    /**
-     * Execute a prepared query statement.
-     *
-     * @param array specifies all necessary information
-     *              for bindParam() the array elements must use keys corresponding
-     *              to the number of the position of the parameter.
-     * @param mixed specifies which result class to use
-     * @param mixed specifies which class to wrap results in
-     *
-     * @return mixed MDB2_Result or integer (affected rows) on success,
-     *               a MDB2 error on failure
-     * @access public
-     */
-    function execute($values = null, $result_class = true, $result_wrap_class = false)
-    {
-        if (is_null($this->positions)) {
-            return $this->db->raiseError(MDB2_ERROR, null, null,
-                'Prepared statement has already been freed', __FUNCTION__);
-        }
-        $values = (array)$values;
-        if (!empty($values)) {
-			if(count($this->types)) {
-				$types=$this->types;
-			}else{
-				$types=null;
-			}
-            $err = $this->bindValueArray($values, $types);
-            if (PEAR::isError($err)) {
-                return $this->db->raiseError(MDB2_ERROR, null, null,
-                                            'Binding Values failed with message: ' . $err->getMessage(), __FUNCTION__);
-            }
-        }
-        $result =$this->_execute($result_class, $result_wrap_class);
-        return $result;
-    }
-
-    function __destruct() {
-		$this->free();
-    }
-}
diff --git a/lib/db.php b/lib/db.php
index 6662785646113b33d96e43e61f023fca73ded373..e70d66fc2ba2f8c6403aba9f8bf951ea1e1f1095 100644
--- a/lib/db.php
+++ b/lib/db.php
@@ -20,7 +20,9 @@
  *
  */
 
-class DatabaseException extends Exception{
+define('MDB2_SCHEMA_DUMP_STRUCTURE', '1');
+
+class DatabaseException extends Exception {
 	private $query;
 
 	//FIXME getQuery seems to be unused, maybe use parent constructor with $message, $code and $previous
@@ -29,61 +31,41 @@ class DatabaseException extends Exception{
 		$this->query = $query;
 	}
 
-	public function getQuery(){
+	public function getQuery() {
 		return $this->query;
 	}
 }
 
 /**
  * This class manages the access to the database. It basically is a wrapper for
- * MDB2 with some adaptions.
+ * Doctrine with some adaptions.
  */
 class OC_DB {
-	const BACKEND_PDO=0;
-	const BACKEND_MDB2=1;
+	const BACKEND_DOCTRINE=2;
 
 	static private $preparedQueries = array();
 	static private $cachingEnabled = true;
 
 	/**
-	 * @var MDB2_Driver_Common
+	 * @var \Doctrine\DBAL\Connection
 	 */
-	static private $connection; //the prefered connection to use, either PDO or MDB2
+	static private $connection; //the preferred connection to use, only Doctrine
 	static private $backend=null;
 	/**
-	 * @var MDB2_Driver_Common
-	 */
-	static private $MDB2=null;
-	/**
-	 * @var PDO
+	 * @var \Doctrine\DBAL\Connection
 	 */
-	static private $PDO=null;
-	/**
-	 * @var MDB2_Schema
-	 */
-	static private $schema=null;
+	static private $DOCTRINE=null;
+
 	static private $inTransaction=false;
 	static private $prefix=null;
 	static private $type=null;
 
 	/**
 	 * check which backend we should use
-	 * @return int BACKEND_MDB2 or BACKEND_PDO
+	 * @return int BACKEND_DOCTRINE
 	 */
 	private static function getDBBackend() {
-		//check if we can use PDO, else use MDB2 (installation always needs to be done my mdb2)
-		if(class_exists('PDO') && OC_Config::getValue('installed', false)) {
-			$type = OC_Config::getValue( "dbtype", "sqlite" );
-			if($type=='oci') { //oracle also always needs mdb2
-				return self::BACKEND_MDB2;
-			}
-			if($type=='sqlite3') $type='sqlite';
-			$drivers=PDO::getAvailableDrivers();
-			if(array_search($type, $drivers)!==false) {
-				return self::BACKEND_PDO;
-			}
-		}
-		return self::BACKEND_MDB2;
+		return self::BACKEND_DOCTRINE;
 	}
 
 	/**
@@ -100,28 +82,24 @@ class OC_DB {
 		if(is_null($backend)) {
 			$backend=self::getDBBackend();
 		}
-		if($backend==self::BACKEND_PDO) {
-			$success = self::connectPDO();
-			self::$connection=self::$PDO;
-			self::$backend=self::BACKEND_PDO;
-		}else{
-			$success = self::connectMDB2();
-			self::$connection=self::$MDB2;
-			self::$backend=self::BACKEND_MDB2;
+		if($backend==self::BACKEND_DOCTRINE) {
+			$success = self::connectDoctrine();
+			self::$connection=self::$DOCTRINE;
+			self::$backend=self::BACKEND_DOCTRINE;
 		}
 		return $success;
 	}
 
 	/**
-	 * connect to the database using pdo
+	 * connect to the database using doctrine
 	 *
 	 * @return bool
 	 */
-	public static function connectPDO() {
+	public static function connectDoctrine() {
 		if(self::$connection) {
-			if(self::$backend==self::BACKEND_MDB2) {
+			if(self::$backend!=self::BACKEND_DOCTRINE) {
 				self::disconnect();
-			}else{
+			} else {
 				return true;
 			}
 		}
@@ -134,169 +112,85 @@ class OC_DB {
 		$type = OC_Config::getValue( "dbtype", "sqlite" );
 		if(strpos($host, ':')) {
 			list($host, $port)=explode(':', $host, 2);
-		}else{
+		} else {
 			$port=false;
 		}
-		$opts = array();
-		$datadir=OC_Config::getValue( "datadirectory", OC::$SERVERROOT.'/data' );
-
-		// do nothing if the connection already has been established
-		if(!self::$PDO) {
-			// Add the dsn according to the database type
-			switch($type) {
-				case 'sqlite':
-					$dsn='sqlite2:'.$datadir.'/'.$name.'.db';
-					break;
-				case 'sqlite3':
-					$dsn='sqlite:'.$datadir.'/'.$name.'.db';
-					break;
-				case 'mysql':
-					if($port) {
-						$dsn='mysql:dbname='.$name.';host='.$host.';port='.$port;
-					}else{
-						$dsn='mysql:dbname='.$name.';host='.$host;
-					}
-					$opts[PDO::MYSQL_ATTR_INIT_COMMAND] = "SET NAMES 'UTF8'";
-					break;
-				case 'pgsql':
-					if($port) {
-						$dsn='pgsql:dbname='.$name.';host='.$host.';port='.$port;
-					}else{
-						$dsn='pgsql:dbname='.$name.';host='.$host;
-					}
-					/**
-					* Ugly fix for pg connections pbm when password use spaces
-					*/
-					$e_user = addslashes($user);
-					$e_password = addslashes($pass);
-					$pass = $user = null;
-					$dsn .= ";user='$e_user';password='$e_password'";
-					/** END OF FIX***/
-					break;
-				case 'oci': // Oracle with PDO is unsupported
-					if ($port) {
-							$dsn = 'oci:dbname=//' . $host . ':' . $port . '/' . $name;
-					} else {
-							$dsn = 'oci:dbname=//' . $host . '/' . $name;
-					}
-					break;
-				case 'mssql':
-					if ($port) {
-							$dsn='sqlsrv:Server='.$host.','.$port.';Database='.$name;
-					} else {
-							$dsn='sqlsrv:Server='.$host.';Database='.$name;
-					}
-					break;
-				default:
-					return false;
-			}
-			self::$PDO=new PDO($dsn, $user, $pass, $opts);
-			
-			// We always, really always want associative arrays
-			self::$PDO->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
-			self::$PDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-		}
-		return true;
-	}
-
-	/**
-	 * connect to the database using mdb2
-	 */
-	public static function connectMDB2() {
-		if(self::$connection) {
-			if(self::$backend==self::BACKEND_PDO) {
-				self::disconnect();
-			}else{
-				return true;
-			}
-		}
-		self::$preparedQueries = array();
-		// The global data we need
-		$name = OC_Config::getValue( "dbname", "owncloud" );
-		$host = OC_Config::getValue( "dbhost", "" );
-		$user = OC_Config::getValue( "dbuser", "" );
-		$pass = OC_Config::getValue( "dbpassword", "" );
-		$type = OC_Config::getValue( "dbtype", "sqlite" );
-		$SERVERROOT=OC::$SERVERROOT;
-		$datadir=OC_Config::getValue( "datadirectory", "$SERVERROOT/data" );
 
 		// do nothing if the connection already has been established
-		if(!self::$MDB2) {
-			// Require MDB2.php (not required in the head of the file so we only load it when needed)
-			require_once 'MDB2.php';
-
-			// Prepare options array
-			$options = array(
-					'portability' => MDB2_PORTABILITY_ALL - MDB2_PORTABILITY_FIX_CASE,
-					'log_line_break' => '<br>',
-					'idxname_format' => '%s',
-					'debug' => true,
-					'quote_identifier' => true
-					);
-
-			// Add the dsn according to the database type
+		if(!self::$DOCTRINE) {
+			$config = new \Doctrine\DBAL\Configuration();
 			switch($type) {
 				case 'sqlite':
 				case 'sqlite3':
-					$dsn = array(
-						'phptype'  => $type,
-						'database' => "$datadir/$name.db",
-						'mode' => '0644'
+					$datadir=OC_Config::getValue( "datadirectory", OC::$SERVERROOT.'/data' );
+					$connectionParams = array(
+							'user' => $user,
+							'password' => $pass,
+							'path' => $datadir.'/'.$name.'.db',
+							'driver' => 'pdo_sqlite',
 					);
 					break;
 				case 'mysql':
-					$dsn = array(
-						'phptype'  => 'mysql',
-						'username' => $user,
-						'password' => $pass,
-						'hostspec' => $host,
-						'database' => $name
+					$connectionParams = array(
+							'user' => $user,
+							'password' => $pass,
+							'host' => $host,
+							'port' => $port,
+							'dbname' => $name,
+							'charset' => 'UTF8',
+							'driver' => 'pdo_mysql',
 					);
 					break;
 				case 'pgsql':
-					$dsn = array(
-						'phptype'  => 'pgsql',
-						'username' => $user,
-						'password' => $pass,
-						'hostspec' => $host,
-						'database' => $name
+					$connectionParams = array(
+							'user' => $user,
+							'password' => $pass,
+							'host' => $host,
+							'port' => $port,
+							'dbname' => $name,
+							'driver' => 'pdo_pgsql',
 					);
 					break;
 				case 'oci':
-					$dsn = array(
-						'phptype'  => 'oci8',
-						'username' => $user,
-						'password' => $pass,
-						'service'  => $name,
-						'hostspec' => $host,
-						'charset' => 'AL32UTF8',
+					$connectionParams = array(
+							'user' => $user,
+							'password' => $pass,
+							'host' => $host,
+							'dbname' => $name,
+							'charset' => 'AL32UTF8',
+							'driver' => 'oci8',
 					);
+					if (!empty($port)) {
+						$connectionParams['port'] = $port;
+					}
 					break;
 				case 'mssql':
-					$dsn = array(
-						'phptype' => 'sqlsrv',
-						'username' => $user,
-						'password' => $pass,
-						'hostspec' => $host,
-						'database' => $name,
-						'charset' => 'UTF-8'
+					$connectionParams = array(
+							'user' => $user,
+							'password' => $pass,
+							'host' => $host,
+							'port' => $port,
+							'dbname' => $name,
+							'charset' => 'UTF8',
+							'driver' => 'pdo_sqlsrv',
 					);
-					$options['portability'] = $options['portability'] - MDB2_PORTABILITY_EMPTY_TO_NULL;
 					break;
 				default:
 					return false;
 			}
+			try {
+				self::$DOCTRINE = \Doctrine\DBAL\DriverManager::getConnection($connectionParams, $config);
+			} catch(\Doctrine\DBAL\DBALException $e) {
+				OC_Log::write('core', $e->getMessage(), OC_Log::FATAL);
+				OC_User::setUserId(null);
 
-			// Try to establish connection
-			self::$MDB2 = MDB2::factory( $dsn, $options );
-			
-			self::raiseExceptionOnError( self::$MDB2 );
-
-			// We always, really always want associative arrays
-			self::$MDB2->setFetchMode(MDB2_FETCHMODE_ASSOC);
+				// send http status 503
+				header('HTTP/1.1 503 Service Temporarily Unavailable');
+				header('Status: 503 Service Temporarily Unavailable');
+				OC_Template::printErrorPage('Failed to connect to database');
+				die();
+			}
 		}
-
-		// we are done. great!
 		return true;
 	}
 
@@ -306,34 +200,19 @@ class OC_DB {
 	 * @param int $limit
 	 * @param int $offset
 	 * @param bool $isManipulation
-	 * @return MDB2_Statement_Common prepared SQL query
+	 * @throws DatabaseException
+	 * @return \Doctrine\DBAL\Statement prepared SQL query
 	 *
-	 * SQL query via MDB2 prepare(), needs to be execute()'d!
+	 * SQL query via Doctrine prepare(), needs to be execute()'d!
 	 */
 	static public function prepare( $query , $limit = null, $offset = null, $isManipulation = null) {
 
 		if (!is_null($limit) && $limit != -1) {
-			if (self::$backend == self::BACKEND_MDB2) {
-				//MDB2 uses or emulates limits & offset internally
-				self::$MDB2->setLimit($limit, $offset);
-			} else {
-				//PDO does not handle limit and offset.
-				//FIXME: check limit notation for other dbs
-				//the following sql thus might needs to take into account db ways of representing it
-				//(oracle has no LIMIT / OFFSET)
-				$limit = (int)$limit;
-				$limitsql = ' LIMIT ' . $limit;
-				if (!is_null($offset)) {
-					$offset = (int)$offset;
-					$limitsql .= ' OFFSET ' . $offset;
-				}
-				//insert limitsql
-				if (substr($query, -1) == ';') { //if query ends with ;
-					$query = substr($query, 0, -1) . $limitsql . ';';
-				} else {
-					$query.=$limitsql;
-				}
+			if ($limit === -1) {
+				$limit = null;
 			}
+			$platform = self::$connection->getDatabasePlatform();
+			$query = $platform->modifyLimitQuery($query, $limit, $offset);
 		} else {
 			if (isset(self::$preparedQueries[$query]) and self::$cachingEnabled) {
 				return self::$preparedQueries[$query];
@@ -354,26 +233,14 @@ class OC_DB {
 		}
 		
 		// return the result
-		if(self::$backend==self::BACKEND_MDB2) {
-			// differentiate between query and manipulation
-			if ($isManipulation) {
-				$result = self::$connection->prepare( $query, null, MDB2_PREPARE_MANIP );
-			} else {
-				$result = self::$connection->prepare( $query, null, MDB2_PREPARE_RESULT );
-			}
-
-			// Die if we have an error (error means: bad query, not 0 results!)
-			if( self::isError($result)) {
-				throw new DatabaseException($result->getMessage(), $query);
-			}
-		}else{
-			try{
+		if (self::$backend == self::BACKEND_DOCTRINE) {
+			try {
 				$result=self::$connection->prepare($query);
-			}catch(PDOException $e) {
-				throw new DatabaseException($e->getMessage(), $query);
+			} catch(\Doctrine\DBAL\DBALException $e) {
+				throw new \DatabaseException($e->getMessage(), $query);
 			}
 			// differentiate between query and manipulation
-			$result = new PDOStatementWrapper($result, $isManipulation);
+			$result=new OC_DB_StatementWrapper($result, $isManipulation);
 		}
 		if ((is_null($limit) || $limit == -1) and self::$cachingEnabled ) {
 			$type = OC_Config::getValue( "dbtype", "sqlite" );
@@ -412,7 +279,7 @@ class OC_DB {
 	
 	/**
 	 * @brief execute a prepared statement, on error write log and throw exception
-	 * @param mixed $stmt PDOStatementWrapper | MDB2_Statement_Common ,
+	 * @param mixed $stmt OC_DB_StatementWrapper,
 	 *					  an array with 'sql' and optionally 'limit' and 'offset' keys
 	 *					.. or a simple sql query string
 	 * @param array $parameters
@@ -445,7 +312,7 @@ class OC_DB {
 			$stmt = self::prepare($stmt['sql'], $stmt['limit'], $stmt['offset']);
 		}
 		self::raiseExceptionOnError($stmt, 'Could not prepare statement');
-		if ($stmt instanceof PDOStatementWrapper || $stmt instanceof MDB2_Statement_Common) {
+		if ($stmt instanceof OC_DB_StatementWrapper) {
 			$result = $stmt->execute($parameters);
 			self::raiseExceptionOnError($result, 'Could not execute statement');
 		} else {
@@ -465,7 +332,7 @@ class OC_DB {
 	 * @return int id
 	 * @throws DatabaseException
 	 *
-	 * MDB2 lastInsertID()
+	 * \Doctrine\DBAL\Connection lastInsertId
 	 *
 	 * Call this method right after the insert command or other functions may
 	 * cause trouble!
@@ -478,12 +345,20 @@ class OC_DB {
 			$row = $result->fetchRow();
 			self::raiseExceptionOnError($row, 'fetching row for insertid failed');
 			return $row['id'];
-		} else if( $type === 'mssql' || $type === 'oci') {
+		} else if( $type === 'mssql') {
 			if($table !== null) {
 				$prefix = OC_Config::getValue( "dbtableprefix", "oc_" );
 				$table = str_replace( '*PREFIX*', $prefix, $table );
 			}
-			$result = self::$connection->lastInsertId($table);
+			return self::$connection->lastInsertId($table);
+		}
+		if( $type === 'oci' ) {
+			if($table !== null) {
+				$prefix = OC_Config::getValue( "dbtableprefix", "oc_" );
+				$suffix = '_SEQ';
+				$table = '"'.str_replace( '*PREFIX*', $prefix, $table ).$suffix.'"';
+			}
+			return self::$connection->lastInsertId($table);
 		} else {
 			if($table !== null) {
 				$prefix = OC_Config::getValue( "dbtableprefix", "oc_" );
@@ -505,18 +380,14 @@ class OC_DB {
 	public static function disconnect() {
 		// Cut connection if required
 		if(self::$connection) {
-			if(self::$backend==self::BACKEND_MDB2) {
-				self::$connection->disconnect();
-			}
 			self::$connection=false;
-			self::$MDB2=false;
-			self::$PDO=false;
+			self::$DOCTRINE=false;
 		}
 
 		return true;
 	}
 
-	/**
+	/** else {
 	 * @brief saves database scheme to xml file
 	 * @param string $file name of file
 	 * @param int $mode
@@ -525,18 +396,8 @@ class OC_DB {
 	 * TODO: write more documentation
 	 */
 	public static function getDbStructure( $file, $mode=MDB2_SCHEMA_DUMP_STRUCTURE) {
-		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, $mode );
-
-		return true;
+		self::connectDoctrine();
+		return OC_DB_Schema::getDbStructure(self::$DOCTRINE, $file);
 	}
 
 	/**
@@ -547,134 +408,25 @@ class OC_DB {
 	 * TODO: write more documentation
 	 */
 	public static function createDbFromStructure( $file ) {
-		$CONFIG_DBNAME  = OC_Config::getValue( "dbname", "owncloud" );
-		$CONFIG_DBTABLEPREFIX = OC_Config::getValue( "dbtableprefix", "oc_" );
-		$CONFIG_DBTYPE = OC_Config::getValue( "dbtype", "sqlite" );
-
-		// cleanup the cached queries
-		self::$preparedQueries = array();
-
-		self::connectScheme();
-
-		// read file
-		$content = file_get_contents( $file );
-
-		// Make changes and save them to an in-memory file
-		$file2 = 'static://db_scheme';
-		$content = str_replace( '*dbname*', $CONFIG_DBNAME, $content );
-		$content = str_replace( '*dbprefix*', $CONFIG_DBTABLEPREFIX, $content );
-		/* FIXME: use CURRENT_TIMESTAMP for all databases. mysql supports it as a default for DATETIME since 5.6.5 [1]
-		 * as a fallback we could use <default>0000-01-01 00:00:00</default> everywhere
-		 * [1] http://bugs.mysql.com/bug.php?id=27645
-		 * http://dev.mysql.com/doc/refman/5.0/en/timestamp-initialization.html
-		 * http://www.postgresql.org/docs/8.1/static/functions-datetime.html
-		 * http://www.sqlite.org/lang_createtable.html
-		 * http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions037.htm
-		 */
-		if( $CONFIG_DBTYPE == 'pgsql' ) { //mysql support it too but sqlite doesn't
-			$content = str_replace( '<default>0000-00-00 00:00:00</default>',
-				'<default>CURRENT_TIMESTAMP</default>', $content );
-		}
-
-		file_put_contents( $file2, $content );
-
-		// Try to create tables
-		$definition = self::$schema->parseDatabaseDefinitionFile( $file2 );
-
-		//clean up memory
-		unlink( $file2 );
-		
-		self::raiseExceptionOnError($definition,'Failed to parse the database definition');
-
-		if(OC_Config::getValue('dbtype', 'sqlite')==='oci') {
-			unset($definition['charset']); //or MDB2 tries SHUTDOWN IMMEDIATE
-			$oldname = $definition['name'];
-			$definition['name']=OC_Config::getValue( "dbuser", $oldname );
-		}
-
-		// we should never drop a database
-		$definition['overwrite'] = false;
-
-		$ret=self::$schema->createDatabase( $definition );
-
-		self::raiseExceptionOnError($ret,'Failed to create the database structure');
-
-		return true;
+		self::connectDoctrine();
+		return OC_DB_Schema::createDbFromStructure(self::$DOCTRINE, $file);
 	}
 
 	/**
 	 * @brief update the database scheme
 	 * @param string $file file to read structure from
+	 * @throws Exception
 	 * @return bool
 	 */
 	public static function updateDbFromStructure($file) {
-		$CONFIG_DBTABLEPREFIX = OC_Config::getValue( "dbtableprefix", "oc_" );
-		$CONFIG_DBTYPE = OC_Config::getValue( "dbtype", "sqlite" );
-
-		self::connectScheme();
-		
-		if(OC_Config::getValue('dbtype', 'sqlite')==='oci') {
-			//set dbname, it is unset because oci uses 'service' to connect
-			self::$schema->db->database_name=self::$schema->db->dsn['username'];
-		}
-
-		// read file
-		$content = file_get_contents( $file );
-
-		$previousSchema = self::$schema->getDefinitionFromDatabase();
-		self::raiseExceptionOnError($previousSchema,'Failed to get existing database structure for updating');
-
-		// Make changes and save them to an in-memory file
-		$file2 = 'static://db_scheme';
-		$content = str_replace( '*dbname*', $previousSchema['name'], $content );
-		$content = str_replace( '*dbprefix*', $CONFIG_DBTABLEPREFIX, $content );
-		/* FIXME: use CURRENT_TIMESTAMP for all databases. mysql supports it as a default for DATETIME since 5.6.5 [1]
-		 * as a fallback we could use <default>0000-01-01 00:00:00</default> everywhere
-		 * [1] http://bugs.mysql.com/bug.php?id=27645
-		 * http://dev.mysql.com/doc/refman/5.0/en/timestamp-initialization.html
-		 * http://www.postgresql.org/docs/8.1/static/functions-datetime.html
-		 * http://www.sqlite.org/lang_createtable.html
-		 * http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions037.htm
-		 */
-		if( $CONFIG_DBTYPE == 'pgsql' ) { //mysql support it too but sqlite doesn't
-			$content = str_replace( '<default>0000-00-00 00:00:00</default>',
-				'<default>CURRENT_TIMESTAMP</default>', $content );
-		}
-		if(OC_Config::getValue('dbtype', 'sqlite')==='oci') {
-			unset($previousSchema['charset']); //or MDB2 tries SHUTDOWN IMMEDIATE
-			$oldname = $previousSchema['name'];
-			$previousSchema['name']=OC_Config::getValue( "dbuser", $oldname );
-			//TODO check identifiers are at most 30 chars long
-		}
-		file_put_contents( $file2, $content );
-		$op = self::$schema->updateDatabase($file2, $previousSchema, array(), false);
-
-		//clean up memory
-		unlink( $file2 );
-
-		self::raiseExceptionOnError($op,'Failed to update database structure');
-		return true;
-	}
-
-	/**
-	 * @brief connects to a MDB2 database scheme
-	 * @returns bool
-	 *
-	 * Connects to a MDB2 database scheme
-	 */
-	private static function connectScheme() {
-		// We need a mdb2 database connection
-		self::connectMDB2();
-		self::$MDB2->loadModule('Manager');
-		self::$MDB2->loadModule('Reverse');
-
-		// Connect if this did not happen before
-		if(!self::$schema) {
-			require_once 'MDB2/Schema.php';
-			self::$schema=MDB2_Schema::factory(self::$MDB2);
+		self::connectDoctrine();
+		try {
+			$result = OC_DB_Schema::updateDbFromStructure(self::$DOCTRINE, $file);
+		} catch (Exception $e) {
+			OC_Log::write('core', 'Failed to update database structure ('.$e.')', OC_Log::FATAL);
+			throw $e;
 		}
-
-		return true;
+		return $result;
 	}
 
 	/**
@@ -733,7 +485,7 @@ class OC_DB {
 
 		try {
 			$result = self::executeAudited($query, $inserts);
-		} catch(PDOException $e) {
+		} catch(\Doctrine\DBAL\DBALException $e) {
 			OC_Template::printExceptionErrorPage( $e );
 		}
 
@@ -765,14 +517,14 @@ class OC_DB {
 			$query = str_replace( '`', '"', $query );
 			$query = str_ireplace( 'NOW()', 'datetime(\'now\')', $query );
 			$query = str_ireplace( 'UNIX_TIMESTAMP()', 'strftime(\'%s\',\'now\')', $query );
-		}elseif( $type == 'pgsql' ) {
+		} elseif( $type == 'pgsql' ) {
 			$query = str_replace( '`', '"', $query );
 			$query = str_ireplace( 'UNIX_TIMESTAMP()', 'cast(extract(epoch from current_timestamp) as integer)',
 				$query );
-		}elseif( $type == 'oci'  ) {
+		} elseif( $type == 'oci'  ) {
 			$query = str_replace( '`', '"', $query );
 			$query = str_ireplace( 'NOW()', 'CURRENT_TIMESTAMP', $query );
-			$query = str_ireplace( 'UNIX_TIMESTAMP()', '((CAST(SYS_EXTRACT_UTC(systimestamp) AS DATE))-TO_DATE(\'1970101000000\',\'YYYYMMDDHH24MiSS\'))*24*3600', $query );
+			$query = str_ireplace( 'UNIX_TIMESTAMP()', "(cast(sys_extract_utc(systimestamp) as date) - date'1970-01-01') * 86400", $query );
 		}elseif( $type == 'mssql' ) {
 			$query = preg_replace( "/\`(.*?)`/", "[$1]", $query );
 			$query = str_ireplace( 'NOW()', 'CURRENT_TIMESTAMP', $query );
@@ -848,9 +600,8 @@ class OC_DB {
 	 * @param string $tableName the table to drop
 	 */
 	public static function dropTable($tableName) {
-		self::connectMDB2();
-		self::$MDB2->loadModule('Manager');
-		self::$MDB2->dropTable($tableName);
+		self::connectDoctrine();
+		OC_DB_Schema::dropTable(self::$DOCTRINE, $tableName);
 	}
 
 	/**
@@ -858,50 +609,17 @@ class OC_DB {
 	 * @param string $file the xml file describing the tables
 	 */
 	public static function removeDBStructure($file) {
-		$CONFIG_DBNAME  = OC_Config::getValue( "dbname", "owncloud" );
-		$CONFIG_DBTABLEPREFIX = OC_Config::getValue( "dbtableprefix", "oc_" );
-		self::connectScheme();
-
-		// read file
-		$content = file_get_contents( $file );
-
-		// Make changes and save them to a temporary file
-		$file2 = tempnam( 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 );
-
-		// get the tables
-		$definition = self::$schema->parseDatabaseDefinitionFile( $file2 );
-
-		// Delete our temporary file
-		unlink( $file2 );
-		$tables=array_keys($definition['tables']);
-		foreach($tables as $table) {
-			self::dropTable($table);
-		}
+		self::connectDoctrine();
+		OC_DB_Schema::removeDBStructure(self::$DOCTRINE, $file);
 	}
 
 	/**
-	 * @brief replaces the owncloud tables with a new set
+	 * @brief replaces the ownCloud tables with a new set
 	 * @param $file string path to the MDB2 xml db export file
 	 */
 	public static function replaceDB( $file ) {
-		$apps = OC_App::getAllApps();
-		self::beginTransaction();
-		// Delete the old tables
-		self::removeDBStructure( OC::$SERVERROOT . '/db_structure.xml' );
-
-		foreach($apps as $app) {
-			$path = OC_App::getAppPath($app).'/appinfo/database.xml';
-			if(file_exists($path)) {
-				self::removeDBStructure( $path );
-			}
-		}
-
-		// Create new tables
-		self::createDBFromStructure( $file );
-		self::commit();
+		self::connectDoctrine();
+		OC_DB_Schema::replaceDB(self::$DOCTRINE, $file);
 	}
 
 	/**
@@ -910,9 +628,6 @@ class OC_DB {
 	 */
 	public static function beginTransaction() {
 		self::connect();
-		if (self::$backend==self::BACKEND_MDB2 && !self::$connection->supports('transactions')) {
-			return false;
-		}
 		self::$connection->beginTransaction();
 		self::$inTransaction=true;
 		return true;
@@ -933,24 +648,16 @@ class OC_DB {
 	}
 
 	/**
-	 * check if a result is an error, works with MDB2 and PDOException
+	 * check if a result is an error, works with Doctrine
 	 * @param mixed $result
 	 * @return bool
 	 */
 	public static function isError($result) {
-		//MDB2 returns an MDB2_Error object
-		if (class_exists('PEAR') === true && PEAR::isError($result)) {
-			return true;
-		}
-		//PDO returns false on error (and throws an exception)
-		if (self::$backend===self::BACKEND_PDO and $result === false) {
-			return true;
-		}
-
-		return false;
+		//Doctrine returns false on error (and throws an exception)
+		return $result === false;
 	}
 	/**
-	 * check if a result is an error and throws an exception, works with MDB2 and PDOException
+	 * check if a result is an error and throws an exception, works with \Doctrine\DBAL\DBALException
 	 * @param mixed $result
 	 * @param string $message
 	 * @return void
@@ -968,32 +675,19 @@ class OC_DB {
 	}
 
 	public static function getErrorCode($error) {
-		if ( class_exists('PEAR') === true && PEAR::isError($error) ) {
-			/** @var $error PEAR_Error */
-			return $error->getCode();
-		}
-		if ( self::$backend==self::BACKEND_PDO and self::$PDO ) {
-			return self::$PDO->errorCode();
-		}
-
-		return -1;
+		$code = self::$connection->errorCode();
+		return $code;
 	}
 	/**
 	 * returns the error code and message as a string for logging
-	 * works with MDB2 and PDOException
+	 * works with DoctrineException
 	 * @param mixed $error
 	 * @return string
 	 */
 	public static function getErrorMessage($error) {
-		if ( class_exists('PEAR') === true && PEAR::isError($error) ) {
-			$msg = $error->getCode() . ': ' . $error->getMessage();
-			$msg .= ' (' . $error->getDebugInfo() . ')';
-
-			return $msg;
-		}
-		if (self::$backend==self::BACKEND_PDO and self::$PDO) {
-			$msg = self::$PDO->errorCode() . ': ';
-			$errorInfo = self::$PDO->errorInfo();
+		if (self::$backend==self::BACKEND_DOCTRINE and self::$DOCTRINE) {
+			$msg = self::$DOCTRINE->errorCode() . ': ';
+			$errorInfo = self::$DOCTRINE->errorInfo();
 			if (is_array($errorInfo)) {
 				$msg .= 'SQLSTATE = '.$errorInfo[0] . ', ';
 				$msg .= 'Driver Code = '.$errorInfo[1] . ', ';
@@ -1015,180 +709,3 @@ class OC_DB {
 		self::$cachingEnabled = $enabled;
 	}
 }
-
-/**
- * small wrapper around PDOStatement to make it behave ,more like an MDB2 Statement
- */
-class PDOStatementWrapper{
-	/**
-	 * @var PDOStatement
-	 */
-	private $statement = null;
-	private $isManipulation = false;
-	private $lastArguments = array();
-
-	public function __construct($statement, $isManipulation = false) {
-		$this->statement = $statement;
-		$this->isManipulation = $isManipulation;
-	}
-
-	/**
-	 * make execute return the result or updated row count instead of a bool
-	 */
-	public function execute($input=array()) {
-		if(OC_Config::getValue( "log_query", false)) {
-			$params_str = str_replace("\n"," ",var_export($input,true));
-			OC_Log::write('core', 'DB execute with arguments : '.$params_str, OC_Log::DEBUG);
-		}
-		$this->lastArguments = $input;
-		if (count($input) > 0) {
-
-			if (!isset($type)) {
-				$type = OC_Config::getValue( "dbtype", "sqlite" );
-			}
-
-			if ($type == 'mssql') {
-				$input = $this->tryFixSubstringLastArgumentDataForMSSQL($input);
-			}
-
-			$result = $this->statement->execute($input);
-		} else {
-			$result = $this->statement->execute();
-		}
-		
-		if ($result === false) {
-			return false;
-		}
-		if ($this->isManipulation) {
-			return $this->statement->rowCount();
-		} else {
-			return $this;
-		}
-	}
-
-	private function tryFixSubstringLastArgumentDataForMSSQL($input) {
-		$query = $this->statement->queryString;
-		$pos = stripos ($query, 'SUBSTRING');
-
-		if ( $pos === false) {
-			return;
-		}
-
-		try {
-			$newQuery = '';
-
-			$cArg = 0;
-
-			$inSubstring = false;
-
-			// Create new query
-			for ($i = 0; $i < strlen ($query); $i++) {
-				if ($inSubstring == false) {
-					// Defines when we should start inserting values
-					if (substr ($query, $i, 9) == 'SUBSTRING') {
-						$inSubstring = true;
-					}
-				} else {
-					// Defines when we should stop inserting values
-					if (substr ($query, $i, 1) == ')') {
-						$inSubstring = false;
-					}
-				}
-
-				if (substr ($query, $i, 1) == '?') {
-					// We found a question mark
-					if ($inSubstring) {
-						$newQuery .= $input[$cArg];
-
-						//
-						// Remove from input array
-						//
-						array_splice ($input, $cArg, 1);
-					} else {
-						$newQuery .= substr ($query, $i, 1);
-						$cArg++;
-					}
-				} else {
-					$newQuery .= substr ($query, $i, 1);
-				}
-			}
-
-			// The global data we need
-			$name = OC_Config::getValue( "dbname", "owncloud" );
-			$host = OC_Config::getValue( "dbhost", "" );
-			$user = OC_Config::getValue( "dbuser", "" );
-			$pass = OC_Config::getValue( "dbpassword", "" );
-			if (strpos($host,':')) {
-				list($host, $port) = explode(':', $host, 2);
-			} else {
-				$port = false;
-			}
-			$opts = array();
-
-			if ($port) {
-				$dsn = 'sqlsrv:Server='.$host.','.$port.';Database='.$name;
-			} else {
-				$dsn = 'sqlsrv:Server='.$host.';Database='.$name;
-			}
-
-			$PDO = new PDO($dsn, $user, $pass, $opts);
-			$PDO->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
-			$PDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-
-			$this->statement = $PDO->prepare($newQuery);
-
-			$this->lastArguments = $input;
-
-			return $input;
-		} catch (PDOException $e){
-			$entry = 'PDO DB Error: "'.$e->getMessage().'"<br />';
-			$entry .= 'Offending command was: '.$this->statement->queryString .'<br />';
-			$entry .= 'Input parameters: ' .print_r($input, true).'<br />';
-			$entry .= 'Stack trace: ' .$e->getTraceAsString().'<br />';
-			OC_Log::write('core', $entry, OC_Log::FATAL);
-			OC_User::setUserId(null);
-
-			// send http status 503
-			header('HTTP/1.1 503 Service Temporarily Unavailable');
-			header('Status: 503 Service Temporarily Unavailable');
-			OC_Template::printErrorPage('Failed to connect to database');
-			die ($entry);
-		}
-	}
-
-	/**
-	 * provide numRows
-	 */
-	public function numRows() {
-		$regex = '/^SELECT\s+(?:ALL\s+|DISTINCT\s+)?(?:.*?)\s+FROM\s+(.*)$/i';
-		if (preg_match($regex, $this->statement->queryString, $output) > 0) {
-			$query = OC_DB::prepare("SELECT COUNT(*) FROM {$output[1]}");
-			return $query->execute($this->lastArguments)->fetchColumn();
-		}else{
-			return $this->statement->rowCount();
-		}
-	}
-
-	/**
-	 * provide an alias for fetch
-	 */
-	public function fetchRow() {
-		return $this->statement->fetch();
-	}
-
-	/**
-	 * pass all other function directly to the PDOStatement
-	 */
-	public function __call($name, $arguments) {
-		return call_user_func_array(array($this->statement, $name), $arguments);
-	}
-
-	/**
-	 * Provide a simple fetchOne.
-	 * fetch single column from the next row
-	 * @param int $colnum the column number to fetch
-	 */
-	public function fetchOne($colnum = 0) {
-		return $this->statement->fetchColumn($colnum);
-	}
-}
diff --git a/lib/db/mdb2schemareader.php b/lib/db/mdb2schemareader.php
new file mode 100644
index 0000000000000000000000000000000000000000..0ead9528c937d5b41d85b2103a7eb5182dbcf80a
--- /dev/null
+++ b/lib/db/mdb2schemareader.php
@@ -0,0 +1,241 @@
+<?php
+/**
+ * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+class OC_DB_MDB2SchemaReader {
+	static protected $DBNAME;
+	static protected $DBTABLEPREFIX;
+	static protected $platform;
+
+	/**
+	 * @param $file
+	 * @param $platform
+	 * @return \Doctrine\DBAL\Schema\Schema
+	 * @throws DomainException
+	 */
+	public static function loadSchemaFromFile($file, $platform) {
+		self::$DBNAME  = OC_Config::getValue( "dbname", "owncloud" );
+		self::$DBTABLEPREFIX = OC_Config::getValue( "dbtableprefix", "oc_" );
+		self::$platform = $platform;
+		$schema = new \Doctrine\DBAL\Schema\Schema();
+		$xml = simplexml_load_file($file);
+		foreach($xml->children() as $child) {
+			switch($child->getName()) {
+				case 'name':
+				case 'create':
+				case 'overwrite':
+				case 'charset':
+					break;
+				case 'table':
+					self::loadTable($schema, $child);
+					break;
+				default:
+					throw new DomainException('Unknown element: '.$child->getName());
+
+			}
+		}
+		return $schema;
+	}
+
+	/**
+	 * @param\Doctrine\DBAL\Schema\Schema $schema
+	 * @param $xml
+	 * @throws DomainException
+	 */
+	private static function loadTable($schema, $xml) {
+		foreach($xml->children() as $child) {
+			switch($child->getName()) {
+				case 'name':
+					$name = (string)$child;
+					$name = str_replace( '*dbprefix*', self::$DBTABLEPREFIX, $name );
+					$name = self::$platform->quoteIdentifier($name);
+					$table = $schema->createTable($name);
+					break;
+				case 'create':
+				case 'overwrite':
+				case 'charset':
+					break;
+				case 'declaration':
+					self::loadDeclaration($table, $child);
+					break;
+				default:
+					throw new DomainException('Unknown element: '.$child->getName());
+
+			}
+		}
+	}
+
+	/**
+	 * @param \Doctrine\DBAL\Schema\Table $table
+	 * @param $xml
+	 * @throws DomainException
+	 */
+	private static function loadDeclaration($table, $xml) {
+		foreach($xml->children() as $child) {
+			switch($child->getName()) {
+				case 'field':
+					self::loadField($table, $child);
+					break;
+				case 'index':
+					self::loadIndex($table, $child);
+					break;
+				default:
+					throw new DomainException('Unknown element: '.$child->getName());
+
+			}
+		}
+	}
+
+	private static function loadField($table, $xml) {
+		$options = array();
+		foreach($xml->children() as $child) {
+			switch($child->getName()) {
+				case 'name':
+					$name = (string)$child;
+					$name = self::$platform->quoteIdentifier($name);
+					break;
+				case 'type':
+					$type = (string)$child;
+					switch($type) {
+						case 'text':
+							$type = 'string';
+							break;
+						case 'clob':
+							$type = 'text';
+							break;
+						case 'timestamp':
+							$type = 'datetime';
+							break;
+						// TODO
+						return;
+					}
+					break;
+				case 'length':
+					$length = (string)$child;
+					$options['length'] = $length;
+					break;
+				case 'unsigned':
+					$unsigned = self::asBool($child);
+					$options['unsigned'] = $unsigned;
+					break;
+				case 'notnull':
+					$notnull = self::asBool($child);
+					$options['notnull'] = $notnull;
+					break;
+				case 'autoincrement':
+					$autoincrement = self::asBool($child);
+					$options['autoincrement'] = $autoincrement;
+					break;
+				case 'default':
+					$default = (string)$child;
+					$options['default'] = $default;
+					break;
+				case 'comments':
+					$comment = (string)$child;
+					$options['comment'] = $comment;
+					break;
+				default:
+					throw new DomainException('Unknown element: '.$child->getName());
+
+			}
+		}
+		if (isset($name) && isset($type)) {
+			if (empty($options['default'])) {
+				if (empty($options['notnull']) || !$options['notnull']) {
+					unset($options['default']);
+					$options['notnull'] = false;
+				} else {
+					$options['default'] = '';
+				}
+				if ($type == 'integer') {
+					$options['default'] = 0;
+				}
+				if (!empty($options['autoincrement']) && $options['autoincrement']) {
+					unset($options['default']);
+				}
+			}
+			if ($type == 'integer' && isset($options['length'])) {
+				$length = $options['length'];
+				if ($length < 4) {
+					$type = 'smallint';
+				}
+				else if ($length > 4) {
+					$type = 'bigint';
+				}
+			}
+			if (!empty($options['autoincrement'])
+			    && !empty($options['notnull'])) {
+				$options['primary'] = true;
+			}
+			$table->addColumn($name, $type, $options);
+			if (!empty($options['primary']) && $options['primary']) {
+				$table->setPrimaryKey(array($name));
+			}
+		}
+	}
+
+	private static function loadIndex($table, $xml) {
+		$name = null;
+		$fields = array();
+		foreach($xml->children() as $child) {
+			switch($child->getName()) {
+				case 'name':
+					$name = (string)$child;
+					break;
+				case 'primary':
+					$primary = self::asBool($child);
+					break;
+				case 'unique':
+					$unique = self::asBool($child);
+					break;
+				case 'field':
+					foreach($child->children() as $field) {
+						switch($field->getName()) {
+							case 'name':
+								$field_name = (string)$field;
+								$field_name = self::$platform->quoteIdentifier($field_name);
+								$fields[] = $field_name;
+								break;
+							case 'sorting':
+								break;
+							default:
+								throw new DomainException('Unknown element: '.$field->getName());
+
+						}
+					}
+					break;
+				default:
+					throw new DomainException('Unknown element: '.$child->getName());
+
+			}
+		}
+		if (!empty($fields)) {
+			if (isset($primary) && $primary) {
+				$table->setPrimaryKey($fields, $name);
+			} else
+			if (isset($unique) && $unique) {
+				$table->addUniqueIndex($fields, $name);
+			} else {
+				$table->addIndex($fields, $name);
+			}
+		} else {
+			throw new DomainException('Empty index definition: '.$name.' options:'. print_r($fields, true));
+		}
+	}
+
+	private static function asBool($xml) {
+		$result = (string)$xml;
+		if ($result == 'true') {
+			$result = true;
+		} else
+		if ($result == 'false') {
+			$result = false;
+		}
+		return (bool)$result;
+	}
+
+}
diff --git a/lib/db/mdb2schemawriter.php b/lib/db/mdb2schemawriter.php
new file mode 100644
index 0000000000000000000000000000000000000000..21b43cbfe806849279729a6c22a1cc99dd9fc520
--- /dev/null
+++ b/lib/db/mdb2schemawriter.php
@@ -0,0 +1,133 @@
+<?php
+/**
+ * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+class OC_DB_MDB2SchemaWriter {
+
+	/**
+	 * @param $file
+	 * @param \Doctrine\DBAL\Schema\AbstractSchemaManager $sm
+	 * @return bool
+	 */
+	static public function saveSchemaToFile($file, $sm) {
+		$xml = new SimpleXMLElement('<database/>');
+		$xml->addChild('name', OC_Config::getValue( "dbname", "owncloud" ));
+		$xml->addChild('create', 'true');
+		$xml->addChild('overwrite', 'false');
+		$xml->addChild('charset', 'utf8');
+		foreach ($sm->listTables() as $table) {
+			self::saveTable($table, $xml->addChild('table'));
+		}
+		file_put_contents($file, $xml->asXML());
+		return true;
+	}
+
+	private static function saveTable($table, $xml) {
+		$xml->addChild('name', $table->getName());
+		$declaration = $xml->addChild('declaration');
+		foreach($table->getColumns() as $column) {
+			self::saveColumn($column, $declaration->addChild('field'));
+		}
+		foreach($table->getIndexes() as $index) {
+			if ($index->getName() == 'PRIMARY') {
+				$autoincrement = false;
+				foreach($index->getColumns() as $column) {
+					if ($table->getColumn($column)->getAutoincrement()) {
+						$autoincrement = true;
+					}
+				}
+				if ($autoincrement) {
+					continue;
+				}
+			}
+			self::saveIndex($index, $declaration->addChild('index'));
+		}
+	}
+
+	private static function saveColumn($column, $xml) {
+		$xml->addChild('name', $column->getName());
+		switch($column->getType()) {
+			case 'SmallInt':
+			case 'Integer':
+			case 'BigInt':
+				$xml->addChild('type', 'integer');
+				$default = $column->getDefault();
+				if (is_null($default) && $column->getAutoincrement()) {
+					$default = '0';
+				}
+				$xml->addChild('default', $default);
+				$xml->addChild('notnull', self::toBool($column->getNotnull()));
+				if ($column->getAutoincrement()) {
+					$xml->addChild('autoincrement', '1');
+				}
+				if ($column->getUnsigned()) {
+					$xml->addChild('unsigned', 'true');
+				}
+				$length = '4';
+				if ($column->getType() == 'SmallInt') {
+					$length = '2';
+				}
+				elseif ($column->getType() == 'BigInt') {
+					$length = '8';
+				}
+				$xml->addChild('length', $length);
+				break;
+			case 'String':
+				$xml->addChild('type', 'text');
+				$default = trim($column->getDefault());
+				if ($default === '') {
+					$default = false;
+				}
+				$xml->addChild('default', $default);
+				$xml->addChild('notnull', self::toBool($column->getNotnull()));
+				$xml->addChild('length', $column->getLength());
+				break;
+			case 'Text':
+				$xml->addChild('type', 'clob');
+				$xml->addChild('notnull', self::toBool($column->getNotnull()));
+				break;
+			case 'Decimal':
+				$xml->addChild('type', 'decimal');
+				$xml->addChild('default', $column->getDefault());
+				$xml->addChild('notnull', self::toBool($column->getNotnull()));
+				$xml->addChild('length', '15');
+				break;
+			case 'Boolean':
+				$xml->addChild('type', 'integer');
+				$xml->addChild('default', $column->getDefault());
+				$xml->addChild('notnull', self::toBool($column->getNotnull()));
+				$xml->addChild('length', '1');
+				break;
+			case 'DateTime':
+				$xml->addChild('type', 'timestamp');
+				$xml->addChild('default', $column->getDefault());
+				$xml->addChild('notnull', self::toBool($column->getNotnull()));
+				break;
+
+		}
+	}
+
+	private static function saveIndex($index, $xml) {
+		$xml->addChild('name', $index->getName());
+		if ($index->isPrimary()) {
+			$xml->addChild('primary', 'true');
+		}
+		elseif ($index->isUnique()) {
+			$xml->addChild('unique', 'true');
+		}
+		foreach($index->getColumns() as $column) {
+			$field = $xml->addChild('field');
+			$field->addChild('name', $column);
+			$field->addChild('sorting', 'ascending');
+			
+		}
+	}
+
+	private static function toBool($bool) {
+		return $bool ? 'true' : 'false';
+	}
+}
diff --git a/lib/db/schema.php b/lib/db/schema.php
new file mode 100644
index 0000000000000000000000000000000000000000..fa053c64ef05c38b4d8fe4a26d4fecf491ce7ea3
--- /dev/null
+++ b/lib/db/schema.php
@@ -0,0 +1,136 @@
+<?php
+/**
+ * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+class OC_DB_Schema {
+	/**
+	 * @brief saves database scheme to xml file
+	 * @param \Doctrine\DBAL\Connection $conn
+	 * @param string $file name of file
+	 * @param int|string $mode
+	 * @return bool
+	 *
+	 * TODO: write more documentation
+	 */
+	public static function getDbStructure( $conn, $file, $mode=MDB2_SCHEMA_DUMP_STRUCTURE) {
+		$sm = $conn->getSchemaManager();
+
+		return OC_DB_MDB2SchemaWriter::saveSchemaToFile($file, $sm);
+	}
+
+	/**
+	 * @brief Creates tables from XML file
+	 * @param string $file file to read structure from
+	 * @return bool
+	 *
+	 * TODO: write more documentation
+	 */
+	public static function createDbFromStructure( $conn, $file ) {
+		$toSchema = OC_DB_MDB2SchemaReader::loadSchemaFromFile($file, $conn->getDatabasePlatform());
+		return self::executeSchemaChange($conn, $toSchema);
+	}
+
+	/**
+	 * @brief update the database scheme
+	 * @param string $file file to read structure from
+	 * @return bool
+	 */
+	public static function updateDbFromStructure($conn, $file) {
+		$sm = $conn->getSchemaManager();
+		$fromSchema = $sm->createSchema();
+
+		$toSchema = OC_DB_MDB2SchemaReader::loadSchemaFromFile($file, $conn->getDatabasePlatform());
+
+		// remove tables we don't know about
+		foreach($fromSchema->getTables() as $table) {
+			if (!$toSchema->hasTable($table->getName())) {
+				$fromSchema->dropTable($table->getName());
+			}
+		}
+		// remove sequences we don't know about
+		foreach($fromSchema->getSequences() as $table) {
+			if (!$toSchema->hasSequence($table->getName())) {
+				$fromSchema->dropSequence($table->getName());
+			}
+		}
+
+		$comparator = new \Doctrine\DBAL\Schema\Comparator();
+		$schemaDiff = $comparator->compare($fromSchema, $toSchema);
+
+		$platform = $conn->getDatabasePlatform();
+		$tables = $schemaDiff->newTables + $schemaDiff->changedTables + $schemaDiff->removedTables;
+		foreach($tables as $tableDiff) {
+			$tableDiff->name = $platform->quoteIdentifier($tableDiff->name);
+		}
+
+
+		//$from = $fromSchema->toSql($conn->getDatabasePlatform());
+		//$to = $toSchema->toSql($conn->getDatabasePlatform());
+		//echo($from[9]);
+		//echo '<br>';
+		//echo($to[9]);
+		//var_dump($from, $to);
+		return self::executeSchemaChange($conn, $schemaDiff);
+	}
+
+	/**
+	 * @brief drop a table
+	 * @param string $tableName the table to drop
+	 */
+	public static function dropTable($conn, $tableName) {
+		$sm = $conn->getSchemaManager();
+		$fromSchema = $sm->createSchema();
+		$toSchema = clone $fromSchema;
+		$toSchema->dropTable($tableName);
+		$sql = $fromSchema->getMigrateToSql($toSchema, $conn->getDatabasePlatform());
+		$conn->execute($sql);
+	}
+
+	/**
+	 * remove all tables defined in a database structure xml file
+	 * @param string $file the xml file describing the tables
+	 */
+	public static function removeDBStructure($conn, $file) {
+		$fromSchema = OC_DB_MDB2SchemaReader::loadSchemaFromFile($file, $conn->getDatabasePlatform());
+		$toSchema = clone $fromSchema;
+		foreach($toSchema->getTables() as $table) {
+			$toSchema->dropTable($table->getName());
+		}
+		$comparator = new \Doctrine\DBAL\Schema\Comparator();
+		$schemaDiff = $comparator->compare($fromSchema, $toSchema);
+		self::executeSchemaChange($conn, $schemaDiff);
+	}
+
+	/**
+	 * @brief replaces the ownCloud tables with a new set
+	 * @param $file string path to the MDB2 xml db export file
+	 */
+	public static function replaceDB( $conn, $file ) {
+		$apps = OC_App::getAllApps();
+		self::beginTransaction();
+		// Delete the old tables
+		self::removeDBStructure( $conn, OC::$SERVERROOT . '/db_structure.xml' );
+
+		foreach($apps as $app) {
+			$path = OC_App::getAppPath($app).'/appinfo/database.xml';
+			if(file_exists($path)) {
+				self::removeDBStructure( $conn, $path );
+			}
+		}
+
+		// Create new tables
+		self::commit();
+	}
+
+	private static function executeSchemaChange($conn, $schema) {
+		$conn->beginTransaction();
+		foreach($schema->toSql($conn->getDatabasePlatform()) as $sql) {
+			$conn->query($sql);
+		}
+		$conn->commit();
+	}
+}
diff --git a/lib/db/statementwrapper.php b/lib/db/statementwrapper.php
new file mode 100644
index 0000000000000000000000000000000000000000..f7bc45e068f8385fcbabbfee5602ddd4039fdcab
--- /dev/null
+++ b/lib/db/statementwrapper.php
@@ -0,0 +1,191 @@
+<?php
+/**
+ * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+/**
+ * small wrapper around \Doctrine\DBAL\Driver\Statement to make it behave, more like an MDB2 Statement
+ */
+class OC_DB_StatementWrapper {
+	/**
+	 * @var \Doctrine\DBAL\Driver\Statement
+	 */
+	private $statement = null;
+	private $isManipulation = false;
+	private $lastArguments = array();
+
+	public function __construct($statement, $isManipulation) {
+		$this->statement = $statement;
+		$this->isManipulation = $isManipulation;
+	}
+
+	/**
+	 * pass all other function directly to the \Doctrine\DBAL\Driver\Statement
+	 */
+	public function __call($name,$arguments) {
+		return call_user_func_array(array($this->statement,$name), $arguments);
+	}
+
+	/**
+	 * provide numRows
+	 */
+	public function numRows() {
+		$type = OC_Config::getValue( "dbtype", "sqlite" );
+		if ($type == 'oci') {
+			// OCI doesn't have a queryString, just do a rowCount for now
+			return $this->statement->rowCount();
+		}
+		$regex = '/^SELECT\s+(?:ALL\s+|DISTINCT\s+)?(?:.*?)\s+FROM\s+(.*)$/i';
+		$queryString = $this->statement->getWrappedStatement()->queryString;
+		if (preg_match($regex, $queryString, $output) > 0) {
+			$query = OC_DB::prepare("SELECT COUNT(*) FROM {$output[1]}");
+			return $query->execute($this->lastArguments)->fetchColumn();
+		}else{
+			return $this->statement->rowCount();
+		}
+	}
+
+	/**
+	 * make execute return the result instead of a bool
+	 */
+	public function execute($input=array()) {
+		if(OC_Config::getValue( "log_query", false)) {
+			$params_str = str_replace("\n"," ",var_export($input,true));
+			OC_Log::write('core', 'DB execute with arguments : '.$params_str, OC_Log::DEBUG);
+		}
+		$this->lastArguments = $input;
+		if (count($input) > 0) {
+
+			if (!isset($type)) {
+				$type = OC_Config::getValue( "dbtype", "sqlite" );
+			}
+
+			if ($type == 'mssql') {
+				$input = $this->tryFixSubstringLastArgumentDataForMSSQL($input);
+			}
+
+			$result = $this->statement->execute($input);
+		} else {
+			$result = $this->statement->execute();
+		}
+		
+		if ($result === false) {
+			return false;
+		}
+		if ($this->isManipulation) {
+			return $this->statement->rowCount();
+		} else {
+			return $this;
+		}
+	}
+
+	private function tryFixSubstringLastArgumentDataForMSSQL($input) {
+		$query = $this->statement->getWrappedStatement()->queryString;
+		$pos = stripos ($query, 'SUBSTRING');
+
+		if ( $pos === false) {
+			return $input;
+		}
+
+		try {
+			$newQuery = '';
+
+			$cArg = 0;
+
+			$inSubstring = false;
+
+			// Create new query
+			for ($i = 0; $i < strlen ($query); $i++) {
+				if ($inSubstring == false) {
+					// Defines when we should start inserting values
+					if (substr ($query, $i, 9) == 'SUBSTRING') {
+						$inSubstring = true;
+					}
+				} else {
+					// Defines when we should stop inserting values
+					if (substr ($query, $i, 1) == ')') {
+						$inSubstring = false;
+					}
+				}
+
+				if (substr ($query, $i, 1) == '?') {
+					// We found a question mark
+					if ($inSubstring) {
+						$newQuery .= $input[$cArg];
+
+						//
+						// Remove from input array
+						//
+						array_splice ($input, $cArg, 1);
+					} else {
+						$newQuery .= substr ($query, $i, 1);
+						$cArg++;
+					}
+				} else {
+					$newQuery .= substr ($query, $i, 1);
+				}
+			}
+
+			// The global data we need
+			$name = OC_Config::getValue( "dbname", "owncloud" );
+			$host = OC_Config::getValue( "dbhost", "" );
+			$user = OC_Config::getValue( "dbuser", "" );
+			$pass = OC_Config::getValue( "dbpassword", "" );
+			if (strpos($host,':')) {
+				list($host, $port) = explode(':', $host, 2);
+			} else {
+				$port = false;
+			}
+			$opts = array();
+
+			if ($port) {
+				$dsn = 'sqlsrv:Server='.$host.','.$port.';Database='.$name;
+			} else {
+				$dsn = 'sqlsrv:Server='.$host.';Database='.$name;
+			}
+
+			$PDO = new PDO($dsn, $user, $pass, $opts);
+			$PDO->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
+			$PDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+			$this->statement = $PDO->prepare($newQuery);
+
+			$this->lastArguments = $input;
+
+			return $input;
+		} catch (PDOException $e){
+			$entry = 'PDO DB Error: "'.$e->getMessage().'"<br />';
+			$entry .= 'Offending command was: '.$this->statement->queryString .'<br />';
+			$entry .= 'Input parameters: ' .print_r($input, true).'<br />';
+			$entry .= 'Stack trace: ' .$e->getTraceAsString().'<br />';
+			OC_Log::write('core', $entry, OC_Log::FATAL);
+			OC_User::setUserId(null);
+
+			// send http status 503
+			header('HTTP/1.1 503 Service Temporarily Unavailable');
+			header('Status: 503 Service Temporarily Unavailable');
+			OC_Template::printErrorPage('Failed to connect to database');
+			die ($entry);
+		}
+	}
+    
+	/**
+	 * provide an alias for fetch
+	 */
+	public function fetchRow() {
+		return $this->statement->fetch();
+	}
+
+	/**
+	 * Provide a simple fetchOne.
+	 * fetch single column from the next row
+	 * @param int $colnum the column number to fetch
+	 * @return string
+	 */
+	public function fetchOne($colnum = 0) {
+		return $this->statement->fetchColumn($colnum);
+	}
+}
diff --git a/tests/lib/db.php b/tests/lib/db.php
index 69e3542f9263f4a29cdf2b309cdb014fb6089464..e817a2db5edc3dd9ca53ccdfb0d6654be639f244 100644
--- a/tests/lib/db.php
+++ b/tests/lib/db.php
@@ -37,7 +37,7 @@ class Test_DB extends PHPUnit_Framework_TestCase {
 		$result = $query->execute(array('uri_1'));
 		$this->assertTrue((bool)$result);
 		$row = $result->fetchRow();
-		$this->assertFalse((bool)$row); //PDO returns false, MDB2 returns null
+		$this->assertFalse($row);
 		$query = OC_DB::prepare('INSERT INTO `*PREFIX*'.$this->table2.'` (`fullname`,`uri`) VALUES (?,?)');
 		$result = $query->execute(array('fullname test', 'uri_1'));
 		$this->assertEquals(1, $result);
@@ -94,7 +94,7 @@ class Test_DB extends PHPUnit_Framework_TestCase {
 		$query = OC_DB::prepare('SELECT * FROM `*PREFIX*'.$this->table3.'`');
 		$result = $query->execute();
 		$this->assertTrue((bool)$result);
-		$this->assertEquals(4, $result->numRows());
+		$this->assertEquals(4, count($result->fetchAll()));
 	}
 
 	public function testinsertIfNotExistDontOverwrite() {
diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php
index 830913a91ad991161d4cebcce871b63504fadca9..3bac9e770aa1b73fa81bd0b162a3c83618bdc8ce 100644
--- a/tests/lib/files/view.php
+++ b/tests/lib/files/view.php
@@ -20,10 +20,19 @@ class View extends \PHPUnit_Framework_TestCase {
 	private $storages = array();
 
 	public function setUp() {
+		\OC_User::clearBackends();
+		\OC_User::useBackend(new \OC_User_Dummy());
+
+		//login
+		\OC_User::createUser('test', 'test');
+		$this->user=\OC_User::getUser();
+		\OC_User::setUserId('test');
+
 		\OC\Files\Filesystem::clearMounts();
 	}
 
 	public function tearDown() {
+		\OC_User::setUserId($this->user);
 		foreach ($this->storages as $storage) {
 			$cache = $storage->getCache();
 			$ids = $cache->getAll();