Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

EXTRACTION/INSERTION DE CONDITIONS SQL DANS UNE REQUÊTE


Information sur la source

Catégorie :Base de données Classé sous : SQL, Requête, Filtre, remplacement, conditions Niveau : Initié Date de création : 28/02/2008 Date de mise à jour : 20/03/2008 05:46:09 Vu : 5 883

Note :
Aucune note

Commentaire sur cette source (5)
Ajouter un commentaire et/ou une note

Description

Cette fonction permet de remplacer et/ou d'insérer des conditions SQL dans une requête.
Cela est pratique pour les formulaires dynamiques dont la mise à jour repose sur les valeurs uploadées par l'internaute.

Elle est composé d'une fonction de vérification de l'intégrité du tableau de critères passé en paramètre (Verif_Interg_Tbl) et de la fonction d'extraction et d'insertion proprement dite (Place_cond_SQL)

Un petit exemple :
$SQL='SELECT Toto FROM Tata WHERE Titi<>\'Gros Minet\'';
echo $SQL donnera 'SELECT Toto FROM Tata WHERE Titi<>'Gros Minet'

$Tbl_insert[0][0]='Champ1';$Tbl_insert[0][1]=0;$Tbl_insert[0][2]='';$Tbl_insert[0][3]='or';
$Tbl_insert[1][0]='Champ2';$Tbl_insert[1][1]='C\'était';$Tbl_insert[1][2]='\'';$Tbl_insert[1][3]='';
$Tbl_insert[2][0]='Champ3';$Tbl_insert[2][1]='le temps béni';$Tbl_insert[2][2]='\'';$Tbl_insert[2][3]='and';
$Tbl_insert[3][0]='Champ4';$Tbl_insert[3][1]='de la rengaine';$Tbl_insert[3][2]='\'';$Tbl_insert[3][3]='or';
$Tbl_insert[4][0]='Champ5';$Tbl_insert[4][1]='Serge';$Tbl_insert[4][2]='\'';$Tbl_insert[4][3]='and';
$Tbl_insert[5][0]='Champ6';$Tbl_insert[5][1]='Lama';$Tbl_insert[5][2]='\'';$Tbl_insert[5][3]='or';

echo Place_cond_SQL($SQL,$Tbl_insert,'AND Titi BETWEEN \'Toi AND Moi\'') donnera

SELECT Toto FROM Tata WHERE Champ1=0 AND Champ2='C\'était' AND Champ3='le temps béni' OR Champ4='de la rengaine' AND Champ5='Serge' OR Champ6='Lama' AND Titi BETWEEN \'Toi AND Moi\''
 

