".htmlentities($sql, ENT_COMPAT, getsetting("charset", "ISO-8859-1")).""); } else { output("`^Table `#%s`^ created.`n", $tablename); } }else{ //the table exists, so we need to compare it against the descriptor. $existing = table_create_descriptor($tablename); reset($descriptor); $changes = array(); while (list($key,$val)=each($descriptor)){ if ($key == "RequireMyISAM") continue; $val['type'] = descriptor_sanitize_type($val['type']); if (!isset($val['name'])) { if (($val['type']=="key" || $val['type']=="unique key" || $val['type']=="primary key")){ if (substr($key,0,4)=="key-"){ $val['name']=substr($key,4); }else{ debug("Warning: the descriptor for $tablename includes a {$val['type']} which isn't named correctly. It should be named key-$key. In your code, it should look something like this (the important change is bolded):
\"key-$key\"=>array(\"type\"=>\"{$val['type']}\",\"columns\"=>\"{$val['columns']}\")
The consequence of this is that your keys will be destroyed and recreated each time the table is synchronized until this is addressed."); $val['name']=$key; } }else{ $val['name']=$key; } }else{ if ($val['type']=="key" || $val['type']=="unique key" || $val['type']=="primary key"){ $key = "key-".$val['name']; }else{ $key = $val['name']; } } $newsql = descriptor_createsql($val); if (!isset($existing[$key])){ //this is a new column. array_push($changes,"ADD $newsql"); }else{ //this is an existing column, let's make sure the //descriptors match. $oldsql = descriptor_createsql($existing[$key]); if ($oldsql != $newsql){ //this descriptor line has changed. Change the //table to suit. debug("Old: $oldsql
New:$newsql"); if ($existing[$key]['type']=="key" || $existing[$key]['type']=="unique key"){ array_push($changes, "DROP KEY {$existing[$key]['name']}"); array_push($changes,"ADD $newsql"); }elseif ($existing[$key]['type']=="primary key"){ array_push($changes,"DROP PRIMARY KEY"); array_push($changes,"ADD $newsql"); }else{ array_push($changes, "CHANGE {$existing[$key]['name']} $newsql"); } }//end if }//end if unset($existing[$key]); }//end while //drop no longer needed columns if (!$nodrop){ reset($existing); while (list($key,$val)=each($existing)){ //This column no longer exists. if ($val['type']=="key" || $val['type']=="unique key"){ $sql = "DROP KEY {$val['name']}"; }elseif ($val['type']=="primary key"){ $sql = "DROP PRIMARY KEY"; }else{ $sql = "DROP {$val['name']}"; } array_push($changes,$sql); }//end while } if (count($changes)>0) { //we have changes to do! Woohoo! $sql = "ALTER TABLE $tablename \n".join(",\n",$changes); debug(nl2br($sql)); db_query($sql); return count($changes); } }//end if }//end function function table_create_from_descriptor($tablename,$descriptor){ $sql = "CREATE TABLE $tablename (\n"; $type = "INNODB"; reset($descriptor); $i=0; while (list($key,$val)=each($descriptor)){ if ($key === "RequireMyISAM" && $val == 1) { // Let's hope that we don't run into badly formatted strings // but you know what, if we do, tough if (db_get_server_version() < "4.0.14") { $type = "MyISAM"; } continue; } elseif ($key === "RequireMyISAM") { continue; } if (!isset($val['name'])) { if (($val['type']=="key" || $val['type']=="unique key" || $val['type']=="primary key")){ if (substr($key,0,4)=="key-"){ $val['name']=substr($key,4); }else{ debug("Warning: the descriptor for $tablename includes a {$val['type']} which isn't named correctly. It should be named key-$key. In your code, it should look something like this (the important change is bolded):
\"key-$key\"=>array(\"type\"=>\"{$val['type']}\",\"columns\"=>\"{$val['columns']}\")
The consequence of this is that your keys will be destroyed and recreated each time the table is synchronized until this is addressed."); $val['name']=$key; } }else{ $val['name']=$key; } }else{ if ($val['type']=="key" || $val['type']=="unique key" || $val['type']=="primary key"){ $key = "key-".$val['name']; }else{ $key = $val['name']; } } if ($i>0) $sql.=",\n"; $sql .= descriptor_createsql($val); $i++; } $sql .= ") engine=$type"; return $sql; } function table_create_descriptor($tablename){ //this function assumes that $tablename is already passed //through db_prefix. $descriptor = array(); //fetch column desc's $sql = "DESCRIBE $tablename"; $result = db_query($sql); while ($row = db_fetch_assoc($result)){ $item = array(); $item['name']=$row['Field']; $item['type']=$row['Type']; if ($row['Null']) $item['null'] = true; if (trim($row['Default'])!="") $item['default']=$row['Default']; if (trim($row['Extra'])!=="") $item['extra']=$row['Extra']; $descriptor[$item['name']] = $item; } $sql = "SHOW KEYS FROM $tablename"; $result = db_query($sql); while ($row = db_fetch_assoc($result)){ if ($row['Seq_in_index']>1){ //this is a secondary+ column on some previous key; //add this to that column's keys. $str = $row['Column_name']; if ($row['Sub_part']) $str .= "(" . $row['Sub_part'] . ")"; $descriptor['key-'.$row['Key_name']]['columns'] .= ",".$str; }else{ $item = array(); $item['name'] = $row['Key_name']; if ($row['Key_name']=="PRIMARY") $item['type'] = "primary key"; else $item['type'] = "key"; if ($row['Non_unique']==0) $item['unique'] = true; $str = $row['Column_name']; if ($row['Sub_part']) $str .= "(" . $row['Sub_part'] . ")"; $item['columns'] = $str; $descriptor['key-'.$item['name']] = $item; }//end if }//end while return $descriptor; } function descriptor_createsql($input){ $input['type'] = descriptor_sanitize_type($input['type']); if ($input['type']=="key" || $input['type']=='unique key'){ //this is a standard index if (is_array($input['columns'])) $input['columns'] = join(",",$input['columns']); if (!isset($input['name'])) { //if the user didn't define a name we should give it one if (strpos($input['columns'],",")!==false){ //if there are multiple columns, the name is just the //first column $input['name'] = substr($input['columns'],strpos($input['columns'],",")); }else{ //if there is only one column, the key name is the same //as the column name. $input['name'] = $input['columns']; } } if (substr($input['type'],0,7)=="unique ") $input['unique'] = true; $return = (isset($input['unique']) && $input['unique']?"UNIQUE ":"") ."KEY {$input['name']} " ."({$input['columns']})"; }elseif ($input['type']=="primary key"){ //this is a primary key if (is_array($input['columns'])) $input['columns'] = join(",",$input['columns']); $return = "PRIMARY KEY ({$input['columns']})"; }else{ //this is a standard column if (!array_key_exists('extra', $input)) $input['extra']=""; $return = $input['name']." " .$input['type'] .(isset($input['null']) && $input['null']?"":" NOT NULL") .(isset($input['default']) && $input['default']>""?" default '{$input['default']}'":"") ." ".$input['extra']; } return $return; } function descriptor_sanitize_type($type){ $type = strtolower($type); $changes = array( "primary index"=>"primary key", "primary"=>"primary key", "index"=>"key", "unique index"=>"unique key", ); if (isset($changes[$type])) return $changes[$type]; else return $type; } ?>