Mysql
 sql >> Base de données >  >> RDS >> Mysql

Comment obtenir des structures de table à partir d'un fichier .frm en utilisant PHP ?

Oui il est possible de récupérer au moins une partie des informations. (Pour le bénéfice des autres lecteurs, le poseur de la question sait déjà qu'il existe des moyens plus simples d'obtenir les métadonnées de la colonne).

Le défi est que les fichiers .frm ne sont pas si bien documentés car tout besoin de les déchiffrer par la communauté générale est assez rare. Le format des fichiers peut également varier en fonction du système d'exploitation.

Cependant, en visualisant les fichiers avec hexdump ou un utilitaire similaire, vous pouvez voir en partie ce qui se passe. Alors mieux vaut lire les fichiers dans un programme PHP et décoder les données binaires brutes.

Je l'ai fait comme exercice il y a quelque temps, et j'ai pu récupérer le nombre de colonnes, les noms de colonnes et les types de colonnes.

Vous trouverez ci-dessous un exemple montrant comment extraire les noms de colonne. Mon .frm était pour un nom de table "stops", mais vous pouvez remplacer votre propre .frm.

<?php
$fileName = "stops.frm";

// read file into an array of char
//---------------------------------
$handle = fopen($fileName, "rb");
$contents = fread($handle, filesize($fileName));
fclose($handle);
$fileSize=strlen($contents);  // save the filesize fot later printing

// locate the column data near the end of the file
//-------------------------------------------------
$index = 6;    // location of io_size
$io_size_lo = ord($contents[$index]);  
$io_size_hi = ord($contents[$index+1]);
$io_size = $io_size_hi *0x100 + $io_size_lo; // read IO_SIZE

$index = 10;  // location of record length
$rec_len_lo = ord($contents[$index]);
$rec_len_hi = ord($contents[$index+1]);
$rec_len = $rec_len_hi * 0x100 + $rec_len_lo; // read rec_length

// this formula uses io_size and rec_length to get to column data
$colIndex = ( (  (($io_size + $rec_len)/$io_size)   + 1) * $io_size ) + 258;
$colIndex -= 0x3000;   // this is not documented but seems to work!

// find number of columns in the table
//------------------------------------------------- 
echo PHP_EOL."Col data at 0x".dechex($colIndex).PHP_EOL;
$numCols = ord($contents[$colIndex]);

//Extract the column names
//--------------------------------------
$colNameIndex = $colIndex+0x50;   //0X50 by inspection
echo "Col names at 0x".dechex($colNameIndex).PHP_EOL;
$cols=array();
for ($col = 0; $col < $numCols; $col++){
    $nameLen = ord($contents[$colNameIndex++]);          // name length is at ist posn
    $cols[]['ColumnName']= substr($contents,$colNameIndex,$nameLen-1); // read the name
    $colNameIndex+=$nameLen+2;        // skip ahead to next name (2 byte gap after \0)
}
print_r($cols);

Cela devrait vous aider à démarrer. J'ajouterai à cela quand j'aurai le temps dans les prochains jours si vous pensez que cela va dans la bonne direction.

MODIFIER. J'ai mis à jour le code pour qu'il fonctionne pour n'importe quel fichier .frm (de Table). Bien sûr, il existe un outil gratuit pour récupérer mySQL (basé sur le moteur innoDB) disponible sur https:/ /github.com/twindb/undrop-for-innodb . Après avoir lu le code et les blogs associés, ils n'utilisent pas les fichiers .FRM pour la récupération. Les mêmes informations de table sont également stockées dans le dictionnaire innoDB et ils l'utilisent pour récupérer les formats de table, etc.

Il existe également un moyen de lire le contenu des fichiers .FRM. Ceci est décrit ici https://twindb.com /comment-récupérer-la-structure-de-la-table-de-frm-fichiers-en-ligne/ . Cependant, ils utilisent mySQL pour lire les fichiers .frm et recréer des tables à partir de là.

Il existe également un utilitaire un ensemble d'utilitaires trouvé ici https://www .mysql.com/why-mysql/presentations/mysql-utilities/ qui contient un lecteur .frm. Cela a été fait par Oracle, qui sont les seuls à connaître le format des fichiers .frm ! L'utilitaire est gratuit, vous pouvez donc le télécharger.

Oracle publie quelques informations sur le format des fichiers .frm https ://dev.mysql.com/doc/internals/en/frm-file-format.html , mais il est à la fois incomplet et incorrect ! Voir cette question Stack précédente.>https://dba.stackexchange.com/questions/208198/mysql-frm-file-format-how-to-extract-column-info

Maintenant, après tout cela, si vous voulez toujours essayer d'analyser les fichiers .frm vous-même pour le plaisir ou pour apprendre, alors vous devez être patient et passer du temps à démêler une structure assez compliquée. Si vous voulez continuer à essayer, c'est OK, mais envoyez-moi votre fichier .FRM (à example@sqldat .com ) afin que je puisse le vérifier et je vous enverrai du code PHP dans quelques jours qui extraira des informations supplémentaires comme le type de données et les tailles d'affichage.