The DBStructure class now exists

This commit is contained in:
Michael 2017-12-14 21:14:02 +00:00
parent 15d42de647
commit 0d2087fe6e

View file

@ -1,19 +1,26 @@
<?php <?php
/** /**
* @file include/dbstructure.php * @file src/Database/DBStructure.php
*/ */
use Friendica\App; namespace Friendica\Database;
use Friendica\Core\System;
use Friendica\Core\Config; use Friendica\Core\Config;
use Friendica\Database\DBM; use Friendica\Database\DBM;
use dba;
require_once "boot.php"; require_once "boot.php";
require_once "include/text.php"; require_once "include/text.php";
/* /**
* @brief This class contain functions for the database management
*
* This class contains functions that doesn't need to know if pdo, mysqli or whatever is used.
*/
class DBStructure {
/*
* Converts all tables from MyISAM to InnoDB * Converts all tables from MyISAM to InnoDB
*/ */
function convert_to_innodb() { public static function convertToInnoDB() {
$r = q("SELECT `TABLE_NAME` FROM `information_schema`.`tables` WHERE `engine` = 'MyISAM' AND `table_schema` = '%s'", $r = q("SELECT `TABLE_NAME` FROM `information_schema`.`tables` WHERE `engine` = 'MyISAM' AND `table_schema` = '%s'",
dbesc(dba::database_name())); dbesc(dba::database_name()));
@ -28,18 +35,20 @@ function convert_to_innodb() {
$result = dba::e($sql); $result = dba::e($sql);
if (!DBM::is_result($result)) { if (!DBM::is_result($result)) {
print_update_error($sql); self::printUpdateError($sql);
}
} }
} }
}
/* /*
* send the email and do what is needed to do on update fails * send the email and do what is needed to do on update fails
* *
* @param update_id (int) number of failed update * @param update_id (int) number of failed update
* @param error_message (str) error message * @param error_message (str) error message
*/ */
function update_fail($update_id, $error_message) { public static function updateFail($update_id, $error_message) {
$a = get_app();
//send the administrators an e-mail //send the administrators an e-mail
$admin_mail_list = "'".implode("','", array_map(dbesc, explode(",", str_replace(" ", "", $a->config['admin_email']))))."'"; $admin_mail_list = "'".implode("','", array_map(dbesc, explode(",", str_replace(" ", "", $a->config['admin_email']))))."'";
$adminlist = q("SELECT uid, language, email FROM user WHERE email IN (%s)", $adminlist = q("SELECT uid, language, email FROM user WHERE email IN (%s)",
@ -78,11 +87,11 @@ function update_fail($update_id, $error_message) {
} }
//try the logger //try the logger
logger("CRITICAL: Database structure update failed: ".$retval); logger("CRITICAL: Database structure update failed: ".$error_message);
} }
function table_structure($table) { private static function tableStructure($table) {
$structures = q("DESCRIBE `%s`", $table); $structures = q("DESCRIBE `%s`", $table);
$full_columns = q("SHOW FULL COLUMNS FROM `%s`", $table); $full_columns = q("SHOW FULL COLUMNS FROM `%s`", $table);
@ -100,7 +109,7 @@ function table_structure($table) {
$fielddata = array(); $fielddata = array();
$indexdata = array(); $indexdata = array();
if (DBM::is_result($indexes)) if (DBM::is_result($indexes)) {
foreach ($indexes AS $index) { foreach ($indexes AS $index) {
if ($index['Key_name'] != 'PRIMARY' && $index['Non_unique'] == '0' && !isset($indexdata[$index["Key_name"]])) { if ($index['Key_name'] != 'PRIMARY' && $index['Non_unique'] == '0' && !isset($indexdata[$index["Key_name"]])) {
$indexdata[$index["Key_name"]] = array('UNIQUE'); $indexdata[$index["Key_name"]] = array('UNIQUE');
@ -108,12 +117,13 @@ function table_structure($table) {
$column = $index["Column_name"]; $column = $index["Column_name"];
if (($index["Sub_part"] != "")) { if ($index["Sub_part"] != "") {
$column .= "(".$index["Sub_part"].")"; $column .= "(".$index["Sub_part"].")";
} }
$indexdata[$index["Key_name"]][] = $column; $indexdata[$index["Key_name"]][] = $column;
} }
}
if (DBM::is_result($structures)) { if (DBM::is_result($structures)) {
foreach ($structures AS $field) { foreach ($structures AS $field) {
$fielddata[$field["Field"]]["type"] = $field["Type"]; $fielddata[$field["Field"]]["type"] = $field["Type"];
@ -141,9 +151,9 @@ function table_structure($table) {
} }
return array("fields" => $fielddata, "indexes" => $indexdata, "table_status" => $table_status); return array("fields" => $fielddata, "indexes" => $indexdata, "table_status" => $table_status);
} }
function print_structure($database) { public static function printStructure($database) {
echo "-- ------------------------------------------\n"; echo "-- ------------------------------------------\n";
echo "-- ".FRIENDICA_PLATFORM." ".FRIENDICA_VERSION." (".FRIENDICA_CODENAME,")\n"; echo "-- ".FRIENDICA_PLATFORM." ".FRIENDICA_VERSION." (".FRIENDICA_CODENAME,")\n";
echo "-- DB_UPDATE_VERSION ".DB_UPDATE_VERSION."\n"; echo "-- DB_UPDATE_VERSION ".DB_UPDATE_VERSION."\n";
@ -152,29 +162,27 @@ function print_structure($database) {
echo "--\n"; echo "--\n";
echo "-- TABLE $name\n"; echo "-- TABLE $name\n";
echo "--\n"; echo "--\n";
db_create_table($name, $structure['fields'], true, false, $structure["indexes"]); self::createTable($name, $structure['fields'], true, false, $structure["indexes"]);
echo "\n"; echo "\n";
} }
} }
/** /**
* @brief Print out database error messages * @brief Print out database error messages
* *
* @param string $message Message to be added to the error message * @param string $message Message to be added to the error message
* *
* @return string Error message * @return string Error message
*/ */
function print_update_error($message) { private static function printUpdateError($message) {
echo sprintf(t("\nError %d occurred during database update:\n%s\n"), echo sprintf(t("\nError %d occurred during database update:\n%s\n"),
dba::errorNo(), dba::errorMessage()); dba::errorNo(), dba::errorMessage());
return t('Errors encountered performing database changes: ').$message.EOL; return t('Errors encountered performing database changes: ').$message.EOL;
} }
function update_structure($verbose, $action, $tables=null, $definition=null) {
global $a;
public static function updateStructure($verbose, $action, $tables = null, $definition = null) {
if ($action) { if ($action) {
Config::set('system', 'maintenance', 1); Config::set('system', 'maintenance', 1);
Config::set('system', 'maintenance_reason', sprintf(t(': Database update'), DBM::date().' '.date('e'))); Config::set('system', 'maintenance_reason', sprintf(t(': Database update'), DBM::date().' '.date('e')));
@ -196,13 +204,13 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
$table = current($table); $table = current($table);
logger(sprintf('updating structure for table %s ...', $table), LOGGER_DEBUG); logger(sprintf('updating structure for table %s ...', $table), LOGGER_DEBUG);
$database[$table] = table_structure($table); $database[$table] = self::tableStructure($table);
} }
} }
// Get the definition // Get the definition
if (is_null($definition)) { if (is_null($definition)) {
$definition = db_definition(); $definition = self::definition();
} }
// MySQL >= 5.7.4 doesn't support the IGNORE keyword in ALTER TABLE statements // MySQL >= 5.7.4 doesn't support the IGNORE keyword in ALTER TABLE statements
@ -219,9 +227,9 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
$group_by = ""; $group_by = "";
$sql3 = ""; $sql3 = "";
if (!isset($database[$name])) { if (!isset($database[$name])) {
$r = db_create_table($name, $structure["fields"], $verbose, $action, $structure['indexes']); $r = self::createTable($name, $structure["fields"], $verbose, $action, $structure['indexes']);
if (!DBM::is_result($r)) { if (!DBM::is_result($r)) {
$errors .= print_update_error($name); $errors .= self::printUpdateError($name);
} }
$is_new_table = True; $is_new_table = True;
} else { } else {
@ -258,7 +266,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
$new_index_definition = "__NOT_SET__"; $new_index_definition = "__NOT_SET__";
} }
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=self::dropIndex($indexname);
if ($sql3 == "") { if ($sql3 == "") {
$sql3 = "ALTER".$ignore." TABLE `".$temp_name."` ".$sql2; $sql3 = "ALTER".$ignore." TABLE `".$temp_name."` ".$sql2;
} else { } else {
@ -269,7 +277,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
// Compare the field structure field by field // Compare the field structure field by field
foreach ($structure["fields"] AS $fieldname => $parameters) { foreach ($structure["fields"] AS $fieldname => $parameters) {
if (!isset($database[$name]["fields"][$fieldname])) { if (!isset($database[$name]["fields"][$fieldname])) {
$sql2=db_add_table_field($fieldname, $parameters); $sql2=self::addTableField($fieldname, $parameters);
if ($sql3 == "") { if ($sql3 == "") {
$sql3 = "ALTER" . $ignore . " TABLE `".$temp_name."` ".$sql2; $sql3 = "ALTER" . $ignore . " TABLE `".$temp_name."` ".$sql2;
} else { } else {
@ -291,7 +299,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
$current_field_definition = implode(",", $field_definition); $current_field_definition = implode(",", $field_definition);
$new_field_definition = implode(",", $parameters); $new_field_definition = implode(",", $parameters);
if ($current_field_definition != $new_field_definition) { if ($current_field_definition != $new_field_definition) {
$sql2 = db_modify_table_field($fieldname, $parameters); $sql2 = self::modifyTableField($fieldname, $parameters);
if ($sql3 == "") { if ($sql3 == "") {
$sql3 = "ALTER" . $ignore . " TABLE `".$temp_name."` ".$sql2; $sql3 = "ALTER" . $ignore . " TABLE `".$temp_name."` ".$sql2;
} else { } else {
@ -316,11 +324,11 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
} }
$new_index_definition = implode(",",$fieldnames); $new_index_definition = implode(",",$fieldnames);
if ($current_index_definition != $new_index_definition) { if ($current_index_definition != $new_index_definition) {
$sql2 = db_create_index($indexname, $fieldnames); $sql2 = self::createIndex($indexname, $fieldnames);
// Fetch the "group by" fields for unique indexes // Fetch the "group by" fields for unique indexes
if ($fieldnames[0] == "UNIQUE") { if ($fieldnames[0] == "UNIQUE") {
$group_by = db_group_by($indexname, $fieldnames); $group_by = self::groupBy($indexname, $fieldnames);
} }
if ($sql2 != "") { if ($sql2 != "") {
if ($sql3 == "") { if ($sql3 == "") {
@ -362,7 +370,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
} }
if ($field_definition['Collation'] != $parameters['Collation']) { if ($field_definition['Collation'] != $parameters['Collation']) {
$sql2 = db_modify_table_field($fieldname, $parameters); $sql2 = self::modifyTableField($fieldname, $parameters);
if (($sql3 == "") || (substr($sql3, -2, 2) == "; ")) { if (($sql3 == "") || (substr($sql3, -2, 2) == "; ")) {
$sql3 .= "ALTER" . $ignore . " TABLE `".$temp_name."` ".$sql2; $sql3 .= "ALTER" . $ignore . " TABLE `".$temp_name."` ".$sql2;
} else { } else {
@ -419,21 +427,21 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
} else { } else {
dba::e("DROP TABLE IF EXISTS `".$temp_name."`;"); dba::e("DROP TABLE IF EXISTS `".$temp_name."`;");
if (!DBM::is_result($r)) { if (!DBM::is_result($r)) {
$errors .= print_update_error($sql3); $errors .= self::printUpdateError($sql3);
return $errors; return $errors;
} }
$r = dba::e("CREATE TABLE `".$temp_name."` LIKE `".$name."`;"); $r = dba::e("CREATE TABLE `".$temp_name."` LIKE `".$name."`;");
if (!DBM::is_result($r)) { if (!DBM::is_result($r)) {
$errors .= print_update_error($sql3); $errors .= self::printUpdateError($sql3);
return $errors; return $errors;
} }
} }
} }
$r = @dba::e($sql3); $r = dba::e($sql3);
if (!DBM::is_result($r)) { if (!DBM::is_result($r)) {
$errors .= print_update_error($sql3); $errors .= self::printUpdateError($sql3);
} }
if ($is_unique && ($temp_name != $name)) { if ($is_unique && ($temp_name != $name)) {
if ($ignore != "") { if ($ignore != "") {
@ -441,17 +449,17 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
} else { } else {
$r = dba::e("INSERT INTO `".$temp_name."` SELECT ".$field_list." FROM `".$name."`".$group_by.";"); $r = dba::e("INSERT INTO `".$temp_name."` SELECT ".$field_list." FROM `".$name."`".$group_by.";");
if (!DBM::is_result($r)) { if (!DBM::is_result($r)) {
$errors .= print_update_error($sql3); $errors .= self::printUpdateError($sql3);
return $errors; return $errors;
} }
$r = dba::e("DROP TABLE `".$name."`;"); $r = dba::e("DROP TABLE `".$name."`;");
if (!DBM::is_result($r)) { if (!DBM::is_result($r)) {
$errors .= print_update_error($sql3); $errors .= self::printUpdateError($sql3);
return $errors; return $errors;
} }
$r = dba::e("RENAME TABLE `".$temp_name."` TO `".$name."`;"); $r = dba::e("RENAME TABLE `".$temp_name."` TO `".$name."`;");
if (!DBM::is_result($r)) { if (!DBM::is_result($r)) {
$errors .= print_update_error($sql3); $errors .= self::printUpdateError($sql3);
return $errors; return $errors;
} }
} }
@ -472,17 +480,18 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
} }
return $errors; return $errors;
} }
function db_field_command($parameters, $create = true) { private static function FieldCommand($parameters, $create = true) {
$fieldstruct = $parameters["type"]; $fieldstruct = $parameters["type"];
if (!is_null($parameters["Collation"])) { if (!is_null($parameters["Collation"])) {
$fieldstruct .= " COLLATE ".$parameters["Collation"]; $fieldstruct .= " COLLATE ".$parameters["Collation"];
} }
if ($parameters["not null"]) if ($parameters["not null"]) {
$fieldstruct .= " NOT NULL"; $fieldstruct .= " NOT NULL";
}
if (isset($parameters["default"])) { if (isset($parameters["default"])) {
if (strpos(strtolower($parameters["type"]),"int")!==false) { if (strpos(strtolower($parameters["type"]),"int")!==false) {
@ -491,26 +500,23 @@ function db_field_command($parameters, $create = true) {
$fieldstruct .= " DEFAULT '".$parameters["default"]."'"; $fieldstruct .= " DEFAULT '".$parameters["default"]."'";
} }
} }
if ($parameters["extra"] != "") if ($parameters["extra"] != "") {
$fieldstruct .= " ".$parameters["extra"]; $fieldstruct .= " ".$parameters["extra"];
}
/*if (($parameters["primary"] != "") && $create) /*if (($parameters["primary"] != "") && $create)
$fieldstruct .= " PRIMARY KEY";*/ $fieldstruct .= " PRIMARY KEY";*/
return($fieldstruct); return($fieldstruct);
} }
function db_create_table($name, $fields, $verbose, $action, $indexes=null) {
global $a;
private static function createTable($name, $fields, $verbose, $action, $indexes=null) {
$r = true; $r = true;
$sql = "";
$sql_rows = array(); $sql_rows = array();
$primary_keys = array(); $primary_keys = array();
foreach ($fields AS $fieldname => $field) { foreach ($fields AS $fieldname => $field) {
$sql_rows[] = "`".dbesc($fieldname)."` ".db_field_command($field); $sql_rows[] = "`".dbesc($fieldname)."` ".self::FieldCommand($field);
if (x($field,'primary') && $field['primary']!='') { if (x($field,'primary') && $field['primary']!='') {
$primary_keys[] = $fieldname; $primary_keys[] = $fieldname;
} }
@ -518,44 +524,46 @@ function db_create_table($name, $fields, $verbose, $action, $indexes=null) {
if (!is_null($indexes)) { if (!is_null($indexes)) {
foreach ($indexes AS $indexname => $fieldnames) { foreach ($indexes AS $indexname => $fieldnames) {
$sql_index = db_create_index($indexname, $fieldnames, ""); $sql_index = self::createIndex($indexname, $fieldnames, "");
if (!is_null($sql_index)) $sql_rows[] = $sql_index; if (!is_null($sql_index)) {
$sql_rows[] = $sql_index;
}
} }
} }
$sql = implode(",\n\t", $sql_rows); $sql = implode(",\n\t", $sql_rows);
$sql = sprintf("CREATE TABLE IF NOT EXISTS `%s` (\n\t", dbesc($name)).$sql."\n) DEFAULT COLLATE utf8mb4_general_ci"; $sql = sprintf("CREATE TABLE IF NOT EXISTS `%s` (\n\t", dbesc($name)).$sql."\n) DEFAULT COLLATE utf8mb4_general_ci";
if ($verbose) if ($verbose) {
echo $sql.";\n"; echo $sql.";\n";
}
if ($action) if ($action) {
$r = @dba::e($sql); $r = dba::e($sql);
}
return $r; return $r;
} }
function db_add_table_field($fieldname, $parameters) { private static function addTableField($fieldname, $parameters) {
$sql = sprintf("ADD `%s` %s", dbesc($fieldname), db_field_command($parameters)); $sql = sprintf("ADD `%s` %s", dbesc($fieldname), self::FieldCommand($parameters));
return($sql); return($sql);
} }
function db_modify_table_field($fieldname, $parameters) { private static function modifyTableField($fieldname, $parameters) {
$sql = sprintf("MODIFY `%s` %s", dbesc($fieldname), db_field_command($parameters, false)); $sql = sprintf("MODIFY `%s` %s", dbesc($fieldname), self::FieldCommand($parameters, false));
return($sql); return($sql);
} }
function db_drop_index($indexname) { private static function dropIndex($indexname) {
$sql = sprintf("DROP INDEX `%s`", dbesc($indexname)); $sql = sprintf("DROP INDEX `%s`", dbesc($indexname));
return($sql); return($sql);
} }
function db_create_index($indexname, $fieldnames, $method="ADD") {
private static function createIndex($indexname, $fieldnames, $method = "ADD") {
$method = strtoupper(trim($method)); $method = strtoupper(trim($method));
if ($method!="" && $method!="ADD") { if ($method!="" && $method!="ADD") {
throw new Exception("Invalid parameter 'method' in db_create_index(): '$method'"); throw new Exception("Invalid parameter 'method' in self::createIndex(): '$method'");
killme();
} }
if ($fieldnames[0] == "UNIQUE") { if ($fieldnames[0] == "UNIQUE") {
@ -565,8 +573,9 @@ function db_create_index($indexname, $fieldnames, $method="ADD") {
$names = ""; $names = "";
foreach ($fieldnames AS $fieldname) { foreach ($fieldnames AS $fieldname) {
if ($names != "") if ($names != "") {
$names .= ","; $names .= ",";
}
if (preg_match('|(.+)\((\d+)\)|', $fieldname, $matches)) { if (preg_match('|(.+)\((\d+)\)|', $fieldname, $matches)) {
$names .= "`".dbesc($matches[1])."`(".intval($matches[2]).")"; $names .= "`".dbesc($matches[1])."`(".intval($matches[2]).")";
@ -582,10 +591,9 @@ function db_create_index($indexname, $fieldnames, $method="ADD") {
$sql = sprintf("%s INDEX `%s` (%s)", $method, dbesc($indexname), $names); $sql = sprintf("%s INDEX `%s` (%s)", $method, dbesc($indexname), $names);
return($sql); return($sql);
} }
function db_group_by($indexname, $fieldnames) {
private static function groupBy($indexname, $fieldnames) {
if ($fieldnames[0] != "UNIQUE") { if ($fieldnames[0] != "UNIQUE") {
return ""; return "";
} }
@ -594,8 +602,9 @@ function db_group_by($indexname, $fieldnames) {
$names = ""; $names = "";
foreach ($fieldnames AS $fieldname) { foreach ($fieldnames AS $fieldname) {
if ($names != "") if ($names != "") {
$names .= ","; $names .= ",";
}
if (preg_match('|(.+)\((\d+)\)|', $fieldname, $matches)) { if (preg_match('|(.+)\((\d+)\)|', $fieldname, $matches)) {
$names .= "`".dbesc($matches[1])."`"; $names .= "`".dbesc($matches[1])."`";
@ -606,10 +615,9 @@ function db_group_by($indexname, $fieldnames) {
$sql = sprintf(" GROUP BY %s", $names); $sql = sprintf(" GROUP BY %s", $names);
return $sql; return $sql;
} }
function db_definition() {
public static function definition() {
$database = array(); $database = array();
$database["addon"] = array( $database["addon"] = array(
@ -1677,4 +1685,5 @@ function db_definition() {
); );
return($database); return($database);
}
} }