Source

  • <?php
  • function Verif_Interg_Tbl(&$Tbl,$Nbre_Col=0,$Nbre_Lignes=0)
  • {
  • //Cette fonction vérifie que le nombre de colonnes et/ou de lignes attendues dans un tableau sont bien là
  • $Lignes=sizeof($Tbl);
  • if($Nbre_Lignes>0 & $Lignes!=$Nbre_Lignes) return false;//Les colonnes
  • foreach($Tbl as $Colonne)
  • {
  • if($Nbre_Col>0 & sizeof($Colonne)!=$Nbre_Col)return false; //Les colonnes des lignes du tableau
  • }
  • return true;
  • }
  • function Place_cond_SQL($Source,$Tbl_insert=array(),$Filtre_insecable="")
  • {/*Place_cond_SQL permet d'ajouter ou de remplacer les conditions de filtre existant sur une requête SQL
  • tout en concervant les paramètres de tri initiaux.
  • $Tbl_insert est un tableau dont la structure est :
  • [x][0] : Nom du champ sur lequel s'opère le filtre
  • [x][1] : Valeur à appliquer au filtre
  • [x][2] : Caractère déterminant le type de valeur ' pour String et Date
  • [x][3] : Liaison avec le critère précédent. Si vide, il sera mis par défaut AND
  • $Filtre_insecable sera toujours interprêté comme une liaison AND même s'il commence par AND ou OR.
  • Règle des liaisons entre le champ n et le champ n+1 :
  • Liaison n = AND et Liaison n+1= AND => La laison sera champ n AND champ n+1
  • Liaison n = OR et Liaison n+1= AND => La laison sera champ n AND champ n+1
  • Liaison n = OR et Liaison n+1= OR => La laison sera champ n OR champ n+1
  • Liaison n = AND et Liaison n+1= OR => La laison sera champ n OR champ n+1
  • On extrait tout sauf les conditions de filtre
  • Au pire, une requête peut avoir la nomenclature suivante
  • [...]WHERE[...]GROUP BY[...]HAVING[...]ORDER BY[...]*/
  • if(sizeof($Tbl_insert)>0) if(!Verif_Interg_Tbl($Tbl_insert,4)) die('Le tableau d\'insertion de critères n\' a pas 4 colonnes partout !<br>Veuillez vérifier la deuxième dimension []<b><u>[]</u></b>');
  • $Pds_Mot=0;
  • $Pos_Mot_cle[0] = preg_match_all("~[[:space:]]+WHERE[[:space:]]+~i",$Source,$Occurrences[0])==0 ? 0: stripos($Source,"WHERE");
  • $Pos_Mot_cle[1] = preg_match_all("~[[:space:]]+GROUP[[:space:]]+BY[[:space:]]+~i",$Source,$Occurrences[1])==0 ? 0: stripos($Source,"GROUP");
  • $Pos_Mot_cle[2] = preg_match_all("~[[:space:]]+HAVING[[:space:]]+~i",$Source,$Occurrences[2])==0 ? 0: stripos($Source,"HAVING");
  • $Pos_Mot_cle[3] = preg_match_all("~[[:space:]]+ORDER[[:space:]]+BY[[:space:]]+~i",$Source,$Occurrences[3])==0 ? 0: stripos($Source,"ORDER");
  • //On vérifie qu'il n'y a pas plusieurs occurrences pour un même mot clé
  • $Nbre_Occ=sizeof($Occurrences[0][0]);
  • if($Nbre_Occ>1)die("Il y a ".$Nbre_Occ." WHERE dans votre SQL !");
  • $Nbre_Occ=sizeof($Occurrences[1][0]);
  • if($Nbre_Occ>1)die("Il y a ".$Nbre_Occ." GROUP BY dans votre SQL !");
  • $Nbre_Occ=sizeof($Occurrences[2][0]);
  • if($Nbre_Occ>1)die("Il y a ".$Nbre_Occ." HAVING dans votre SQL !");
  • $Nbre_Occ=sizeof($Occurrences[3][0]);
  • if($Nbre_Occ>1)die("Il y a ".$Nbre_Occ." ORDER BY dans votre SQL !");
  • //On détermine quels mots clés sont présents
  • for($a=0;$a<4;$a++)
  • {
  • if($Pos_Mot_cle[$a]>0)
  • {
  • switch($a)
  • {
  • case 0:
  • $Pds_Mot+=3;
  • break;
  • case 1:
  • $Pds_Mot+=7;
  • break;
  • case 2:
  • $Pds_Mot+=9;
  • break;
  • case 3:
  • $Pds_Mot+=11;
  • break;
  • }
  • }
  • }
  • /*En fonction des cas, on élabore le SQL
  • $SQL[0] est le début du SQL avant tout mot clé de tri
  • $SQL[1] contient tout le SQL de filtrage
  • $SQL[2] pour placer le GROUP BY
  • $SQL[3] pour placer le ORDER*/
  • $SQL[0] = ''; $SQL[2] = ''; $SQL[3] = '';
  • if(preg_match("~^[[:space:]]*(AND|OR)[[:space:]]+~i",$Filtre_insecable)) $Filtre_insecable=preg_replace("~^[[:space:]]*(AND|OR)[[:space:]]+~i",'',$Filtre_insecable);
  • switch($Pds_Mot)
  • {
  • case 0: //Aucun mot clé
  • $SQL[0][0]=$Source;
  • break;
  • case 3: //WHERE
  • case 10: //WHERE+GROUP
  • case 12: //WHERE+HAVING
  • case 14: //WHERE+ORDER
  • case 19: //WHERE+GROUP+HAVING
  • case 21: //WHERE+GROUP+ORDER
  • case 23: //WHERE+HAVING+ORDER
  • case 30: //WHERE+GROUP+HAVING+ORDER
  • preg_match("~.+WHERE~is",$Source,$SQL[0]);
  • $SQL[0][0]=substr($SQL[0][0],0,strlen($SQL[0][0])-5).' ';
  • break;
  • case 7: //GROUP
  • case 16: //GROUP+HAVING
  • case 18: //GROUP+ORDER
  • case 27: //GROUP+HAVING+ORDER
  • preg_match("~.+GROUP([[:space:]]+)BY~is",$Source,$SQL[0]);
  • $SQL[0][0]=substr($SQL[0][0],0,strlen($SQL[0][0])-7-strlen($SQL[0][1])).' ';
  • break;
  • case 9: //HAVING
  • case 20: //HAVING+ORDER
  • preg_match("~.+HAVING~is",$Source,$SQL[0]);
  • $SQL[0][0]=substr($SQL[0][0],0,strlen($SQL[0][0])-6).' ';
  • break;
  • case 11: //ORDER
  • preg_match("~.ORDER+([[:space:]]+)BY~is",$Source,$SQL[0]);
  • $SQL[0][0]=substr($SQL[0][0],0,strlen($SQL[0][0])-7-strlen($SQL[0][1])).' ';
  • }
  • switch($Pds_Mot)
  • {
  • case 7:
  • case 10:
  • preg_match("~GROUP.+~is",$Source,$SQL[2]);
  • $SQL[2][0].=' ';
  • break;
  • case 16:
  • case 19:
  • case 27:
  • case 30:
  • preg_match("~GROUP.+HAVING~is",$Source,$SQL[2]);
  • $SQL[2][0]=substr($SQL[2][0],0,strlen($SQL[2][0])-6).' ';
  • break;
  • case 18:
  • case 21:
  • preg_match("~GROUP.+ORDER~is",$Source,$SQL[2]);
  • $SQL[2][0]=substr($SQL[2][0],0,strlen($SQL[2][0])-5).' ';
  • break;
  • }
  • switch($Pds_Mot)
  • {
  • case 9:
  • case 10:
  • case 11:
  • case 14:
  • case 18:
  • case 20:
  • case 21:
  • case 23:
  • case 27:
  • case 30:
  • preg_match("~ORDER.+~is",$Source,$SQL[3]);
  • break;
  • }
  • $SQL[0][0] .= ' WHERE ';
  • //On génère les critères de filtrage
  • Foreach($Tbl_insert as $Cle => $Valeur)
  • {
  • $Liaison=strlen($Tbl_insert[$Cle][3])==0 |(trim(strtoupper($Tbl_insert[$Cle][3]))!='AND' & trim(strtoupper($Tbl_insert[$Cle][3]))!='OR') ? 'AND':trim($Tbl_insert[$Cle][3]);
  • if(strlen($Tbl_insert[$Cle][1])>0) $SQL[1] .= ' '.$Liaison.' '.$Tbl_insert[$Cle][0].'='.$Tbl_insert[$Cle][2].addslashes($Tbl_insert[$Cle][1]).$Tbl_insert[$Cle][2].' '.$Liaison.' ';
  • }
  • //On enlève tout le superflus
  • If(strlen($SQL[1])>0)
  • {
  • $SQL[1]=preg_replace("~(AND|OR)[[:space:]]+AND~i","AND",$SQL[1]);
  • $SQL[1]=preg_replace("~(AND|OR)[[:space:]]+OR~i","OR",$SQL[1]);
  • }
  • //On rajoute les critères à ne pas supprimer
  • $SQL[1] .= $Filtre_insecable;
  • //On enlève l'éventuel AND ou OR de fin s'il n'y a pas de filtre insécable
  • $SQL[1]=trim($SQL[1]);
  • $SQL[1]=preg_replace("~[[:space:]]+(AND|OR)$~i","",$SQL[1]);
  • //S'il aucune condition n'est appliquée, on enlève le WHERE mis par défaut précédemment.
  • $Check_WHERE=strtoupper(rtrim($SQL[0][0]));
  • if(substr($Check_WHERE,-5)=='WHERE' & strlen($SQL[1])==0) $SQL[0][0]=substr($Check_WHERE,0,strlen($Check_WHERE)-5);
  • $SQL[0][0]=$SQL[0][0].$SQL[1].' '.$SQL[2][0].$SQL[3][0];
  • $SQL[0][0]=preg_replace("~WHERE[[:space:]]+(AND|OR)[[:space:]]+~i","WHERE ",$SQL[0][0]);
  • //On renvoie le tout
  • return $SQL[0][0];
  • }
  • ?>
