mirror of
https://github.com/e107inc/e107.git
synced 2025-08-03 21:27:25 +02:00
Table update handler; start enhancements
This commit is contained in:
@@ -11,8 +11,8 @@
|
|||||||
| GNU General Public License (http://gnu.org).
|
| GNU General Public License (http://gnu.org).
|
||||||
|
|
|
|
||||||
| $Source: /cvs_backup/e107_0.8/e107_admin/sql/core_sql.php,v $
|
| $Source: /cvs_backup/e107_0.8/e107_admin/sql/core_sql.php,v $
|
||||||
| $Revision: 1.3 $
|
| $Revision: 1.4 $
|
||||||
| $Date: 2007-09-22 21:46:09 $
|
| $Date: 2007-12-08 15:11:43 $
|
||||||
| $Author: e107steved $
|
| $Author: e107steved $
|
||||||
+----------------------------------------------------------------------------+
|
+----------------------------------------------------------------------------+
|
||||||
*/
|
*/
|
||||||
@@ -34,15 +34,40 @@ exit;
|
|||||||
# Database : <variable>
|
# Database : <variable>
|
||||||
# --------------------------------------------------------
|
# --------------------------------------------------------
|
||||||
|
|
||||||
|
#
|
||||||
|
# Table structure for table `audit_log` - user audit trail
|
||||||
|
#
|
||||||
|
CREATE TABLE audit_log (
|
||||||
|
dblog_id int(10) unsigned NOT NULL auto_increment,
|
||||||
|
dblog_datestamp int(10) unsigned NOT NULL default '0',
|
||||||
|
dblog_microtime int(10) unsigned NOT NULL default '0',
|
||||||
|
dblog_eventcode varchar(10) NOT NULL default '',
|
||||||
|
dblog_user_id int(10) unsigned NOT NULL default '0',
|
||||||
|
dblog_user_name varchar(100) NOT NULL default '',
|
||||||
|
dblog_ip varchar(45) NOT NULL default '',
|
||||||
|
dblog_title varchar(255) NOT NULL default '',
|
||||||
|
dblog_remarks text NOT NULL,
|
||||||
|
PRIMARY KEY (dblog_id),
|
||||||
|
KEY dblog_datestamp (dblog_datestamp)
|
||||||
|
) TYPE=MyISAM AUTO_INCREMENT=1;
|
||||||
|
# --------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Table structure for table `banlist`
|
# Table structure for table `banlist`
|
||||||
#
|
#
|
||||||
|
|
||||||
CREATE TABLE banlist (
|
CREATE TABLE banlist (
|
||||||
banlist_ip varchar(100) NOT NULL default '',
|
banlist_ip varchar(100) NOT NULL default '',
|
||||||
|
banlist_bantype tinyint(3) unsigned NOT NULL default '0',
|
||||||
|
banlist_datestamp int(10) unsigned NOT NULL default '0',
|
||||||
|
banlist_banexpires int(10) unsigned NOT NULL default '0',
|
||||||
banlist_admin smallint(5) unsigned NOT NULL default '0',
|
banlist_admin smallint(5) unsigned NOT NULL default '0',
|
||||||
banlist_reason tinytext NOT NULL,
|
banlist_reason tinytext NOT NULL,
|
||||||
PRIMARY KEY (banlist_ip)
|
banlist_notes tinytext NOT NULL,
|
||||||
|
PRIMARY KEY (banlist_ip),
|
||||||
|
KEY banlist_datestamp (banlist_datestamp),
|
||||||
|
KEY banlist_banexpires (banlist_banexpires)
|
||||||
) TYPE=MyISAM;
|
) TYPE=MyISAM;
|
||||||
# --------------------------------------------------------
|
# --------------------------------------------------------
|
||||||
|
|
||||||
@@ -105,13 +130,16 @@ CREATE TABLE core (
|
|||||||
#
|
#
|
||||||
CREATE TABLE dblog (
|
CREATE TABLE dblog (
|
||||||
dblog_id int(10) unsigned NOT NULL auto_increment,
|
dblog_id int(10) unsigned NOT NULL auto_increment,
|
||||||
dblog_type varchar(60) NOT NULL default '',
|
|
||||||
dblog_datestamp int(10) unsigned NOT NULL default '0',
|
dblog_datestamp int(10) unsigned NOT NULL default '0',
|
||||||
|
dblog_microtime int(10) unsigned NOT NULL default '0',
|
||||||
|
dblog_type tinyint(3) NOT NULL default '0',
|
||||||
|
dblog_eventcode varchar(10) NOT NULL default '',
|
||||||
dblog_user_id int(10) unsigned NOT NULL default '0',
|
dblog_user_id int(10) unsigned NOT NULL default '0',
|
||||||
dblog_ip varchar(80) NOT NULL default '',
|
dblog_ip varchar(45) NOT NULL default '',
|
||||||
dblog_title varchar(255) NOT NULL default '',
|
dblog_title varchar(255) NOT NULL default '',
|
||||||
dblog_remarks text NOT NULL,
|
dblog_remarks text NOT NULL,
|
||||||
PRIMARY KEY (dblog_id)
|
PRIMARY KEY (dblog_id),
|
||||||
|
KEY dblog_datestamp (dblog_datestamp)
|
||||||
) TYPE=MyISAM;
|
) TYPE=MyISAM;
|
||||||
# --------------------------------------------------------
|
# --------------------------------------------------------
|
||||||
|
|
||||||
@@ -364,6 +392,28 @@ CREATE TABLE rbinary (
|
|||||||
) TYPE=MyISAM;
|
) TYPE=MyISAM;
|
||||||
# --------------------------------------------------------
|
# --------------------------------------------------------
|
||||||
|
|
||||||
|
#
|
||||||
|
# Table structure for table `rl_history` - rolling log
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE rl_history (
|
||||||
|
dblog_id int(10) unsigned NOT NULL auto_increment,
|
||||||
|
dblog_datestamp int(10) unsigned NOT NULL default '0',
|
||||||
|
dblog_microtime int(10) unsigned NOT NULL default '0',
|
||||||
|
dblog_type tinyint(3) NOT NULL default '0',
|
||||||
|
dblog_eventcode varchar(10) NOT NULL default '',
|
||||||
|
dblog_user_id int(10) unsigned NOT NULL default '0',
|
||||||
|
dblog_user_name varchar(100) NOT NULL default '',
|
||||||
|
dblog_ip varchar(45) NOT NULL default '',
|
||||||
|
dblog_caller varchar(255) NOT NULL default '',
|
||||||
|
dblog_title varchar(255) NOT NULL default '',
|
||||||
|
dblog_remarks text NOT NULL,
|
||||||
|
PRIMARY KEY (dblog_id),
|
||||||
|
KEY dblog_datestamp (dblog_datestamp)
|
||||||
|
) TYPE=MyISAM AUTO_INCREMENT=1;
|
||||||
|
|
||||||
|
# --------------------------------------------------------
|
||||||
|
|
||||||
#
|
#
|
||||||
# Table structure for table `session`
|
# Table structure for table `session`
|
||||||
#
|
#
|
||||||
@@ -484,6 +534,10 @@ CREATE TABLE userclass_classes (
|
|||||||
userclass_name varchar(100) NOT NULL default '',
|
userclass_name varchar(100) NOT NULL default '',
|
||||||
userclass_description varchar(250) NOT NULL default '',
|
userclass_description varchar(250) NOT NULL default '',
|
||||||
userclass_editclass tinyint(3) unsigned NOT NULL default '0',
|
userclass_editclass tinyint(3) unsigned NOT NULL default '0',
|
||||||
|
userclass_parent tinyint(3) unsigned NOT NULL default '0',
|
||||||
|
userclass_accum varchar(250) NOT NULL default '',
|
||||||
|
userclass_visibility tinyint(3) unsigned NOT NULL default '0',
|
||||||
|
userclass_icon varchar(250) NOT NULL default '',
|
||||||
PRIMARY KEY (userclass_id)
|
PRIMARY KEY (userclass_id)
|
||||||
) TYPE=MyISAM;
|
) TYPE=MyISAM;
|
||||||
# --------------------------------------------------------
|
# --------------------------------------------------------
|
||||||
|
@@ -11,13 +11,14 @@
|
|||||||
| GNU General Public License (http://gnu.org).
|
| GNU General Public License (http://gnu.org).
|
||||||
|
|
|
|
||||||
| $Source: /cvs_backup/e107_0.8/e107_admin/update_routines.php,v $
|
| $Source: /cvs_backup/e107_0.8/e107_admin/update_routines.php,v $
|
||||||
| $Revision: 1.10 $
|
| $Revision: 1.11 $
|
||||||
| $Date: 2007-09-22 21:46:09 $
|
| $Date: 2007-12-08 15:11:43 $
|
||||||
| $Author: e107steved $
|
| $Author: e107steved $
|
||||||
+----------------------------------------------------------------------------+
|
+----------------------------------------------------------------------------+
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once("../class2.php");
|
require_once("../class2.php");
|
||||||
|
require_once(e_HANDLER.'db_table_admin_class.php');
|
||||||
|
|
||||||
|
|
||||||
// Modified update routine - combines checking and update code into one block per function
|
// Modified update routine - combines checking and update code into one block per function
|
||||||
@@ -163,7 +164,7 @@ function update_core_prefs($type='')
|
|||||||
{
|
{
|
||||||
if ($k && !array_key_exists($k,$pref))
|
if ($k && !array_key_exists($k,$pref))
|
||||||
{
|
{
|
||||||
if ($just_check) return update_needed();
|
if ($just_check) return update_needed('Missing pref: '.$k);
|
||||||
$pref[$k] = $v;
|
$pref[$k] = $v;
|
||||||
$do_save = TRUE;
|
$do_save = TRUE;
|
||||||
}
|
}
|
||||||
@@ -181,11 +182,21 @@ function update_706_to_800($type='')
|
|||||||
global $sql,$ns, $pref;
|
global $sql,$ns, $pref;
|
||||||
|
|
||||||
// List of unwanted $pref values which can go
|
// List of unwanted $pref values which can go
|
||||||
$obs_prefs = array('frontpage_type');
|
$obs_prefs = array('frontpage_type','rss_feeds');
|
||||||
|
|
||||||
// List of DB tables not required (includes a few from 0.6xx)
|
// List of DB tables not required (includes a few from 0.6xx)
|
||||||
$obs_tables = array('flood', 'headlines', 'stat_info', 'stat_counter', 'stat_last');
|
$obs_tables = array('flood', 'headlines', 'stat_info', 'stat_counter', 'stat_last');
|
||||||
|
|
||||||
|
|
||||||
|
// List of DB tables newly required (defined in core_sql.php)
|
||||||
|
$new_tables = array('audit_log', 'rl_history');
|
||||||
|
|
||||||
|
|
||||||
|
// List of changed DB tables (defined in core_sql.php)
|
||||||
|
// (primarily those which have changed significantly; for the odd field write some explicit code - it'll run faster)
|
||||||
|
$changed_tables = array('dblog','rl_history', 'userclass_classes', 'banlist');
|
||||||
|
|
||||||
|
|
||||||
// List of DB tables (key) and field (value) which need changing to accommodate IPV6 addresses
|
// List of DB tables (key) and field (value) which need changing to accommodate IPV6 addresses
|
||||||
$ip_upgrade = array('comments' => 'comment_ip',
|
$ip_upgrade = array('comments' => 'comment_ip',
|
||||||
'download_requests' => 'download_request_ip',
|
'download_requests' => 'download_request_ip',
|
||||||
@@ -195,7 +206,8 @@ function update_706_to_800($type='')
|
|||||||
'user' => 'user_ip',
|
'user' => 'user_ip',
|
||||||
'chatbox' => 'cb_ip'
|
'chatbox' => 'cb_ip'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$db_parser = new db_table_admin; // Class to read table defs and process them
|
||||||
$do_save = FALSE;
|
$do_save = FALSE;
|
||||||
|
|
||||||
$just_check = $type == 'do' ? FALSE : TRUE; // TRUE if we're just seeing if an update is needed
|
$just_check = $type == 'do' ? FALSE : TRUE; // TRUE if we're just seeing if an update is needed
|
||||||
@@ -307,6 +319,61 @@ function update_706_to_800($type='')
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Tables defined in core_sql.php
|
||||||
|
//---------------------------------
|
||||||
|
|
||||||
|
// New tables required (list at top. Definitions in core_sql.php)
|
||||||
|
foreach ($new_tables as $nt)
|
||||||
|
{
|
||||||
|
if (!mysql_table_exists($nt))
|
||||||
|
{
|
||||||
|
if ($just_check) return update_needed("Add table: ".$nt);
|
||||||
|
// Get the definition
|
||||||
|
$defs = $db_parser->get_table_def($nt,e_ADMIN."sql/core_sql.php");
|
||||||
|
if (count($defs))
|
||||||
|
{ // **** Add in table here
|
||||||
|
$sql->db_Select_gen('CREATE TABLE `'.MPREFIX.$defs[0][1].'` ('.$defs[0][2].') TYPE='.$defs[0][3]);
|
||||||
|
catch_error();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // error parsing defs file
|
||||||
|
}
|
||||||
|
unset($defs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Tables whose definition needs changing significantly
|
||||||
|
foreach ($changed_tables as $ct)
|
||||||
|
{
|
||||||
|
$req_defs = $db_parser->get_table_def($ct,e_ADMIN."sql/core_sql.php");
|
||||||
|
$req_fields = $db_parser->parse_field_defs($req_defs[0][2]); // Required definitions
|
||||||
|
// echo $db_parser->make_field_list($req_fields);
|
||||||
|
|
||||||
|
if ((($actual_defs = $db_parser->get_current_table($ct)) === FALSE) || !is_array($actual_defs)) // Adds current default prefix
|
||||||
|
{
|
||||||
|
echo "Couldn't get table structure: {$ct}<br />";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// echo $db_parser->make_table_list($actual_defs);
|
||||||
|
$actual_fields = $db_parser->parse_field_defs($actual_defs[0][2]);
|
||||||
|
// echo $db_parser->make_field_list($actual_fields);
|
||||||
|
|
||||||
|
$diffs = $db_parser->compare_field_lists($req_fields,$actual_fields);
|
||||||
|
if (count($diffs[0]))
|
||||||
|
{ // Changes needed
|
||||||
|
if ($just_check) return update_needed("Field changes rqd; table: ".$ct);
|
||||||
|
// Do the changes here
|
||||||
|
$qry = 'ALTER TABLE '.MPREFIX.$ct.' '.implode(', ',$diffs[1]);
|
||||||
|
// echo "Query: ".$qry."<br />";
|
||||||
|
mysql_query($qry);
|
||||||
|
catch_error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Obsolete tables (list at top)
|
// Obsolete tables (list at top)
|
||||||
foreach ($obs_tables as $ot)
|
foreach ($obs_tables as $ot)
|
||||||
{
|
{
|
||||||
|
382
e107_handlers/db_table_admin_class.php
Normal file
382
e107_handlers/db_table_admin_class.php
Normal file
@@ -0,0 +1,382 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
+----------------------------------------------------------------------------+
|
||||||
|
| e107 website system
|
||||||
|
|
|
||||||
|
| <20>Steve Dunstan 2001-2002
|
||||||
|
| http://e107.org
|
||||||
|
| jalist@e107.org
|
||||||
|
|
|
||||||
|
| Released under the terms and conditions of the
|
||||||
|
| GNU General Public License (http://gnu.org).
|
||||||
|
|
|
||||||
|
| $Source: /cvs_backup/e107_0.8/e107_handlers/db_table_admin_class.php,v $
|
||||||
|
| $Revision: 1.1 $
|
||||||
|
| $Date: 2007-12-08 15:11:50 $
|
||||||
|
| $Author: e107steved $
|
||||||
|
+----------------------------------------------------------------------------+
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Database utilities for admin tasks:
|
||||||
|
Get structure of a table from a database
|
||||||
|
Get structure of a table from a file
|
||||||
|
First level parse of table structure
|
||||||
|
Parse of field definitions part of table structure
|
||||||
|
Comparison of two structures, including generation of MySQL to make them the same
|
||||||
|
Some crude printing utilities
|
||||||
|
|
||||||
|
Note: there are some uncommented 'echo' statements which are intentional to highlight that something's gone wrong! (not that it should, of course)
|
||||||
|
*/
|
||||||
|
|
||||||
|
class db_table_admin
|
||||||
|
{
|
||||||
|
var $file_buffer = ''; // Contents of a file
|
||||||
|
var $last_file = '';
|
||||||
|
|
||||||
|
// Get list of fields and keys for a table - return FALSE if unsuccessful
|
||||||
|
// Return as for get_table_def
|
||||||
|
function get_current_table($table_name, $prefix = "")
|
||||||
|
{
|
||||||
|
global $sql;
|
||||||
|
|
||||||
|
if (!$prefix) $prefix = MPREFIX;
|
||||||
|
// echo "Get table structure for: {$table_name}, prefix: {$prefix}<br />";
|
||||||
|
$sql->db_Select_gen('SET SQL_QUOTE_SHOW_CREATE = 1');
|
||||||
|
$qry = 'SHOW CREATE TABLE `'.$prefix.$table_name."`";
|
||||||
|
if (!($z = $sql->db_Select_gen($qry))) return FALSE;
|
||||||
|
$row = $sql->db_Fetch();
|
||||||
|
$tmp = str_replace("`", "", stripslashes($row[1])).';'; // Add semicolon to work with our parser
|
||||||
|
$count = preg_match_all("#CREATE\s+?TABLE\s+?`{0,1}({$prefix}{$table_name})`{0,1}\s+?\((.*?)\)\s+?(?:TYPE|ENGINE)\s*\=\s*(.*?);#is",$tmp,$matches,PREG_SET_ORDER);
|
||||||
|
if ($count === FALSE) return "Error occurred";
|
||||||
|
if (!$count) return "No matches";
|
||||||
|
return $matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Routine to do first-level parse of table structure
|
||||||
|
//---------------------------------------------------
|
||||||
|
// Given the name of a file, returns an array, with each element being a table creation definition.
|
||||||
|
// Tracks the last file read - only reads it once
|
||||||
|
// If the file name is an empty string, uses a previously read/set buffer
|
||||||
|
// If a table name is given, returns only that table's info; otherwise returns a list of all tables
|
||||||
|
// The table name must include a prefix where appropriate (although not required with standard E107 table definition files)
|
||||||
|
// Each element is itself an array:
|
||||||
|
// [0] - The complete string which creates a table (unless a prefix needs adding to the table name), including terminating ';'
|
||||||
|
// [1] - The table name. Any backticks are stripped
|
||||||
|
// [2] - Field definitions, with the surrounding (...) stripped
|
||||||
|
// [3] - The 'TYPE' field ('TYPE=' is stripped) and any AUTO-INCREMENT definition or other text.
|
||||||
|
// function get_table_def($table_name='',$file_name = e_ADMIN."sql/core_sql.php")
|
||||||
|
function get_table_def($table_name='',$file_name ="")
|
||||||
|
{
|
||||||
|
if ($file_name != '')
|
||||||
|
{ // Read in and buffer a new file (if we've not already got one)
|
||||||
|
if ($this->last_file != $file_name)
|
||||||
|
{
|
||||||
|
if (!is_readable($file_name)) return "No file";
|
||||||
|
$temp = file_get_contents($file_name);
|
||||||
|
// Strip any php header
|
||||||
|
$this->file_buffer = preg_replace("#\<\?php.*?\?\>#mis",'',$temp);
|
||||||
|
$this->last_file = $file_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$table_name) $table_name = '\w+?';
|
||||||
|
// Regex should be identical to that in get_current_table (apart from the source text variable name)
|
||||||
|
$count = preg_match_all("#CREATE\s+?TABLE\s+?`{0,1}({$table_name})`{0,1}\s+?\((.*?)\)\s+?(?:TYPE|ENGINE)\s*\=\s*(.*?);#is",$this->file_buffer,$matches,PREG_SET_ORDER);
|
||||||
|
if ($count === FALSE) return "Error occurred";
|
||||||
|
if (!$count) return "No matches";
|
||||||
|
return $matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Parses the block of lines which make up the field and index definitions
|
||||||
|
// Returns an array where each entry is the definitions of a field or index
|
||||||
|
function parse_field_defs($text)
|
||||||
|
{
|
||||||
|
$ans = array();
|
||||||
|
$field_lines = explode(',',$text);
|
||||||
|
foreach ($field_lines as $fv)
|
||||||
|
{
|
||||||
|
unset($defs);
|
||||||
|
$fv = trim(str_replace(' ',' ',$fv));
|
||||||
|
// echo "Line: ".$fv."<br />";
|
||||||
|
if ($fv)
|
||||||
|
{
|
||||||
|
$fd = explode(' ',$fv);
|
||||||
|
switch (strtoupper($fd[0]))
|
||||||
|
{
|
||||||
|
case 'PRIMARY' :
|
||||||
|
if (strtoupper($fd[1]) == 'KEY')
|
||||||
|
$defs['type'] = 'pkey';
|
||||||
|
$defs['name'] = $fd[2];
|
||||||
|
break;
|
||||||
|
case 'UNIQUE' :
|
||||||
|
if (count($fd) < 3)
|
||||||
|
{
|
||||||
|
echo "Truncated definition after UNIQUE {$i}: ".$fd[1]."<br />";
|
||||||
|
}
|
||||||
|
elseif (strtoupper($fd[1]) == 'KEY')
|
||||||
|
{
|
||||||
|
$defs['type'] = 'ukey';
|
||||||
|
$defs['name'] = $fd[2];
|
||||||
|
if (isset($fd[3])) $defs['keyfield'] = $fd[3]; else $defs['keyfield'] = '['.$fd[2].']';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
echo "Unrecognised word after UNIQUE in definition {$i}: ".$fd[1]."<br />";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'KEY' :
|
||||||
|
$defs['type'] = 'key';
|
||||||
|
$defs['name'] = $fd[1];
|
||||||
|
if (isset($fd[2])) $defs['keyfield'] = $fd[2]; else $defs['keyfield'] = '['.$fd[1].']';
|
||||||
|
break;
|
||||||
|
default : // Must be a DB field name
|
||||||
|
$defs['type'] = 'field';
|
||||||
|
$defs['name'] = $fd[0];
|
||||||
|
$defs['fieldtype'] = $fd[1];
|
||||||
|
$i = 2; // First unused field
|
||||||
|
if ((strpos($fd[1],'int') === 0) || (strpos($fd[1],'tinyint') === 0) || (strpos($fd[1],'smallint') === 0) || (strpos($fd[1],'bigint') === 0))
|
||||||
|
{
|
||||||
|
if (isset($fd[2]) && (strtoupper($fd[2]) == 'UNSIGNED'))
|
||||||
|
{
|
||||||
|
$defs['vartype'] = $fd[2];
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ($i < count($fd))
|
||||||
|
{
|
||||||
|
switch(strtoupper($fd[$i]))
|
||||||
|
{
|
||||||
|
case 'NOT' :
|
||||||
|
if (isset($fd[$i+1]) && strtoupper($fd[$i+1]) == 'NULL')
|
||||||
|
{
|
||||||
|
$i++;
|
||||||
|
$defs['nulltype'] = 'NOT NULL';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Syntax error
|
||||||
|
echo "Unrecognised word in definition {$i} after 'NOT': ".$fd[$i+1]."<br />";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'DEFAULT' :
|
||||||
|
if (isset($fd[$i+1]))
|
||||||
|
{
|
||||||
|
$i++;
|
||||||
|
$defs['default'] = $fd[$i];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'COLLATE' :
|
||||||
|
$i++; // Just skip over - we ignore collation
|
||||||
|
break;
|
||||||
|
case 'AUTO_INCREMENT' :
|
||||||
|
$defs['autoinc'] = TRUE;
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
echo "Unknown definition {$i}: ".$fd[$i]."<br />";
|
||||||
|
}
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count($defs) > 1) $ans[] = $defs; else echo "Partial definition<br />";
|
||||||
|
}
|
||||||
|
if (!count($ans)) return FALSE;
|
||||||
|
return $ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Utility routine - given our array-based definition, create a string MySQL field definition
|
||||||
|
function make_def($list)
|
||||||
|
{
|
||||||
|
switch ($list['type'])
|
||||||
|
{
|
||||||
|
case 'key' :
|
||||||
|
return 'KEY '.$list['name'].' ('.$list['name'].')';
|
||||||
|
case 'ukey' :
|
||||||
|
return 'UNIQUE KEY '.$list['name'].' ('.$list['name'].')';
|
||||||
|
case 'pkey' :
|
||||||
|
return 'PRIMARY KEY ('.$list['name'].')';
|
||||||
|
case 'field' : // Require a field - got a key. so add a field at the end
|
||||||
|
$def = $list['name'];
|
||||||
|
if (isset($list['fieldtype'])) $def .= ' '.$list['fieldtype'];
|
||||||
|
if (isset($list['vartype'])) $def .= ' '.$list['vartype'];
|
||||||
|
if (isset($list['nulltype'])) $def .= ' '.$list['nulltype'];
|
||||||
|
if (isset($list['default'])) $def .= ' default '.$list['default'];
|
||||||
|
if (varsettrue($list['autoinc'])) $def .= ' auto_increment';
|
||||||
|
return $def;
|
||||||
|
}
|
||||||
|
return "Cannot generate definition for: ".$list['type'].' '.$list['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Compare two field/index lists as generated by parse_field_defs
|
||||||
|
// If $stop_on_error is TRUE, returns TRUE if the same, false if different
|
||||||
|
// Return a text list of differences, plus an array of MySQL queries to fix
|
||||||
|
// List1 is the reference, List 2 is the actual
|
||||||
|
// This version looks ahead on a failed match, and moves a field up in the table if already defined - should retain as much as possible
|
||||||
|
function compare_field_lists($list1, $list2, $stop_on_error=FALSE)
|
||||||
|
{
|
||||||
|
$i = 0; // Counts records in list1 (required format)
|
||||||
|
$j = 0; // Counts records in $created_list (our 'table so far' list)
|
||||||
|
$error_list = array(); // Free text list of differences
|
||||||
|
$change_list = array(); // MySQL statements to implement changes
|
||||||
|
$created_list = array(); // List of field defs that we build up (just names)
|
||||||
|
while ($i < count($list1))
|
||||||
|
{
|
||||||
|
if (count($list2) == 0)
|
||||||
|
{ // Missing field at end
|
||||||
|
if ($stop_on_error) return FALSE;
|
||||||
|
$error_list[] = 'Missing field at end: '.$list1[$i]['name'];
|
||||||
|
$change_list[] = 'ADD '.$this->make_def($list1[$i]);
|
||||||
|
$created_list[$j] = $list1[$i]['name'];
|
||||||
|
$j++;
|
||||||
|
}
|
||||||
|
elseif ($list1[$i]['type'] == $list2[0]['type'])
|
||||||
|
{ // Worth doing a compare - fields are same type
|
||||||
|
if (strcasecmp($list1[$i]['name'],$list2[0]['name']) != 0)
|
||||||
|
{ // Names differ, so need to add or subtract a field.
|
||||||
|
// echo $i.': names differ - '.$list1[$i]['name'].', '.$list2[0]['name'].'<br />';
|
||||||
|
if ($stop_on_error) return FALSE;
|
||||||
|
$found = FALSE;
|
||||||
|
for ($k = 0; $k < count($list2); $k++)
|
||||||
|
{
|
||||||
|
// echo "Compare ".$list1[$i]['name'].' with '.$list2[$k]['name'];
|
||||||
|
if (strcasecmp($list1[$i]['name'],$list2[$k]['name']) == 0)
|
||||||
|
{ // Field found; we need to move it up
|
||||||
|
// echo " - match<br />";
|
||||||
|
$found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// echo " - no match<br />";
|
||||||
|
}
|
||||||
|
if ($found)
|
||||||
|
{
|
||||||
|
$error_list[] = 'Field out of position: '.$list2[$k]['name'];
|
||||||
|
$change_list[] = 'MODIFY '.$this->make_def($list1[$i]).(count($created_list) ? ' AFTER '.$created_list[count($created_list)-1] : ' FIRST');
|
||||||
|
array_splice($list2,$k,1); // Finished with this element - delete it, and renumber the keys
|
||||||
|
$created_list[$j] = $list1[$i]['name'];
|
||||||
|
$j++;
|
||||||
|
// The above also amends any parameters as necessary
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Need to insert a field
|
||||||
|
$error_list[] = 'Missing field: '.$list1[$i]['name'].' (found: '.$list2[0]['type'].' '.$list2[0]['name'].')';
|
||||||
|
$change_list[] = 'ADD '.$this->make_def($list1[$i]).(count($created_list) ? ' AFTER '.$created_list[count($created_list)-1] : ' FIRST');
|
||||||
|
$created_list[$j] = $list1[$i]['name'];
|
||||||
|
$j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Field/index is present as required; may be changes though
|
||||||
|
// Any difference and we need to update the table
|
||||||
|
// echo $i.': name match - '.$list1[$i]['name'].'<br />';
|
||||||
|
foreach ($list1[$i] as $fi => $v)
|
||||||
|
{
|
||||||
|
$t = $list2[0][$fi];
|
||||||
|
if (stripos($v,'varchar') !== FALSE) $v = substr($v,3); // Treat char, varchar the same
|
||||||
|
if (stripos($t,'varchar') !== FALSE) $t = substr($t,3); // Treat char, varchar the same
|
||||||
|
if (strcasecmp($t , $v) !== 0)
|
||||||
|
{
|
||||||
|
if ($stop_on_error) return FALSE;
|
||||||
|
$error_list[] = 'Incorrect definition: '.$fi.' = '.$v;
|
||||||
|
$change_list[] = 'MODIFY '.$this->make_def($list1[$i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
array_shift($list2);
|
||||||
|
$created_list[$j] = $list1[$i]['name'];
|
||||||
|
$j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Field type has changed. We know fields come before indexes. So something's missing
|
||||||
|
// echo $i.': types differ - '.$list1[$i]['type'].' '.$list1[$i]['name'].', '.$list2[$k]['type'].' '.$list2[$k]['name'].'<br />';
|
||||||
|
if ($stop_on_error) return FALSE;
|
||||||
|
switch ($list1[$i]['type'])
|
||||||
|
{
|
||||||
|
case 'key' :
|
||||||
|
case 'ukey' :
|
||||||
|
case 'pkey' : // Require a key - got a field
|
||||||
|
while ((count($list2)>0) && ($list2[0]['type'] == 'field'))
|
||||||
|
{
|
||||||
|
$error_list[] = 'Extra field: '.$list2[0]['name'];
|
||||||
|
$change_list[] = 'DROP '.$list2[0]['name'];
|
||||||
|
array_shift($list2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'field' : // Require a field - got a key. so add a field at the end
|
||||||
|
$error_list[] = 'Missing field: '.$list1[$i]['name'].' (found: '.$list2[0]['type'].' '.$list2[0]['name'].')';
|
||||||
|
$change_list[] = 'ADD '.$this->make_def($list1[$i]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
$error_list[] = 'Unknown field type: '.$list1[$i]['type'];
|
||||||
|
$change_list[] = ''; // Null entry to keep them in step
|
||||||
|
}
|
||||||
|
} // End - missing or extra field
|
||||||
|
|
||||||
|
$i++; // On to next field
|
||||||
|
}
|
||||||
|
if ($stop_on_error) return TRUE; // If doing a simple comparison and we get to here, all matches
|
||||||
|
return array($error_list, $change_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Return a table of info from the output of get_table_def
|
||||||
|
function make_table_list($result)
|
||||||
|
{
|
||||||
|
if (!is_array($result)) return "Not an array<br />";
|
||||||
|
$text = "<table>";
|
||||||
|
for ($i = 0; $i < count($result); $i++)
|
||||||
|
{
|
||||||
|
$text .= "<tr><td>{$result[$i][0]}</td>";
|
||||||
|
$text .= "<td>{$result[$i][1]}</td>";
|
||||||
|
$text .= "<td>{$result[$i][2]}</td>";
|
||||||
|
$text .= "<td>{$result[$i][3]}</td></tr>\n";
|
||||||
|
}
|
||||||
|
$text .= "</table><br /><br />";
|
||||||
|
return $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Return a table of info from the output of parse_field_defs()
|
||||||
|
function make_field_list($fields)
|
||||||
|
{
|
||||||
|
$text = "<table>";
|
||||||
|
foreach ($fields as $f)
|
||||||
|
{
|
||||||
|
switch($f['type'])
|
||||||
|
{
|
||||||
|
case 'pkey' :
|
||||||
|
$text .= "<tr><td>PRIMARY KEY</td><td>{$f['name']}</td><td> </td></tr>";
|
||||||
|
break;
|
||||||
|
case 'ukey' :
|
||||||
|
$text .= "<tr><td>UNIQUE KEY</td><td>{$f['name']}</td><td>{$f['keyfield']}</td></tr>";
|
||||||
|
break;
|
||||||
|
case 'key' :
|
||||||
|
$text .= "<tr><td>KEY</td><td>{$f['name']}</td><td>{$f['keyfield']}</td></tr>";
|
||||||
|
break;
|
||||||
|
case 'field' :
|
||||||
|
$text .= "<tr><td>FIELD</td><td>{$f['name']}</td><td>{$f['fieldtype']}";
|
||||||
|
if (isset($f['vartype'])) $text .= " ".$f['vartype'];
|
||||||
|
$text .= "</td>";
|
||||||
|
if (isset($f['nulltype'])) $text .= "<td>{$f['nulltype']}</td>"; else $text .= "<td> </td>";
|
||||||
|
if (isset($f['default'])) $text .= "<td>default {$f['default']}</td>"; elseif
|
||||||
|
(isset($f['autoinc'])) $text .= "<td>AUTO_INCREMENT</td>"; else $text .= "<td> </td>";
|
||||||
|
$text .= "</tr>";
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
$text .= "<tr><td>!!Unknown!!</td><td>{$f['type']}</td><td> </td></tr>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$text .= "</table><br /><br />--Ends--<br />";
|
||||||
|
return $text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
Reference in New Issue
Block a user