So, das wäre das Beste aus zwei Welten (nun ja). Getestet habe ich es, aber ein Code-Review durch jemand anderen ist vermutlich eine gute Idee.
Ich habe auch die Funktionserläuterung angepasst, sie hatte es nötig. Die z.Z. verwendete Version unternimmt übrigens keinen Konvertierungsversuch, sondern überlässt die Arbeit mySQL - aber den Satz habe ich drin gelassen, klingt doch schöner...
Code: Alles auswählen
function dbUpgradeTable ($table, $field, $type, $null, $key, $default, $extra, $upgradeStatement) {
global $dbupgrade1; // HerrB: not used: , $dbupgrade2;
global $columnCache;
global $tableCache;
if (!is_object($dbupgrade1)) {
$dbupgrade1 = new DB_Upgrade;
}
/* HerrB: Not used */
/* if (!is_object($dbupgrade2)) {
$dbupgrade2 = new DB_Upgrade;
} */
/* Function logic:
* 1 .) Check, if the table exists
* 2a.) If not, create it with the field specification, exit
* 2b.) If the table exists, check, if the field exist
* 3 .) If not, try to find the field using previous names (if specified in $field like "name1,name2")
* 4a.) If the field hasn't been found, create the field as specified, exit
* 4b.) If the field has been found using a previous name (if specified) rename the column to $field
* 5 .) As the field has been found, check, if the field's type is matching
* 5a.) If the type is matching, exit
* 5b.) If the field's content type is not matching, try to convert first (e.g. string to int
* or int to string), then use the upgrade statement if applicable
*
* Note about the upgrade statement:
* - the code must be eval'able
* - the code needs to read $oldVal (old field value) and needs to set $newVal (value to which the field will be set)
* - $oldVal might be empty if the field didn't exist
* - $tableValues['fieldname'] contains the already existing values */
/* Parameter checking for $null
* If parameter is "" or "NULL" or "YES", we know that
* we want the colum to forbid null entries. */
if ($null == "NULL" || $null == "YES") {
$parameter['NULL'] = "NULL";
$null = "YES";
} else {
$parameter['NULL'] = "NOT NULL";
$null = "";
}
/* Parameter checking for $key
* If parameter is "" or "NULL" or "YES", we know that
* we want the primary key. */
if ($key == "PRI") {
$parameter['KEY'] = "PRIMARY KEY";
} else {
$parameter['KEY'] = "";
}
/* Parameter check for $default
* If set, create a default value */
if ($default != "") {
$parameter['DEFAULT'] = "DEFAULT '$default'";
}
if (!dbTableExists($table)) {
$createTable = " CREATE TABLE $table ($field $type ".$parameter['NULL']." ".$parameter['DEFAULT']." ".$parameter['KEY'] .")";
$dbupgrade1->query($createTable);
$tableCache[] = $table;
return;
}
$structure = dbGetColumns($table);
// $savedPrimaryKey = dbGetPrimaryKeyName($table); /* HerrB: Nowhere used */
/* If $field contains "," previous names has been specified; separate from $field */
$sepPos = strpos($field, ",");
if ($sepPos === false) {
$previousName = "";
} else {
$previousName = substr($field, $sepPos + 1);
$field = substr($field, 0, $sepPos);
}
if (!array_key_exists($field,$structure)) {
/* HerrB: Search field using $previousName */
$blnFound = false;
if ($previousName != "") {
$arrPreviousName = explode(",", $previousName);
foreach ($arrPreviousName as $strPrevious) {
$strPrevious = trim($strPrevious); // Maybe someone has used field1, field2, ..., trim spaces
if (array_key_exists($strPrevious,$structure)) {
$blnFound = true;
break;
}
}
}
if ($blnFound) {
/* Rename column, update array, proceed */
if ($structure[$strPrevious]['Null'] == 'YES') {
$alterField = " ALTER TABLE `$table` CHANGE COLUMN `$strPrevious` `$field` ".$structure[$strPrevious]['Type']." DEFAULT '".$structure[$strPrevious]['Default']."'";
} else {
$alterField = " ALTER TABLE `$table` CHANGE COLUMN `$strPrevious` `$field` ".$structure[$strPrevious]['Type']." NOT NULL DEFAULT '".$structure[$strPrevious]['Default']."'";
}
$dbupgrade1->query($alterField);
$columnCache[$table] = "";
$structure = dbGetColumns($table);
} else {
/* Add column as specified */
$createField = " ALTER TABLE $table ADD COLUMN $field $type ".$parameter['NULL']." ".$parameter['DEFAULT']." ".$parameter['KEY'];
$dbupgrade1->query($createField);
$columnCache[$table] = "";
return;
}
}
/* Third check: Compare field properties */
if (($structure[$field]['Type'] != $type) ||
($structure[$field]['Null'] != $null) ||
($structure[$field]['Key'] != $key) ||
($structure[$field]['Default'] != $default) ||
($structure[$field]['Extra'] != $extra)) {
if ($structure[$field]['Key'] == "PRI") {
return "The primary key is not allowed to change";
}
if ($structure[$field]['Key'] == "MUL") {
return;
}
/* HerrB: So ... this would it do, too, but maybe there is a reason ...
if ($structure[$field]['Key'] == "PRI" || $structure[$field]['Key'] == "MUL") {
return "Primary or multiple key is not allowed to change";
} */
$alterField = " ALTER TABLE $table CHANGE COLUMN $field $field $type ".$parameter['NULL']." ".$parameter['DEFAULT']." ".$parameter['KEY'];
$dbupgrade1->query($alterField);
$columnCache[$table] = "";
}
}
Einige Zeilen habe ich auskommentiert, da sie in der Funktion nicht verwendet und keine Subroutinen aufgerufen werden - das kann dann wohl weg.
Das bei der Abfrage auf Multiple Keys keine Rückgabe stattfindet, hat vielleicht einen Grund, ansonsten könnte man die angegeben Abfrage übernehmen.
Hat das eigentlich einen spezifischen Grund, warum die SQL-Statements alle mit zwei Leerzeichen anfangen?
Die entsprechenden Zeilen in der dbUpgrade.php müssten dann so lauten:
Code: Alles auswählen
dbUpgradeTable($prefix."_news", 'modified,lastmodified', 'datetime', '', '', '0000-00-00 00:00:00', '','');
...
dbUpgradeTable($prefix."_news_rcp", 'modified,lastmodified', 'datetime', '', '', '0000-00-00 00:00:00', '','');
Ist kein Komma enthalten, wird nur nach $field gesucht (Zielname). Ist ein Komma enthalten, entspricht der erste Name dem Zielnamen, alle weiteren sind Alias- bzw. alte Namen. Ggf. angefügte Leerzeichen werden entfernt (z.B. vor name2 bei "name1, name2,...").
Gruß
HerrB