<?php
function Verif_Interg_Tbl(&$Tbl,$Nbre_Col=0,$Nbre_Lignes=0)
{
  //Cette fonction vérifie que le nombre de colonnes et/ou de lignes attendues dans un tableau sont bien là
  $Lignes=sizeof($Tbl);
  if($Nbre_Lignes>0 & $Lignes!=$Nbre_Lignes) return false;//Les colonnes
  foreach($Tbl as $Colonne)
  {
    if($Nbre_Col>0 & sizeof($Colonne)!=$Nbre_Col)return false; //Les colonnes des lignes du tableau
  }
  return true;
}

function Place_cond_SQL($Source,$Tbl_insert=array(),$Filtre_insecable="")
{/*Place_cond_SQL permet d'ajouter ou de remplacer les conditions de filtre existant sur une requête SQL
tout en concervant les paramètres de tri initiaux.
$Tbl_insert est un tableau dont la structure est :
[x][0] : Nom du champ sur lequel s'opère le filtre
[x][1] : Valeur à appliquer au filtre
[x][2] : Caractère déterminant le type de valeur ' pour String et Date
[x][3] : Liaison avec le critère précédent. Si vide, il sera mis par défaut AND

$Filtre_insecable sera toujours interprêté comme une liaison AND même s'il commence par AND ou OR.

Règle des liaisons entre le champ n et le champ n+1 :

Liaison n = AND et Liaison n+1= AND => La laison sera champ n AND champ n+1
Liaison n = OR et Liaison n+1= AND => La laison sera champ n AND champ n+1
Liaison n = OR et Liaison n+1= OR => La laison sera champ n OR champ n+1
Liaison n = AND et Liaison n+1= OR => La laison sera champ n OR champ n+1

On extrait tout sauf les conditions de filtre
Au pire, une requête peut avoir la nomenclature suivante
[...]WHERE[...]GROUP BY[...]HAVING[...]ORDER BY[...]*/

if(sizeof($Tbl_insert)>0) if(!Verif_Interg_Tbl($Tbl_insert,4)) die('Le tableau d\'insertion de critères n\' a pas 4 colonnes partout !<br>Veuillez vérifier la deuxième dimension []<b><u>[]</u></b>');

$Pds_Mot=0;
$Pos_Mot_cle[0] = preg_match_all("~[[:space:]]+WHERE[[:space:]]+~i",$Source,$Occurrences[0])==0 ? 0: stripos($Source,"WHERE");
$Pos_Mot_cle[1] = preg_match_all("~[[:space:]]+GROUP[[:space:]]+BY[[:space:]]+~i",$Source,$Occurrences[1])==0 ? 0: stripos($Source,"GROUP");
$Pos_Mot_cle[2] = preg_match_all("~[[:space:]]+HAVING[[:space:]]+~i",$Source,$Occurrences[2])==0 ? 0: stripos($Source,"HAVING");
$Pos_Mot_cle[3] = preg_match_all("~[[:space:]]+ORDER[[:space:]]+BY[[:space:]]+~i",$Source,$Occurrences[3])==0 ? 0: stripos($Source,"ORDER");

//On vérifie qu'il n'y a pas plusieurs occurrences pour un même mot clé
$Nbre_Occ=sizeof($Occurrences[0][0]);
if($Nbre_Occ>1)die("Il y a ".$Nbre_Occ." WHERE dans votre SQL !");

$Nbre_Occ=sizeof($Occurrences[1][0]);
if($Nbre_Occ>1)die("Il y a ".$Nbre_Occ." GROUP BY dans votre SQL !");

$Nbre_Occ=sizeof($Occurrences[2][0]);
if($Nbre_Occ>1)die("Il y a ".$Nbre_Occ." HAVING dans votre SQL !");

$Nbre_Occ=sizeof($Occurrences[3][0]);
if($Nbre_Occ>1)die("Il y a ".$Nbre_Occ." ORDER BY dans votre SQL !");

//On détermine quels mots clés sont présents
for($a=0;$a<4;$a++)
{
  if($Pos_Mot_cle[$a]>0)
  {
    switch($a)
    {
      case 0:
      $Pds_Mot+=3;
      break;

      case 1:
      $Pds_Mot+=7;
      break;
      case 2:
      $Pds_Mot+=9;
      break;
      case 3:
      $Pds_Mot+=11;
      break;
    }
  }
}
/*En fonction des cas, on élabore le SQL
$SQL[0] est le début du SQL avant tout mot clé de tri
$SQL[1] contient tout le SQL de filtrage
$SQL[2] pour placer le GROUP BY
$SQL[3] pour placer le ORDER*/
$SQL[0] = ''; $SQL[2] = ''; $SQL[3] = '';

if(preg_match("~^[[:space:]]*(AND|OR)[[:space:]]+~i",$Filtre_insecable)) $Filtre_insecable=preg_replace("~^[[:space:]]*(AND|OR)[[:space:]]+~i",'',$Filtre_insecable);

switch($Pds_Mot)
{
  case 0:   //Aucun mot clé
  $SQL[0][0]=$Source;
  break;
  case 3:   //WHERE
  case 10:  //WHERE+GROUP
  case 12:  //WHERE+HAVING
  case 14:  //WHERE+ORDER
  case 19:  //WHERE+GROUP+HAVING
  case 21:  //WHERE+GROUP+ORDER
  case 23:  //WHERE+HAVING+ORDER
  case 30:  //WHERE+GROUP+HAVING+ORDER
    preg_match("~.+WHERE~is",$Source,$SQL[0]);
    $SQL[0][0]=substr($SQL[0][0],0,strlen($SQL[0][0])-5).' ';
  break;
  case 7:   //GROUP
  case 16:  //GROUP+HAVING
  case 18:  //GROUP+ORDER
  case 27:  //GROUP+HAVING+ORDER
    preg_match("~.+GROUP([[:space:]]+)BY~is",$Source,$SQL[0]);
    $SQL[0][0]=substr($SQL[0][0],0,strlen($SQL[0][0])-7-strlen($SQL[0][1])).' ';
  break;
  case 9:   //HAVING
  case 20:  //HAVING+ORDER
    preg_match("~.+HAVING~is",$Source,$SQL[0]);
    $SQL[0][0]=substr($SQL[0][0],0,strlen($SQL[0][0])-6).' ';
  break;
  case 11:  //ORDER
    preg_match("~.ORDER+([[:space:]]+)BY~is",$Source,$SQL[0]);
    $SQL[0][0]=substr($SQL[0][0],0,strlen($SQL[0][0])-7-strlen($SQL[0][1])).' ';
}

switch($Pds_Mot)
{
  case 7:
  case 10:
    preg_match("~GROUP.+~is",$Source,$SQL[2]);
    $SQL[2][0].=' ';
  break;
  case 16:
  case 19:
  case 27:
  case 30:
    preg_match("~GROUP.+HAVING~is",$Source,$SQL[2]);
    $SQL[2][0]=substr($SQL[2][0],0,strlen($SQL[2][0])-6).' ';
  break;
  case 18:
  case 21:
    preg_match("~GROUP.+ORDER~is",$Source,$SQL[2]);
    $SQL[2][0]=substr($SQL[2][0],0,strlen($SQL[2][0])-5).' ';
  break;
}

switch($Pds_Mot)
{
  case 9:
  case 10:
  case 11:
  case 14:
  case 18:
  case 20:
  case 21:
  case 23:
  case 27:
  case 30:
    preg_match("~ORDER.+~is",$Source,$SQL[3]);
  break;
}
$SQL[0][0] .= ' WHERE ';
//On génère les critères de filtrage
Foreach($Tbl_insert as $Cle => $Valeur)
{
  $Liaison=strlen($Tbl_insert[$Cle][3])==0 |(trim(strtoupper($Tbl_insert[$Cle][3]))!='AND' & trim(strtoupper($Tbl_insert[$Cle][3]))!='OR') ? 'AND':trim($Tbl_insert[$Cle][3]);
  if(strlen($Tbl_insert[$Cle][1])>0) $SQL[1] .= ' '.$Liaison.' '.$Tbl_insert[$Cle][0].'='.$Tbl_insert[$Cle][2].addslashes($Tbl_insert[$Cle][1]).$Tbl_insert[$Cle][2].' '.$Liaison.' ';
}
//On enlève tout le superflus
If(strlen($SQL[1])>0)
{
    $SQL[1]=preg_replace("~(AND|OR)[[:space:]]+AND~i","AND",$SQL[1]);
    $SQL[1]=preg_replace("~(AND|OR)[[:space:]]+OR~i","OR",$SQL[1]);
}
//On rajoute les critères à ne pas supprimer
$SQL[1] .= $Filtre_insecable;
//On enlève l'éventuel AND ou OR de fin s'il n'y a pas de filtre insécable
$SQL[1]=trim($SQL[1]);
$SQL[1]=preg_replace("~[[:space:]]+(AND|OR)$~i","",$SQL[1]);
//S'il aucune condition n'est appliquée, on enlève le WHERE mis par défaut précédemment.
$Check_WHERE=strtoupper(rtrim($SQL[0][0]));
if(substr($Check_WHERE,-5)=='WHERE' & strlen($SQL[1])==0) $SQL[0][0]=substr($Check_WHERE,0,strlen($Check_WHERE)-5);
$SQL[0][0]=$SQL[0][0].$SQL[1].' '.$SQL[2][0].$SQL[3][0];
$SQL[0][0]=preg_replace("~WHERE[[:space:]]+(AND|OR)[[:space:]]+~i","WHERE ",$SQL[0][0]);

//On renvoie le tout
return $SQL[0][0];
}
?>

