1
0
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:
e107steved
2007-12-08 15:11:50 +00:00
parent 818a1cd4c9
commit 4be55c71ce
3 changed files with 514 additions and 11 deletions

View File

@@ -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;
# -------------------------------------------------------- # --------------------------------------------------------

View File

@@ -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)
{ {

View 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>&nbsp;</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>&nbsp;</td>";
if (isset($f['default'])) $text .= "<td>default {$f['default']}</td>"; elseif
(isset($f['autoinc'])) $text .= "<td>AUTO_INCREMENT</td>"; else $text .= "<td>&nbsp;</td>";
$text .= "</tr>";
break;
default :
$text .= "<tr><td>!!Unknown!!</td><td>{$f['type']}</td><td>&nbsp;</td></tr>";
}
}
$text .= "</table><br /><br />--Ends--<br />";
return $text;
}
}
?>