Convertire database da/a tabelle con prefissi

6 contenuti / 0 new
Ultimo contenuto
Convertire database da/a tabelle con prefissi
AllegatoDimensione
Plain text icon sql-parser.php_.txt1.45 KB
Plain text icon test.sql_.txt973 byte
Plain text icon result.sql_.txt1.03 KB

Come copiare due database con prefissi diversi o uno con e l'altro senza prefisso.
(Tutto questo perchè aruba.it mette sempre un prefisso 'drupal_', e perchè il cliente vuole aruba.it a tutti i costi...)

Prima ho scaricato l'SQL usando mysqldump e Backup and Migrate.
Il commando di mysqldump era:

mysqldump --user=user --password=password --default-character-set=utf8 --skip-extended-insert db-name > db.sql

Poi ho dato un analisi al testo usando grep -rno "\`.*[^\`]\`" db.sql > grep.txt con qualche risultato inaspettato. mysqldump usa multiple righe per creare le tabelle se non usi --skip-extended-insert.
Andiamo vedere un pò meglio il codice generato. Primo mysqldump:

--
-- Table structure for table `webform`
--
DROP TABLE IF EXISTS `webform`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `webform` (
  `nid` int(10) unsigned NOT NULL,
  ...
  PRIMARY KEY (`nid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `webform`
--
LOCK TABLES `webform` WRITE;
/*!40000 ALTER TABLE `webform` DISABLE KEYS */;
INSERT INTO `webform` VALUES (11, ...);
INSERT INTO `webform` VALUES (21, ...);
/*!40000 ALTER TABLE `webform` ENABLE KEYS */;
UNLOCK TABLES;

Adesso quello di Backup and Migrate:
DROP TABLE IF EXISTS `webform`;
CREATE TABLE `webform` ( `nid` int(10) unsigned NOT NULL, ... PRIMARY KEY (`nid`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `webform` VALUES ('11', ...);
INSERT INTO `webform` VALUES ('21', ...);

Quindi gli commandi SQL (per entrambi) con riferimenti alle tabelle sono:
DROP TABLE IF EXISTS
CREATE TABLE
LOCK TABLES
ALTER TABLE
INSERT INTO

Bene. Ma sfortunatamente non possiamo usare sed per un ben noto problema - non si può mettere backticks (`) nel testo di sostituzione - sigh. Allora scriviamo un piccolo script PHP:
#!/usr/bin/env php
<?php
// Simple program to change the table prefix on mysqldumps
//   Usage: php sql-parser.php input-filename old-prefix new-prefix
// Example: php sql-parser.php test.sql "" "drupal_"
if ($argc != 4) {
  print "  Usage: php sql-parser.php input-filename old-prefix new-prefix\n";
  print "Example: php sql-parser.php test.sql '' 'drupal_'\n";
}
else {
  $handle = fopen($argv[1], "r");
  $old_prefix = $argv[2];
  $new_prefix = $argv[3];
  $line_number = 0;
  while (!feof($handle)) {
    $line = fgets($handle);
    $line_number++;
    // Order is important here
    if (preg_match("/^( *)INSERT *INTO *\`". $old_prefix ."(.*)/i", $line, $matches)) {
      print "INSERT INTO `". $new_prefix . $matches[2] ."\n";
    }
    else if (preg_match("/^( *)DROP *TABLE *IF *EXISTS *\`". $old_prefix ."(.*)/i", $line, $matches)) {
      print "DROP TABLE IF EXISTS `". $new_prefix . $matches[2] ."\n";
    }
    else if (preg_match("/^( *)CREATE *TABLE *\`". $old_prefix ."(.*)/i", $line, $matches)) {
      print "CREATE TABLE `". $new_prefix . $matches[2] ."\n";
    }
    else if (preg_match("/^( *)LOCK *TABLES *\`". $old_prefix ."(.*)/i", $line, $matches)) {
      print "LOCK TABLES `". $new_prefix . $matches[2] ."\n";
    }
    else if (preg_match("/(.*)ALTER *TABLE *\`". $old_prefix ."(.*)/i", $line, $matches)) {
      print $matches[1] ."ALTER TABLE `". $new_prefix . $matches[2] ."\n";
    }
    else {
      print $line;
    }
  }
  fclose($handle);
}

Non ho usato la formula (già discusso su questo sito) più semplice di:
sed -i 's/pippo_/ciccio_/g' pippodatabase.sql
perchè può creare problemi:

  1. L'opzione g significa globale, quindi potrebbe potenzialmente cambiare testo nei values di un insert
  2. (Anche ma non solo per questo motivo) potrebbe fallire silenziosamente.
  3. E impossibile aggiungere o togliere un prefisso, solo cambiarlo.

Preferisco, con decine di migliaia di righe se non centinaia di migliaia di righe che sarà mysql stesso ad urlare in dolore se c'è un errore...

Come si usa.
Utilizzo: php sql-parser.php input-filename old-prefix new-prefix
Esempio: php sql-parser.php mysqldump.sql '' 'drupal_' > modified-dump.sql

E sufficiente, come prima approccio digitare: php sql-parser.php, perchè in mancanza di parametri lui spiega cosa devi scrivere. Per utenti Linux è sufficiente scrivere ./sql-parser.php.

Allora, come test del programma stesso, puoi prendere il file test.sql_.txt, rinominandolo test.sql. Quindi lancia il programma digitando php sql-parser.php test.sql '' 'drupal_' > result.sql. Il risultato dovrebbe essere uguale al file result.sql_.txt.

Fatto il dovuto controllo (della serie fidarsi è bene, non fidarsi è meglio), adesso poi usare il programma 'sul serio' sul proprio database.

Dopo, per restaurare il db:
sudo mysql --user=user --password=password --default-character-set=utf8 db-name < modified-database.sql
Oppure, se non dispone di un terminale sul proprio server, sarà sufficiente spedire il file (magari archiviato) a phpmyadmin.

Testato questo pomeriggio (04/03/2010), prima in locale, poi trasferito su aruba.it usando phpmyadmin, su un file di 1.4MB, 22,500 statement SQL. Tutto liscio come l'olio - una volta raccolte le olive, frantumato e filtrato, ovviamente.

Commenti o migliorerie ben accettati, prima di aggiungere questo alla documentazione...

John

P.S. I file allegati vanno rinominati; basta togliere la '_.txt' finale...

ciao, grazie per il lavoro che fatto.

io purtroppo sono molto a digiuno di php.
Mi diresti passo passo cosa fare con i file che hai allegato.

Ho fatto il backup con Bascup and Migrate delle vecchie tabelle, poi sono passato all'hosting di Aruba...ma comincio a pentirmene....

Ringrazi se funziona anche per te ;-)