Conclusion

Cette fonction est utilisée, entre autre sur la page http://www.vipere.lekod.com/Francais/Stats.php
 

Historique

02 mars 2008 15:01:37 :
Optimisation du code
03 mars 2008 06:10:59 :
Débugage de la ligne 154 et des PCRE qui n'étaient pas tous avec l'option i.
04 mars 2008 06:43:35 :
Débugage pour que tous les test sur la chaîne SQL soient insensible à la casse. - Changement des strpos en stripos pour la détermination de la position des mots-clés - Mise en majuscules de $Check_WHERE
04 mars 2008 06:46:50 :
Débugage pour que tous les tests sur $Source soient insensibles à la casse. - Changement des strpos en stripos - Mise en majuscules de $Check_WHERE
04 mars 2008 06:55:36 :
Débugage, pas assez de caféïne dans le sang - strtolower est remplacé par strtoupper. Pardon
05 mars 2008 06:15:03 :
Pour la récupération des tronçons de SQL servant à alimenter le tableau $SQL, activation de l'option "s" dans les PCRE des lignes 103 à 171 afin que l'extraction des parties SQL se fasse lorsque $Source s'étale sur plusieurs lignes.
13 mars 2008 09:14:19 :
Implémentation de la version 2 - Vérification de l'intégrité du tableau passé en paramètre - Possibilité de choisir AND ou OR comme critère de condition - Gestion des apostrophes pour les valeurs String
13 mars 2008 09:15:44 :
Voir ci-dessus
20 mars 2008 05:46:09 :
Débugage de la ligne 175 pour tenir compte d'un OR final.

