/** * @brief update the database scheme * @param string $file file to read structure from * @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(); if (PEAR::isError($previousSchema)) { $error = $previousSchema->getMessage(); $detail = $previousSchema->getDebugInfo(); $message = 'Failed to get existing database structure for updating (' . $error . ', ' . $detail . ')'; OC_Log::write('core', $message, OC_Log::FATAL); throw new Exception($message); } // 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); if (PEAR::isError($op)) { $error = $op->getMessage(); $detail = $op->getDebugInfo(); $message = 'Failed to update database structure (' . $error . ', ' . $detail . ')'; OC_Log::write('core', $message, OC_Log::FATAL); throw new Exception($message); } return true; }