-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
523 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
$config = array( | ||
"database" => array( | ||
'source' => array( 'driver' => 'mysql', | ||
'connect' => 'mysql_connect', | ||
'host' => 'localhost', | ||
'login' => 'sole', | ||
'password' => 'notocar', | ||
'database' => 'jahnet_v2', | ||
'prefix' => ''), | ||
'destination' => array( 'driver' => 'mysql', | ||
'connect' => 'mysql_connect', | ||
'host' => 'localhost', | ||
'login' => 'sole', | ||
'password' => 'notocar', | ||
'database' => 'jahnet_cake', | ||
'prefix' => '') | ||
) | ||
); | ||
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
<html> | ||
<head><title>migrate!</title></head> | ||
<body> | ||
<style type="text/css">.error{font-weight: bold; color:#900;}</style> | ||
<?php | ||
require_once('config.php'); | ||
require_once('tables.php'); | ||
|
||
$t_start = time(); | ||
|
||
$db_src = new Database($config['database']['source']); | ||
$db_dst = new Database($config['database']['destination']); | ||
|
||
foreach($tables as $table) { | ||
$src_fields = $db_src->get_table_fields($table['source']); | ||
$excluded = isset($table['exclude']) ? explode(",", $table['exclude']) : array(); | ||
$included = isset($table['include']) ? explode(",", $table['include']) : array(); | ||
if(count($excluded)>0 && count($included)>0) { | ||
ER("Error in $table: both included and excluded fields at the same time. Skipping."); | ||
continue; | ||
} else if(count($excluded)>0) { | ||
$mode = "excluding"; | ||
} else if(count($included)>0) { | ||
$mode = "including"; | ||
} | ||
|
||
$dst_fields = array(); | ||
foreach($src_fields as $name => $field) { | ||
if($mode=="excluding" && in_array($name, $excluded)) { | ||
continue; | ||
} else if($mode=="including" && !in_array($name, $included)) { | ||
continue; | ||
} | ||
if(isset($table['map']) && array_key_exists($name, $table['map'])) { | ||
$dst_name = $table['map'][$name]; | ||
$field['src_name'] = $name; | ||
} else { | ||
$dst_name = $name; | ||
} | ||
$dst_fields[$dst_name] = $field; | ||
} | ||
|
||
$table_info = | ||
array( | ||
"name" => $table['destination'], | ||
"fields" => $dst_fields | ||
); | ||
|
||
$update_mode = $db_dst->table_exists($table_info['name']); | ||
$res = $db_dst->process_table($table_info); | ||
if($res!=false) { | ||
$first_field = array_shift(array_keys($src_fields)); | ||
$query = "SELECT * FROM {$db_src->name}.$table[source] ORDER BY $first_field ASC"; | ||
$res = mysql_query($query, $db_src->dbh); | ||
while($row = mysql_fetch_assoc($res)) { | ||
if(!$update_mode) { | ||
$q_insert = "INSERT INTO {$db_dst->name}.$table[destination] "; | ||
$pairs = get_field_pairs($dst_fields, $row); | ||
$columns = implode(",", array_keys($pairs)); | ||
$values = implode(",", array_values($pairs)); | ||
$q_insert .= "($columns) VALUES ($values);"; | ||
$res_insert = mysql_query($q_insert); | ||
if(!$res_insert) { | ||
ER($res_insert.": ".mysql_error()); | ||
} | ||
} else { | ||
$q_update = "UPDATE {$db_dst->name}.$table[destination] SET "; | ||
$pairs = get_field_pairs($dst_fields, $row); | ||
$sql_pairs = array(); | ||
foreach($pairs as $field=>$value) { | ||
$sql_pairs[] = " $field = $value"; | ||
} | ||
$q_update.= implode(", ", $sql_pairs); | ||
$q_update.= " WHERE id='".$row[$table['use_key']]."'"; | ||
$res_update = mysql_query($q_update); | ||
if(!$res_update) { | ||
ER($res_update.": ".mysql_error()); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
$t_total = time() - $t_start; | ||
echo "$t_total seconds!!"; | ||
|
||
function get_field_pairs($dst_fields, $row) { | ||
$pairs = array(); | ||
foreach($dst_fields as $name=>$field) { | ||
if(isset($row[$name])) { | ||
$value = "'".addslashes($row[$name])."'"; | ||
} else if (isset($row[$field['src_name']])) { | ||
$value = "'".addslashes($row[$field['src_name']])."'"; | ||
} else { | ||
continue; | ||
} | ||
$pairs["`$name`"] = $value; | ||
} | ||
return $pairs; | ||
} | ||
|
||
class Database { | ||
var $dbh; | ||
var $name; | ||
|
||
function Database($db_config) { | ||
$f = $db_config['connect']; | ||
$this->dbh = $f($db_config['server'], $db_config['login'], $db_config['password']); | ||
$this->name = $db_config['database']; | ||
} | ||
|
||
function get_table_fields($table) { | ||
// do a show fields, return associative array | ||
$query = "SHOW FIELDS FROM {$this->name}.$table"; | ||
$res = mysql_query($query, $this->dbh); | ||
$fields = array(); | ||
while($row = mysql_fetch_assoc($res)) { | ||
$name = $row['Field']; | ||
$fields[$name]['type'] = $row['Type']; | ||
$fields[$name]['null'] = $row['Null']=="YES" ? true : false; | ||
$fields[$name]['key'] = !empty($row['Key']) ? $row['Key'] : null; | ||
$fields[$name]['default'] = isset($row['Default']) ? $row['Default'] : null; | ||
$fields[$name]['extra'] = !empty($row['Extra']) ? $row['Extra'] : null; | ||
} | ||
return $fields; | ||
} | ||
|
||
/** | ||
* take care of creating or updating the table structure (depending on the table previously existing or not) | ||
*/ | ||
function process_table($table_info) { | ||
print_r($table_info);echo "<hr />"; | ||
if($this->table_exists($table_info['name'])) { | ||
$query = "ALTER TABLE {$this->name}.`$table_info[name]`"; | ||
} else { | ||
$query = "CREATE TABLE {$this->name}.`$table_info[name]` ("; | ||
$create = true; | ||
} | ||
|
||
$columns = array(); | ||
$keys = array(); | ||
foreach($table_info['fields'] as $name => $field) { | ||
$column = "\n\t"; | ||
if(!$create) { | ||
$column .= "ADD COLUMN "; | ||
} | ||
$column .= "`$name` $field[type]"; | ||
if(!$field['null']) | ||
$column .= " NOT NULL"; | ||
if(!is_null($field['extra'])) | ||
$column .= " $field[extra]"; | ||
if(!is_null($field['default'])) | ||
$column .= " default '$field[default]'"; | ||
else | ||
$column .= " default NULL"; | ||
$columns [] = $column; | ||
|
||
if(isset($field['key'])) { | ||
$keys[$field['key']][] = $name; | ||
} | ||
} | ||
|
||
$query .= implode(",", $columns); | ||
|
||
$constraints = array(); | ||
foreach($keys as $key=>$keyfields) { | ||
for($i=0; $i<count($keyfields); $i++) { | ||
$keyfields[$i] = "`".$keyfields[$i]."`"; | ||
} | ||
$keytext = implode(",", $keyfields); | ||
if($key=="PRI") { | ||
$constraints[$key] = "PRIMARY KEY($keytext)"; | ||
} else if($key=="UNI") { | ||
$constraints[$key] = "UNIQUE($keytext)"; | ||
} | ||
if(!$create) { | ||
$constraints[$key] = "ADD ".$constraints[$key]; | ||
} | ||
} | ||
if(count($constraints)>0) { | ||
$query.= ",\n".implode(",\n", $constraints); | ||
} | ||
|
||
if($create) { | ||
$query .="\n)"; | ||
} | ||
echo "<pre>$query</pre>"; | ||
$res = mysql_query($query, $this->dbh); | ||
if($res == false) { | ||
ER(mysql_error()); | ||
} else { | ||
OK("processed"); | ||
} | ||
return $res; | ||
} | ||
|
||
function table_exists($table) { | ||
if (mysql_query("SELECT 1 FROM ".$this->name.".`".$table."` LIMIT 0", $this->dbh)) { | ||
return true; | ||
} else { | ||
return false; | ||
} | ||
} | ||
} | ||
|
||
function OK($text) { | ||
echo "<p>$text</p>"; | ||
} | ||
|
||
function ER($text) { | ||
echo "<p class=\"error\">$text</p>"; | ||
} | ||
?> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
Script for importing and transforming databases | ||
----------------------------------------------- | ||
|
||
1. Configuration | ||
2. Use it! | ||
|
||
|
||
1. Configuration | ||
================= | ||
|
||
There are two files you need to alter appropiately: | ||
|
||
a) config.php | ||
|
||
There's the definition of the source and destination databases. The syntax is the same than cake php's one. | ||
|
||
You can also use the same database as source and destination - but horrible things may happen if there are overlappings between table names. This has not been tested. | ||
|
||
b) tables.php | ||
|
||
Here you specify the tables you want to move, with the modifications required: | ||
|
||
Create an entry in $tables for each table in the source database that you want to process. This is the meaning of each parameter: | ||
|
||
- source: table name in the source database | ||
|
||
- destination: table name in the destination database | ||
|
||
- map: array containing field names in the source database and their correspondence in the destination one. This is how field names are renamed. For example, you can map fname to first_name with $map = array('fname' => 'first_name'); | ||
|
||
- exclude: comma separated list of fields you do not want to include when copying the table | ||
- include: comma separated list of fields you want to include when copying the table | ||
|
||
Please note that you can't specify exclude and include at the same time. Doing so will result in the table being skipped. | ||
|
||
The way it works depends on if 'exclude' or 'include' are specified. | ||
If 'exclude' is specified, the script will include all the fields excluding the specified ones. | ||
If 'include' is specified, the script will include only the specified fields. | ||
|
||
For example, if you need to discard more fields than the ones you want to keep, you'll use only include, avoiding a long "exclude" list. | ||
|
||
- use_key: this is only used when you need to add data from one table into an existing one, i.e. merging two tables. Specify with this the name of the source table which represents the "id" in the destination table. | ||
|
||
Example: | ||
|
||
You have two tables that you want to merge in just one, user and user_details: | ||
user (user_id, name, firstname, etc...) | ||
user_details (user_id, homepage, motto, etc...) | ||
|
||
|
||
In this case $tables will look like this ([...] means there's more irrelevant data: | ||
|
||
$tables[] = | ||
array( | ||
'source' => 'user', | ||
'destination'=> 'users', | ||
'map' => | ||
array( | ||
"user_id" => "id", | ||
"firstname" => "first_name", | ||
"lastname" => "last_name" | ||
), | ||
'exclude' => "type,flagged [...]" | ||
); | ||
|
||
$tables[] = | ||
array( | ||
'source' => 'user_details', | ||
'destination'=> 'users', | ||
'include' => "homepage", | ||
'use_key' => 'user_id' | ||
); | ||
|
||
Note how the main table users is created with the data of user table, and then the data from user_details is merged into users by specifying the destination table 'users' and the key 'user_id'. | ||
|
||
What the script does is detect the table already exist and then instead of generating series of INSERT's, it does generate UPDATE's and adding a "WHERE id = " and the value in the second table of the key you specified. In this case it would be using the value of user_details.user_id, since it's a 1:1 correspondence. | ||
|
||
2. Use it | ||
=========== | ||
|
||
For using this script, place all the files of the db_import folder inside the webroot - so that it can be accessed via a web browser. For example: http://localhost/db_import/db_import.php | ||
If there are errors they will be output. In that case it may be worth to delete all the created tables, fix the errors and re-run the script again. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
<?php | ||
$tables = array(); | ||
|
||
$tables[] = | ||
array( | ||
'source' => 'user', | ||
'destination'=> 'users', | ||
'map' => | ||
array( | ||
"user_id" => "id", | ||
"firstname" => "first_name", | ||
"lastname" => "last_name" | ||
), | ||
'exclude' => "type,flagged,address_id,shipping_address_id,billing_address_id,shiptobilling,from_site_id,pluginz_user_id,jahshaka_user_id,avatar,dob,upload_quota,uploaded_amount,deleted,deleted_date,frontpage" | ||
); | ||
|
||
$tables[] = | ||
array( | ||
'source' => 'user_details', | ||
'destination'=> 'users', | ||
'include' => "homepage,interests,movies,music,skills,role,industry,motto,loc_city,loc_country,user_description,last_updated,profile_viewed", | ||
'use_key' => "user_id" | ||
); | ||
|
||
$tables[] = | ||
array( | ||
'source' => 'user_info', | ||
'destination'=> 'users', | ||
'map' => | ||
array( | ||
'account_created' => "created", | ||
'last_modified' => "modified" | ||
), | ||
'include' => "account_created,last_modified", | ||
'use_key' => "user_id" | ||
); | ||
|
||
$tables[] = | ||
array( | ||
'source' => 'asset', | ||
'destination'=> 'assets', | ||
'map' => | ||
array( | ||
"asset_id" => "id", | ||
"lastname" => "last_name" | ||
), | ||
'exclude' => "GUID,folder" | ||
); | ||
|
||
?> |
Oops, something went wrong.