Commentaires et avis

signaler à un administrateur
Commentaire de neigedhiver le 28/02/2008 15:49:10

Salut,

J'ai pas regardé en détails, mais à vue de nez, tu te compliques la tâche, pour ce qui est des correspondances des mots clés recherchés.
Tu donnes des valeurs, tu testes la somme de, tout ça... C'est bien laborieux.
Tu gagnerais peut-être à utiliser des constantes et des opérateurs binaires :

if ($presence_mots & MOT_WHERE) {

}
elseif ($presence_mots & MOT_HAVING) {

}

quelque chose dans le genre.
Non seulement ce serait plus facile à lire, mais tu gagnerais probablement en performances et en nombre de lignes.

Toujours dans un soucis de gain de performances, je suis persuadé que des expressions régulières compatibles Perl (PCRE) seraient plus appropriées qu'une série de strpos. Et ce serait plus facile à utiliser avec ce dont je te parle plus haut.

Sinon, pour ce qui est de l'idée... Pas mauvaise. Mais quitte à  avoir un moteur qui fait des remplacements dans une requête, autant faire un constructeur complet de requêtes.
Pour ma part, je les construit moi-même, en mettant des conditions et en concaténant. Je pense que j'y gagne encore en perfs...

signaler à un administrateur
Commentaire de 8Tnerolf8 le 28/02/2008 19:11:19

