Пример #1
0
/**
 * Prépare le texte d'une requête avant son exécution
 *
 * Change les préfixes de tables SPIP par ceux véritables
 * 
 * @param string $query     Requête à préparer
 * @param string $db        Nom de la base de donnée
 * @param string $prefixe   Préfixe de tables à appliquer
 * @return string           Requête préparée
 */
function _mysql_traite_query($query, $db = '', $prefixe = '')
{
    if ($GLOBALS['mysql_rappel_nom_base'] and $db) {
        $pref = '`' . $db . '`.';
    } else {
        $pref = '';
    }
    if ($prefixe) {
        $pref .= $prefixe . "_";
    }
    if (!preg_match('/\\s(SET|VALUES|WHERE|DATABASE)\\s/i', $query, $regs)) {
        $suite = '';
    } else {
        $suite = strstr($query, $regs[0]);
        $query = substr($query, 0, -strlen($suite));
        // propager le prefixe en cas de requete imbriquee
        // il faut alors echapper les chaine avant de le faire, pour ne pas risquer de
        // modifier une requete qui est en fait juste du texte dans un champ
        if (stripos($suite, "SELECT") !== false) {
            list($suite, $textes) = query_echappe_textes($suite);
            if (preg_match('/^(.*?)([(]\\s*SELECT\\b.*)$/si', $suite, $r)) {
                $suite = $r[1] . _mysql_traite_query($r[2], $db, $prefixe);
            }
            $suite = query_reinjecte_textes($suite, $textes);
        }
    }
    $r = preg_replace(_SQL_PREFIXE_TABLE_MYSQL, '\\1' . $pref, $query) . $suite;
    // en option, remplacer les emoji (que mysql ne sait pas gérer) en 💩
    if (defined('_MYSQL_NOPLANES') and _MYSQL_NOPLANES and lire_meta('charset_sql_connexion') == 'utf8') {
        include_spip('inc/charsets');
        $r = utf8_noplanes($r);
    }
    #spip_log("_mysql_traite_query: " . substr($r,0, 50) . ".... $db, $prefixe", _LOG_DEBUG);
    return $r;
}
Пример #2
0
 /**
  * Transformer la requete pour SQLite
  * 
  * Enlève les textes, transforme la requête pour quelle soit
  * bien interprétée par SQLite, puis remet les textes
  * la fonction affecte `$this->query`
  */
 function traduire_requete()
 {
     //
     // 1) Protection des textes en les remplacant par des codes
     //
     // enlever les 'textes' et initialiser avec
     list($this->query, $textes) = query_echappe_textes($this->query);
     //
     // 2) Corrections de la requete
     //
     // Correction Create Database
     // Create Database -> requete ignoree
     if (strpos($this->query, 'CREATE DATABASE') === 0) {
         spip_log("Sqlite : requete non executee -> {$this->query}", 'sqlite.' . _LOG_AVERTISSEMENT);
         $this->query = "SELECT 1";
     }
     // Correction Insert Ignore
     // INSERT IGNORE -> insert (tout court et pas 'insert or replace')
     if (strpos($this->query, 'INSERT IGNORE') === 0) {
         spip_log("Sqlite : requete transformee -> {$this->query}", 'sqlite.' . _LOG_DEBUG);
         $this->query = 'INSERT ' . substr($this->query, '13');
     }
     // Correction des dates avec INTERVAL
     // utiliser sql_date_proche() de preference
     if (strpos($this->query, 'INTERVAL') !== false) {
         $this->query = preg_replace_callback("/DATE_(ADD|SUB)(.*)INTERVAL\\s+(\\d+)\\s+([a-zA-Z]+)\\)/U", array(&$this, '_remplacerDateParTime'), $this->query);
     }
     if (strpos($this->query, 'LEFT(') !== false) {
         $this->query = str_replace('LEFT(', '_LEFT(', $this->query);
     }
     if (strpos($this->query, 'TIMESTAMPDIFF(') !== false) {
         $this->query = preg_replace('/TIMESTAMPDIFF\\(\\s*([^,]*)\\s*,/Uims', "TIMESTAMPDIFF('\\1',", $this->query);
     }
     // Correction Using
     // USING (non reconnu en sqlite2)
     // problematique car la jointure ne se fait pas du coup.
     if ($this->sqlite_version == 2 && strpos($this->query, "USING") !== false) {
         spip_log("'USING (champ)' n'est pas reconnu en SQLite 2. Utilisez 'ON table1.champ = table2.champ'", 'sqlite.' . _LOG_ERREUR);
         $this->query = preg_replace('/USING\\s*\\([^\\)]*\\)/', '', $this->query);
     }
     // Correction Field
     // remplace FIELD(table,i,j,k...) par CASE WHEN table=i THEN n ... ELSE 0 END
     if (strpos($this->query, 'FIELD') !== false) {
         $this->query = preg_replace_callback('/FIELD\\s*\\(([^\\)]*)\\)/', array(&$this, '_remplacerFieldParCase'), $this->query);
     }
     // Correction des noms de tables FROM
     // mettre les bons noms de table dans from, update, insert, replace...
     if (preg_match('/\\s(SET|VALUES|WHERE|DATABASE)\\s/iS', $this->query, $regs)) {
         $suite = strstr($this->query, $regs[0]);
         $this->query = substr($this->query, 0, -strlen($suite));
     } else {
         $suite = '';
     }
     $pref = $this->prefixe ? $this->prefixe . "_" : "";
     $this->query = preg_replace('/([,\\s])spip_/S', '\\1' . $pref, $this->query) . $suite;
     // Correction zero AS x
     // pg n'aime pas 0+x AS alias, sqlite, dans le meme style,
     // n'apprecie pas du tout SELECT 0 as x ... ORDER BY x
     // il dit que x ne doit pas être un integer dans le order by !
     // on remplace du coup x par vide() dans ce cas uniquement
     //
     // rien que pour public/vertebrer.php ?
     if (strpos($this->query, "0 AS") !== false) {
         // on ne remplace que dans ORDER BY ou GROUP BY
         if (preg_match('/\\s(ORDER|GROUP) BY\\s/i', $this->query, $regs)) {
             $suite = strstr($this->query, $regs[0]);
             $this->query = substr($this->query, 0, -strlen($suite));
             // on cherche les noms des x dans 0 AS x
             // on remplace dans $suite le nom par vide()
             preg_match_all('/\\b0 AS\\s*([^\\s,]+)/', $this->query, $matches, PREG_PATTERN_ORDER);
             foreach ($matches[1] as $m) {
                 $suite = str_replace($m, 'VIDE()', $suite);
             }
             $this->query .= $suite;
         }
     }
     // Correction possible des divisions entieres
     // Le standard SQL (lequel? ou?) semble indiquer que
     // a/b=c doit donner c entier si a et b sont entiers 4/3=1.
     // C'est ce que retournent effectivement SQL Server et SQLite
     // Ce n'est pas ce qu'applique MySQL qui retourne un reel : 4/3=1.333...
     //
     // On peut forcer la conversion en multipliant par 1.0 avant la division
     // /!\ SQLite 3.5.9 Debian/Ubuntu est victime d'un bug en plus !
     // cf. https://bugs.launchpad.net/ubuntu/+source/sqlite3/+bug/254228
     //     http://www.sqlite.org/cvstrac/tktview?tn=3202
     // (4*1.0/3) n'est pas rendu dans ce cas !
     # $this->query = str_replace('/','* 1.00 / ',$this->query);
     // Correction critere REGEXP, non reconnu en sqlite2
     if ($this->sqlite_version == 2 && strpos($this->query, 'REGEXP') !== false) {
         $this->query = preg_replace('/([^\\s\\(]*)(\\s*)REGEXP(\\s*)([^\\s\\)]*)/', 'REGEXP($4, $1)', $this->query);
     }
     //
     // 3) Remise en place des textes d'origine
     //
     // Correction Antiquotes et echappements
     // ` => rien
     if (strpos($this->query, '`') !== false) {
         $this->query = str_replace('`', '', $this->query);
     }
     $this->query = query_reinjecte_textes($this->query, $textes);
     return $this->query;
 }
