diff --git a/lib/MDB2/Driver/Manager/sqlite3.php b/lib/MDB2/Driver/Manager/sqlite3.php
index c5c19a90fb52de158bf9bab7c318716809b39822..8f4e1312eb8f09faf456d22be3998a5ff490bd28 100644
--- a/lib/MDB2/Driver/Manager/sqlite3.php
+++ b/lib/MDB2/Driver/Manager/sqlite3.php
@@ -168,9 +168,6 @@ class MDB2_Driver_Manager_sqlite3 extends MDB2_Driver_Manager_Common
         if (PEAR::isError($query_fields)) {
             return $query_fields;
         }
-        if (!empty($options['primary'])) {
-            $query_fields.= ', PRIMARY KEY ('.implode(', ', array_keys($options['primary'])).')';
-        }
         if (!empty($options['foreign_keys'])) {
             foreach ($options['foreign_keys'] as $fkname => $fkdef) {
                 if (empty($fkdef)) {
@@ -534,9 +531,26 @@ class MDB2_Driver_Manager_sqlite3 extends MDB2_Driver_Manager_Common
             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);
 
-        // actually sqlite 2.x supports no ALTER TABLE at all .. so we emulate it
+        // for other operations we need to emulate them with sqlite3
         $fields = $db->manager->listTableFields($name);
         if (PEAR::isError($fields)) {
             return $fields;
@@ -636,44 +650,54 @@ class MDB2_Driver_Manager_sqlite3 extends MDB2_Driver_Manager_Common
             }
         }
 
+		//rename the old table so we can create the new one
+        $db->exec("ALTER TABLE $name RENAME TO __$name");
         $data = null;
-        if (!empty($select_fields)) {
-            $query = 'SELECT '.implode(', ', $select_fields).' FROM '.$db->quoteIdentifier($name, true);
-            $data = $db->queryAll($query, null, MDB2_FETCHMODE_ORDERED);
-        }
 
-        $result = $this->dropTable($name);
-        if (PEAR::isError($result)) {
-            return $result;
-        }
 
         $result = $this->createTable($name_new, $fields, $options);
         if (PEAR::isError($result)) {
             return $result;
         }
 
-        foreach ($indexes as $index => $definition) {
-            $this->createIndex($name_new, $index, $definition);
-        }
+        //these seem to only give errors
 
-        foreach ($constraints as $constraint => $definition) {
-            $this->createConstraint($name_new, $constraint, $definition);
-        }
+//         foreach ($indexes as $index => $definition) {
+//             $this->createIndex($name_new, $index, $definition);
+//         }
 
-        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;
-                }
-            }
+//         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;
     }
@@ -798,7 +822,7 @@ class MDB2_Driver_Manager_sqlite3 extends MDB2_Driver_Manager_Common
             return $db;
         }
 
-        $query = "SELECT name FROM sqlite_master WHERE type='table' AND sql NOT NULL ORDER BY name";
+        $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;
diff --git a/lib/MDB2/Driver/Reverse/sqlite3.php b/lib/MDB2/Driver/Reverse/sqlite3.php
index d5595da84c54a53dac0987247e7f99a636b07359..33e5b59026895181e1c029e4264d2e6b3984fc6f 100644
--- a/lib/MDB2/Driver/Reverse/sqlite3.php
+++ b/lib/MDB2/Driver/Reverse/sqlite3.php
@@ -69,7 +69,7 @@ class MDB2_Driver_Reverse_sqlite3 extends MDB2_Driver_Reverse_Common
             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)?( DEFAULT (\'[^\']*\'|[^ ]+))?( NULL| NOT NULL)?( PRIMARY KEY)?(\s*\-\-.*)?$/i';
+        $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)) {
@@ -90,11 +90,16 @@ class MDB2_Driver_Reverse_sqlite3 extends MDB2_Driver_Reverse_Common
             if (isset($matches[8]) && strlen($matches[8])) {
                 $columns[$j]['unsigned'] = true;
             }
-            if (isset($matches[9]) && strlen($matches[9])) {
+            if (isset($matches[10]) && strlen($matches[10])) {
                 $columns[$j]['autoincrement'] = true;
+                $columns[$j]['notnull']=true;
             }
-            if (isset($matches[12]) && strlen($matches[12])) {
-                $default = $matches[12];
+            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));
                 }