Bonsoir NEIGEDHIVER

L'idée de conception par strpos repose sur la détermination de la présence des mots clés par $Pds_Mot. Après, en fonction de la valeur de cette variable, je ne garde que ce qui n'est pas en rapport avec une condition de filtrage.

Ton idée d'utiliser les PCRE est bonne, mais on devrait quand même faire une structure de "case" identique à celle présente dans ma fonction afin de savoir qu'elle sous chaîne capturer en fonction des mots clé SQL présents.

Tu parles de constructeur complet de requêtes. Ce n'est pas le but premier de cette fonction qui est surtout utilisée pour exploiter les valeurs choisies par l'internaute en fonction d'un SQL "racine".

Toujours dans le domaine des contructeurs complets de requêtes, je suis en train de mettre au point une fonction qui génèrera le SQL complet pour des INSERT ou des UPDATE.

Dès que cette fonction sera écrite, je la publierai. Et, "Place_cond_SQL" trouvera toute sa complémentarité car ma fonction de création de requête s'appuiera sur celle-ci afin de générer les clause de conditions de filtrage pour les UPDATE.

signaler à un administrateur
Commentaire de yoman64 le 29/02/2008 09:17:00

Salut,
Bien que je sois d'accord avec neigedhiver à propos des PCRE, si tu souhaite garder tes strpos tu devrais le faire un peu mieu... en effet tu utilise 8 fois strtoupper pour rien, c'est anti-performance. Soit tu crée une variable tampon avec la chaine Upper, soit tu utilise stripos à la place de strpos.

