From 3c85fb8c9a94d4856760a15ea98656a44976a8fa Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sat, 1 Oct 2016 21:40:41 -0400 Subject: [PATCH 01/11] Fix Issue #2816 - Change (P)Config::set to use INSERT >>> ON DUPLICATE KEY UPDATE - Add DB update --- include/Core/Config.php | 30 ++++++------------------------ include/Core/PConfig.php | 27 ++++++++------------------- update.php | 12 +++++++++++- 3 files changed, 25 insertions(+), 44 deletions(-) diff --git a/include/Core/Config.php b/include/Core/Config.php index 5703558cf3..e5515efafc 100644 --- a/include/Core/Config.php +++ b/include/Core/Config.php @@ -126,37 +126,19 @@ class Config { public static function set($family,$key,$value) { global $a; - // If $a->config[$family] has been previously set to '!!', then - // $a->config[$family][$key] will evaluate to $a->config[$family][0], and - // $a->config[$family][$key] = $value will be equivalent to - // $a->config[$family][0] = $value[0] (this causes infuriating bugs), - // so unset the family before assigning a value to a family's key - if($a->config[$family] === '!!') - unset($a->config[$family]); + $a->config[$family][$key] = $value; // manage array value $dbvalue = (is_array($value)?serialize($value):$value); $dbvalue = (is_bool($dbvalue) ? intval($dbvalue) : $dbvalue); - if(is_null(self::get($family,$key,null,true))) { - $a->config[$family][$key] = $value; - $ret = q("INSERT INTO `config` ( `cat`, `k`, `v` ) VALUES ( '%s', '%s', '%s' ) ", - dbesc($family), - dbesc($key), - dbesc($dbvalue) - ); - if($ret) - return $value; - return $ret; - } - $ret = q("UPDATE `config` SET `v` = '%s' WHERE `cat` = '%s' AND `k` = '%s'", - dbesc($dbvalue), + $ret = q("INSERT INTO `config` ( `cat`, `k`, `v` ) VALUES ( '%s', '%s', '%s' ) +ON DUPLICATE KEY UPDATE `v` = '%s'", dbesc($family), - dbesc($key) + dbesc($key), + dbesc($dbvalue), + dbesc($dbvalue) ); - - $a->config[$family][$key] = $value; - if($ret) return $value; return $ret; diff --git a/include/Core/PConfig.php b/include/Core/PConfig.php index 2bc08667a7..082f1c05c2 100644 --- a/include/Core/PConfig.php +++ b/include/Core/PConfig.php @@ -126,27 +126,16 @@ class PConfig { // manage array value $dbvalue = (is_array($value)?serialize($value):$value); - if(is_null(self::get($uid,$family,$key,null, true))) { - $a->config[$uid][$family][$key] = $value; - $ret = q("INSERT INTO `pconfig` ( `uid`, `cat`, `k`, `v` ) VALUES ( %d, '%s', '%s', '%s' ) ", - intval($uid), - dbesc($family), - dbesc($key), - dbesc($dbvalue) - ); - if($ret) - return $value; - return $ret; - } - $ret = q("UPDATE `pconfig` SET `v` = '%s' WHERE `uid` = %d AND `cat` = '%s' AND `k` = '%s'", - dbesc($dbvalue), - intval($uid), - dbesc($family), - dbesc($key) - ); - $a->config[$uid][$family][$key] = $value; + $ret = q("INSERT INTO `pconfig` ( `uid`, `cat`, `k`, `v` ) VALUES ( %d, '%s', '%s', '%s' ) +ON DUPLICATE KEY UPDATE `v` = '%s'", + intval($uid), + dbesc($family), + dbesc($key), + dbesc($dbvalue), + dbesc($dbvalue) + ); if($ret) return $value; return $ret; diff --git a/update.php b/update.php index 31f7852a2f..55db8bca9c 100644 --- a/update.php +++ b/update.php @@ -1677,7 +1677,7 @@ function update_1190() { $idx = array_search($plugin, $plugins_arr); if ($idx !== false){ unset($plugins_arr[$idx]); - //delete forumlist manually from addon and hook table + //delete forumlist manually from addon and hook table // since uninstall_plugin() don't work here q("DELETE FROM `addon` WHERE `name` = 'forumlist' "); q("DELETE FROM `hook` WHERE `file` = 'addon/forumlist/forumlist.php' "); @@ -1728,3 +1728,13 @@ function update_1202() { $r = q("UPDATE `user` SET `account-type` = %d WHERE `page-flags` IN (%d, %d)", dbesc(ACCOUNT_TYPE_COMMUNITY), dbesc(PAGE_COMMUNITY), dbesc(PAGE_PRVGROUP)); } + +function update_1210() { + // Convert config indexes to unique, old_alter_table=1 removes duplicates on ALTER IGNORE + $r = q("SET session old_alter_table=1;"); + $r = q("ALTER TABLE config DROP INDEX cat_k"); + $r = q("ALTER IGNORE TABLE config ADD UNIQUE INDEX cat_k (cat, k)"); + + $r = q("ALTER TABLE pconfig DROP INDEX uid_cat_k"); + $r = q("ALTER IGNORE TABLE pconfig ADD UNIQUE INDEX uid_cat_k (uid, cat, k)"); +} \ No newline at end of file From 3f619726b131296106459544852692aaa54ae7eb Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sat, 1 Oct 2016 23:29:30 -0400 Subject: [PATCH 02/11] Fix Issue #2816 - Update dbstructure instead of update - Add UNIQUE index support to `update_structure()` - Move DB update from `update.php` to `dbstructure.php` - Update DB_VERSION to 1210 --- boot.php | 72 ++++++++++++++++++++--------------------- include/dbstructure.php | 30 +++++++++++++---- update.php | 12 +------ 3 files changed, 61 insertions(+), 53 deletions(-) diff --git a/boot.php b/boot.php index ea14428fd0..97e0c8b367 100644 --- a/boot.php +++ b/boot.php @@ -38,7 +38,7 @@ define ( 'FRIENDICA_PLATFORM', 'Friendica'); define ( 'FRIENDICA_CODENAME', 'Asparagus'); define ( 'FRIENDICA_VERSION', '3.5.1-dev' ); define ( 'DFRN_PROTOCOL_VERSION', '2.23' ); -define ( 'DB_UPDATE_VERSION', 1203 ); +define ( 'DB_UPDATE_VERSION', 1210 ); /** * @brief Constant with a HTML line break. @@ -53,7 +53,7 @@ define ( 'ATOM_TIME', 'Y-m-d\TH:i:s\Z' ); /** * @brief Image storage quality. - * + * * Lower numbers save space at cost of image detail. * For ease of upgrade, please do not change here. Change jpeg quality with * $a->config['system']['jpeg_quality'] = n; @@ -95,7 +95,7 @@ define ( 'DEFAULT_DB_ENGINE', 'MyISAM' ); /** * @name SSL Policy - * + * * SSL redirection policies * @{ */ @@ -106,7 +106,7 @@ define ( 'SSL_POLICY_SELFSIGN', 2 ); /** * @name Logger - * + * * log levels * @{ */ @@ -119,7 +119,7 @@ define ( 'LOGGER_ALL', 4 ); /** * @name Cache - * + * * Cache levels * @{ */ @@ -131,7 +131,7 @@ define ( 'CACHE_HOUR', 3 ); /** * @name Register - * + * * Registration policies * @{ */ @@ -142,7 +142,7 @@ define ( 'REGISTER_OPEN', 2 ); /** * @name Contact_is - * + * * Relationship types * @{ */ @@ -153,7 +153,7 @@ define ( 'CONTACT_IS_FRIEND', 3); /** * @name Update - * + * * DB update return values * @{ */ @@ -205,7 +205,7 @@ define ( 'ACCOUNT_TYPE_COMMUNITY', 3 ); /** * @name CP - * + * * Type of the community page * @{ */ @@ -216,7 +216,7 @@ define ( 'CP_GLOBAL_COMMUNITY', 1 ); /** * @name Network - * + * * Network and protocol family types * @{ */ @@ -288,7 +288,7 @@ define ( 'ZCURL_TIMEOUT' , (-1)); /** * @name Notify - * + * * Email notification options * @{ */ @@ -310,7 +310,7 @@ define ( 'NOTIFY_SYSTEM', 0x8000 ); /** * @name Term - * + * * Tag/term types * @{ */ @@ -330,7 +330,7 @@ define ( 'TERM_OBJ_PHOTO', 2 ); /** * @name Namespaces - * + * * Various namespaces we may need to parse * @{ */ @@ -353,7 +353,7 @@ define ( 'NAMESPACE_ATOM1', 'http://www.w3.org/2005/Atom' ); /** * @name Activity - * + * * Activity stream defines * @{ */ @@ -399,7 +399,7 @@ define ( 'ACTIVITY_OBJ_QUESTION', 'http://activityschema.org/object/question' ); /** * @name Gravity - * + * * Item weight for query ordering * @{ */ @@ -466,9 +466,9 @@ function startup() { /** * * class: App - * + * * @brief Our main application structure for the life of this page. - * + * * Primarily deals with the URL that got us here * and tries to make some sense of it, and * stores our page contents and config storage @@ -1015,9 +1015,9 @@ class App { /** * @brief Register template engine class - * + * * If $name is "", is used class static property $class::$name - * + * * @param string $class * @param string $name */ @@ -1035,7 +1035,7 @@ class App { /** * @brief Return template engine instance. - * + * * If $name is not defined, return engine defined by theme, * or default * @@ -1358,7 +1358,7 @@ class App { /** * @brief Retrieve the App structure - * + * * Useful in functions which require it but don't get it passed to them */ function get_app() { @@ -1612,7 +1612,7 @@ function run_update_function($x) { * and mark it uninstalled in the database (for now we'll remove it). * Then go through the config list and if we have a plugin that isn't installed, * call the install procedure and add it to the database. - * + * * @param App $a * */ @@ -1678,17 +1678,17 @@ function get_guid($size=16, $prefix = "") { } } -/** +/** * @brief Wrapper for adding a login box. - * + * * @param bool $register * If $register == true provide a registration link. * This will most always depend on the value of $a->config['register_policy']. * @param bool $hiddens - * + * * @return string * Returns the complete html for inserting into the page - * + * * @hooks 'login_hook' * string $o */ @@ -1778,7 +1778,7 @@ function goaway($s) { /** * @brief Returns the user id of locally logged in user or false. - * + * * @return int|bool user id or false */ function local_user() { @@ -1789,7 +1789,7 @@ function local_user() { /** * @brief Returns contact id of authenticated site visitor or false - * + * * @return int|bool visitor_id or false */ function remote_user() { @@ -1846,13 +1846,13 @@ function get_max_import_size() { * so plugins can take part in process :) * * @param (string|integer) $cmd program to run or priority - * + * * next args are passed as $cmd command line * e.g.: proc_run("ls","-la","/tmp"); * or: proc_run(PRIORITY_HIGH, "include/notifier.php", "drop", $drop_id); * * @note $cmd and string args are surrounded with "" - * + * * @hooks 'proc_run' * array $arr */ @@ -2011,9 +2011,9 @@ function current_theme(){ /** * @brief Return full URL to theme which is currently in effect. - * + * * Provide a sane default if nothing is chosen or the specified theme does not exist. - * + * * @return string */ function current_theme_url() { @@ -2360,7 +2360,7 @@ function current_load() { /** * @brief get c-style args - * + * * @return int */ function argc() { @@ -2369,7 +2369,7 @@ function argc() { /** * @brief Returns the value of a argv key - * + * * @param int $x argv key * @return string Value of the argv key */ @@ -2382,12 +2382,12 @@ function argv($x) { /** * @brief Get the data which is needed for infinite scroll - * + * * For invinite scroll we need the page number of the actual page * and the the URI where the content of the next page comes from. * This data is needed for the js part in main.js. * Note: infinite scroll does only work for the network page (module) - * + * * @param string $module The name of the module (e.g. "network") * @return array Of infinite scroll data * 'pageno' => $pageno The number of the actual page diff --git a/include/dbstructure.php b/include/dbstructure.php index 0c933c6648..f5a1d4fde4 100644 --- a/include/dbstructure.php +++ b/include/dbstructure.php @@ -78,6 +78,10 @@ function table_structure($table) { if ($index["Index_type"] == "FULLTEXT") continue; + if ($index['Key_name'] != 'PRIMARY' && $index['Non_unique'] == '0' && !isset($indexdata[$index["Key_name"]])) { + $indexdata[$index["Key_name"]] = array('UNIQUE'); + } + $column = $index["Column_name"]; // On utf8mb4 a varchar index can only have a length of 191 // To avoid the need to add this to every index definition we just ignore it here. @@ -151,6 +155,12 @@ function update_structure($verbose, $action, $tables=null, $definition=null) { if (is_null($definition)) $definition = db_definition($charset); + // Ensure index conversion to unique removes duplicates + $sql_config = "SET session old_alter_table=1;"; + if ($verbose) + echo $sql_config."\n"; + if ($action) + @$db->q($sql_config); // Compare it foreach ($definition AS $name => $structure) { @@ -176,7 +186,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) { if ($current_index_definition != $new_index_definition && substr($indexname, 0, 6) != 'local_') { $sql2=db_drop_index($indexname); if ($sql3 == "") - $sql3 = "ALTER TABLE `".$name."` ".$sql2; + $sql3 = "ALTER IGNORE TABLE `".$name."` ".$sql2; else $sql3 .= ", ".$sql2; } @@ -186,7 +196,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) { if (!isset($database[$name]["fields"][$fieldname])) { $sql2=db_add_table_field($fieldname, $parameters); if ($sql3 == "") - $sql3 = "ALTER TABLE `".$name."` ".$sql2; + $sql3 = "ALTER IGNORE TABLE `".$name."` ".$sql2; else $sql3 .= ", ".$sql2; } else { @@ -196,7 +206,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) { if ($current_field_definition != $new_field_definition) { $sql2=db_modify_table_field($fieldname, $parameters); if ($sql3 == "") - $sql3 = "ALTER TABLE `".$name."` ".$sql2; + $sql3 = "ALTER IGNORE TABLE `".$name."` ".$sql2; else $sql3 .= ", ".$sql2; } @@ -220,7 +230,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) { $sql2=db_create_index($indexname, $fieldnames); if ($sql2 != "") { if ($sql3 == "") - $sql3 = "ALTER TABLE `".$name."` ".$sql2; + $sql3 = "ALTER IGNORE TABLE `".$name."` ".$sql2; else $sql3 .= ", ".$sql2; } @@ -324,6 +334,11 @@ function db_create_index($indexname, $fieldnames, $method="ADD") { killme(); } + if ($fieldnames[0] == "UNIQUE") { + array_shift($fieldnames); + $method .= ' UNIQUE'; + } + $names = ""; foreach ($fieldnames AS $fieldname) { if ($names != "") @@ -451,7 +466,7 @@ function db_definition($charset) { ), "indexes" => array( "PRIMARY" => array("id"), - "cat_k" => array("cat(30)","k(30)"), + "cat_k" => array("UNIQUE", "cat(30)","k(30)"), ) ); $database["contact"] = array( @@ -1060,7 +1075,7 @@ function db_definition($charset) { ), "indexes" => array( "PRIMARY" => array("id"), - "uid_cat_k" => array("uid","cat(30)","k(30)"), + "uid_cat_k" => array("UNIQUE", "uid","cat(30)","k(30)"), ) ); $database["photo"] = array( @@ -1484,6 +1499,9 @@ function dbstructure_run(&$argv, &$argc) { if ($argc==2) { switch ($argv[1]) { + case "dryrun": + update_structure(true, false); + return; case "update": update_structure(true, true); set_config('system','build',DB_UPDATE_VERSION); diff --git a/update.php b/update.php index 55db8bca9c..3315beea24 100644 --- a/update.php +++ b/update.php @@ -1,6 +1,6 @@ Date: Sun, 2 Oct 2016 00:23:11 -0400 Subject: [PATCH 03/11] Fix Issue #2816 - Update database.sql --- database.sql | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/database.sql b/database.sql index ecd2be1529..155feb6706 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 3.5.1-dev (Asparagus) --- DB_UPDATE_VERSION 1203 +-- DB_UPDATE_VERSION 1210 -- ------------------------------------------ @@ -58,7 +58,7 @@ CREATE TABLE IF NOT EXISTS `cache` ( `v` text, `expire_mode` int(11) NOT NULL DEFAULT 0, `updated` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', - PRIMARY KEY(`k`), + PRIMARY KEY(`k`(191)), INDEX `updated` (`updated`) ) DEFAULT CHARSET=utf8mb4; @@ -97,7 +97,7 @@ CREATE TABLE IF NOT EXISTS `config` ( `k` varchar(255) NOT NULL DEFAULT '', `v` text, PRIMARY KEY(`id`), - INDEX `cat_k` (`cat`(30),`k`(30)) + UNIQUE INDEX `cat_k` (`cat`(30),`k`(30)) ) DEFAULT CHARSET=utf8mb4; -- @@ -679,7 +679,7 @@ CREATE TABLE IF NOT EXISTS `oembed` ( `url` varchar(255) NOT NULL, `content` text, `created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', - PRIMARY KEY(`url`), + PRIMARY KEY(`url`(191)), INDEX `created` (`created`) ) DEFAULT CHARSET=utf8mb4; @@ -692,7 +692,7 @@ CREATE TABLE IF NOT EXISTS `parsed_url` ( `oembed` tinyint(1) NOT NULL DEFAULT 0, `content` text, `created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', - PRIMARY KEY(`url`,`guessing`,`oembed`), + PRIMARY KEY(`url`(191),`guessing`,`oembed`), INDEX `created` (`created`) ) DEFAULT CHARSET=utf8mb4; @@ -706,7 +706,7 @@ CREATE TABLE IF NOT EXISTS `pconfig` ( `k` varchar(255) NOT NULL DEFAULT '', `v` mediumtext, PRIMARY KEY(`id`), - INDEX `uid_cat_k` (`uid`,`cat`(30),`k`(30)) + UNIQUE INDEX `uid_cat_k` (`uid`,`cat`(30),`k`(30)) ) DEFAULT CHARSET=utf8mb4; -- From 72521cd9c8b38475a990d3c0631d053029dd57f4 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 2 Oct 2016 13:16:31 -0400 Subject: [PATCH 04/11] Fix Issue #2816 - Change new database version number --- boot.php | 2 +- update.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/boot.php b/boot.php index 97e0c8b367..4970574635 100644 --- a/boot.php +++ b/boot.php @@ -38,7 +38,7 @@ define ( 'FRIENDICA_PLATFORM', 'Friendica'); define ( 'FRIENDICA_CODENAME', 'Asparagus'); define ( 'FRIENDICA_VERSION', '3.5.1-dev' ); define ( 'DFRN_PROTOCOL_VERSION', '2.23' ); -define ( 'DB_UPDATE_VERSION', 1210 ); +define ( 'DB_UPDATE_VERSION', 1204 ); /** * @brief Constant with a HTML line break. diff --git a/update.php b/update.php index 3315beea24..b659336abf 100644 --- a/update.php +++ b/update.php @@ -1,6 +1,6 @@ Date: Mon, 3 Oct 2016 19:06:47 -0400 Subject: [PATCH 05/11] Fix Issue #2816 - Add MySQL version condition for IGNORE - Checks for MySQL version before adding the IGNORE keyword on index creation - Added new dryrun command to usage text --- include/dbstructure.php | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/include/dbstructure.php b/include/dbstructure.php index 11b5ded896..6d9485b6e2 100644 --- a/include/dbstructure.php +++ b/include/dbstructure.php @@ -165,6 +165,13 @@ function update_structure($verbose, $action, $tables=null, $definition=null) { if ($action) @$db->q($sql_config); + // MySQL >= 5.7 doesn't support the IGNORE keyword in ALTER TABLE statements + if (version_compare($db->getdb()->server_info, '5.7') >= 0) { + $ignore = ''; + }else { + $ignore = ' IGNORE'; + } + // Compare it foreach ($definition AS $name => $structure) { $is_new_table = False; @@ -189,7 +196,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) { if ($current_index_definition != $new_index_definition && substr($indexname, 0, 6) != 'local_') { $sql2=db_drop_index($indexname); if ($sql3 == "") - $sql3 = "ALTER IGNORE TABLE `".$name."` ".$sql2; + $sql3 = "ALTER TABLE `".$name."` ".$sql2; else $sql3 .= ", ".$sql2; } @@ -199,7 +206,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) { if (!isset($database[$name]["fields"][$fieldname])) { $sql2=db_add_table_field($fieldname, $parameters); if ($sql3 == "") - $sql3 = "ALTER IGNORE TABLE `".$name."` ".$sql2; + $sql3 = "ALTER TABLE `".$name."` ".$sql2; else $sql3 .= ", ".$sql2; } else { @@ -209,7 +216,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) { if ($current_field_definition != $new_field_definition) { $sql2=db_modify_table_field($fieldname, $parameters); if ($sql3 == "") - $sql3 = "ALTER IGNORE TABLE `".$name."` ".$sql2; + $sql3 = "ALTER TABLE `".$name."` ".$sql2; else $sql3 .= ", ".$sql2; } @@ -233,7 +240,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) { $sql2=db_create_index($indexname, $fieldnames); if ($sql2 != "") { if ($sql3 == "") - $sql3 = "ALTER IGNORE TABLE `".$name."` ".$sql2; + $sql3 = "ALTER" . $ignore . " TABLE `".$name."` ".$sql2; else $sql3 .= ", ".$sql2; } @@ -1524,7 +1531,8 @@ function dbstructure_run(&$argv, &$argc) { // print help echo $argv[0]." \n"; echo "\n"; - echo "commands:\n"; + echo "Commands:\n"; + echo "dryrun show database update schema queries without running them\n"; echo "update update database schema\n"; echo "dumpsql dump database schema\n"; return; From a052fe4a98daa10be1656120ec0eb268f3113ecd Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Mon, 3 Oct 2016 19:17:40 -0400 Subject: [PATCH 06/11] Fix Issue #2816 - MySQL version typo --- include/dbstructure.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/dbstructure.php b/include/dbstructure.php index 6d9485b6e2..9e0020fdbe 100644 --- a/include/dbstructure.php +++ b/include/dbstructure.php @@ -165,8 +165,8 @@ function update_structure($verbose, $action, $tables=null, $definition=null) { if ($action) @$db->q($sql_config); - // MySQL >= 5.7 doesn't support the IGNORE keyword in ALTER TABLE statements - if (version_compare($db->getdb()->server_info, '5.7') >= 0) { + // MySQL >= 5.7.4 doesn't support the IGNORE keyword in ALTER TABLE statements + if (version_compare($db->getdb()->server_info, '5.7.4') >= 0) { $ignore = ''; }else { $ignore = ' IGNORE'; From c1611fd3f6b572f17eec04c113272a76667fdad7 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Tue, 4 Oct 2016 23:43:44 -0400 Subject: [PATCH 07/11] Fix Issue #2816 - Add backward compatible server_info support --- include/dba.php | 16 ++++++++++++++++ include/dbstructure.php | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/include/dba.php b/include/dba.php index 97f6c87956..9ccdcd1304 100644 --- a/include/dba.php +++ b/include/dba.php @@ -91,6 +91,22 @@ class dba { return $this->db; } + /** Returns the MySQL server version string + * + * This function discriminate between the deprecated mysql API and the current + * object-oriented mysqli API. Example of returned string: 5.5.46-0+deb8u1 + * + * @return string + */ + public function server_info() { + if ($this->mysqli) { + $return = $this->db->server_info; + } else { + $return = mysql_get_server_info($this->db); + } + return $return; + } + public function q($sql, $onlyquery = false) { global $a; diff --git a/include/dbstructure.php b/include/dbstructure.php index 9e0020fdbe..d3b148b2a8 100644 --- a/include/dbstructure.php +++ b/include/dbstructure.php @@ -166,7 +166,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) { @$db->q($sql_config); // MySQL >= 5.7.4 doesn't support the IGNORE keyword in ALTER TABLE statements - if (version_compare($db->getdb()->server_info, '5.7.4') >= 0) { + if (version_compare($db->server_info(), '5.7.4') >= 0) { $ignore = ''; }else { $ignore = ' IGNORE'; From fe17ce215087eca25204719efbd922c5dd0423de Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Wed, 5 Oct 2016 16:39:37 -0400 Subject: [PATCH 08/11] Add upgrade documentation --- doc/upgrade.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 doc/upgrade.md diff --git a/doc/upgrade.md b/doc/upgrade.md new file mode 100644 index 0000000000..778f9355e6 --- /dev/null +++ b/doc/upgrade.md @@ -0,0 +1,34 @@ +# Considerations before upgrading Friendica + +* [Home](help) + +## MySQL >= 5.7.4 + +Starting from MySQL version 5.7.4, the IGNORE keyword in ALTER TABLE statements is ignored. +This prevents automatic table deduplication if a UNIQUE index is added to a Friendica table's structure. +If a DB update fails for you while creating a UNIQUE index, make sure to manually deduplicate the table before trying the update again. + +### Manual deduplication + +There are two main ways of doing it, either by manually removing the duplicates or by recreating the table. +Manually removing the duplicates is usually faster if they're not too numerous. +To manually remove the duplicates, you need to know the UNIQUE index columns available in `database.sql`. + +```SQL +SELECT GROUP_CONCAT(id), , count(*) as count FROM users +GROUP BY HAVING count >= 2; + +/* delete or merge duplicate from above query */; +``` + +If there are too many rows to handle manually, you can create a new table with the same structure as the table with duplicates and insert the existing content with INSERT IGNORE. +To recreate the table you need to know the table structure available in `database.sql`. + +```SQL +CREATE TABLE _new ; +INSERT IGNORE INTO _new SELECT * FROM ; +DROP TABLE ; +RENAME TABLE _new TO ; +``` + +This method is slower overall, but it is better suited for large numbers of duplicates. \ No newline at end of file From 3e46c69bf6198ff3444c24eaa4491ced97f46e40 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Wed, 5 Oct 2016 16:40:54 -0400 Subject: [PATCH 09/11] Fix wrong database version number in comment --- database.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database.sql b/database.sql index 155feb6706..b7b21ff629 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 3.5.1-dev (Asparagus) --- DB_UPDATE_VERSION 1210 +-- DB_UPDATE_VERSION 1204 -- ------------------------------------------ From b8d6dc591227e510771eb6fc68853c258b57ebbf Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Thu, 6 Oct 2016 21:01:25 -0400 Subject: [PATCH 10/11] Fix Issue #2816 - Bump database version --- boot.php | 2 +- database.sql | 2 +- update.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/boot.php b/boot.php index 4970574635..348b786e4d 100644 --- a/boot.php +++ b/boot.php @@ -38,7 +38,7 @@ define ( 'FRIENDICA_PLATFORM', 'Friendica'); define ( 'FRIENDICA_CODENAME', 'Asparagus'); define ( 'FRIENDICA_VERSION', '3.5.1-dev' ); define ( 'DFRN_PROTOCOL_VERSION', '2.23' ); -define ( 'DB_UPDATE_VERSION', 1204 ); +define ( 'DB_UPDATE_VERSION', 1205 ); /** * @brief Constant with a HTML line break. diff --git a/database.sql b/database.sql index c880e70bf4..f12746e7e5 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 3.5.1-dev (Asparagus) --- DB_UPDATE_VERSION 1204 +-- DB_UPDATE_VERSION 1205 -- ------------------------------------------ diff --git a/update.php b/update.php index b659336abf..01fa220673 100644 --- a/update.php +++ b/update.php @@ -1,6 +1,6 @@ Date: Fri, 7 Oct 2016 08:33:13 -0400 Subject: [PATCH 11/11] Improve comment --- include/dba.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/dba.php b/include/dba.php index 9ccdcd1304..86a3762b44 100644 --- a/include/dba.php +++ b/include/dba.php @@ -91,8 +91,9 @@ class dba { return $this->db; } - /** Returns the MySQL server version string - * + /** + * @brief Returns the MySQL server version string + * * This function discriminate between the deprecated mysql API and the current * object-oriented mysqli API. Example of returned string: 5.5.46-0+deb8u1 *