@@ -107,8 +112,8 @@ class MDB2_Driver_Reverse_sqlite3 extends MDB2_Driver_Reverse_Common
                 $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[13]) && strlen($matches[13])) {
-                $columns[$j]['notnull'] = ($matches[13] === ' NOT NULL');
+            } else if (isset($matches[14]) && strlen($matches[14])) {
+                $columns[$j]['notnull'] = ($matches[14] === ' NOT NULL');
             }
             ++$j;
         }
diff --git a/lib/app.php b/lib/app.php
index 1873e1136cd5ac6166eac2dab4ac7ee4e5f9d420..13c4cef32b41c5db59db6f890c799b2bb14302d6 100644
--- a/lib/app.php
+++ b/lib/app.php
@@ -371,4 +371,35 @@ class OC_App{
 		}
 		return $apps;
 	}
+	
+	/**
+	 * check if any apps need updating and update those
+	 */
+	public static function updateApps(){
+		// The rest comes here
+		$apps = OC_Appconfig::getApps();
+		foreach( $apps as $app ){
+			$installedVersion=OC_Appconfig::getValue($app,'installed_version');
+			$appInfo=OC_App::getAppInfo($app);
+			if (isset($appInfo['version'])) {
+				$currentVersion=$appInfo['version'];
+				if (version_compare($currentVersion, $installedVersion, '>')) {
+					OC_App::updateApp($app);
+				}
+			}
+		}
+	}
+	
+	/**
+	 * update the database for the app and call the update script
+	 * @param string appid
+	 */
+	public static function updateApp($appid){
+		if(file_exists(OC::$SERVERROOT.'/apps/'.$appid.'/appinfo/database.xml')){
+			OC_DB::updateDbFromStructure(OC::$SERVERROOT.'/apps/'.$appid.'/appinfo/database.xml');
+		}
+		if(file_exists(OC::$SERVERROOT.'/apps/'.$appid.'/appinfo/update.php')){
+			include OC::$SERVERROOT.'/apps/'.$appid.'/appinfo/update.php';
+		}
+	}
 }
diff --git a/lib/base.php b/lib/base.php
index 0954e3615bdb03b3e8cfb1de3b6570bc5660a225..c3965c9cd39683e7a6fc2a12dfc2f458bb2dc20e 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -152,6 +152,15 @@ class OC{
 			}
 		}
 
+		$installedVersion=OC_Config::getValue('version','0.0.0');
+		$currentVersion=implode('.',OC_Util::getVersion());
+		if (version_compare($currentVersion, $installedVersion, '>')) {
+			OC_DB::updateDbFromStructure('../db_structure.xml');
+			OC_Config::setValue('version',implode('.',OC_Util::getVersion()));
+		}
+
+		OC_App::updateApps();
+
 		ini_set('session.cookie_httponly','1;');
 		session_start();
 
@@ -230,8 +239,6 @@ if( !isset( $RUNTIME_NOAPPS )){
 	$RUNTIME_NOAPPS = false;
 }
 
