<?php
#=
/****************************************************************************
Copyright 2002, Daniel Deycard, Jacques Messines, Alain Pomirol
(CATICE Académie de Bordeaux)

This file is part of Gibii.

Gibii is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

Gibii is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Gibii; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

****************************************************************************/


//A REFAIRE (en plus joli !) avec des objets et héritage (fichier sql, fichier gz ou autre, tableau) 
//---------

if (!isset($include_scriptSQL)) {
$include_scriptSQL=1;

//ScriptSQL.php : analyse et exécute un script SQL situé dans
//   - un fichier texte,
//   - un tableau de lignes SQL
//L'analyse est un peu fruste mais est suffisante pour les scripts "normaux",
//notamment ceux générés par mysqldump.
//e-mail : daniel.deycard@ac-bordeaux.fr.

//Contraintes pour le script SQL fourni en paramètre (fichier ou tableau) :
//   - le ";" terminant une instruction SQL doit être en fin de ligne (sauf
//     éventuels espaces et tabulations)
//   - inversement, tout ";" rencontré est ignoré sauf s'il est en fin de ligne
//   - les remarques doivent commencer en début de ligne (sauf espaces et
//     tabulations), être sur une seule ligne, et les seuls caractères
//     d'introduction d'une remarque sont "#" et "--".

//Prototype : boolean exectabSQL(array tab [,array erreur])
//le premier tableau est passé par valeur et contient le script
//le deuxième est passé par référence et contiendra les erreurs au retour avec :
//   erreur[i][0] = n° de ligne dans tab de la (i+1)ème erreur
//   erreur[i][1] = texte de l'erreur fourni par MySQL
//La "ligne" de l'erreur indique le ";" de l'instruction SQL ayant provoqué
//l'erreur

//Le résultat de la fonction est vrai sss il n'y a pas d'erreur,
//auquel cas le tableau erreur n'existe pas.

//Une utilisation possible (mais très rustique) de ce tableau est montrée
//dans la fonction SQL_afferreurs, à la fin de ce script

function SQL_exectable($tab,&$erreurs,$callback="") {
 $req="";
 $erreur=0; //indice de rangement des erreurs dans $tresult
 $result=true;
 for($i=0;$i<count($tab); $i++) {
     $ligne=trim($tab[$i]);$long=strlen($ligne);
     if ($long==0 || $ligne[0]=="#" || substr($ligne,0,2)=='--') continue;
     if ($ligne[$long-1]==";") {
         //c'est une fin d'instruction SQL
         $req.=" ".$ligne;
		 if ($callback) {
		     $cr=$callback($req);
		     }
		 else $cr=0;
         if ($cr>=0) {
             //requête acceptée, éventuellement modifiée ($cr=1)
         	$result=@mysql_query($req);
          	if (!$result) {
                 $erreurs[$erreur]['n° ligne']=$i;
                 $erreurs[$erreur]['requête']=$req;
                 $erreurs[$erreur]['erreur']=mysql_error();
                 $erreur++;
                 }
         	}
         else {
             $erreurs[$erreur]['n° ligne']=$i;
             $erreurs[$erreur]['requête']=$req;
             $erreurs[$erreur]['erreur']="Requête rejetée par le filtre '$callback'.";
             $erreur++;
             }
         $req="";
         $ligne="";
     }
     else { //la fin d'instruction n'est pas atteinte
         $req.=" ".$ligne; //on conserve
     }
 }
 if (!empty($req)) {
     $erreurs[$erreur]['n° ligne']=$i;
     //$erreurs[$erreur]['ligne']=$ligne;
     $erreurs[$erreur]['requête']=$req;
     $erreurs[$erreur]['erreur']=mysql_error();
     $erreur++;
 }
 return ($erreur==0);
}

//inutilisble avec les gros fichiers. A refaire avec lecture ligne par ligne
function SQL_execfile($fichier,&$erreurs,$callback="") {
$tab=file($fichier);
$b=SQL_exectable($tab,$erreurs,$callback);
return $b;
}

//quasi-copie de la version tableau. A refaire en plus joli, avec des objets et de la descendance !
function SQL_execgz($fichier,&$erreurs,$callback="",$verbose=false) {
$req="";
$erreur=0; //indice de rangement des erreurs dans $tresult
$compteur=0;
$result=true;
$gz=gzopen($fichier,'r');
while ($ligne=gzgets($gz)) {
	$ligne=trim($ligne);
	$long=strlen($ligne);
	if ($long==0 || $ligne[0]=="#" || substr($ligne,0,2)=='--') {
		if ($verbose) {
			if ($compteur) {
				print $compteur."<br />";
				$compteur=0;
				}
			print "$ligne<br />";
			}
		continue;
		}
	$compteur++;
	if ($ligne[$long-1]==";") {
		 //c'est une fin d'instruction SQL
		 $req.=" ".$ligne;
		 if ($callback) {
		     $cr=$callback($req);
		     }
		 else $cr=0;
		 if ($cr>=0) {
		     //requête acceptée, éventuellement modifiée ($cr=1)
		 	$result=@mysql_query($req);
		  	if (!$result) $cr=-1;
		 	}
		 if ($cr<0) {
		     $erreurs[$erreur]['n° ligne']=$i;
		     $erreurs[$erreur]['requête']=$req;
		     $erreurs[$erreur]['erreur']="Requête rejetée par le filtre '$callback'.";
		     $erreur++;
		     }
		 $req="";
		 $ligne="";
		}
	else { //la fin d'instruction n'est pas atteinte
		$req.=" ".$ligne; //on conserve
		}
	if ($compteur%1000==0 && $verbose) {
		print $compteur." - ";
		if ($compteur%2000==0) superflush();
		}
	}
if (!empty($req)) {
	$erreurs[$erreur]['n° ligne']=$i;
	//$erreurs[$erreur]['ligne']=$ligne;
	$erreurs[$erreur]['requête']=$req;
	$erreurs[$erreur]['erreur']=mysql_error();
	$erreur++;
	}
gzclose($gz);
return ($erreur==0);
}



function SQL_afferreurs($taberr) {
 $nb=count($taberr);
 if ($nb) {
    print "<table>\n";
    print "<tr><th>n° ligne</th>";
    //print "<th>ligne</th>";
    print "<th>requête</th><th>erreur</th></tr>\n";
    for ($i=0; $i<$nb; $i++) {
        print "<tr>\n";
        print "<td>".$taberr[$i]['n° ligne']."</td>\n";
        //print "<td>".$taberr[$i]['ligne']."</td>\n";
        print "<td>".$taberr[$i]['requête']."</td>\n";
        print "<td>".$taberr[$i]['erreur']."</td>\n";
        print "</tr>\n";
    } //for
    print "</table>\n";
 } // if $nb
} //function

} //if (!isset...

?>