Пример #3
0
/**
 * @param $query
 * @param string $db
 * @param string $prefixe
 * @return array|null|string
 */
function traite_query($query, $db = '', $prefixe = '')
{
    if ($GLOBALS['mysql_rappel_nom_base'] and $db) {
        $pref = '`' . $db . '`.';
    } else {
        $pref = '';
    }
    if ($prefixe) {
        $pref .= $prefixe . "_";
    }
    if (!preg_match('/\\s(SET|VALUES|WHERE|DATABASE)\\s/i', $query, $regs)) {
        $suite = '';
    } else {
        $suite = strstr($query, $regs[0]);
        $query = substr($query, 0, -strlen($suite));
        // propager le prefixe en cas de requete imbriquee
        // il faut alors echapper les chaine avant de le faire, pour ne pas risquer de
        // modifier une requete qui est en fait juste du texte dans un champ
        if (stripos($suite, "SELECT") !== false) {
            list($suite, $textes) = query_echappe_textes($suite);
            if (preg_match('/^(.*?)([(]\\s*SELECT\\b.*)$/si', $suite, $r)) {
                $suite = $r[1] . traite_query($r[2], $db, $prefixe);
            }
            $suite = query_reinjecte_textes($suite, $textes);
        }
    }
    $r = preg_replace(_SQL_PREFIXE_TABLE, '\\1' . $pref, $query) . $suite;
    #spip_log("traite_query: " . substr($r,0, 50) . ".... $db, $prefixe", _LOG_DEBUG);
    return $r;
}