-OC::init();
-
 if(!function_exists('get_temp_dir')) {
 	function get_temp_dir() {
 		if( $temp=ini_get('upload_tmp_dir') )        return $temp;
@@ -247,6 +254,8 @@ if(!function_exists('get_temp_dir')) {
 	}
 }
 
+OC::init();
+
 require_once('fakedirstream.php');
 
 
diff --git a/lib/db.php b/lib/db.php
index c7085a975ef663ab666ef5259221ee275b07400b..58a478ba0c03c28fedab13c531029987c13f6afd 100644
--- a/lib/db.php
+++ b/lib/db.php
@@ -71,7 +71,14 @@ class OC_DB {
 	/**
 	 * connect to the database using pdo
 	 */
-	private static function connectPDO(){
+	public static function connectPDO(){
+		if(self::$connection){
+			if(self::$backend==self::BACKEND_MDB2){
+				self::disconnect();
+			}else{
+				return;
+			}
+		}
 		// The global data we need
 		$name = OC_Config::getValue( "dbname", "owncloud" );
 		$host = OC_Config::getValue( "dbhost", "" );
@@ -113,7 +120,14 @@ class OC_DB {
 	/**
 	 * connect to the database using mdb2
 	 */
-	static private function connectMDB2(){
+	public static function connectMDB2(){
+		if(self::$connection){
+			if(self::$backend==self::BACKEND_PDO){
+				self::disconnect();
+			}else{
+				return;
+			}
+		}
 		// The global data we need
 		$name = OC_Config::getValue( "dbname", "owncloud" );
 		$host = OC_Config::getValue( "dbhost", "" );
@@ -255,8 +269,8 @@ class OC_DB {
 				self::$connection->disconnect();
 			}
 			self::$connection=false;
-			self::$mdb2=false;
-			self::$pdo=false;
+			self::$MDB2=false;
+			self::$PDO=false;
 		}
 
 		return true;
@@ -338,7 +352,6 @@ class OC_DB {
 	 * @param $file file to read structure from
 	 */
 	public static function updateDbFromStructure($file){
-		$CONFIG_DBNAME  = OC_Config::getValue( "dbname", "owncloud" );
 		$CONFIG_DBTABLEPREFIX = OC_Config::getValue( "dbtableprefix", "oc_" );
 		$CONFIG_DBTYPE = OC_Config::getValue( "dbtype", "sqlite" );
 
@@ -347,17 +360,17 @@ class OC_DB {
 		// read file
 		$content = file_get_contents( $file );
 		
+		$previousSchema = self::$schema->getDefinitionFromDatabase();
+
 		// 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( '*dbname*', $previousSchema['name'], $content );
 		$content = str_replace( '*dbprefix*', $CONFIG_DBTABLEPREFIX, $content );
 		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 );
-		$previousSchema = self::$schema->getDefinitionFromDatabase();
-		$op = $schema->updateDatabase($file2, $previousSchema, array(), false);
-
+		$op = self::$schema->updateDatabase($file2, $previousSchema, array(), false);
 		if (PEAR::isError($op)) {
 		    $error = $op->getMessage();
 		    OC_Log::write('core','Failed to update database structure ('.$error.')',OC_Log::FATAL);
@@ -375,6 +388,7 @@ class OC_DB {
 	private static function connectScheme(){
 		// We need a mdb2 database connection
 		self::connectMDB2();
+		self::$MDB2->loadModule('Manager');
 
 		// Connect if this did not happen before
 		if(!self::$schema){
diff --git a/lib/setup.php b/lib/setup.php
index b53c626c9a723fd6fa80470b5328990c307038cb..d454c17599dfb6f93136fabaee4c580016769fb6 100644
--- a/lib/setup.php
+++ b/lib/setup.php
@@ -160,8 +160,8 @@ class OC_Setup {
 
 						//add prefix to the postgresql user name to prevent collissions
 						$dbusername='oc_'.$username;
-						//hash the password so we don't need to store the admin config in the config file
-						$dbpassword=md5(time().$password);
+						//create a new password so we don't need to store the admin config in the config file
+						$dbpassword=md5(time());
 						
 						self::pg_createDBUser($dbusername, $dbpassword, $connection);
 						
@@ -221,7 +221,7 @@ class OC_Setup {
 	}
 
 	public static function createDatabase($name,$user,$connection) {
-		//we cant user OC_BD functions here because we need to connect as the administrative user.
+		//we cant use OC_BD functions here because we need to connect as the administrative user.
 		$query = "CREATE DATABASE IF NOT EXISTS  `$name`";
 		$result = mysql_query($query, $connection);
 		if(!$result) {
@@ -243,7 +243,7 @@ class OC_Setup {
 	}
 
 	public static function pg_createDatabase($name,$user,$connection) {
-		//we cant user OC_BD functions here because we need to connect as the administrative user.
+		//we cant use OC_BD functions here because we need to connect as the administrative user.
 		$query = "CREATE DATABASE $name OWNER $user";
 		$result = pg_query($connection, $query);
 		if(!$result) {