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
This commit is contained in:
Hypolite Petovan 2016-10-01 23:29:30 -04:00
parent 3c85fb8c9a
commit 3f619726b1
3 changed files with 61 additions and 53 deletions

View file

@ -38,7 +38,7 @@ define ( 'FRIENDICA_PLATFORM', 'Friendica');
define ( 'FRIENDICA_CODENAME', 'Asparagus'); define ( 'FRIENDICA_CODENAME', 'Asparagus');
define ( 'FRIENDICA_VERSION', '3.5.1-dev' ); define ( 'FRIENDICA_VERSION', '3.5.1-dev' );
define ( 'DFRN_PROTOCOL_VERSION', '2.23' ); define ( 'DFRN_PROTOCOL_VERSION', '2.23' );
define ( 'DB_UPDATE_VERSION', 1203 ); define ( 'DB_UPDATE_VERSION', 1210 );
/** /**
* @brief Constant with a HTML line break. * @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. * @brief Image storage quality.
* *
* Lower numbers save space at cost of image detail. * Lower numbers save space at cost of image detail.
* For ease of upgrade, please do not change here. Change jpeg quality with * For ease of upgrade, please do not change here. Change jpeg quality with
* $a->config['system']['jpeg_quality'] = n; * $a->config['system']['jpeg_quality'] = n;
@ -95,7 +95,7 @@ define ( 'DEFAULT_DB_ENGINE', 'MyISAM' );
/** /**
* @name SSL Policy * @name SSL Policy
* *
* SSL redirection policies * SSL redirection policies
* @{ * @{
*/ */
@ -106,7 +106,7 @@ define ( 'SSL_POLICY_SELFSIGN', 2 );
/** /**
* @name Logger * @name Logger
* *
* log levels * log levels
* @{ * @{
*/ */
@ -119,7 +119,7 @@ define ( 'LOGGER_ALL', 4 );
/** /**
* @name Cache * @name Cache
* *
* Cache levels * Cache levels
* @{ * @{
*/ */
@ -131,7 +131,7 @@ define ( 'CACHE_HOUR', 3 );
/** /**
* @name Register * @name Register
* *
* Registration policies * Registration policies
* @{ * @{
*/ */
@ -142,7 +142,7 @@ define ( 'REGISTER_OPEN', 2 );
/** /**
* @name Contact_is * @name Contact_is
* *
* Relationship types * Relationship types
* @{ * @{
*/ */
@ -153,7 +153,7 @@ define ( 'CONTACT_IS_FRIEND', 3);
/** /**
* @name Update * @name Update
* *
* DB update return values * DB update return values
* @{ * @{
*/ */
@ -205,7 +205,7 @@ define ( 'ACCOUNT_TYPE_COMMUNITY', 3 );
/** /**
* @name CP * @name CP
* *
* Type of the community page * Type of the community page
* @{ * @{
*/ */
@ -216,7 +216,7 @@ define ( 'CP_GLOBAL_COMMUNITY', 1 );
/** /**
* @name Network * @name Network
* *
* Network and protocol family types * Network and protocol family types
* @{ * @{
*/ */
@ -288,7 +288,7 @@ define ( 'ZCURL_TIMEOUT' , (-1));
/** /**
* @name Notify * @name Notify
* *
* Email notification options * Email notification options
* @{ * @{
*/ */
@ -310,7 +310,7 @@ define ( 'NOTIFY_SYSTEM', 0x8000 );
/** /**
* @name Term * @name Term
* *
* Tag/term types * Tag/term types
* @{ * @{
*/ */
@ -330,7 +330,7 @@ define ( 'TERM_OBJ_PHOTO', 2 );
/** /**
* @name Namespaces * @name Namespaces
* *
* Various namespaces we may need to parse * Various namespaces we may need to parse
* @{ * @{
*/ */
@ -353,7 +353,7 @@ define ( 'NAMESPACE_ATOM1', 'http://www.w3.org/2005/Atom' );
/** /**
* @name Activity * @name Activity
* *
* Activity stream defines * Activity stream defines
* @{ * @{
*/ */
@ -399,7 +399,7 @@ define ( 'ACTIVITY_OBJ_QUESTION', 'http://activityschema.org/object/question' );
/** /**
* @name Gravity * @name Gravity
* *
* Item weight for query ordering * Item weight for query ordering
* @{ * @{
*/ */
@ -466,9 +466,9 @@ function startup() {
/** /**
* *
* class: App * class: App
* *
* @brief Our main application structure for the life of this page. * @brief Our main application structure for the life of this page.
* *
* Primarily deals with the URL that got us here * Primarily deals with the URL that got us here
* and tries to make some sense of it, and * and tries to make some sense of it, and
* stores our page contents and config storage * stores our page contents and config storage
@ -1015,9 +1015,9 @@ class App {
/** /**
* @brief Register template engine class * @brief Register template engine class
* *
* If $name is "", is used class static property $class::$name * If $name is "", is used class static property $class::$name
* *
* @param string $class * @param string $class
* @param string $name * @param string $name
*/ */
@ -1035,7 +1035,7 @@ class App {
/** /**
* @brief Return template engine instance. * @brief Return template engine instance.
* *
* If $name is not defined, return engine defined by theme, * If $name is not defined, return engine defined by theme,
* or default * or default
* *
@ -1358,7 +1358,7 @@ class App {
/** /**
* @brief Retrieve the App structure * @brief Retrieve the App structure
* *
* Useful in functions which require it but don't get it passed to them * Useful in functions which require it but don't get it passed to them
*/ */
function get_app() { 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). * 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, * 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. * call the install procedure and add it to the database.
* *
* @param App $a * @param App $a
* *
*/ */
@ -1678,17 +1678,17 @@ function get_guid($size=16, $prefix = "") {
} }
} }
/** /**
* @brief Wrapper for adding a login box. * @brief Wrapper for adding a login box.
* *
* @param bool $register * @param bool $register
* If $register == true provide a registration link. * If $register == true provide a registration link.
* This will most always depend on the value of $a->config['register_policy']. * This will most always depend on the value of $a->config['register_policy'].
* @param bool $hiddens * @param bool $hiddens
* *
* @return string * @return string
* Returns the complete html for inserting into the page * Returns the complete html for inserting into the page
* *
* @hooks 'login_hook' * @hooks 'login_hook'
* string $o * string $o
*/ */
@ -1778,7 +1778,7 @@ function goaway($s) {
/** /**
* @brief Returns the user id of locally logged in user or false. * @brief Returns the user id of locally logged in user or false.
* *
* @return int|bool user id or false * @return int|bool user id or false
*/ */
function local_user() { function local_user() {
@ -1789,7 +1789,7 @@ function local_user() {
/** /**
* @brief Returns contact id of authenticated site visitor or false * @brief Returns contact id of authenticated site visitor or false
* *
* @return int|bool visitor_id or false * @return int|bool visitor_id or false
*/ */
function remote_user() { function remote_user() {
@ -1846,13 +1846,13 @@ function get_max_import_size() {
* so plugins can take part in process :) * so plugins can take part in process :)
* *
* @param (string|integer) $cmd program to run or priority * @param (string|integer) $cmd program to run or priority
* *
* next args are passed as $cmd command line * next args are passed as $cmd command line
* e.g.: proc_run("ls","-la","/tmp"); * e.g.: proc_run("ls","-la","/tmp");
* or: proc_run(PRIORITY_HIGH, "include/notifier.php", "drop", $drop_id); * or: proc_run(PRIORITY_HIGH, "include/notifier.php", "drop", $drop_id);
* *
* @note $cmd and string args are surrounded with "" * @note $cmd and string args are surrounded with ""
* *
* @hooks 'proc_run' * @hooks 'proc_run'
* array $arr * array $arr
*/ */
@ -2011,9 +2011,9 @@ function current_theme(){
/** /**
* @brief Return full URL to theme which is currently in effect. * @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. * Provide a sane default if nothing is chosen or the specified theme does not exist.
* *
* @return string * @return string
*/ */
function current_theme_url() { function current_theme_url() {
@ -2360,7 +2360,7 @@ function current_load() {
/** /**
* @brief get c-style args * @brief get c-style args
* *
* @return int * @return int
*/ */
function argc() { function argc() {
@ -2369,7 +2369,7 @@ function argc() {
/** /**
* @brief Returns the value of a argv key * @brief Returns the value of a argv key
* *
* @param int $x argv key * @param int $x argv key
* @return string Value of the 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 * @brief Get the data which is needed for infinite scroll
* *
* For invinite scroll we need the page number of the actual page * 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. * and the the URI where the content of the next page comes from.
* This data is needed for the js part in main.js. * This data is needed for the js part in main.js.
* Note: infinite scroll does only work for the network page (module) * Note: infinite scroll does only work for the network page (module)
* *
* @param string $module The name of the module (e.g. "network") * @param string $module The name of the module (e.g. "network")
* @return array Of infinite scroll data * @return array Of infinite scroll data
* 'pageno' => $pageno The number of the actual page * 'pageno' => $pageno The number of the actual page

View file

@ -78,6 +78,10 @@ function table_structure($table) {
if ($index["Index_type"] == "FULLTEXT") if ($index["Index_type"] == "FULLTEXT")
continue; 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"]; $column = $index["Column_name"];
// On utf8mb4 a varchar index can only have a length of 191 // 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. // 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)) if (is_null($definition))
$definition = db_definition($charset); $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 // Compare it
foreach ($definition AS $name => $structure) { 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_') { if ($current_index_definition != $new_index_definition && substr($indexname, 0, 6) != 'local_') {
$sql2=db_drop_index($indexname); $sql2=db_drop_index($indexname);
if ($sql3 == "") if ($sql3 == "")
$sql3 = "ALTER TABLE `".$name."` ".$sql2; $sql3 = "ALTER IGNORE TABLE `".$name."` ".$sql2;
else else
$sql3 .= ", ".$sql2; $sql3 .= ", ".$sql2;
} }
@ -186,7 +196,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
if (!isset($database[$name]["fields"][$fieldname])) { if (!isset($database[$name]["fields"][$fieldname])) {
$sql2=db_add_table_field($fieldname, $parameters); $sql2=db_add_table_field($fieldname, $parameters);
if ($sql3 == "") if ($sql3 == "")
$sql3 = "ALTER TABLE `".$name."` ".$sql2; $sql3 = "ALTER IGNORE TABLE `".$name."` ".$sql2;
else else
$sql3 .= ", ".$sql2; $sql3 .= ", ".$sql2;
} else { } else {
@ -196,7 +206,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
if ($current_field_definition != $new_field_definition) { if ($current_field_definition != $new_field_definition) {
$sql2=db_modify_table_field($fieldname, $parameters); $sql2=db_modify_table_field($fieldname, $parameters);
if ($sql3 == "") if ($sql3 == "")
$sql3 = "ALTER TABLE `".$name."` ".$sql2; $sql3 = "ALTER IGNORE TABLE `".$name."` ".$sql2;
else else
$sql3 .= ", ".$sql2; $sql3 .= ", ".$sql2;
} }
@ -220,7 +230,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
$sql2=db_create_index($indexname, $fieldnames); $sql2=db_create_index($indexname, $fieldnames);
if ($sql2 != "") { if ($sql2 != "") {
if ($sql3 == "") if ($sql3 == "")
$sql3 = "ALTER TABLE `".$name."` ".$sql2; $sql3 = "ALTER IGNORE TABLE `".$name."` ".$sql2;
else else
$sql3 .= ", ".$sql2; $sql3 .= ", ".$sql2;
} }
@ -324,6 +334,11 @@ function db_create_index($indexname, $fieldnames, $method="ADD") {
killme(); killme();
} }
if ($fieldnames[0] == "UNIQUE") {
array_shift($fieldnames);
$method .= ' UNIQUE';
}
$names = ""; $names = "";
foreach ($fieldnames AS $fieldname) { foreach ($fieldnames AS $fieldname) {
if ($names != "") if ($names != "")
@ -451,7 +466,7 @@ function db_definition($charset) {
), ),
"indexes" => array( "indexes" => array(
"PRIMARY" => array("id"), "PRIMARY" => array("id"),
"cat_k" => array("cat(30)","k(30)"), "cat_k" => array("UNIQUE", "cat(30)","k(30)"),
) )
); );
$database["contact"] = array( $database["contact"] = array(
@ -1060,7 +1075,7 @@ function db_definition($charset) {
), ),
"indexes" => array( "indexes" => array(
"PRIMARY" => array("id"), "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( $database["photo"] = array(
@ -1484,6 +1499,9 @@ function dbstructure_run(&$argv, &$argc) {
if ($argc==2) { if ($argc==2) {
switch ($argv[1]) { switch ($argv[1]) {
case "dryrun":
update_structure(true, false);
return;
case "update": case "update":
update_structure(true, true); update_structure(true, true);
set_config('system','build',DB_UPDATE_VERSION); set_config('system','build',DB_UPDATE_VERSION);

View file

@ -1,6 +1,6 @@
<?php <?php
define('UPDATE_VERSION' , 1203); define('UPDATE_VERSION' , 1210);
/** /**
* *
@ -1727,14 +1727,4 @@ function update_1190() {
function update_1202() { function update_1202() {
$r = q("UPDATE `user` SET `account-type` = %d WHERE `page-flags` IN (%d, %d)", $r = q("UPDATE `user` SET `account-type` = %d WHERE `page-flags` IN (%d, %d)",
dbesc(ACCOUNT_TYPE_COMMUNITY), dbesc(PAGE_COMMUNITY), dbesc(PAGE_PRVGROUP)); 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)");
} }