Ensuite tu utilise 8 fois strpos alors que 4 suffierait.

Ça serait bien que tu déclare tes variables avant de les utiliser. tu incrémente $Pds_Mot , mais tu ne la déclare null part, c'est une mauvaise chose.

Au risque de démarrer un débat interminable, je crois que les ' devrait être utilisé au lieu des " puisque tu n'utilises aucune chaine n'ayant besoin d'être parser.

Ensuite de la méthode que tu le fais il peut se passer des erreurs d'interprétation si j'insère une comparaison avec un string "WHERE", il va croire qu'il y a un where même si ce n'est pas le cas.

Je crois que ce code aurait besoin d'amélioration, mais ça peut être utile...

Bonne chance

signaler à un administrateur
Commentaire de malalam le 01/03/2008 10:37:21 administrateur CS

Hello,

j'ai aussi des soucis quant à la façon de coder.
En effet, il y a bcp de redondances : si tu dois utiliser un strtoupper ou un strpos sur une même variable plusieurs fois, autant le faire une fois et stocker la valeur.
Ensuite, ton 1er tableau...
Tu crées un tableau qui a TOUJOURS 4 entrées, et dont chaque entrée à une valeur entière. Bon.
Ensuite tu boucles sur ce tableau...avec un for()...et un $a ui ira donc de 0 à 3 de toute manière.
Puis tu fais une condition pour voir si la valeur de $tableau[$a] est supérieure à 0, PUIS tu fais un switch sur...$a...qui, tu le SAIS, sera égal à 0 d'abord, puis à 1, 2 et enfin 3...
Pardonne-moi, mais boucler sur un tableau pour ensuite tester chacune de ses clefs de manière séquentielle, ça n'a pas de sens.
Puisque tu CONNAIS les clefs, autant faire un accès direct :
if($tableau[0] > 0) {$var = valeur}
Ou utiliser un foreach :
foreeach($tableau as $val) {if ($val > 0){$var = valeur}}
Ou encore plus logique : quand tu crées ce même tableau.
Bref, en réflêchissant 2mn, voilà à quoi peut se résumer toute cette partie de ton code en le condensant et en l'optimisant; sans compter qu'on peut ainsi ajouter facilement de nouveaux mots clefs et poids :
<?php
$Source = strtoupper($source);
$Pds_Mot = 0;
$aPds = array(3, 7, 9, 11);
$aNeedles = array('WHERE', 'GROUP BY', 'HAVING', 'ORDER BY');
foreach($aNeedles as $iK => $sNeedle) {
if(false !== ($iPos = strpos($Source, $sNeedle))) {
$_Pos_Mot_Clef[] = $iPos;
$Pds_Mot += $aPds[$iK];
} else {
$_Pos_Mot_Clef[] = 0;
}
}
?>
A mon avis, c'est nettement plus rapide. Et on pourrait en effet condenser encore en utilisant les PCRE.
Ceci dit, comme Neige, je pense que les opérateurs binaires seraient plus appropriés (pour la suite du code, mais cela implique évidemment de ne pas procéder ainsi pour la 1ère partie de ton code).