pepperduke wrote:
ciao, grazie per il lavoro che fatto.

pepperduke wrote:
io purtroppo sono molto a digiuno di php.
Mi diresti passo passo cosa fare con i file che hai allegato.
Ho fatto il backup con Bascup and Migrate delle vecchie tabelle, poi sono passato all'hosting di Aruba...ma comincio a pentirmene....

Già, non è sicuramente il mio hosting preferito...

Allora ho appena aggiornato la misera documentazione sopra. Gurado sotto 'Come si usa', per capire, er, come si usa.

Non so qualè il tuo OS - io uso Linux (Ubuntu). Comunque Windows o Mac che sia, devi aprire un terminale dove puoi scrivere i commandi. E' possibile che su Windows invece di 'php' devi scrivere 'php.exe'. Puoi farlo da solo o con '--version' per prima vedere se hai l'interprete PHP nel tuo path...

Se hai problemi, dimmi il tuo OS ecc. Se non riesco aiutare io, ci sarà pura qualche buon anima che mastica PHP sul tuo OS... Io penso positivo, perchè son vivo...

Più imparo, più dubito.

grazie...ma tu mi sopravvaluti....

avrei bisogno di indiazione del tipo:
1. prendi il file del backup di mysql
2. rinomina nel file pippo.php i seguenti campi...
3. copia tutto nella cartella pluto....

io ho windows xp....

"devi aprire un terminale dove puoi scrivere i commandi"
intendi il comando "esegui" nel menù start?

grazie

Allora, se il DB è abbastanza piccolo (diciamo < 5-10MB) puoi usare Backup & Migrate, altrimenti usi il panello di phpmyadmin

Una volta scaricato il file SQL (se archiviato, tipo zip o tar.gz) bisogna scompattarlo. Per Windows puoi usare 7-Zip per entrambi i formatti.

Per quanto riguardo PHP ed il mio programmino, se devi usare il menù start: Esegui... e digiti cmd
Il manuale PHP (scusa non ho trovato molto in italiano) spiega come fare per Windows: http://php.net/manual/en/install.windows.commandline.php

Più imparo, più dubito.

grazie, gentilissimo, ci provo e ti dico