dolibarr-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Dolibarr-dev] Requetes sql et Postgresql


From: Sébastien mailing
Subject: Re: [Dolibarr-dev] Requetes sql et Postgresql
Date: Fri, 22 Mar 2013 12:48:04 +0000

Hi Marcos,

 

I know but my english is very disastrous.

I will rewrite my post in English …

 

De : dolibarr-dev-bounces+address@hidden [mailto:dolibarr-dev-bounces+address@hidden De la part de Marcos García
Envoyé : vendredi 22 mars 2013 16:39
À : Posts about Dolibarr ERP & CRM development and coding
Objet : Re: [Dolibarr-dev] Requetes sql et Postgresql

 

Hi Sebastian,

Please remember that English is the only official language for this list. If you write your messages in French, most people won't be able to understand you...

Regards, Marcos.

El 22/03/2013 13:31, "Sébastien mailing" <address@hidden> escribió:

Rebonjour,

 

J’utilise comme base de donnée postgresql pour Dolibarr et je rencontre beaucoup de soucis au niveau des types de données comme par exemple les entiers mis entre quote et/ou vide.

Je viens de passer à la 3.3.1 et je me suis retrouvé avec plein de fonction qui ne marchent plus.

 

C’est souvent le même genre de problème, les variables ne sont pas vérifiées ou mal avant d’être intégrées dans une requête.

Exemple dans l’insertion d’une propale :  $sql.= " ".(isset($this->fk_fournprice)?"'".$this->fk_fournprice."'":"null").",";

La variable fk_fournprice est dans les variables de l’objet, le test isset sera donc toujours vrai. Un test empty() serait plus approprié.

(en fait ce code n’est pas sur github, voir mon précédent mail sur la mailing list mais il y en a un peu partout des tests comme celui-là).

 

Il n’a jamais été envisagé d’utiliser une fonction pour la construction des requêtes ? Cela fournit de nombreux avantages :

-          Augmentation de la sécurité, les variables sont toujours vérifiés vis-à-vis de leur type

-          Le code est beaucoup plus lisible

-          Le code est réduit : on ne refait pas continuellement la même chose (price2num, MAIN_DB_PREFIX , escape … )

-          La construction des requêtes est transparente pour l’utilisateur vis-à-vis du gestionnaire de base de données

Les avantages sont encore nombreux et les désavantage quasiment inexistant (en tout cas je n’en vois pas)

 

Une solution à la drupal 6 est plutôt élégante : http://api.drupal.org/api/drupal/includes!database.pgsql.inc/function/db_query/6  et http://api.drupal.org/api/drupal/includes!database.inc/function/_db_query_callback/6

 

Ce qui donnerai par exemple pour dolibarr (pour le fichier pgsql.class.php), deux petites fonctions supplémentaires  (code fait rapidement sans vérification, c’est juste pour présenter la solution) :

 

/**

* Fonction pour la construction d'une requête

*             Les tables sont encadrées par {}, le préfix est ajouté automatiquement

*             Les variables sont définies à partir de leur type

*                             %d Entier

*                             %s Chaine de caractère

*                             %n Réel

*                             %p Prix

*                             %b Boolean

*                             %% Signe %

*            

*             @param string $query Chaîne de la requête à construire

*             @param mixed $args Variables à insérer dans la requête

*             @return string La requite complete

*/

function makeQuery($query, $args = array())

{

                               //récupération des variables

                               $this->query_args = is_array($args) ? $args : array($args);

 

                               //on ajoute le préfix au nom des tables

                               $query = preg_replace('`\{([a-z_]+)\}`', MAIN_DB_PREFIX .'\1', $query);    

                               

                               return preg_replace_callback('/(%d|%s|%n|%p|%b|%%)/', array(&$this, 'makeQueryCallback'), $query);

}

 

 

/**

* Callback pour remplacer les arguments de la requetes.

* Permet d'eviter des injections sql et des erreurs dués au type de données

*  @url http://api.drupal.org/api/function/_db_query_callback/6

*  @url http://api.drupal.org/api/drupal/includes!database.inc/function/_db_query_callback/6

*

* @param String $match Pattern de la variable soit sont type

* @return string La variable correctement formatée

*/

function makeQueryCallback($match)

{

 

                switch ($match[1])

                {

 

                               case '%d': //entier

                                               $value = array_shift($this->query_args);

                                               $value = (int) $value;

                                               return $value;

 

                               case '%s': //chaîne

                                               return "'".$this->escape(array_shift($this->query_args))."'";

 

                               case '%p': //prix

                                               return "'".price2num(array_shift($this->query_args))."'";

 

                               case '%n':

                                               $value = trim(array_shift($this->query_args));

                                               return is_numeric($value) && !preg_match('/x/i', $value) ? $value : '0';

 

                               case '%%':

                                               return '%';

 

                               case '%b':

                                               $val  = array_shift($this->query_args);

                                               // boolean as text

                                               return ( strtolower($val) == 'true' || $val ?  'TRUE' : 'FALSE' );

    }

}

 

 

 

On aurait du coup une requête actuellement codée comme ceci  (je prends un exemple simple):

 

$sql = 'INSERT INTO '.MAIN_DB_PREFIX.'facture_fourn_det (fk_facture_fourn)';

$sql.= ' VALUES ('.$this->id.')';

$resql = $this->db->query($sql);

 

Qui deviendrait  :

 

                $sql = 'INSERT INTO {facture_fourn_det} (fk_facture_fourn) VALUES (%d)';

                $sql  = $this->db->makeQuery($sql, $this->id);

                $resql = $this->db->query($sql);

 

 

C’est relativement simple, les données sont protégées, la lecture n’est pas plus compliquée…

Une fonction comme celle-là ne casse rien et permet de passer au fur et à mesure les requêtes sur ce système.

 

Dans l’attente de vos avis …

Cordialement,

Sébastien


_______________________________________________
Dolibarr-dev mailing list
address@hidden
https://lists.nongnu.org/mailman/listinfo/dolibarr-dev


reply via email to

[Prev in Thread] Current Thread [Next in Thread]