Bref, ton code me semble bien trop compliqué et dans le code, ET dans son utilisation en fait. Je préfère pour ma part avoir des requêtes claires que je peux relire facilement quand je mate mon code. Crois-moi, c'est vital en entreprise : on gagne du temps sur les corrections.
Mais ça reste un avis personnel.

signaler à un administrateur
Commentaire de 8Tnerolf8 le 02/03/2008 15:07:27

Tout d'abord un grand merci à NEIGEDHIVER, YOMAN64 et MALALAM pour leurs suggestions et critiques constructives.
J'ai entièrement remanié le code en fonction de leurs indications afin de l'optimiser.

Ajouter un commentaire

Discussions en rapport avec ce code source dans le forum

requête sql [ par eax ] j'ai un tout petit pbquand je faisselect * from `blabla` where `pouet`=NULLça marche pas je veux juste récupérer mes données pour pouet nulsi qqun con requête sql [ par yeble ] je débute en base de données, j'essaie de reproduire votre exemple de site marchand pour comprendre le fonctionnement.j'ai crée 2 tables (articles, ma Requête sur AS400 [ par Bruto ] Bonjour,j'essaye de lancer une connection sur un as400 et lancer une requête. J'arrive à me connecter à l'as400 via odbc ( via driver client access ) Requête SQL [ par lagombe ] Bonjour à tous,voilà, j'ai une requête SQL qui me renvoie 5 lignes quand je l'éxécute avec phpmyadmin puis lorsque je l'utilise dans du code php (avec affichage requête SQL dans pseudo frame php [ par titsuisse ] Bonjour, J'ai une petite question. J'ai construit mon site en le divisant comme un tableau. Au centre de ce tableau se trouve une page avec un includ help requête SQL [ par hargyll ] Bonsoir j'ai un probl&#232;me sur une requ&#234;te SQL que je n'arrive pas &#224; r&#233;soudre :(Je m'explique, j'aimerais faire une recherche dans u Requête et date, à l'aide !!! [ par Splite ] BonjourVoilà je voudrais executé cette requête SQL sur ma BDD, mais ca ne fonctionne pas, est ce que vous auriez une petite idée, merci $sql_delete = Pb syntax php mysql+systèmes fichiers [ par XFLR6 ] hellodsl pour ce titre un peu bizarre, mais je savais pas quoi mettre d'autre pour qualifier mon problème ...alors voila ;je V vous montrer un bout du Requête SQL [ par nino69 ] Il y a une erreur de syntaxe sur la requ&#234;te ci dessous:"SELECT jet_chantier.'".$_POST['clients']."FROM jet_chantier WHERE jet_chantier.titre_lien Problème requête MySQL [ par albator77 ] Bonjour,Je d&#233;bute en PHP, et j'ai un probl&#232;me :Si je fais la requ&#234;te suivante, il n'y a pas de probl&#232;me :$result_sql = mysql_query


Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Comparez les prix Nouvelle version


LG KP501

Entre 9€ et 159€


Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,593 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.