source: spip-zone/_plugins_/extension_mysqli/req/mysql.php @ 36714

Last change on this file since 36714 was 36714, checked in by gilles.vincent@…, 10 years ago

Ajout d'exemples issus de programmer.spip.org (meme s'il n'ont qu'un rapport lointain, a aide a comprendre)

  • Property svn:keywords set to Id
File size: 40.8 KB
Line 
1<?php
2
3/**
4 * Utilisation du connecteur MySQLi pour SPIP
5 *
6 * @license    GNU/GPL
7 * @package    plugins
8 * @subpackage mysqli
9 * @category   BDD
10 * @version    $Id: mysql.php 36714 2010-03-28 00:04:03Z gilles.vincent@gmail.com $
11 */
12
13
14if (!defined("_ECRIRE_INC_VERSION")) return;
15
16if (!extension_loaded('mysqli')) {
17        charger_php_extension('mysqli');
18}
19
20define('_DEFAULT_DB', 'spip');
21
22/**
23 * fonction pour changer la connexion aux serveurs MySQL en gardant les paramètres existants
24 *
25 * Cette fonction sert de constructeur de l'instance de connexion MySQLi
26 *
27 * @staticvar  array    $last_connect  mémorise les paramètres de connexion
28 * @param      string   $host          serveur MySQL
29 * @param      string   $port          port utilisé
30 * @param      string   $login         login MySQL
31 * @param      string   $pass          mot de passe
32 * @param      string   $db            base utilisée
33 * @param      string   $prefixe       préfixe utilisé
34 * @param      bool     $reconnect     indique si on utilise $last_connect pour se connecter
35 * @return     array
36 */
37function req_mysql_dist($host, $port, $login, $pass, $db='', $prefixe='', $reconnect=FALSE) {
38        static $last_connect = array(); // Pour se reconnecter si neccessaire
39
40        // Il faut initialiser le connexion
41        $connexion = mysqli_init();
42
43        if (!$reconnect) {
44                // On ne vient pas d'un select_db
45                // Possibilite de stocker en php.ini les parametre de connexion
46                if (!$host) $host = ini_get('mysqli.default_host');
47                if (!$host) $host = 'localhost';
48                if (!$port) $port = ini_get('mysqli.default_port');
49                if (!$login) $login = ini_get('mysqli.default_user');
50                if (!$pass) $pass = ini_get('mysqli.default_pw');
51                if (!$db) $db = _DEFAULT_DB;
52        } else {
53                if (empty($host) && empty($port) && empty($login) && empty($pass)){
54                        foreach (array('host','port','login','pass','prefixe') as $a){
55                                $$a = $last_connect[$a];
56                        }
57                }
58        }
59       
60        // Connexion proprement dite
61        // On pourrait encore jouer sur des options et sur le socket a utiliser
62        if (@$connexion->real_connect($host, $login, $pass, $db, $port)) {
63                $last_connect = array (
64                        'host' => $host,
65                        'port' => $port,
66                        'login' => $login,
67                        'pass' => $pass,
68                        'db' => $db,
69                        'prefixe' => $prefixe
70                );
71        } else {
72                return FALSE;
73        }
74
75        // Afin d'eviter les bugs, il peut etre utile d'etre en 'STRICT_ALL_TABLES' par ex.
76        // voir 'STRICT_ALL_TABLES,ANSI_QUOTES,NO_AUTO_VALUE_ON_ZERO,NO_ZERO_DATE,NO_ZERO_IN_DATE'
77        if (defined('_MYSQL_SET_SQL_MODE')) {
78                @$connexion->query("set sql_mode='"._q(_MYSQL_SET_SQL_MODE)."'");
79        }
80
81        return array(
82                'db' => $db,
83                'last' => '',
84                'prefixe' => $prefixe,
85                'link' => $connexion
86        );
87
88}
89
90/**
91 * Tableau de correspondance des appels sql / API mysqli
92 *
93 * @global  array   $GLOBALS['spip_mysql_functions_1']
94 * @name    $spip_mysql_functions_1
95 */
96$GLOBALS['spip_mysql_functions_1'] = array(
97        'alter' => 'spip_mysqli_alter',
98        'count' => 'spip_mysqli_count',
99        'countsel' => 'spip_mysqli_countsel',
100        'create' => 'spip_mysqli_create',
101        'create_base' => 'spip_mysqli_create_base',
102        'create_view' => 'spip_mysqli_create_view',
103        'date_proche' => 'spip_mysqli_date_proche',
104        'delete' => 'spip_mysqli_delete',
105        'drop_table' => 'spip_mysqli_drop_table',
106        'drop_view' => 'spip_mysqli_drop_view',
107        'errno' => 'spip_mysqli_errno',
108        'error' => 'spip_mysqli_error',
109        'explain' => 'spip_mysqli_explain',
110        'fetch' => 'spip_mysqli_fetch',
111        'seek' => 'spip_mysqli_seek',
112        'free' => 'spip_mysqli_free',
113        'hex' => 'spip_mysqli_hex',
114        'in' => 'spip_mysqli_in', 
115        'insert' => 'spip_mysqli_insert',
116        'insertq' => 'spip_mysqli_insertq',
117        'insertq_multi' => 'spip_mysqli_insertq_multi',
118        'listdbs' => 'spip_mysqli_listdbs',
119        'multi' => 'spip_mysqli_multi',
120        'optimize' => 'spip_mysqli_optimize',
121        'query' => 'spip_mysqli_query',
122        'quote' => 'spip_mysqli_quote',
123        'replace' => 'spip_mysqli_replace',
124        'replace_multi' => 'spip_mysqli_replace_multi',
125        'repair' => 'spip_mysqli_repair',
126        'select' => 'spip_mysqli_select',
127        'selectdb' => 'spip_mysqli_selectdb',
128        'set_charset' => 'spip_mysqli_set_charset',
129        'get_charset' => 'spip_mysqli_get_charset',
130        'showbase' => 'spip_mysqli_showbase',
131        'showtable' => 'spip_mysqli_showtable',
132        'update' => 'spip_mysqli_update',
133        'updateq' => 'spip_mysqli_updateq',
134        //// association de chaque nom http d'un charset aux couples MySQL
135        'charsets' => array(
136                'cp1250'=>array('charset'=>'cp1250','collation'=>'cp1250_general_ci'),
137                'cp1251'=>array('charset'=>'cp1251','collation'=>'cp1251_general_ci'),
138                'cp1256'=>array('charset'=>'cp1256','collation'=>'cp1256_general_ci'),
139                'iso-8859-1'=>array('charset'=>'latin1','collation'=>'latin1_swedish_ci'),
140                //'iso-8859-6'=>array('charset'=>'latin1','collation'=>'latin1_swedish_ci'),
141                'iso-8859-9'=>array('charset'=>'latin5','collation'=>'latin5_turkish_ci'),
142                //'iso-8859-15'=>array('charset'=>'latin1','collation'=>'latin1_swedish_ci'),
143                'utf-8'=>array('charset'=>'utf8','collation'=>'utf8_general_ci')
144                )
145        );
146
147
148/**
149 * Appelée à chaque connexion, cette requête fixe le charset utilisé pour les futures requêtes
150 *
151 * @link    http://doc.spip.org/@spip_mysql_set_charset
152 * @param   string  $charset   Le charset à utiliser
153 * @param   string  $serveur   Identifiant du serveur concerné
154 * @param   bool    $requeter  Inutilisé
155 * @param   bool    $requeter  Inutilisé
156 * @return  bool    TRUE si l'affectation a réussi
157 */
158function spip_mysqli_set_charset($charset, $serveur='',$requeter=true,$requeter=true){
159        $link = &$GLOBALS['connexions'][$serveur ? $serveur : 0]['link'];
160        $ok = FALSE;
161        if (version_compare(PHP_VERSION , '5.1.5', '>=')) {
162                $ok = $link->set_charset($charset);
163        }
164        if (!$ok) {
165            $ok = $link->query("SET NAMES '"._q($charset)."'");
166        }
167        return $ok;
168}
169
170/**
171 * Récupère les charsets disponibles
172 *
173 * @link    http://doc.spip.org/@spip_mysql_get_charset
174 * @param   array   $charset   Pattern pour restreindre les résultats
175 * @param   string  $serveur   Identifiant du serveur
176 * @param   bool    $requeter  Inutilisé
177 * @return  mysqli_result
178 */
179function spip_mysqli_get_charset($charset=array(), $serveur='',$requeter=true){
180        $connexion = &$GLOBALS['connexions'][$serveur ? $serveur : 0];
181        $connexion['last'] = $c = "SHOW CHARACTER SET"
182        . (!$charset ? '' : (" LIKE "._q($charset['charset'])));
183        $link = $connexion['link'];
184        return $link->query($c);
185}
186
187/**
188 * Fonction de requête générale, munie d'une trace à la demande
189 *
190 * @link    http://doc.spip.org/@spip_mysql_query
191 * @param   string  $query     La requête MySQL
192 * @param   string  $serveur   Identifiant du connecteur à utiliser
193 * @param   bool    $requeter  Inutilisé
194 * @return  mixed
195 */
196function spip_mysqli_query($query, $serveur='',$requeter=true) {
197
198        $connexion = &$GLOBALS['connexions'][$serveur ? $serveur : 0];
199        $prefixe = $connexion['prefixe'];
200        $link = $connexion['link'];
201        $db = $connexion['db'];
202
203        $query = traite_mysqli_query($query, $db, $prefixe);
204
205        // renvoyer la requete inerte si demandee
206        if (!$requeter) return $query;
207
208        if (isset($_GET['var_profile'])) {
209                include_spip('public/tracer');
210                $t = trace_query_start();
211        } else $t = 0 ;
212 
213        $connexion['last'] = $query;
214        $r = $link->real_query($query);
215        if ($r) $result = $link->use_result();
216        if ($result) $r = $result;
217
218        return $t ? trace_query_end($query, $t, $r , $serveur) : $r;
219}
220
221/**
222 * Modifie la structure d'une table ou base
223 *
224 * S'utilisera comme ceci :
225 * <code>
226 * sql_alter("TABLE table ADD COLUMN colonne INT");
227 * sql_alter("TABLE table ADD colonne INT"); // COLUMN est optionnel
228 * sql_alter("TABLE table CHANGE colonne colonne INT DEFAUT '0'");
229 * sql_alter("TABLE table ADD INDEX colonne (colonne)");
230 * sql_alter("TABLE table DROP INDEX colonne");
231 * sql_alter("TABLE table DROP COLUMN colonne");
232 * sql_alter("TABLE table DROP colonne"); // COLUMN est optionnel
233 * // possibilité de passer plusieurs actions :
234 * sql_alter("TABLE table DROP colonneA, DROP colonneB");
235 * </code>
236 *
237 * @link    http://doc.spip.org/@spip_mysql_alter
238 * @param   string  $query     La requête MySQL
239 * @param   string  $serveur   Identifiant du connecteur à utiliser
240 * @param   bool    $requeter  Inutilisé
241 * @return  mysqli_result
242 */
243function spip_mysqli_alter($query, $serveur='',$requeter=true){
244        return spip_mysqli_query("ALTER ".$query, $serveur, $requeter); # i.e. que PG se debrouille
245}
246
247/**
248 * Lance la défragmentation d'une table
249 *
250 * @link    http://doc.spip.org/@spip_mysql_optimize
251 * @param   string  $table     La table à défragmenter
252 * @param   string  $serveur   Identifiant du connecteur à utiliser
253 * @param   bool    $requeter  Inutilisé
254 * @return  bool
255 */
256function spip_mysqli_optimize($table, $serveur='',$requeter=true){
257        spip_mysqli_query("OPTIMIZE TABLE ". $table);
258        return true;
259}
260
261/**
262 * Obtenir des informations sur les SELECT
263 *
264 * @link    http://doc.spip.org/@spip_mysql_explain
265 * @param   string  $query         La requête MySQL
266 * @param   string  $serveur   Identifiant du connecteur à utiliser
267 * @param   bool    $requeter    Inutilisé
268 * @return  array
269 */
270function spip_mysqli_explain($query, $serveur='',$requeter=true){
271        if (strpos(ltrim($query), 'SELECT') !== 0) return array();
272        $connexion = &$GLOBALS['connexions'][$serveur ? $serveur : 0];
273        $prefixe = $connexion['prefixe'];
274        $link = $connexion['link'];
275        $db = $connexion['db'];
276
277        $query = 'EXPLAIN ' . traite_mysqli_query($query, $db, $prefixe);
278        $r = $link->query($query);
279        return $r;
280}
281
282/**
283 * fonction instance de sql_select
284 *
285 * voir ses specs dans {@link http://doc.spip.org/abstract_sql-php abstract_sql.php}<br>
286 * Traite_mysqli_query pourrait y etre fait d'avance ce serait moins cher<br>
287 * Les \n et \t sont utiles au debusqueur.
288 *
289 * La fonction {@link http://doc.spip.org/@sql_select sql_select()} est souvent couplée à
290 * {@link http://doc.spip.org/@sql_select sql_fetch()} comme ceci :
291 * <code>
292 * // sélection
293 * if ($resultats = sql_select('colonne', 'table')) {
294 *     // boucler sur les résultats
295 *     while ($res = sql_fetch($resultats)) {
296 *         // utiliser les résultats
297 *         // $res['colonne']
298 *     }
299 * }
300 * </code>
301 *
302 * @link    http://doc.spip.org/@spip_mysql_select
303 * @param   string|array    $select     liste des champs à récupérer
304 * @param   string|array    $from       Liste des tables
305 * @param   string|array    $where      Conditions que les lignes sélectionnées doivent satisfaire
306 * @param   string|array    $groupby    Colonnes qui déterminent le tri des lignes
307 * @param   string|array    $orderby    Ordre des résultats
308 * @param   string|array    $limit      Nombre de résultats + Offset
309 * @param   string          $having     Peut servir de fonction d'aggrégation
310 * @param   string          $serveur    Identifiant du connecteur à utiliser
311 * @param   bool            $requeter   Inutilisé
312 * @return  mixed
313 */
314function spip_mysqli_select($select, $from, $where='',
315                           $groupby='', $orderby='', $limit='', $having='',
316                           $serveur='',$requeter=true) {
317
318
319        $from = (!is_array($from) ? $from : spip_mysqli_select_as($from));
320        $query = 
321                  calculer_mysqli_expression('SELECT', $select, ', ')
322                . calculer_mysqli_expression('FROM', $from, ', ')
323                . calculer_mysqli_expression('WHERE', $where)
324                . calculer_mysqli_expression('GROUP BY', $groupby, ',')
325                . calculer_mysqli_expression('HAVING', $having)
326                . ($orderby ? ("\nORDER BY " . spip_mysqli_order($orderby)) :'')
327                . ($limit ? "\nLIMIT $limit" : '');
328
329        // renvoyer la requete inerte si demandee
330        if ($requeter === false) return $query;
331        $r = spip_mysqli_query($query, $serveur, $requeter);
332        return $r ? $r : $query;
333}
334
335/**
336 * Définir l'ordre des résultats
337 *
338 * 0+x avec un champ x commencant par des chiffres est converti par MySQL
339 * en le nombre qui commence x.
340 *
341 * Pas portable malheureusement, on laisse pour le moment.
342 *
343 * @link    http://doc.spip.org/@spip_mysql_order
344 * @param   string|array    $orderby   Le ou les colonnes
345 * @return  string
346 */
347function spip_mysqli_order($orderby)
348{
349        return (is_array($orderby)) ? join(", ", $orderby) :  $orderby;
350}
351
352
353/**
354 * Construction d'une expression_where
355 *
356 * @link    http://doc.spip.org/@calculer_mysqli_where
357 * @param   array|string    $v   arbre abstrait des conditions
358 * @return  string
359 */
360function calculer_mysqli_where($v)
361{
362        if (!is_array($v))
363          return $v ;
364
365        $op = array_shift($v);
366        if (!($n=count($v)))
367                return $op;
368        else {
369                $arg = calculer_mysqli_where(array_shift($v));
370                if ($n==1) {
371                          return "$op($arg)";
372                } else {
373                        $arg2 = calculer_mysqli_where(array_shift($v));
374                        if ($n==2) {
375                                return "($arg $op $arg2)";
376                        } else return "($arg $op ($arg2) : $v[0])";
377                }
378        }
379}
380
381/**
382 * Calcule un bloc d'expression MySQL
383 *
384 * @link    http://doc.spip.org/@calculer_mysql_expression
385 * @param   string          $expression   Expression déjà évaluée
386 * @param   array|string    $v            tableau des éléments à rassembler
387 * @param   string          $join         séparateur servant à rassembler les éléments de $v
388 * @return  string
389 */
390function calculer_mysqli_expression($expression, $v, $join = 'AND'){
391        if (empty($v))
392                return '';
393       
394        $exp = "\n$expression ";
395       
396        if (!is_array($v)) {
397                return $exp . $v;
398        } else {
399                if (strtoupper($join) === 'AND')
400                        return $exp . join("\n\t$join ", array_map('calculer_mysqli_where', $v));
401                else
402                        return $exp . join($join, $v);
403        }
404}
405
406/**
407 * Création de la liste des éléments à sélectionner dans la requête SQL
408 *
409 * @link    http://doc.spip.org/@spip_mysql_select_as
410 * @param   array   $args   Liste des éléments
411 * @return  string
412 */
413function spip_mysqli_select_as($args)
414{
415        $res = '';
416        foreach($args as $k => $v) {
417                if (substr($k,-1)=='@') {
418                        // c'est une jointure qui se refere au from precedent
419                        // pas de virgule
420                  $res .= '  ' . $v ;
421                }
422                else {
423                  if (!is_numeric($k)) {
424                        $p = strpos($v, " ");
425                        if ($p)
426                          $v = substr($v,0,$p) . " AS `$k`" . substr($v,$p);
427                        else $v .= " AS `$k`";
428                  }
429                     
430                  $res .= ', ' . $v ;
431                }
432        }
433        return substr($res,2);
434}
435
436/**
437 * Changer les noms des tables ($table_prefix)
438 *
439 * Quand tous les appels SQL seront abstraits on pourra l'améliorer
440 */
441define('_SQL_PREFIXE_TABLE', '/([,\s])spip_/S');
442
443/**
444 * Prépare une requête incomplète
445 *
446 * @link    http://doc.spip.org/@traite_mysql_query
447 * @param   string  $query    La requête partielle
448 * @param   string  $db       Le nom de la base
449 * @param   string  $prefixe  Prefixe des tables SPIP
450 * @return  string
451 */
452function traite_mysqli_query($query, $db='', $prefixe='') {
453
454        if ($GLOBALS['mysqli_rappel_nom_base'] AND $db)
455                $pref = '`'. $db.'`.';
456        else $pref = '';
457
458        if ($prefixe)
459                $pref .= $prefixe . "_";
460
461        if (!preg_match('/\s(SET|VALUES|WHERE|DATABASE)\s/i', $query, $regs)) {
462                $suite ='';
463        } else {
464                $suite = strstr($query, $regs[0]);
465                $query = substr($query, 0, -strlen($suite));
466                if (preg_match('/^(.*?)([(]\s*SELECT\b.*)$/si', $suite, $r)) {
467                  $suite = $r[1] . traite_mysqli_query($r[2], $db, $prefixe);
468                }
469        }
470        $r = preg_replace(_SQL_PREFIXE_TABLE, '\1'.$pref, $query) . $suite;
471        # spip_log("traite_mysqli_query: " . substr($r,0, 50) . ".... $db, $prefixe");
472        return $r;
473}
474
475/**
476 * Sélectionne une base de données par défaut pour les requêtes
477 *
478 * @link    http://doc.spip.org/@spip_mysql_selectdb
479 * @param   string  $db        Nom de la base
480 * @param   string  $serveur   Identifiant du connecteur SPIP
481 * @param   bool    $requeter  Inutilisé
482 * @return  bool    TRUE en cas de succès
483 */
484function spip_mysqli_selectdb($db, $serveur='',$requeter=true) {
485        $link = &$GLOBALS['connexions'][$serveur ? $serveur : 0]['link'];
486        return $link->select_db($db);
487}
488
489/**
490 * Retourne les bases accessibles
491 *
492 * Attention on n'a pas toujours les droits
493 *
494 * @link    http://doc.spip.org/@spip_mysql_listdbs
495 * @param   string  $serveur   Identifiant du connecteur SPIP
496 * @param   bool    $requeter  Inutilisé
497 * @return  mysqli_result
498 */
499function spip_mysqli_listdbs($serveur='',$requeter=true) {
500        return spip_mysqli_query("show databases",$serveur,$requeter);
501}
502
503/**
504 * Fonction de création d'une table SQL nommée $nom
505 *
506 * Cette fonction utilise 2 tableaux PHP :
507 * - champs: champ => type
508 * - cles: type-de-cle => champ(s)
509 *
510 * si $autoinc, c'est une auto-increment (i.e. serial) sur la Primary Key.<br>
511 * Le nom des caches doit être inférieur à 64 caractères
512 *
513 * @link    http://doc.spip.org/@spip_mysql_create
514 * @param   string  $nom        Table à créer
515 * @param   array   $champs     Liste des champs
516 * @param   array   $cles       Liste des clés
517 * @param   bool    $autoinc    TRUE si auto-increment sur la clé primaire
518 * @param   bool    $temporary  TRUE si Table temporaire
519 * @param   string  $serveur    Identifiant du connecteur concernée
520 * @param   bool    $requeter   Inutilisé
521 * @return  bool    TRUE si la création s'est bien passée
522 */
523function spip_mysqli_create($nom, $champs, $cles, $autoinc=false, $temporary=false, $serveur='',$requeter=true) {
524
525        $query = ''; $keys = ''; $s = ''; $p='';
526
527        // certains plugins declarent les tables  (permet leur inclusion dans le dump)
528        // sans les renseigner (laisse le compilo recuperer la description)
529        if (!is_array($champs) || !is_array($cles)) 
530                return;
531
532        foreach($cles as $k => $v) {
533                $keys .= "$s\n\t\t$k ($v)";
534                if ($k == "PRIMARY KEY")
535                        $p = $v;
536                $s = ",";
537        }
538        $s = '';
539       
540        $character_set = "";
541        if (@$GLOBALS['meta']['charset_sql_base'])
542                $character_set .= " CHARACTER SET ".$GLOBALS['meta']['charset_sql_base'];
543        if (@$GLOBALS['meta']['charset_collation_sql_base'])
544                $character_set .= " COLLATE ".$GLOBALS['meta']['charset_collation_sql_base'];
545
546        foreach($champs as $k => $v) {
547                if (preg_match(',([a-z]*\s*(\(\s*[0-9]*\s*\))?(\s*binary)?),i',$v,$defs)){
548                        if (preg_match(',(char|text),i',$defs[1]) AND !preg_match(',binary,i',$defs[1]) ){
549                                $v = $defs[1] . $character_set . ' ' . substr($v,strlen($defs[1]));
550                        }
551                }
552
553                $query .= "$s\n\t\t$k $v"
554                        . (($autoinc && ($p == $k) && preg_match(',\b(big|small|medium)?int\b,i', $v))
555                                ? " auto_increment"
556                                : ''
557                        );
558                $s = ",";
559        }
560        $temporary = $temporary ? 'TEMPORARY':'';
561        $q = "CREATE $temporary TABLE IF NOT EXISTS $nom ($query" . ($keys ? ",$keys" : '') . ")".
562        ($character_set?" DEFAULT $character_set":"")
563        ."\n";
564        return spip_mysqli_query($q, $serveur);
565}
566
567/**
568 * Créer une base de données sur un connecteur SPIP
569 *
570 * @param   string  $nom       Nom de la base
571 * @param   string  $serveur   Identifiant du connecteur à utiliser
572 * @param   bool    $requeter  Inutilisé
573 * @return  bool    TRUE si succès
574 */
575function spip_mysqli_create_base($nom, $serveur='',$requeter=true) {
576  return spip_mysqli_query("CREATE DATABASE `$nom`", $serveur, $requeter);
577}
578
579/**
580 * Fonction de création d'une vue SQL nommée $nom
581 *
582 * <b>Application :</b><br>
583 * Ce petit exemple montre le fonctionnement, en créant une table
584 * (bien inutile) à partir de 2 colonnes d’une rubrique :
585 * <code>
586 * $select = sql_get_select(array(
587 *         'r.titre AS t',
588 *         'r.id_rubrique AS id'
589 *     ), array(
590 *         'spip_rubriques AS r'
591 *     ));
592 * // creer la vue
593 * sql_create_view('spip_short_rub', $select);
594 * // utiliser :
595 * $titre = sql_getfetsel('t', 'spip_short_rub', 'id=8');
596 * </code>
597 * @link    http://doc.spip.org/@spip_mysql_create_view
598 * @param   string  $nom
599 * @param   string  $query_select
600 * @param   string  $serveur         Identifiant du connecteur à utiliser
601 * @param   bool    $requeter        Inutilisé
602 * @return  bool
603 */
604function spip_mysqli_create_view($nom, $query_select, $serveur='',$requeter=true) {
605        if (!$query_select) return false;
606        // vue deja presente
607        if (sql_showtable($nom, false, $serveur)) {
608                spip_log("Echec creation d'une vue sql ($nom) car celle-ci existe deja (serveur:$serveur)");
609                return false;
610        }
611       
612        $query = "CREATE VIEW $nom AS ". $query_select;
613        return spip_mysqli_query($query, $serveur, $requeter);
614}
615
616
617/**
618 * Supprime une table MySQL
619 *
620 * @link    http://doc.spip.org/@spip_mysql_drop_table
621 * @param   string  $table      La table
622 * @param   string  $exist      Est-ce qu'on teste l'existence de la table
623 * @param   string  $serveur    Identifiant du connecteur à utiliser
624 * @param   bool    $requeter   Inutilisé
625 * @return  bool    TRUE si la suppression a fonctionné
626 */
627function spip_mysqli_drop_table($table, $exist='', $serveur='',$requeter=true)
628{
629        if ($exist) $exist =" IF EXISTS";
630        return spip_mysqli_query("DROP TABLE$exist $table", $serveur, $requeter);
631}
632
633/**
634 * Supprime une vue
635 *
636 * @link    http://doc.spip.org/@spip_mysql_drop_view
637 * @param   string  $view      Nom de la vue
638 * @param   string  $exist     Doit-on tester son existence ?
639 * @param   string  $serveur   Identifiant du connecteur à utiliser
640 * @param   bool    $requeter  Inutilisé
641 * @return  bool    TRUE si la suppression a fonctionné
642 */
643function spip_mysqli_drop_view($view, $exist='', $serveur='',$requeter=true) {
644        if ($exist) $exist =" IF EXISTS";
645        return spip_mysqli_query("DROP VIEW$exist $view", $serveur, $requeter);
646}
647
648/**
649 * Liste des tables selon un certain critère
650 *
651 * @link    http://doc.spip.org/@spip_mysql_showbase
652 * @param   string  $match     Critère de recherche
653 * @param   string  $serveur   Identifiant du connecteur à utiliser
654 * @param   bool    $requeter  Inutilisé
655 * @return  mysqli_result
656 */
657function spip_mysqli_showbase($match, $serveur='',$requeter=true)
658{
659        return spip_mysqli_query("SHOW TABLES LIKE '$match'", $serveur, $requeter);
660}
661
662/**
663 * Tente la réparation d'une table
664 *
665 * @link    http://doc.spip.org/@spip_mysql_repair
666 * @param   string  $table     La table
667 * @param   string  $serveur   Identifiant du connecteur à utiliser
668 * @param   bool    $requeter  Inutilisé
669 * @return  bool    TRUE en cas de succès
670 */
671function spip_mysqli_repair($table, $serveur='',$requeter=true)
672{
673        return spip_mysqli_query("REPAIR TABLE $table", $serveur, $requeter);
674}
675
676/**
677 * Récupère la definition d'une table ou d'une vue MySQL
678 *
679 * Les éléments obtenus sont les colonnes, indexes, etc.. <br>
680 * au même format que la définition des tables de SPIP
681 *
682 * @link    http://doc.spip.org/@spip_mysql_showtable
683 * @param   string  $nom_table   nom de la table ou vue MySQL
684 * @param   string  $serveur     Identifiant du connecteur à utiliser
685 * @param   bool    $requeter    TRUE pour créer une représentation abstraite SPIP
686 * @return  mixed
687 */
688function spip_mysqli_showtable($nom_table, $serveur='',$requeter=true)
689{
690        $s = spip_mysqli_query("SHOW CREATE TABLE `$nom_table`", $serveur, $requeter);
691        if (!$s) return '';
692        if (!$requeter) return $s;
693
694        list(,$a) = mysqli_fetch_array($s ,MYSQLI_NUM);
695        if (preg_match("/^[^(),]*\((([^()]*\([^()]*\)[^()]*)*)\)[^()]*$/", $a, $r)){
696                $dec = $r[1];
697                if (preg_match("/^(.*?),([^,]*KEY.*)$/s", $dec, $r)) {
698                  $namedkeys = $r[2];
699                  $dec = $r[1];
700                }
701                else 
702                  $namedkeys = "";
703
704                $fields = array();
705                foreach(preg_split("/,\s*`/",$dec) as $v) {
706                  preg_match("/^\s*`?([^`]*)`\s*(.*)/",$v,$r);
707                  $fields[strtolower($r[1])] = $r[2];
708                }
709                $keys = array();
710
711                foreach(preg_split('/\)\s*,?/',$namedkeys) as $v) {
712                  if (preg_match("/^\s*([^(]*)\((.*)$/",$v,$r)) {
713                        $k = str_replace("`", '', trim($r[1]));
714                        $t = strtolower(str_replace("`", '', $r[2]));
715                        if ($k && !isset($keys[$k])) $keys[$k] = $t; else $keys[] = $t;
716                  }
717                }
718                $s->free();
719                return array('field' => $fields, 'key' => $keys);
720        }
721
722        $res = spip_mysqli_query("SHOW COLUMNS FROM `$nom_table`", $serveur);
723        if($res) {
724          $nfields = array();
725          $nkeys = array();
726          while($val = spip_mysqli_fetch($res)) {
727                $nfields[$val["Field"]] = $val['Type'];
728                if($val['Null']=='NO') {
729                  $nfields[$val["Field"]] .= ' NOT NULL'; 
730                }
731                if($val['Default'] === '0' || $val['Default']) {
732                  if(preg_match('/[A-Z_]/',$val['Default'])) {
733                        $nfields[$val["Field"]] .= ' DEFAULT '.$val['Default'];           
734                  } else {
735                        $nfields[$val["Field"]] .= " DEFAULT '".$val['Default']."'";             
736                  }
737                }
738                if($val['Extra'])
739                  $nfields[$val["Field"]] .= ' '.$val['Extra'];
740                if($val['Key'] == 'PRI') {
741                  $nkeys['PRIMARY KEY'] = $val["Field"];
742                } else if($val['Key'] == 'MUL') {
743                  $nkeys['KEY '.$val["Field"]] = $val["Field"];
744                } else if($val['Key'] == 'UNI') {
745                  $nkeys['UNIQUE KEY '.$val["Field"]] = $val["Field"];
746                }
747          }
748          $res->free();
749          return array('field' => $nfields, 'key' => $nkeys);
750        }
751        return "";
752}
753
754//
755// Récupération des résultats
756//
757
758/**
759 * Retourne un tableau qui correspond à la ligne lue ou NULL s'il n'y a plus
760 * de lignes dans le jeu de résultats $r.
761 *
762 * Cette fonction s’utilise en partenariat étroit avec sql_select(),
763 * souvent employé dans cette association :
764 * <code>
765 * if ($res = sql_select('colonne', 'table')) {
766 *     while ($r = sql_fetch($res)) {
767 *         // utilisation des resultats avec $r['colonne']
768 *     }
769 * }
770 * </code>
771 *
772 * @link http://doc.spip.org/@spip_mysql_fetch
773 * @param   mysqli_result   $r         Le jeu de résultats
774 * @param   int             $t         Type de résultat : MYSQLI_ASSOC, MYSQLI_NUM ou MYSQLI_BOTH
775 * @param   string          $serveur   Inutilisé
776 * @param   bool            $requeter  Inutilisé
777 * @return  mixed           le résultat sous forme de tableau ou NULL si pas de résultat
778 */
779function spip_mysqli_fetch($r, $t='', $serveur='',$requeter=true) {
780        $res = NULL;
781        if (!$t) $t = MYSQLI_ASSOC;
782        if ($r) {
783            $res = $r->fetch_array($t);
784        }
785        return $res;
786}
787
788/**
789 * Déplace le pointeur interne de résultat associé au jeu de résultats
790 * représenté par result, en le faisant pointer sur la ligne spécifiée
791 * par row_number.
792 *
793 * @param   mysqli_result  $r
794 * @param   int            $row_number
795 * @param   string         $serveur       Inutilisé
796 * @param   bool           $requeter       Inutilisé
797 * @return  bool           TRUE en cas de succès
798 */
799function spip_mysqli_seek($r, $row_number, $serveur='',$requeter=true) {
800        if ($r instanceof MySQLi_Result) {
801            $res = $r->data_seek($row_number);
802            $r->free();
803            return $res;
804        }
805}
806
807
808/**
809 * Retourne le nombre de résultats d'un SELECT.
810 *
811 * <b>Application</b> :<br>
812 * Retourner <i>false</i> s’il y a des articles dans une rubrique :
813 * <code>
814 * if (sql_countsel('spip_articles', array(
815 *    "id_rubrique=$id_rubrique",
816 *    "statut <> 'poubelle'"
817 *    ))) {
818 *    return false;
819 * }
820 * </code>
821 *
822 * @link    http://doc.spip.org/@spip_mysql_countsel
823 * @param   array|string   $from
824 * @param   array|string   $where
825 * @param   array|string   $groupby
826 * @param   array|string   $having
827 * @param   string         $serveur   Identifiant du connecteur à utiliser
828 * @param   bool           $requeter
829 * @return  mixed
830 */
831function spip_mysqli_countsel($from = array(), $where = array(),
832                             $groupby = '', $having = array(), $serveur='',$requeter=true)
833{
834        $c = !$groupby ? '*' : ('DISTINCT ' . (is_string($groupby) ? $groupby : join(',', $groupby)));
835
836        $r = spip_mysqli_select("COUNT($c)", $from, $where,'', '', '', $having, $serveur, $requeter);
837
838        if (!$requeter) return $r;
839        if (!($r)) return 0;
840        list($c) = $r->fetch_array(MYSQLI_NUM);
841        $r->free();
842        return $c;
843}
844
845/**
846 * Retourne une chaîne décrivant la dernière erreur
847 *
848 * @link    http://doc.spip.org/@spip_mysql_error
849 * @param   string   $serveur   Identifiant du connecteur à utiliser
850 * @return  string
851 */
852function spip_mysqli_error($serveur='') {
853        $connexion = &$GLOBALS['connexions'][$serveur ? $serveur : 0];
854        $link = $connexion['link'];
855        return $link->error . $connexion['last'];
856}
857
858/**
859 * Retourne le dernier code d'erreur produit.
860 *
861 * En cas de perte de connexion avec le serveur, il ne faut pas recalculer le cache.
862 *
863 * @link    http://doc.spip.org/@spip_mysql_errno
864 * @param   string  $serveur   Identifiant du connecteur à utiliser
865 * @return  int
866 */
867function spip_mysqli_errno($serveur='') {
868        $connexion = &$GLOBALS['connexions'][$serveur ? $serveur : 0];
869        $link = $connexion['link'];
870        $s = $link->errno;
871        // 2006 MySQL server has gone away
872        // 2013 Lost connection to MySQL server during query
873        if (in_array($s, array(2006,2013)))
874                define('spip_interdire_cache', true);
875        return $s;
876}
877
878/**
879 * Retourne le nombre de lignes dans le jeu de résultats.
880 *
881 * @link    http://doc.spip.org/@spip_mysql_count
882 * @param   mysqli_result   $r
883 * @param   string          $serveur   Identifiant du connecteur à utiliser
884 * @param   bool            $requeter  Inutilisé
885 * @return  int
886 */
887function spip_mysqli_count($r, $serveur='',$requeter=true) {
888        if ($r instanceof MySQLi_Result)
889            return $r->num_rows;
890}
891
892
893/**
894 * Libère la mémoire associée à un résultat.
895 *
896 * À noter que des fonctions de l’API appellent cette fonction automatiquement. C’est le cas de :
897 * - {@link http://doc.spip.org/@sql_fetsel sql_fetsel} (et {@link http://doc.spip.org/@sql_getfetsel sql_getfetsel}),
898 * - {@link http://doc.spip.org/@sql_fetch_all sql_fetch_all} (et {@link http://doc.spip.org/@sql_allfetsel sql_allfetsel}),
899 * - {@link http://doc.spip.org/@sql_in_select sql_in_select}.
900
901 * @link    http://doc.spip.org/@spip_mysql_free
902 * @param   mysqli_result   $r
903 * @param   string          $serveur    Identifiant du connecteur à utiliser
904 * @param   bool            $requeter   Inutilisé
905 * @return  void
906 */
907function spip_mysqli_free($r, $serveur='',$requeter=true) {
908        if ($r instanceof MySQLi_Result)
909            $r->free();
910}
911
912/**
913 * insère une nouvelle ligne dans une table existante.
914 *
915 * @link    http://doc.spip.org/@spip_mysql_insert
916 * @param   string  $table     La table
917 * @param   string  $champs    Liste des champs
918 * @param   string  $valeurs   valeurs de chaque champ
919 * @param   string  $desc      Inutilisé
920 * @param   string  $serveur   Identifiant du connecteur à utiliser
921 * @param   bool    $requeter  Inutilisé
922 * @return  mixed   L'identifiant de l'élément inséré, FALSE en cas d'échec
923 */
924function spip_mysqli_insert($table, $champs, $valeurs, $desc='', $serveur='',$requeter=true) {
925
926        $connexion = &$GLOBALS['connexions'][$serveur ? $serveur : 0];
927        $prefixe = $connexion['prefixe'];
928        $link = $connexion['link'];
929        $db = $connexion['db'];
930
931        if ($prefixe) $table = preg_replace('/^spip/', $prefixe, $table);
932
933        if (isset($_GET['var_profile'])) {
934                include_spip('public/tracer');
935                $t = trace_query_start();
936        } else $t = 0 ;
937 
938        $connexion['last'] = $query ="INSERT INTO $table $champs VALUES $valeurs";
939#       spip_log($query);
940        if ($link->query($query))
941                $r = $link->insert_id;
942        else $r = false;
943
944        return $t ? trace_query_end($query, $t, $r, $serveur) : $r;
945
946        // return $r ? $r : (($r===0) ? -1 : 0); pb avec le multi-base.
947}
948
949/**
950 * Insère une nouvelle ligne dans une table existante.
951 *
952 * @link    http://doc.spip.org/@spip_mysql_insertq
953 * @param   string  $table     La table
954 * @param   array   $couples   couples champ => valeur
955 * @param   array   $desc      description de la table
956 * @param   string  $serveur   Identifiant du connecteur à utiliser
957 * @param   bool    $requeter  Inutilisé
958 * @return  mixed   L'identifiant de l'élément inséré, FALSE en cas d'échec
959 */
960function spip_mysqli_insertq($table, $couples=array(), $desc=array(), $serveur='',$requeter=true) {
961
962        if (!$desc) $desc = description_table($table);
963        if (!$desc) $couples = array();
964        $fields =  isset($desc['field'])?$desc['field']:array();
965
966        foreach ($couples as $champ => $val) {
967                $couples[$champ]= spip_mysqli_cite($val, $fields[$champ]);
968        }
969
970        return spip_mysqli_insert($table, "(".join(',',array_keys($couples)).")", "(".join(',', $couples).")", $desc, $serveur, $requeter);
971}
972
973
974/**
975 * Insère plusieures lignes dans une table existante.
976 *
977 * @link    http://doc.spip.org/@spip_mysql_insertq_multi
978 * @param   string  $table         La table
979 * @param   array   $tab_couples   couples champ => valeur
980 * @param   array   $desc          description de la table
981 * @param   string  $serveur       Identifiant du connecteur à utiliser
982 * @param   bool    $requeter      Inutilisé
983 * @return  mixed   le dernier insert_id ou FALSE en cas d'échec
984 */
985function spip_mysqli_insertq_multi($table, $tab_couples=array(), $desc=array(), $serveur='',$requeter=true) {
986
987        if (!$desc) $desc = description_table($table);
988        if (!$desc) $tab_couples = array();
989        $fields =  isset($desc['field'])?$desc['field']:array();
990       
991        $cles = "(" . join(',',array_keys($tab_couples[0])) . ')';
992        $valeurs = array();
993        foreach ($tab_couples as $couples) {
994                foreach ($couples as $champ => $val){
995                        $couples[$champ]= spip_mysqli_cite($val, $fields[$champ]);
996                }
997                $valeurs[] = '(' .join(',', $couples) . ')';
998        }
999
1000        // Inserer par groupes de 100 max pour eviter un debordement de pile
1001        $r = false;
1002        do {
1003                $ins = array_slice($valeurs,0,100);
1004                $valeurs = array_slice($valeurs,100);
1005                $r = spip_mysqli_insert($table, $cles, join(', ', $ins), $desc, $serveur, $requeter);
1006        }  while (count($valeurs));
1007
1008        return $r; // dans le cas d'une table auto_increment, le dernier insert_id
1009}
1010
1011/**
1012 * Modifie une ligne dans une table existante.
1013 *
1014 * @link    http://doc.spip.org/@spip_mysql_update
1015 * @param   string  $table    La table
1016 * @param   array   $champs   tableau associatif champ => valeur
1017 * @param   string  $where    Condition que doivent respecter les lignes modifiées
1018 * @param   string  $desc     Inutilisé
1019 * @param   string  $serveur  Identifiant du connecteur à utiliser
1020 * @param   bool    $requeter
1021 * @return  mixed
1022 */
1023function spip_mysqli_update($table, $champs, $where='', $desc='', $serveur='',$requeter=true) {
1024        $set = array();
1025        foreach ($champs as $champ => $val)
1026                $set[] = $champ . "=$val";
1027        if (!empty($set))
1028                return spip_mysqli_query(
1029                          calculer_mysqli_expression('UPDATE', $table, ',')
1030                        . calculer_mysqli_expression('SET', $set, ',')
1031                        . calculer_mysqli_expression('WHERE', $where), 
1032                        $serveur, $requeter);
1033}
1034
1035/**
1036 * Modifie une ligne dans une table existante.
1037 *
1038 * les valeurs sont des constantes a mettre entre apostrophes
1039 * sauf les expressions de date lorsqu'il s'agit de fonctions SQL (NOW etc)
1040 *
1041 * @link    http://doc.spip.org/@spip_mysql_updateq
1042 * @param   string          $table    La table
1043 * @param   array           $champs   tableau associatif champ => valeur
1044 * @param   array|string    $where    Condition que doivent respecter les lignes modifiées
1045 * @param   array           $desc     description des champs de la table
1046 * @param   string          $serveur  Identifiant du connecteur à utiliser
1047 * @param   bool            $requeter
1048 * @return  mixed
1049 */
1050function spip_mysqli_updateq($table, $champs, $where='', $desc=array(), $serveur='',$requeter=true) {
1051
1052        if (!$champs) return;
1053        if (!$desc) $desc = description_table($table);
1054        if (!$desc) $champs = array(); else $fields =  $desc['field'];
1055        $set = array();
1056        foreach ($champs as $champ => $val) {
1057                $set[] = $champ . '=' . spip_mysqli_cite($val, $fields[$champ]);
1058        }
1059        return spip_mysqli_query(
1060                          calculer_mysqli_expression('UPDATE', $table, ',')
1061                        . calculer_mysqli_expression('SET', $set, ',')
1062                        . calculer_mysqli_expression('WHERE', $where),
1063                        $serveur, $requeter);
1064}
1065
1066/**
1067 * Supprime une ligne d'une table existente.
1068 *
1069 * <b>Exemple</b> :<br>
1070 * Supprimer la liaison entre des rubriques et un mot donné :
1071 * <code>
1072 * sql_delete("spip_mots_rubriques", "id_mot=$id_mot");
1073 * </code>
1074 * @link    http://doc.spip.org/@spip_mysql_delete
1075 * @param   string         $table      La table
1076 * @param   array|string   $where      Condition que doivent respecter les lignes supprimées
1077 * @param   string         $serveur    Identifiant du connecteur à utiliser
1078 * @param   bool           $requeter   Inutilisé
1079 * @return  mixed          Le nombre de lignes supprimées, FALSE en cas d'échec
1080 */
1081function spip_mysqli_delete($table, $where='', $serveur='',$requeter=true) {
1082        $res = spip_mysqli_query(
1083                          calculer_mysqli_expression('DELETE FROM', $table, ',')
1084                        . calculer_mysqli_expression('WHERE', $where),
1085                        $serveur, $requeter);
1086        if ($res){
1087                $link = $GLOBALS['connexions'][$serveur ? $serveur : 0]['link'];
1088                return $link->affected_rows;
1089        }
1090        else
1091                return false;
1092}
1093
1094/**
1095 * insère une ligne dans une table existante.
1096 *
1097 * Si une vieille ligne a la même valeur pour un index UNIQUE ou une clef primaire,
1098 * la vieille ligne sera remplacée par la nouvelle.
1099 * Le nombre de lignes affectées sera alors de 2
1100 *
1101 * @link    http://doc.spip.org/@spip_mysql_replace
1102 * @param   string  $table     La table
1103 * @param   array   $couples   tableau associatif champ => valeur
1104 * @param   array   $desc      Inutilisé
1105 * @param   string  $serveur   Identifiant du connecteur à utiliser
1106 * @param   bool    $requeter
1107 * @return  bool    FALSE en cas d'échec
1108 */
1109function spip_mysqli_replace($table, $couples, $desc=array(), $serveur='',$requeter=true) {
1110        return spip_mysqli_query("REPLACE $table (" . join(',',array_keys($couples)) . ') VALUES (' .join(',',array_map('_q', $couples)) . ')', $serveur, $requeter);
1111}
1112
1113
1114/**
1115 * Remplace plusieures lignes d'une table existente
1116 *
1117 * @link    http://doc.spip.org/@spip_mysql_replace_multi
1118 * @param   string  $table         La table
1119 * @param   array   $tab_couples   tableau associatif champ => valeur
1120 * @param   array   $desc          Inutilisé
1121 * @param   string  $serveur       Identifiant du connecteur à utiliser
1122 * @param   bool    $requeter
1123 * @return  bool
1124 */
1125function spip_mysqli_replace_multi($table, $tab_couples, $desc=array(), $serveur='',$requeter=true) {
1126        $cles = "(" . join(',',array_keys($tab_couples[0])). ')';
1127        $valeurs = array();
1128        foreach ($tab_couples as $couples) {
1129                $valeurs[] = '(' .join(',',array_map('_q', $couples)) . ')';
1130        }
1131        $valeurs = implode(', ',$valeurs);
1132        return spip_mysqli_query("REPLACE $table $cles VALUES $valeurs", $serveur, $requeter);
1133}
1134
1135
1136/**
1137 * Construit une expression pour extraire un champ multi dans une requête.
1138 *
1139 * @link    http://doc.spip.org/@spip_mysql_multi
1140 * @param   string  $objet  champ MySQL contenant éventuellement un champ multi
1141 * @param   string  $lang   code langue qui determine le champ multi à récupérer
1142 * @return  string
1143 */
1144function spip_mysqli_multi ($objet, $lang) {
1145        $lengthlang = strlen("[$lang]");
1146        $posmulti = "INSTR(".$objet.", '<multi>')";
1147        $posfinmulti = "INSTR(".$objet.", '</multi>')";
1148        $debutchaine = "LEFT(".$objet.", $posmulti-1)";
1149        $finchaine = "RIGHT(".$objet.", CHAR_LENGTH(".$objet.") -(7+$posfinmulti))";
1150        $chainemulti = "TRIM(SUBSTRING(".$objet.", $posmulti+7, $posfinmulti -(7+$posmulti)))";
1151        $poslang = "INSTR($chainemulti,'[".$lang."]')";
1152        $poslang = "IF($poslang=0,INSTR($chainemulti,']')+1,$poslang+$lengthlang)";
1153        $chainelang = "TRIM(SUBSTRING(".$objet.", $posmulti+7+$poslang-1,$posfinmulti -($posmulti+7+$poslang-1) ))";
1154        $posfinlang = "INSTR(".$chainelang.", '[')";
1155        $chainelang = "IF($posfinlang>0,LEFT($chainelang,$posfinlang-1),$chainelang)";
1156        //$chainelang = "LEFT($chainelang,$posfinlang-1)";
1157        $retour = "(TRIM(IF($posmulti = 0 , ".
1158                "     TRIM(".$objet."), ".
1159                "     CONCAT( ".
1160                "          $debutchaine, ".
1161                "          IF( ".
1162                "               $poslang = 0, ".
1163                "                     $chainemulti, ".
1164                "               $chainelang".
1165                "          ), ". 
1166                "          $finchaine".
1167                "     ) ".
1168                "))) AS multi";
1169
1170        return $retour;
1171}
1172
1173/**
1174 * Contruire une chaîne permettant d'utiliser un code hexadécimal dans une requête.
1175 *
1176 * @link    http://doc.spip.org/@spip_mysql_hex
1177 * @param   int    $v
1178 * @return  string
1179 */
1180function spip_mysqli_hex($v)
1181{
1182        return "0x" . $v;
1183}
1184
1185/**
1186 * Echappe une chaine pour la rendre utilisable par MySQL.
1187 *
1188 * @param   mixed   $v      valeur à traiter
1189 * @param   string  $type   type
1190 * @return  mixed
1191 */
1192function spip_mysqli_quote($v, $type='')
1193{
1194        return ($type === 'int' AND !$v) ? '0' :  spip_mysqli_q($v);
1195}
1196
1197/**
1198 * Préparer un élément pour qu'il puisse être utilisé dans les requêtes plus tard.
1199 *
1200 * @link http://doc.spip.org/@_q
1201 * @internal Le traitement se fait de manière récursive sur les tableaux
1202 * @param   mixed   $a
1203 * @return  mixed
1204 */
1205function spip_mysqli_q($a) {
1206        $link = &$GLOBALS['connexions'][0]['link'];
1207        return (is_numeric($a)) ? strval($a) :
1208                (!is_array($a) ? ("'" . $link->real_escape_string($a) . "'")
1209                 : join(",", array_map('spip_mysqli_q', $a)));
1210}
1211
1212
1213/**
1214 * Calcul de date.
1215 *
1216 * @param   string   $champ
1217 * @param   int      $interval
1218 * @param   string   $unite
1219 * @return  string
1220 */
1221function spip_mysqli_date_proche($champ, $interval, $unite)
1222{
1223        return '('
1224        . $champ
1225        . (($interval <= 0) ? '>' : '<')
1226        . (($interval <= 0) ? 'DATE_SUB' : 'DATE_ADD')
1227        . '('
1228        . sql_quote(date('Y-m-d H:i:s'))
1229        . ', INTERVAL '
1230        . (($interval > 0) ? $interval : (0-$interval))
1231        . ' '
1232        . $unite
1233        . '))';
1234}
1235
1236/**
1237 * IN (...) est limité à 255 elements, d'où cette fonction assistante.
1238 *
1239 * @link    http://doc.spip.org/@spip_mysql_in
1240 * @param   string  $val
1241 * @param   string  $valeurs
1242 * @param   string  $not
1243 * @param   string  $serveur   Identifiant du connecteur à utiliser
1244 * @param   bool    $requeter  Inutilisé
1245 * @return  string
1246 */
1247function spip_mysqli_in($val, $valeurs, $not='', $serveur='',$requeter=true) {
1248        $n = $i = 0;
1249        $in_sql ="";
1250        while ($n = strpos($valeurs, ',', $n+1)) {
1251          if ((++$i) >= 255) {
1252                        $in_sql .= "($val $not IN (" .
1253                          substr($valeurs, 0, $n) .
1254                          "))\n" .
1255                          ($not ? "AND\t" : "OR\t");
1256                        $valeurs = substr($valeurs, $n+1);
1257                        $i = $n = 0;
1258                }
1259        }
1260        $in_sql .= "($val $not IN ($valeurs))";
1261
1262        return "($in_sql)";
1263}
1264
1265/**
1266 * Echappe une chaine pour l'utiliser dans une requête MySQL.
1267 *
1268 * @link    http://doc.spip.org/@spip_mysql_cite
1269 * @param   string  $v      la valeur à traiter
1270 * @param   string  $type   son type
1271 * @return  string  la chaine préparée
1272 */
1273function spip_mysqli_cite($v, $type) {
1274        $link = &$GLOBALS['connexions'][0]['link'];
1275        if (sql_test_date($type) AND preg_match('/^\w+\(/', $v)
1276        OR (sql_test_int($type)
1277                 AND (is_numeric($v)
1278                      OR (ctype_xdigit(substr($v,2))
1279                          AND $v[0]=='0' AND $v[1]=='x'))))
1280                return $v;
1281        else return  ("'" . $link->real_escape_string($v) . "'");
1282}
1283
1284
1285?>
Note: See TracBrowser for help on using the repository browser.