[SPIP][PLUGINS] v3.0-->v3.2
[lhc/web/www.git] / www / ecrire / base / abstract_sql.php
1 <?php
2
3 /* *************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2017 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
8 * *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
12
13 /**
14 * Definition de l'API SQL
15 *
16 * Ce fichier definit la couche d'abstraction entre SPIP et ses serveurs SQL.
17 * Cette version 1 est un ensemble de fonctions ecrites rapidement
18 * pour generaliser le code strictement MySQL de SPIP <= 1.9.2
19 * Des retouches sont a prevoir apres l'experience des premiers portages.
20 * Les symboles sql_* (constantes et nom de fonctions) sont reserves
21 * a cette interface, sans quoi le gestionnaire de version dysfonctionnera.
22 *
23 * @package SPIP\Core\SQL\API
24 * @version 1
25 */
26
27 if (!defined('_ECRIRE_INC_VERSION')) {
28 return;
29 }
30
31 /** Version de l'API SQL */
32 define('sql_ABSTRACT_VERSION', 1);
33 include_spip('base/connect_sql');
34
35 /**
36 * Retourne la pile de fonctions utilisée lors de la précence d'une erreur SQL
37 *
38 * @note
39 * Ignore les fonctions `include_once`, `include_spip`, `find_in_path`
40 * @param bool $compil_info
41 * - false : Retourne un texte présentant les fonctions utilisées
42 * - true : retourne un tableau indiquant un contexte de compilation à l'origine de la requête,
43 * utile pour présenter une erreur au débuggueur via `erreur_squelette()`
44 * @return array|string
45 * contexte de l'erreur
46 **/
47 function sql_error_backtrace($compil_info = false) {
48 $trace = debug_backtrace();
49 $caller = array_shift($trace);
50 while (count($trace) and (empty($trace[0]['file']) or $trace[0]['file'] === $caller['file'] or $trace[0]['file'] === __FILE__)) {
51 array_shift($trace);
52 }
53
54 if ($compil_info) {
55 $contexte_compil = array(
56 $trace[0]['file'],// sourcefile
57 '', //nom
58 (isset($trace[1]) ? $trace[1]['function'] . "(){\n" : '')
59 . $trace[0]['function'] . "();"
60 . (isset($trace[1]) ? "\n}" : ''), //id_boucle
61 $trace[0]['line'], // ligne
62 $GLOBALS['spip_lang'], // lang
63 );
64
65 return $contexte_compil;
66 }
67
68 $message = count($trace) ? $trace[0]['file'] . " L" . $trace[0]['line'] : "";
69 $f = array();
70 while (count($trace) and $t = array_shift($trace)) {
71 if (in_array($t['function'], array('include_once', 'include_spip', 'find_in_path'))) {
72 break;
73 }
74 $f[] = $t['function'];
75 }
76 if (count($f)) {
77 $message .= " [" . implode("(),", $f) . "()]";
78 }
79
80 return $message;
81 }
82
83
84 /**
85 * Charge le serveur de base de donnees
86 *
87 * Fonction principale. Elle charge l'interface au serveur de base de donnees
88 * via la fonction spip_connect_version qui etablira la connexion au besoin.
89 * Elle retourne la fonction produisant la requete SQL demandee
90 * Erreur fatale si la fonctionnalite est absente sauf si le 3e arg <> false
91 *
92 * @internal Cette fonction de base est appelee par les autres fonctions sql_*
93 * @param string $ins_sql
94 * Instruction de l'API SQL demandee (insertq, update, select...)
95 * @param string $serveur
96 * Nom du connecteur ('' pour celui par defaut a l'installation de SPIP)
97 * @param bool $continue
98 * true pour ne pas generer d'erreur si le serveur SQL ne dispose pas de la fonction demandee
99 * @return string|array
100 * Nom de la fonction a appeler pour l'instruction demandee pour le type de serveur SQL correspondant au fichier de connexion.
101 * Si l'instruction demandee n'existe pas, retourne la liste de toutes les instructions du serveur SQL avec $continue a true.
102 *
103 **/
104 function sql_serveur($ins_sql = '', $serveur = '', $continue = false) {
105 static $sql_serveur = array();
106 if (!isset($sql_serveur[$serveur][$ins_sql])) {
107 $f = spip_connect_sql(sql_ABSTRACT_VERSION, $ins_sql, $serveur, $continue);
108 if (!is_string($f) or !$f) {
109 return $f;
110 }
111 $sql_serveur[$serveur][$ins_sql] = $f;
112 }
113
114 return $sql_serveur[$serveur][$ins_sql];
115 }
116
117 /**
118 * Demande si un charset est disponible
119 *
120 * Demande si un charset (tel que utf-8) est disponible
121 * sur le gestionnaire de base de données de la connexion utilisée
122 *
123 * @api
124 * @see sql_set_charset() pour utiliser un charset
125 *
126 * @param string $charset
127 * Le charset souhaité
128 * @param string $serveur
129 * Le nom du connecteur
130 * @param bool $option
131 * Inutilise
132 * @return string|bool
133 * Retourne le nom du charset si effectivement trouvé, sinon false.
134 **/
135 function sql_get_charset($charset, $serveur = '', $option = true) {
136 // le nom http du charset differe parfois du nom SQL utf-8 ==> utf8 etc.
137 $desc = sql_serveur('', $serveur, true, true);
138 $desc = $desc[sql_ABSTRACT_VERSION];
139 $c = $desc['charsets'][$charset];
140 if ($c) {
141 if (function_exists($f = @$desc['get_charset'])) {
142 if ($f($c, $serveur, $option !== false)) {
143 return $c;
144 }
145 }
146 }
147 spip_log("SPIP ne connait pas les Charsets disponibles sur le serveur $serveur. Le serveur choisira seul.",
148 _LOG_AVERTISSEMENT);
149
150 return false;
151 }
152
153
154 /**
155 * Regler le codage de connexion
156 *
157 * Affecte un charset (tel que utf-8) sur la connexion utilisee
158 * avec le gestionnaire de base de donnees
159 *
160 * @api
161 * @see sql_get_charset() pour tester l'utilisation d'un charset
162 *
163 * @param string $charset
164 * Le charset souhaite
165 * @param string $serveur
166 * Le nom du connecteur
167 * @param bool|string $option
168 * Peut avoir 2 valeurs :
169 * - true pour executer la requete.
170 * - continue pour ne pas echouer en cas de serveur sql indisponible.
171 *
172 * @return bool
173 * Retourne true si elle reussie.
174 **/
175 function sql_set_charset($charset, $serveur = '', $option = true) {
176 $f = sql_serveur('set_charset', $serveur, $option === 'continue' or $option === false);
177 if (!is_string($f) or !$f) {
178 return false;
179 }
180
181 return $f($charset, $serveur, $option !== false);
182 }
183
184
185 /**
186 * Effectue une requête de selection
187 *
188 * Fonction de selection (SELECT), retournant la ressource interrogeable par sql_fetch.
189 *
190 * @api
191 * @see sql_fetch() Pour boucler sur les resultats de cette fonction
192 *
193 * @param array|string $select
194 * Liste des champs a recuperer (Select)
195 * @param array|string $from
196 * Tables a consulter (From)
197 * @param array|string $where
198 * Conditions a remplir (Where)
199 * @param array|string $groupby
200 * Critere de regroupement (Group by)
201 * @param array|string $orderby
202 * Tableau de classement (Order By)
203 * @param string $limit
204 * Critere de limite (Limit)
205 * @param array $having
206 * Tableau des des post-conditions a remplir (Having)
207 * @param string $serveur
208 * Le serveur sollicite (pour retrouver la connexion)
209 * @param bool|string $option
210 * Peut avoir 3 valeurs :
211 *
212 * - false -> ne pas l'exécuter mais la retourner,
213 * - continue -> ne pas echouer en cas de serveur sql indisponible,
214 * - true|array -> executer la requête.
215 * Le cas array est, pour une requete produite par le compilateur,
216 * un tableau donnnant le contexte afin d'indiquer le lieu de l'erreur au besoin
217 *
218 *
219 * @return mixed
220 * Ressource SQL
221 *
222 * - Ressource SQL pour sql_fetch, si la requete est correcte
223 * - false en cas d'erreur
224 * - Chaine contenant la requete avec $option=false
225 *
226 * Retourne false en cas d'erreur, apres l'avoir denoncee.
227 * Les portages doivent retourner la requete elle-meme en cas d'erreur,
228 * afin de disposer du texte brut.
229 *
230 **/
231 function sql_select(
232 $select = array(),
233 $from = array(),
234 $where = array(),
235 $groupby = array(),
236 $orderby = array(),
237 $limit = '',
238 $having = array(),
239 $serveur = '',
240 $option = true
241 ) {
242 $f = sql_serveur('select', $serveur, $option === 'continue' or $option === false);
243 if (!is_string($f) or !$f) {
244 return false;
245 }
246
247 $debug = (defined('_VAR_MODE') and _VAR_MODE == 'debug');
248 if (($option !== false) and !$debug) {
249 $res = $f($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur,
250 is_array($option) ? true : $option);
251 } else {
252 $query = $f($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur, false);
253 if (!$option) {
254 return $query;
255 }
256 // le debug, c'est pour ce qui a ete produit par le compilateur
257 if (isset($GLOBALS['debug']['aucasou'])) {
258 list($table, $id, ) = $GLOBALS['debug']['aucasou'];
259 $nom = $GLOBALS['debug_objets']['courant'] . $id;
260 $GLOBALS['debug_objets']['requete'][$nom] = $query;
261 }
262 $res = $f($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur, true);
263 }
264
265 // en cas d'erreur
266 if (!is_string($res)) {
267 return $res;
268 }
269 // denoncer l'erreur SQL dans sa version brute
270 spip_sql_erreur($serveur);
271 // idem dans sa version squelette (prefixe des tables non substitue)
272 $contexte_compil = sql_error_backtrace(true);
273 erreur_squelette(array(sql_errno($serveur), sql_error($serveur), $res), $contexte_compil);
274
275 return false;
276 }
277
278
279 /**
280 * Recupere la syntaxe de la requete select sans l'executer
281 *
282 * Passe simplement $option a false au lieu de true
283 * sans obliger a renseigner tous les arguments de sql_select.
284 * Les autres parametres sont identiques.
285 *
286 * @api
287 * @uses sql_select()
288 *
289 * @param array|string $select
290 * Liste des champs a recuperer (Select)
291 * @param array|string $from
292 * Tables a consulter (From)
293 * @param array|string $where
294 * Conditions a remplir (Where)
295 * @param array|string $groupby
296 * Critere de regroupement (Group by)
297 * @param array|string $orderby
298 * Tableau de classement (Order By)
299 * @param string $limit
300 * Critere de limite (Limit)
301 * @param array $having
302 * Tableau des des post-conditions a remplir (Having)
303 * @param string $serveur
304 * Le serveur sollicite (pour retrouver la connexion)
305 *
306 * @return mixed
307 * Chaine contenant la requete
308 * ou false en cas d'erreur
309 *
310 **/
311 function sql_get_select(
312 $select = array(),
313 $from = array(),
314 $where = array(),
315 $groupby = array(),
316 $orderby = array(),
317 $limit = '',
318 $having = array(),
319 $serveur = ''
320 ) {
321 return sql_select($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur, false);
322 }
323
324
325 /**
326 * Retourne le nombre de lignes d'une sélection
327 *
328 * Ramène seulement et tout de suite le nombre de lignes
329 * Pas de colonne ni de tri à donner donc.
330 *
331 * @api
332 * @see sql_count()
333 * @example
334 * ```
335 * if (sql_countsel('spip_mots_liens', array(
336 * "objet=".sql_quote('article'),
337 * "id_article=".sql_quote($id_article)) > 0) {
338 * // ...
339 * }
340 * ```
341 *
342 * @param array|string $from
343 * Tables a consulter (From)
344 * @param array|string $where
345 * Conditions a remplir (Where)
346 * @param array|string $groupby
347 * Critere de regroupement (Group by)
348 * @param array $having
349 * Tableau des des post-conditions a remplir (Having)
350 * @param string $serveur
351 * Le serveur sollicite (pour retrouver la connexion)
352 * @param bool|string $option
353 * Peut avoir 3 valeurs :
354 *
355 * - false -> ne pas l'executer mais la retourner,
356 * - continue -> ne pas echouer en cas de serveur sql indisponible,
357 * - true -> executer la requete.
358 *
359 * @return int|bool
360 * - Nombre de lignes de resultat
361 * - ou false en cas d'erreur
362 *
363 **/
364 function sql_countsel(
365 $from = array(),
366 $where = array(),
367 $groupby = array(),
368 $having = array(),
369 $serveur = '',
370 $option = true
371 ) {
372 $f = sql_serveur('countsel', $serveur, $option === 'continue' or $option === false);
373 if (!is_string($f) or !$f) {
374 return false;
375 }
376 $r = $f($from, $where, $groupby, $having, $serveur, $option !== false);
377 if ($r === false) {
378 spip_sql_erreur($serveur);
379 }
380
381 return $r;
382 }
383
384 /**
385 * Modifie la structure de la base de données
386 *
387 * Effectue une opération ALTER.
388 *
389 * @example
390 * ```
391 * sql_alter('DROP COLUMN supprimer');
392 * ```
393 *
394 * @api
395 * @param string $q
396 * La requête à exécuter (sans la préceder de 'ALTER ')
397 * @param string $serveur
398 * Le serveur sollicite (pour retrouver la connexion)
399 * @param bool|string $option
400 * Peut avoir 2 valeurs :
401 *
402 * - true : exécuter la requete
403 * - 'continue' : ne pas échouer en cas de serveur sql indisponible
404 * @return mixed
405 * 2 possibilités :
406 *
407 * - Incertain en cas d'exécution correcte de la requête
408 * - false en cas de serveur indiponible ou d'erreur
409 *
410 * Ce retour n'est pas pertinent pour savoir si l'opération est correctement réalisée.
411 **/
412 function sql_alter($q, $serveur = '', $option = true) {
413 $f = sql_serveur('alter', $serveur, $option === 'continue' or $option === false);
414 if (!is_string($f) or !$f) {
415 return false;
416 }
417 $r = $f($q, $serveur, $option !== false);
418 if ($r === false) {
419 spip_sql_erreur($serveur);
420 }
421
422 return $r;
423 }
424
425 /**
426 * Retourne un enregistrement d'une selection
427 *
428 * Retourne un resultat d'une ressource obtenue avec sql_select()
429 *
430 * @api
431 * @param mixed $res
432 * Ressource retournee par sql_select()
433 * @param string $serveur
434 * Le nom du connecteur
435 * @param bool|string $option
436 * Peut avoir 2 valeurs :
437 * - true -> executer la requete
438 * - continue -> ne pas echouer en cas de serveur sql indisponible
439 *
440 * @return array
441 * Tableau de cles (colonnes SQL ou alias) / valeurs (valeurs dans la colonne de la table ou calculee)
442 * presentant une ligne de resultat d'une selection
443 */
444 function sql_fetch($res, $serveur = '', $option = true) {
445 $f = sql_serveur('fetch', $serveur, $option === 'continue' or $option === false);
446 if (!is_string($f) or !$f) {
447 return false;
448 }
449
450 return $f($res, null, $serveur, $option !== false);
451 }
452
453
454 /**
455 * Retourne tous les enregistrements d'une selection
456 *
457 * Retourne tous les resultats d'une ressource obtenue avec sql_select()
458 * dans un tableau
459 *
460 * @api
461 * @param mixed $res
462 * Ressource retournee par sql_select()
463 * @param string $serveur
464 * Le nom du connecteur
465 * @param bool|string $option
466 * Peut avoir 2 valeurs :
467 * - true -> executer la requete
468 * - continue -> ne pas echouer en cas de serveur sql indisponible
469 *
470 * @return array
471 * Tableau contenant les enregistrements.
472 * Chaque entree du tableau est un autre tableau
473 * de cles (colonnes SQL ou alias) / valeurs (valeurs dans la colonne de la table ou calculee)
474 * presentant une ligne de resultat d'une selection
475 */
476 function sql_fetch_all($res, $serveur = '', $option = true) {
477 $rows = array();
478 if (!$res) {
479 return $rows;
480 }
481 $f = sql_serveur('fetch', $serveur, $option === 'continue' or $option === false);
482 if (!is_string($f) or !$f) {
483 return array();
484 }
485 while ($r = $f($res, null, $serveur, $option !== false)) {
486 $rows[] = $r;
487 }
488 sql_free($res, $serveur);
489
490 return $rows;
491 }
492
493 /**
494 * Déplace le pointeur d'une ressource de sélection
495 *
496 * Deplace le pointeur sur un numéro de ligne précisé
497 * sur une ressource issue de sql_select, afin que
498 * le prochain sql_fetch récupère cette ligne.
499 *
500 * @api
501 * @see sql_skip() Pour sauter des enregistrements
502 *
503 * @param mixed $res
504 * Ressource issue de sql_select
505 * @param int $row_number
506 * Numero de ligne sur laquelle placer le pointeur
507 * @param string $serveur
508 * Le nom du connecteur
509 * @param bool|string $option
510 * Peut avoir 2 valeurs :
511 * - true -> executer la requete
512 * - continue -> ne pas echouer en cas de serveur sql indisponible
513 *
514 * @return bool
515 * Operation effectuée (true), sinon false.
516 **/
517 function sql_seek($res, $row_number, $serveur = '', $option = true) {
518 $f = sql_serveur('seek', $serveur, $option === 'continue' or $option === false);
519 if (!is_string($f) or !$f) {
520 return false;
521 }
522 $r = $f($res, $row_number, $serveur, $option !== false);
523 if ($r === false) {
524 spip_sql_erreur($serveur);
525 }
526
527 return $r;
528 }
529
530
531 /**
532 * Liste des bases de donnees accessibles
533 *
534 * Retourne un tableau du nom de toutes les bases de donnees
535 * accessibles avec les permissions de l'utilisateur SQL
536 * de cette connexion.
537 * Attention on n'a pas toujours les droits !
538 *
539 * @api
540 * @param string $serveur
541 * Nom du connecteur
542 * @param bool|string $option
543 * Peut avoir 2 valeurs :
544 * - true -> executer la requete
545 * - continue -> ne pas echouer en cas de serveur sql indisponible
546 *
547 * @return array|bool
548 * Tableau contenant chaque nom de base de donnees.
549 * False en cas d'erreur.
550 **/
551 function sql_listdbs($serveur = '', $option = true) {
552 $f = sql_serveur('listdbs', $serveur, $option === 'continue' or $option === false);
553 if (!is_string($f) or !$f) {
554 return false;
555 }
556 $r = $f($serveur);
557 if ($r === false) {
558 spip_sql_erreur($serveur);
559 }
560
561 return $r;
562 }
563
564
565 /**
566 * Demande d'utiliser d'une base de donnees
567 *
568 * @api
569 * @param string $nom
570 * Nom de la base a utiliser
571 * @param string $serveur
572 * Nom du connecteur
573 * @param bool|string $option
574 * Peut avoir 2 valeurs :
575 *
576 * - true -> executer la requete
577 * - continue -> ne pas echouer en cas de serveur sql indisponible
578 *
579 * @return bool|string
580 * - True ou nom de la base en cas de success.
581 * - False en cas d'erreur.
582 **/
583 function sql_selectdb($nom, $serveur = '', $option = true) {
584 $f = sql_serveur('selectdb', $serveur, $option === 'continue' or $option === false);
585 if (!is_string($f) or !$f) {
586 return false;
587 }
588 $r = $f($nom, $serveur, $option !== false);
589 if ($r === false) {
590 spip_sql_erreur($serveur);
591 }
592
593 return $r;
594 }
595
596 /**
597 * Retourne le nombre de lignes d’une ressource de sélection obtenue
598 * avec `sql_select()`
599 *
600 * @api
601 * @see sql_select()
602 * @see sql_countsel()
603 *
604 * @param Ressource $res
605 * Ressource SQL
606 * @param string $serveur
607 * Nom du connecteur
608 * @param bool|string $option
609 * Peut avoir 2 valeurs :
610 *
611 * - true -> executer la requete
612 * - continue -> ne pas echouer en cas de serveur sql indisponible
613 * @return bool|string
614 * - int Nombre de lignes,
615 * - false en cas d'erreur.
616 **/
617 function sql_count($res, $serveur = '', $option = true) {
618 $f = sql_serveur('count', $serveur, $option === 'continue' or $option === false);
619 if (!is_string($f) or !$f) {
620 return false;
621 }
622 $r = $f($res, $serveur, $option !== false);
623 if ($r === false) {
624 spip_sql_erreur($serveur);
625 }
626
627 return $r;
628 }
629
630 /**
631 * Libère une ressource de résultat
632 *
633 * Indique au gestionnaire SQL de libérer de sa mémoire la ressoucre de
634 * résultat indiquée car on n'a plus besoin de l'utiliser.
635 *
636 * @param Ressource|Object $res
637 * Ressource de résultat
638 * @param string $serveur
639 * Nom de la connexion
640 * @param bool|string $option
641 * Peut avoir 2 valeurs :
642 *
643 * - true -> exécuter la requete
644 * - continue -> ne pas échouer en cas de serveur SQL indisponible
645 * @return bool
646 * True si réussi
647 */
648 function sql_free($res, $serveur = '', $option = true) {
649 $f = sql_serveur('free', $serveur, $option === 'continue' or $option === false);
650 if (!is_string($f) or !$f) {
651 return false;
652 }
653
654 return $f($res);
655 }
656
657
658 /**
659 * Insère une ligne dans une table
660 *
661 * @see sql_insertq()
662 * @see sql_quote()
663 * @note
664 * Cette fonction ne garantit pas une portabilité totale,
665 * et n'est là que pour faciliter des migrations de vieux scripts.
666 * Préférer sql_insertq.
667 *
668 * @param string $table
669 * Nom de la table SQL
670 * @param string $noms
671 * Liste des colonnes impactées,
672 * @param string $valeurs
673 * Liste des valeurs,
674 * @param array $desc
675 * Tableau de description des colonnes de la table SQL utilisée
676 * (il sera calculé si nécessaire s'il n'est pas transmis).
677 * @param string $serveur
678 * Nom du connecteur
679 * @param bool|string $option
680 * Peut avoir 3 valeurs :
681 *
682 * - false : ne pas l'exécuter mais la retourner,
683 * - true : exécuter la requête
684 * - 'continue' : ne pas échouer en cas de serveur sql indisponible
685 *
686 * @return bool|string
687 * - int|true identifiant de l'élément inséré (si possible), ou true, si réussite
688 * - Texte de la requête si demandé,
689 * - False en cas d'erreur.
690 **/
691 function sql_insert($table, $noms, $valeurs, $desc = array(), $serveur = '', $option = true) {
692 $f = sql_serveur('insert', $serveur, $option === 'continue' or $option === false);
693 if (!is_string($f) or !$f) {
694 return false;
695 }
696 $r = $f($table, $noms, $valeurs, $desc, $serveur, $option !== false);
697 if ($r === false or $r === null) {
698 spip_sql_erreur($serveur);
699 $r = false;
700 }
701
702 return $r;
703 }
704
705 /**
706 * Insère une ligne dans une table
707 *
708 * Protègera chaque valeur comme sql_quote.
709 *
710 * @api
711 * @see sql_insert()
712 * @see sql_insertq_multi()
713 * @see sql_quote()
714 * @see objet_inserer()
715 * @example
716 * ```
717 * $titre = _request('titre');
718 * $id = sql_insertq('spip_rubriques', array('titre' => $titre));
719 * ```
720 *
721 * @param string $table
722 * Nom de la table SQL
723 * @param array $couples
724 * Tableau (nom => valeur)
725 * @param array $desc
726 * Tableau de description des colonnes de la table SQL utilisée
727 * (il sera calculé si nécessaire s'il n'est pas transmis).
728 * @param string $serveur
729 * Nom du connecteur
730 * @param bool|string $option
731 * Peut avoir 3 valeurs :
732 *
733 * - false : ne pas l'exécuter mais la retourner,
734 * - true : exécuter la requête
735 * - 'continue' : ne pas échouer en cas de serveur sql indisponible
736 *
737 * @return bool|string
738 * - int|true identifiant de l'élément inséré (si possible), ou true, si réussite
739 * - Texte de la requête si demandé,
740 * - False en cas d'erreur.
741 **/
742 function sql_insertq($table, $couples = array(), $desc = array(), $serveur = '', $option = true) {
743 $f = sql_serveur('insertq', $serveur, $option === 'continue' or $option === false);
744 if (!is_string($f) or !$f) {
745 return false;
746 }
747 $r = $f($table, $couples, $desc, $serveur, $option !== false);
748 if ($r === false or $r === null) {
749 spip_sql_erreur($serveur);
750 $r = false;
751 }
752
753 return $r;
754 }
755
756 /**
757 * Insère plusieurs lignes d'un coup dans une table
758 *
759 * Insère en une opération plusieurs éléments au schéma identique
760 * dans une table de la base de données. Lorsque les portages le permettent,
761 * ils utilisent une seule requête SQL pour réaliser l’ajout.
762 *
763 * @api
764 * @see sql_insertq()
765 *
766 * @param string $table
767 * Nom de la table SQL
768 * @param array $couples
769 * Tableau de tableaux associatifs (nom => valeur)
770 * @param array $desc
771 * Tableau de description des colonnes de la table SQL utilisée
772 * (il sera calculé si nécessaire s'il n'est pas transmis).
773 * @param string $serveur
774 * Nom du connecteur
775 * @param bool|string $option
776 * Peut avoir 3 valeurs :
777 *
778 * - false : ne pas l'exécuter mais la retourner,
779 * - true : exécuter la requête
780 * - 'continue' : ne pas échouer en cas de serveur sql indisponible
781 *
782 * @return bool|string
783 * - True en cas de succès,
784 * - Texte de la requête si demandé,
785 * - False en cas d'erreur.
786 **/
787 function sql_insertq_multi($table, $couples = array(), $desc = array(), $serveur = '', $option = true) {
788 $f = sql_serveur('insertq_multi', $serveur, $option === 'continue' or $option === false);
789 if (!is_string($f) or !$f) {
790 return false;
791 }
792 $r = $f($table, $couples, $desc, $serveur, $option !== false);
793 if ($r === false or $r === null) {
794 spip_sql_erreur($serveur);
795 $r = false;
796 }
797
798 return $r;
799 }
800
801 /**
802 * Met à jour des enregistrements d'une table SQL
803 *
804 * Les valeurs ne sont pas échappées, ce qui permet de modifier une colonne
805 * en utilisant la valeur d'une autre colonne ou une expression SQL.
806 *
807 * Il faut alors protéger avec sql_quote() manuellement les valeurs qui
808 * en ont besoin.
809 *
810 * Dans les autres cas, préférer sql_updateq().
811 *
812 * @api
813 * @see sql_updateq()
814 *
815 * @param string $table
816 * Nom de la table
817 * @param array $exp
818 * Couples (colonne => valeur)
819 * @param string|array $where
820 * Conditions a remplir (Where)
821 * @param array $desc
822 * Tableau de description des colonnes de la table SQL utilisée
823 * (il sera calculé si nécessaire s'il n'est pas transmis).
824 * @param string $serveur
825 * Nom de la connexion
826 * @param bool|string $option
827 * Peut avoir 3 valeurs :
828 *
829 * - false : ne pas l'exécuter mais la retourner,
830 * - true : exécuter la requête
831 * - 'continue' : ne pas échouer en cas de serveur sql indisponible
832 * @return array|bool|string
833 * - string : texte de la requête si demandé
834 * - true si la requête a réussie, false sinon
835 * - array Tableau décrivant la requête et son temps d'exécution si var_profile est actif
836 */
837 function sql_update($table, $exp, $where = '', $desc = array(), $serveur = '', $option = true) {
838 $f = sql_serveur('update', $serveur, $option === 'continue' or $option === false);
839 if (!is_string($f) or !$f) {
840 return false;
841 }
842 $r = $f($table, $exp, $where, $desc, $serveur, $option !== false);
843 if ($r === false) {
844 spip_sql_erreur($serveur);
845 }
846
847 return $r;
848 }
849
850
851 /**
852 * Met à jour du contenu d’une table SQL
853 *
854 * Le contenu transmis à la fonction est protégé automatiquement
855 * comme sql_quote().
856 *
857 * @api
858 * @see sql_quote()
859 * @see sql_update()
860 * @example
861 * ```
862 * sql_updateq('table', array('colonne' => $valeur), 'id_table=' . intval($id_table));
863 * sql_updateq("spip_auteurs", array("statut" => '6forum'), "id_auteur=$id_auteur") ;
864 * ```
865 * @note
866 * sql_update() est presque toujours appelée sur des constantes ou des dates
867 * Cette fonction (sql_updateq) est donc plus utile que la précédente,
868 * d'autant qu'elle permet de gerer les différences de représentation des constantes.
869 *
870 * @param string $table
871 * Nom de la table SQL
872 * @param array $exp
873 * Couples (colonne => valeur)
874 * @param array|string $where
875 * Conditions à vérifier
876 * @param array $desc
877 * Tableau de description des colonnes de la table SQL utilisée
878 * (il sera calculé si nécessaire s'il n'est pas transmis).
879 * @param string $serveur
880 * Nom du connecteur
881 * @param bool|string $option
882 * Peut avoir 3 valeurs :
883 *
884 * - false : ne pas l'exécuter mais la retourner,
885 * - true : exécuter la requête
886 * - 'continue' : ne pas échouer en cas de serveur sql indisponible
887 * @return bool|string
888 * - true si réussite
889 * - Texte de la requête si demandé,
890 * - False en cas d'erreur.
891 **/
892 function sql_updateq($table, $exp, $where = '', $desc = array(), $serveur = '', $option = true) {
893 $f = sql_serveur('updateq', $serveur, $option === 'continue' or $option === false);
894 if (!is_string($f) or !$f) {
895 return false;
896 }
897 $r = $f($table, $exp, $where, $desc, $serveur, $option !== false);
898 if ($r === false) {
899 spip_sql_erreur($serveur);
900 }
901
902 return $r;
903 }
904
905 /**
906 * Supprime des enregistrements d'une table
907 *
908 * @example
909 * ```
910 * sql_delete('spip_articles', 'id_article='.sql_quote($id_article));
911 * ```
912 *
913 * @api
914 * @param string $table
915 * Nom de la table SQL
916 * @param string|array $where
917 * Conditions à vérifier
918 * @param string $serveur
919 * Nom du connecteur
920 * @param bool|string $option
921 * Peut avoir 3 valeurs :
922 *
923 * - false : ne pas l'exécuter mais la retourner,
924 * - true : exécuter la requête
925 * - 'continue' : ne pas échouer en cas de serveur sql indisponible
926 *
927 * @return bool|string
928 * - int : nombre de suppressions réalisées,
929 * - Texte de la requête si demandé,
930 * - False en cas d'erreur.
931 **/
932 function sql_delete($table, $where = '', $serveur = '', $option = true) {
933 $f = sql_serveur('delete', $serveur, $option === 'continue' or $option === false);
934 if (!is_string($f) or !$f) {
935 return false;
936 }
937 $r = $f($table, $where, $serveur, $option !== false);
938 if ($r === false) {
939 spip_sql_erreur($serveur);
940 }
941
942 return $r;
943 }
944
945 /**
946 * Insère où met à jour une entrée d’une table SQL
947 *
948 * La clé ou les cles primaires doivent être présentes dans les données insérés.
949 * La fonction effectue une protection automatique des données.
950 *
951 * Préférez sql_insertq() et sql_updateq().
952 *
953 * @see sql_insertq()
954 * @see sql_updateq()
955 *
956 * @param string $table
957 * Nom de la table SQL
958 * @param array $couples
959 * Couples colonne / valeur à modifier,
960 * @param array $desc
961 * Tableau de description des colonnes de la table SQL utilisée
962 * (il sera calculé si nécessaire s'il n'est pas transmis).
963 * @param string $serveur
964 * Nom du connecteur
965 * @param bool|string $option
966 * Peut avoir 3 valeurs :
967 *
968 * - false : ne pas l'exécuter mais la retourner,
969 * - true : exécuter la requête
970 * - 'continue' : ne pas échouer en cas de serveur sql indisponible
971 *
972 * @return bool|string
973 * - true si réussite
974 * - Texte de la requête si demandé,
975 * - False en cas d'erreur.
976 **/
977 function sql_replace($table, $couples, $desc = array(), $serveur = '', $option = true) {
978 $f = sql_serveur('replace', $serveur, $option === 'continue' or $option === false);
979 if (!is_string($f) or !$f) {
980 return false;
981 }
982 $r = $f($table, $couples, $desc, $serveur, $option !== false);
983 if ($r === false) {
984 spip_sql_erreur($serveur);
985 }
986
987 return $r;
988 }
989
990
991 /**
992 * Insère où met à jour des entrées d’une table SQL
993 *
994 * La clé ou les cles primaires doivent être présentes dans les données insérés.
995 * La fonction effectue une protection automatique des données.
996 *
997 * Préférez sql_insertq_multi() et sql_updateq().
998 *
999 * @see sql_insertq_multi()
1000 * @see sql_updateq()
1001 * @see sql_replace()
1002 *
1003 * @param string $table
1004 * Nom de la table SQL
1005 * @param array $tab_couples
1006 * Tableau de tableau (colonne / valeur à modifier),
1007 * @param array $desc
1008 * Tableau de description des colonnes de la table SQL utilisée
1009 * (il sera calculé si nécessaire s'il n'est pas transmis).
1010 * @param string $serveur
1011 * Nom du connecteur
1012 * @param bool|string $option
1013 * Peut avoir 3 valeurs :
1014 *
1015 * - false : ne pas l'exécuter mais la retourner,
1016 * - true : exécuter la requête
1017 * - 'continue' : ne pas échouer en cas de serveur sql indisponible
1018 *
1019 * @return bool|string
1020 * - true si réussite
1021 * - Texte de la requête si demandé,
1022 * - False en cas d'erreur.
1023 **/
1024 function sql_replace_multi($table, $tab_couples, $desc = array(), $serveur = '', $option = true) {
1025 $f = sql_serveur('replace_multi', $serveur, $option === 'continue' or $option === false);
1026 if (!is_string($f) or !$f) {
1027 return false;
1028 }
1029 $r = $f($table, $tab_couples, $desc, $serveur, $option !== false);
1030 if ($r === false) {
1031 spip_sql_erreur($serveur);
1032 }
1033
1034 return $r;
1035 }
1036
1037 /**
1038 * Supprime une table SQL (structure et données)
1039 *
1040 * @api
1041 * @see sql_create()
1042 * @see sql_drop_view()
1043 *
1044 * @param string $table
1045 * Nom de la table
1046 * @param string $exist
1047 * true pour ajouter un test sur l'existence de la table, false sinon
1048 * @param string $serveur
1049 * Nom du connecteur
1050 * @param bool|string $option
1051 * Peut avoir 3 valeurs :
1052 *
1053 * - false : ne pas l'exécuter mais la retourner,
1054 * - true : exécuter la requête
1055 * - 'continue' : ne pas échouer en cas de serveur sql indisponible
1056 * @return bool|string
1057 * - True en cas de succès,
1058 * - Texte de la requête si demandé,
1059 * - False en cas d'erreur.
1060 **/
1061 function sql_drop_table($table, $exist = '', $serveur = '', $option = true) {
1062 $f = sql_serveur('drop_table', $serveur, $option === 'continue' or $option === false);
1063 if (!is_string($f) or !$f) {
1064 return false;
1065 }
1066 $r = $f($table, $exist, $serveur, $option !== false);
1067 if ($r === false) {
1068 spip_sql_erreur($serveur);
1069 }
1070
1071 return $r;
1072 }
1073
1074 /**
1075 * Supprime une vue SQL
1076 *
1077 * @api
1078 * @see sql_create_view()
1079 * @see sql_drop_table()
1080 *
1081 * @param string $table Nom de la vue SQL
1082 * @param string $exist True pour ajouter un test d'existence avant de supprimer
1083 * @param string $serveur Nom de la connexion
1084 * @param bool $option
1085 * Peut avoir 3 valeurs :
1086 *
1087 * - false : ne pas l'exécuter mais la retourner,
1088 * - true : exécuter la requête
1089 * - 'continue' : ne pas échouer en cas de serveur sql indisponible
1090 * @return bool|string
1091 * - string Texte de la requête si demandé
1092 * - true si la requête a réussie, false sinon
1093 */
1094 function sql_drop_view($table, $exist = '', $serveur = '', $option = true) {
1095 $f = sql_serveur('drop_view', $serveur, $option === 'continue' or $option === false);
1096 if (!is_string($f) or !$f) {
1097 return false;
1098 }
1099 $r = $f($table, $exist, $serveur, $option !== false);
1100 if ($r === false) {
1101 spip_sql_erreur($serveur);
1102 }
1103
1104 return $r;
1105 }
1106
1107 /**
1108 * Retourne une ressource de la liste des tables de la base de données
1109 *
1110 * @api
1111 * @see sql_alltable()
1112 *
1113 * @param string $spip
1114 * Filtre sur tables retournées
1115 * - NULL : retourne les tables SPIP uniquement (tables préfixées avec le préfixe de la connexion)
1116 * - '%' : retourne toutes les tables de la base
1117 * @param string $serveur
1118 * Le nom du connecteur
1119 * @param bool|string $option
1120 * Peut avoir 3 valeurs :
1121 * - false -> ne pas l'executer mais la retourner,
1122 * - continue -> ne pas echouer en cas de serveur sql indisponible,
1123 * - true -> executer la requete.
1124 * @return ressource
1125 * Ressource à utiliser avec sql_fetch()
1126 **/
1127 function sql_showbase($spip = null, $serveur = '', $option = true) {
1128 $f = sql_serveur('showbase', $serveur, $option === 'continue' or $option === false);
1129 if (!is_string($f) or !$f) {
1130 return false;
1131 }
1132
1133 // la globale n'est remplie qu'apres l'appel de sql_serveur.
1134 if ($spip == null) {
1135 $connexion = $GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
1136 $spip = $connexion['prefixe'] . '\_%';
1137 }
1138
1139 return $f($spip, $serveur, $option !== false);
1140 }
1141
1142 /**
1143 * Retourne la liste des tables SQL
1144 *
1145 * @api
1146 * @uses sql_showbase()
1147 * @param string $spip
1148 * Filtre sur tables retournées
1149 * - NULL : retourne les tables SPIP uniquement (tables préfixées avec le préfixe de la connexion)
1150 * - '%' : retourne toutes les tables de la base
1151 * @param string $serveur
1152 * Le nom du connecteur
1153 * @param bool|string $option
1154 * Peut avoir 3 valeurs :
1155 * - false -> ne pas l'executer mais la retourner,
1156 * - continue -> ne pas echouer en cas de serveur sql indisponible,
1157 * - true -> executer la requete.
1158 * @return array
1159 * Liste des tables SQL
1160 **/
1161 function sql_alltable($spip = null, $serveur = '', $option = true) {
1162 $q = sql_showbase($spip, $serveur, $option);
1163 $r = array();
1164 if ($q) {
1165 while ($t = sql_fetch($q, $serveur)) {
1166 $r[] = array_shift($t);
1167 }
1168 }
1169
1170 return $r;
1171 }
1172
1173 /**
1174 * Retourne la liste (et description) des colonnes et key d’une table SQL
1175 *
1176 * @note
1177 * Dans la plupart des situations, il vaut mieux utiliser directement
1178 * la fonction trouver_table() qui possède un cache.
1179 *
1180 * @api
1181 * @see base_trouver_table_dist()
1182 *
1183 * @param string $table
1184 * Nom de la table SQL
1185 * @param bool $table_spip
1186 * true pour remplacer automatiquement « spip » par le vrai préfixe de table
1187 * @param string $serveur
1188 * Nom du connecteur
1189 * @param bool|string $option
1190 * Peut avoir 3 valeurs :
1191 *
1192 * - false : ne pas l'exécuter mais la retourner,
1193 * - 'continue' : ne pas échouer en cas de serveur SQL indisponible,
1194 * - true : exécuter la requete.
1195 * @return bool|array
1196 * - false en cas d'echec
1197 * - sinon array : Tableau avec
1198 * - 'field' => array(colonne => description)
1199 * - 'key' => array(type => key)
1200 * - 'join' => array() // jointures, si déclarées.
1201 **/
1202 function sql_showtable($table, $table_spip = false, $serveur = '', $option = true) {
1203 $f = sql_serveur('showtable', $serveur, $option === 'continue' or $option === false);
1204 if (!is_string($f) or !$f) {
1205 return false;
1206 }
1207
1208 // la globale n'est remplie qu'apres l'appel de sql_serveur.
1209 if ($table_spip) {
1210 $connexion = $GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
1211 $prefixe = $connexion['prefixe'];
1212 $vraie_table = prefixer_table_spip($table, $prefixe);
1213 } else {
1214 $vraie_table = $table;
1215 }
1216
1217 $f = $f($vraie_table, $serveur, $option !== false);
1218 if (!$f) {
1219 return array();
1220 }
1221 if (isset($GLOBALS['tables_principales'][$table]['join'])) {
1222 $f['join'] = $GLOBALS['tables_principales'][$table]['join'];
1223 } elseif (isset($GLOBALS['tables_auxiliaires'][$table]['join'])) {
1224 $f['join'] = $GLOBALS['tables_auxiliaires'][$table]['join'];
1225 }
1226
1227 return $f;
1228 }
1229
1230 /**
1231 * Crée une table dans la base de données
1232 *
1233 * @api
1234 * @example
1235 * ```
1236 * sql_create("spip_tables",
1237 * array(
1238 * "id_table" => "bigint(20) NOT NULL default '0'",
1239 * "colonne1"=> "varchar(3) NOT NULL default 'oui'",
1240 * "colonne2"=> "text NOT NULL default ''"
1241 * ),
1242 * array(
1243 * 'PRIMARY KEY' => "id_table",
1244 * 'KEY colonne1' => "colonne1"
1245 * )
1246 * );
1247 * ```
1248 *
1249 * @param string $nom
1250 * Nom de la table
1251 * @param array $champs
1252 * Couples (colonne => description)
1253 * @param array $cles
1254 * Clé (nomdelaclef => champ)
1255 * @param bool $autoinc
1256 * Si un champ est clef primaire est numérique alors la propriété
1257 * d’autoincrémentation sera ajoutée
1258 * @param bool $temporary
1259 * true pour créer une table temporaire (au sens SQL)
1260 * @param string $serveur
1261 * Nom du connecteur
1262 * @param bool|string $option
1263 * Peut avoir 3 valeurs :
1264 *
1265 * - false : ne pas l'exécuter mais la retourner,
1266 * - 'continue' : ne pas échouer en cas de serveur SQL indisponible,
1267 * - true : exécuter la requete.
1268 * @return bool
1269 * true si succès, false en cas d'echec
1270 **/
1271 function sql_create(
1272 $nom,
1273 $champs,
1274 $cles = array(),
1275 $autoinc = false,
1276 $temporary = false,
1277 $serveur = '',
1278 $option = true
1279 ) {
1280 $f = sql_serveur('create', $serveur, $option === 'continue' or $option === false);
1281 if (!is_string($f) or !$f) {
1282 return false;
1283 }
1284 $r = $f($nom, $champs, $cles, $autoinc, $temporary, $serveur, $option !== false);
1285 if ($r === false) {
1286 spip_sql_erreur($serveur);
1287 }
1288
1289 return $r;
1290 }
1291
1292 /**
1293 * Crée une base de données
1294 *
1295 * @api
1296 * @param string $nom Nom de la base (sans l'extension de fichier si gestionnaire SQLite)
1297 * @param string $serveur Nom de la connexion
1298 * @param bool $option
1299 * Peut avoir 3 valeurs :
1300 *
1301 * - false : ne pas l'exécuter mais la retourner,
1302 * - true : exécuter la requête
1303 * - 'continue' : ne pas échouer en cas de serveur sql indisponible
1304 * @return bool true si la base est créee.
1305 **/
1306 function sql_create_base($nom, $serveur = '', $option = true) {
1307 $f = sql_serveur('create_base', $serveur, $option === 'continue' or $option === false);
1308 if (!is_string($f) or !$f) {
1309 return false;
1310 }
1311 $r = $f($nom, $serveur, $option !== false);
1312 if ($r === false) {
1313 spip_sql_erreur($serveur);
1314 }
1315
1316 return $r;
1317 }
1318
1319
1320 /**
1321 * Crée une vue SQL
1322 *
1323 * @api
1324 * @see sql_drop_view()
1325 * @see sql_create()
1326 * @see sql_get_select() Pour obtenir le texte de la requête SELECT pour créer la vue.
1327 *
1328 * @param string $nom
1329 * Nom de la vue
1330 * @param string $select_query
1331 * Une requête SELECT, idéalement crée avec `sql_get_select(...)`
1332 * @param string $serveur
1333 * Nom du connecteur
1334 * @param bool|string $option
1335 * Peut avoir 3 valeurs :
1336 *
1337 * - false : ne pas l'exécuter mais la retourner,
1338 * - true : exécuter la requête
1339 * - 'continue' : ne pas échouer en cas de serveur sql indisponible
1340 * @return bool|string
1341 * - true si succès,
1342 * - texte de la requête si demandé
1343 * - false en cas d'échec.
1344 **/
1345 function sql_create_view($nom, $select_query, $serveur = '', $option = true) {
1346 $f = sql_serveur('create_view', $serveur, $option === 'continue' or $option === false);
1347 if (!is_string($f) or !$f) {
1348 return false;
1349 }
1350 $r = $f($nom, $select_query, $serveur, $option !== false);
1351 if ($r === false) {
1352 spip_sql_erreur($serveur);
1353 }
1354
1355 return $r;
1356 }
1357
1358 /**
1359 * Retourne l'instruction SQL pour obtenir le texte d'un champ contenant
1360 * une balise `<multi>` dans la langue indiquée
1361 *
1362 * Cette sélection est mise dans l'alias `multi` (instruction AS multi).
1363 *
1364 * @example
1365 * ```
1366 * $t = sql_multi('chapo', 'fr');
1367 * ```
1368 * @api
1369 * @param string $sel
1370 * Colonne ayant le texte
1371 * @param string $lang
1372 * Langue à extraire
1373 * @param string $serveur
1374 * Nom du connecteur
1375 * @param bool|string $option
1376 * Peut avoir 2 valeurs :
1377 *
1378 * - true : exécuter la requête
1379 * - 'continue' : ne pas échouer en cas de serveur sql indisponible
1380 * @return string
1381 * Texte de sélection pour la requête
1382 */
1383 function sql_multi($sel, $lang, $serveur = '', $option = true) {
1384 $f = sql_serveur('multi', $serveur, $option === 'continue' or $option === false);
1385 if (!is_string($f) or !$f) {
1386 return false;
1387 }
1388
1389 return $f($sel, $lang);
1390 }
1391
1392
1393 /**
1394 * Retourne la dernière erreur connue
1395 *
1396 * @api
1397 * @param string $serveur
1398 * Nom du connecteur
1399 * @return bool|string
1400 * Description de l'erreur
1401 * False si le serveur est indisponible
1402 */
1403 function sql_error($serveur = '') {
1404 $f = sql_serveur('error', $serveur, 'continue');
1405 if (!is_string($f) or !$f) {
1406 return false;
1407 }
1408
1409 return $f('query inconnue', $serveur);
1410 }
1411
1412 /**
1413 * Retourne le numéro de la derniere erreur connue
1414 *
1415 * @api
1416 * @param string $serveur
1417 * Nom du connecteur
1418 * @return bool|int
1419 * Numéro de l'erreur
1420 * False si le serveur est indisponible
1421 */
1422 function sql_errno($serveur = '') {
1423 $f = sql_serveur('errno', $serveur, 'continue');
1424 if (!is_string($f) or !$f) {
1425 return false;
1426 }
1427
1428 return $f($serveur);
1429 }
1430
1431 /**
1432 * Retourne une explication de requête (Explain) SQL
1433 *
1434 * @api
1435 * @param string $q Texte de la requête
1436 * @param string $serveur Nom de la connexion
1437 * @param bool $option
1438 * Peut avoir 3 valeurs :
1439 *
1440 * - false : ne pas l'exécuter mais la retourner,
1441 * - true : exécuter la requête
1442 * - 'continue' : ne pas échouer en cas de serveur sql indisponible
1443 * @return array Tableau de l'explication
1444 */
1445 function sql_explain($q, $serveur = '', $option = true) {
1446 $f = sql_serveur('explain', $serveur, 'continue');
1447 if (!is_string($f) or !$f) {
1448 return false;
1449 }
1450 $r = $f($q, $serveur, $option !== false);
1451 if ($r === false) {
1452 spip_sql_erreur($serveur);
1453 }
1454
1455 return $r;
1456 }
1457
1458 /**
1459 * Optimise une table SQL
1460 *
1461 * @api
1462 * @param string $table Nom de la table
1463 * @param string $serveur Nom de la connexion
1464 * @param bool $option
1465 * Peut avoir 3 valeurs :
1466 *
1467 * - false : ne pas l'exécuter mais la retourner,
1468 * - true : exécuter la requête
1469 * - 'continue' : ne pas échouer en cas de serveur sql indisponible
1470 * @return bool Toujours true
1471 */
1472 function sql_optimize($table, $serveur = '', $option = true) {
1473 $f = sql_serveur('optimize', $serveur, $option === 'continue' or $option === false);
1474 if (!is_string($f) or !$f) {
1475 return false;
1476 }
1477 $r = $f($table, $serveur, $option !== false);
1478 if ($r === false) {
1479 spip_sql_erreur($serveur);
1480 }
1481
1482 return $r;
1483 }
1484
1485 /**
1486 * Répare une table SQL
1487 *
1488 * @api
1489 * @param string $table Nom de la table SQL
1490 * @param string $serveur Nom de la connexion
1491 * @param bool $option
1492 * Peut avoir 3 valeurs :
1493 *
1494 * - false : ne pas l'exécuter mais la retourner,
1495 * - true : exécuter la requête
1496 * - 'continue' : ne pas échouer en cas de serveur sql indisponible
1497 * @return bool|string
1498 * - string Texte de la requête si demandée,
1499 * - true si la requête a réussie, false sinon
1500 */
1501 function sql_repair($table, $serveur = '', $option = true) {
1502 $f = sql_serveur('repair', $serveur, $option === 'continue' or $option === false);
1503 if (!is_string($f) or !$f) {
1504 return false;
1505 }
1506 $r = $f($table, $serveur, $option !== false);
1507 if ($r === false) {
1508 spip_sql_erreur($serveur);
1509 }
1510
1511 return $r;
1512 }
1513
1514
1515 /**
1516 * Exécute une requête SQL
1517 *
1518 * Fonction la plus générale ... et la moins portable
1519 * À n'utiliser qu'en dernière extrémité
1520 *
1521 * @api
1522 * @param string $ins Requête
1523 * @param string $serveur Nom de la connexion
1524 * @param bool $option
1525 * Peut avoir 3 valeurs :
1526 *
1527 * - false : ne pas l'exécuter mais la retourner,
1528 * - true : exécuter la requête
1529 * - 'continue' : ne pas échouer en cas de serveur sql indisponible
1530 * @return array|resource|string|bool
1531 * - string : Texte de la requête si on ne l'exécute pas
1532 * - ressource|bool : Si requête exécutée
1533 * - array : Tableau décrivant requête et temps d'exécution si var_profile actif pour tracer.
1534 */
1535 function sql_query($ins, $serveur = '', $option = true) {
1536 $f = sql_serveur('query', $serveur, $option === 'continue' or $option === false);
1537 if (!is_string($f) or !$f) {
1538 return false;
1539 }
1540 $r = $f($ins, $serveur, $option !== false);
1541 if ($r === false) {
1542 spip_sql_erreur($serveur);
1543 }
1544
1545 return $r;
1546 }
1547
1548 /**
1549 * Retourne la première ligne d'une sélection
1550 *
1551 * Retourne la première ligne de résultat d'une sélection
1552 * comme si l'on appelait successivement `sql_select()` puis `sql_fetch()`
1553 *
1554 * @example
1555 * ```
1556 * $art = sql_fetsel(array('id_rubrique','id_secteur'), 'spip_articles', 'id_article='.sql_quote($id_article));
1557 * $id_rubrique = $art['id_rubrique'];
1558 * ```
1559 *
1560 * @api
1561 * @uses sql_select()
1562 * @uses sql_fetch()
1563 * @see sql_getfetsel()
1564 *
1565 * @param array|string $select
1566 * Liste des champs a recuperer (Select)
1567 * @param array|string $from
1568 * Tables a consulter (From)
1569 * @param array|string $where
1570 * Conditions a remplir (Where)
1571 * @param array|string $groupby
1572 * Critere de regroupement (Group by)
1573 * @param array|string $orderby
1574 * Tableau de classement (Order By)
1575 * @param string $limit
1576 * Critere de limite (Limit)
1577 * @param array $having
1578 * Tableau des des post-conditions a remplir (Having)
1579 * @param string $serveur
1580 * Le serveur sollicite (pour retrouver la connexion)
1581 * @param bool|string $option
1582 * Peut avoir 3 valeurs :
1583 * - true -> executer la requete.
1584 * - continue -> ne pas echouer en cas de serveur sql indisponible.
1585 * - false -> ne pas l'executer mais la retourner.
1586 *
1587 * @return array
1588 * Tableau de la premiere ligne de resultat de la selection tel que
1589 * `array('id_rubrique' => 1, 'id_secteur' => 2)`
1590 *
1591 **/
1592 function sql_fetsel(
1593 $select = array(),
1594 $from = array(),
1595 $where = array(),
1596 $groupby = array(),
1597 $orderby = array(),
1598 $limit = '',
1599 $having = array(),
1600 $serveur = '',
1601 $option = true
1602 ) {
1603 $q = sql_select($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur, $option);
1604 if ($option === false) {
1605 return $q;
1606 }
1607 if (!$q) {
1608 return array();
1609 }
1610 $r = sql_fetch($q, $serveur, $option);
1611 sql_free($q, $serveur, $option);
1612
1613 return $r;
1614 }
1615
1616
1617 /**
1618 * Retourne le tableau de toutes les lignes d'une selection
1619 *
1620 * Retourne toutes les lignes de resultat d'une selection
1621 * comme si l'on appelait successivement sql_select() puis while(sql_fetch())
1622 *
1623 * @example
1624 * ```
1625 * $rubs = sql_allfetsel('id_rubrique', 'spip_articles', 'id_secteur='.sql_quote($id_secteur));
1626 * // $rubs = array(array('id_rubrique'=>1), array('id_rubrique'=>3, ...)
1627 * ```
1628 *
1629 * @api
1630 * @uses sql_select()
1631 * @uses sql_fetch()
1632 *
1633 * @param array|string $select
1634 * Liste des champs a recuperer (Select)
1635 * @param array|string $from
1636 * Tables a consulter (From)
1637 * @param array|string $where
1638 * Conditions a remplir (Where)
1639 * @param array|string $groupby
1640 * Critere de regroupement (Group by)
1641 * @param array|string $orderby
1642 * Tableau de classement (Order By)
1643 * @param string $limit
1644 * Critere de limite (Limit)
1645 * @param array $having
1646 * Tableau des des post-conditions a remplir (Having)
1647 * @param string $serveur
1648 * Le serveur sollicite (pour retrouver la connexion)
1649 * @param bool|string $option
1650 * Peut avoir 3 valeurs :
1651 * - true -> executer la requete.
1652 * - continue -> ne pas echouer en cas de serveur sql indisponible.
1653 * - false -> ne pas l'executer mais la retourner.
1654 *
1655 * @return array
1656 * Tableau de toutes les lignes de resultat de la selection
1657 * Chaque entree contient un tableau des elements demandees dans le SELECT.
1658 * {@example
1659 * ```
1660 * array(
1661 * array('id_rubrique' => 1, 'id_secteur' => 2)
1662 * array('id_rubrique' => 4, 'id_secteur' => 2)
1663 * ...
1664 * )
1665 * ```
1666 * }
1667 *
1668 **/
1669 function sql_allfetsel(
1670 $select = array(),
1671 $from = array(),
1672 $where = array(),
1673 $groupby = array(),
1674 $orderby = array(),
1675 $limit = '',
1676 $having = array(),
1677 $serveur = '',
1678 $option = true
1679 ) {
1680 $q = sql_select($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur, $option);
1681 if ($option === false) {
1682 return $q;
1683 }
1684
1685 return sql_fetch_all($q, $serveur, $option);
1686 }
1687
1688
1689 /**
1690 * Retourne un unique champ d'une selection
1691 *
1692 * Retourne dans la premiere ligne de resultat d'une selection
1693 * un unique champ demande
1694 *
1695 * @example
1696 * ```
1697 * $id_rubrique = sql_getfetsel('id_rubrique', 'spip_articles', 'id_article='.sql_quote($id_article));
1698 * ```
1699 *
1700 * @api
1701 * @uses sql_fetsel()
1702 *
1703 * @param array|string $select
1704 * Liste des champs à récupérer (Select)
1705 * @param array|string $from
1706 * Tables à consulter (From)
1707 * @param array|string $where
1708 * Conditions à remplir (Where)
1709 * @param array|string $groupby
1710 * Critère de regroupement (Group by)
1711 * @param array|string $orderby
1712 * Tableau de classement (Order By)
1713 * @param string $limit
1714 * Critère de limite (Limit)
1715 * @param array $having
1716 * Tableau des des post-conditions à remplir (Having)
1717 * @param string $serveur
1718 * Le serveur sollicité (pour retrouver la connexion)
1719 * @param bool|string $option
1720 * Peut avoir 3 valeurs :
1721 *
1722 * - true -> executer la requete.
1723 * - continue -> ne pas echouer en cas de serveur sql indisponible.
1724 * - false -> ne pas l'executer mais la retourner.
1725 *
1726 * @return mixed
1727 * Contenu de l'unique valeur demandee du premier enregistrement retourne
1728 * ou NULL si la requete ne retourne aucun enregistrement
1729 *
1730 **/
1731 function sql_getfetsel(
1732 $select,
1733 $from = array(),
1734 $where = array(),
1735 $groupby = array(),
1736 $orderby = array(),
1737 $limit = '',
1738 $having = array(),
1739 $serveur = '',
1740 $option = true
1741 ) {
1742 if (preg_match('/\s+as\s+(\w+)$/i', $select, $c)) {
1743 $id = $c[1];
1744 } elseif (!preg_match('/\W/', $select)) {
1745 $id = $select;
1746 } else {
1747 $id = 'n';
1748 $select .= ' AS n';
1749 }
1750 $r = sql_fetsel($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur, $option);
1751 if ($option === false) {
1752 return $r;
1753 }
1754 if (!$r) {
1755 return null;
1756 }
1757
1758 return $r[$id];
1759 }
1760
1761 /**
1762 * Retourne le numero de version du serveur SQL
1763 *
1764 * @api
1765 * @param string $serveur
1766 * Nom du connecteur
1767 * @param bool|string $option
1768 * Peut avoir 2 valeurs :
1769 * - true pour executer la requete.
1770 * - continue pour ne pas echouer en cas de serveur sql indisponible.
1771 *
1772 * @return string
1773 * Numero de version du serveur SQL
1774 **/
1775 function sql_version($serveur = '', $option = true) {
1776 $row = sql_fetsel("version() AS n", '', '', '', '', '', '', $serveur);
1777
1778 return ($row['n']);
1779 }
1780
1781 /**
1782 * Informe si le moteur SQL prefere utiliser des transactions
1783 *
1784 * Cette fonction experimentale est pour l'instant presente pour accelerer certaines
1785 * insertions multiples en SQLite, en les encadrant d'une transaction.
1786 * SQLite ne cree alors qu'un verrou pour l'ensemble des insertions
1787 * et non un pour chaque, ce qui accelere grandement le processus.
1788 * Evidemment, si une des insertions echoue, rien ne sera enregistre.
1789 * Pour ne pas perturber les autres moteurs, cette fonction permet
1790 * de verifier que le moteur prefere utiliser des transactions dans ce cas.
1791 *
1792 * @example
1793 * ```
1794 * if (sql_preferer_transaction()) {
1795 * sql_demarrer_transaction();
1796 * }
1797 * ```
1798 *
1799 * @api
1800 * @see sql_demarrer_transaction()
1801 * @see sql_terminer_transaction()
1802 *
1803 * @param string $serveur
1804 * Nom du connecteur
1805 * @param bool|string $option
1806 * Peut avoir 2 valeurs :
1807 * - true pour executer la requete.
1808 * - continue pour ne pas echouer en cas de serveur sql indisponible.
1809 *
1810 * @return bool
1811 * Le serveur SQL prefere t'il des transactions pour les insertions multiples ?
1812 **/
1813 function sql_preferer_transaction($serveur = '', $option = true) {
1814 $f = sql_serveur('preferer_transaction', $serveur, 'continue');
1815 if (!is_string($f) or !$f) {
1816 return false;
1817 }
1818 $r = $f($serveur, $option !== false);
1819 if ($r === false) {
1820 spip_sql_erreur($serveur);
1821 }
1822
1823 return $r;
1824 }
1825
1826 ;
1827
1828 /**
1829 * Démarre une transaction
1830 *
1831 * @api
1832 * @see sql_terminer_transaction() Pour cloturer la transaction
1833 *
1834 * @param string $serveur
1835 * Nom du connecteur
1836 * @param bool|string $option
1837 * Peut avoir 3 valeurs :
1838 *
1839 * - true pour executer la requete.
1840 * - continue pour ne pas echouer en cas de serveur sql indisponible.
1841 * - false pour obtenir le code de la requete
1842 *
1843 * @return bool
1844 * true si la transaction est demarree
1845 * false en cas d'erreur
1846 **/
1847 function sql_demarrer_transaction($serveur = '', $option = true) {
1848 $f = sql_serveur('demarrer_transaction', $serveur, 'continue');
1849 if (!is_string($f) or !$f) {
1850 return false;
1851 }
1852 $r = $f($serveur, $option !== false);
1853 if ($r === false) {
1854 spip_sql_erreur($serveur);
1855 }
1856
1857 return $r;
1858 }
1859
1860 ;
1861
1862 /**
1863 * Termine une transaction
1864 *
1865 * @api
1866 * @see sql_demarrer_transaction() Pour demarrer une transaction
1867 *
1868 * @param string $serveur
1869 * Nom du connecteur
1870 * @param bool|string $option
1871 * Peut avoir 3 valeurs :
1872 *
1873 * - true pour executer la requete.
1874 * - continue pour ne pas echouer en cas de serveur sql indisponible.
1875 * - false pour obtenir le code de la requete
1876 *
1877 * @return bool
1878 * true si la transaction est demarree
1879 * false en cas d'erreur
1880 **/
1881 function sql_terminer_transaction($serveur = '', $option = true) {
1882 $f = sql_serveur('terminer_transaction', $serveur, 'continue');
1883 if (!is_string($f) or !$f) {
1884 return false;
1885 }
1886 $r = $f($serveur, $option !== false);
1887 if ($r === false) {
1888 spip_sql_erreur($serveur);
1889 }
1890
1891 return $r;
1892 }
1893
1894 ;
1895
1896
1897 /**
1898 * Prépare une chaine hexadécimale
1899 *
1900 * Prend une chaîne sur l'aphabet hexa
1901 * et retourne sa représentation numérique attendue par le serveur SQL.
1902 * Par exemple : FF ==> 0xFF en MySQL mais x'FF' en PG
1903 *
1904 * @api
1905 * @param string $val
1906 * Chaine hexadécimale
1907 * @param string $serveur
1908 * Nom du connecteur
1909 * @param bool|string $option
1910 * Peut avoir 2 valeurs :
1911 *
1912 * - true pour exécuter la demande.
1913 * - 'continue' pour ne pas échouer en cas de serveur SQL indisponible.
1914 * @return string
1915 * Valeur hexadécimale attendue par le serveur SQL
1916 **/
1917 function sql_hex($val, $serveur = '', $option = true) {
1918 $f = sql_serveur('hex', $serveur, $option === 'continue' or $option === false);
1919 if (!is_string($f) or !$f) {
1920 return false;
1921 }
1922
1923 return $f($val);
1924 }
1925
1926 /**
1927 * Echapper du contenu
1928 *
1929 * Echappe du contenu selon ce qu'attend le type de serveur SQL
1930 * et en fonction du type de contenu.
1931 *
1932 * Permet entre autres de se protéger d'injections SQL.
1933 *
1934 * Cette fonction est automatiquement appelée par les fonctions `sql_*q`
1935 * tel que `sql_instertq` ou `sql_updateq`
1936 *
1937 * @api
1938 * @param string $val
1939 * Chaine à echapper
1940 * @param string $serveur
1941 * Nom du connecteur
1942 * @param string $type
1943 * Peut contenir une declaration de type de champ SQL.
1944 * Exemple : `int NOT NULL` qui sert alors aussi à calculer le type d'échappement
1945 * @return string
1946 * La chaine echappee
1947 **/
1948 function sql_quote($val, $serveur = '', $type = '') {
1949 $f = sql_serveur('quote', $serveur, true);
1950 if (!is_string($f) or !$f) {
1951 $f = '_q';
1952 }
1953
1954 return $f($val, $type);
1955 }
1956
1957 /**
1958 * Tester si une date est proche de la valeur d'un champ
1959 *
1960 * @api
1961 * @param string $champ
1962 * Nom du champ a tester
1963 * @param int $interval
1964 * Valeur de l'intervalle : -1, 4, ...
1965 * @param string $unite
1966 * Utité utilisée (DAY, MONTH, YEAR, ...)
1967 * @param string $serveur
1968 * Nom du connecteur
1969 * @param bool|string $option
1970 * Peut avoir 2 valeurs :
1971 *
1972 * - true pour exécuter la demande.
1973 * - 'continue' pour ne pas échouer en cas de serveur SQL indisponible.
1974 * @return string|bool
1975 * - string : Expression SQL
1976 * - false si le serveur SQL est indisponible
1977 **/
1978 function sql_date_proche($champ, $interval, $unite, $serveur = '', $option = true) {
1979 $f = sql_serveur('date_proche', $serveur, true);
1980 if (!is_string($f) or !$f) {
1981 return false;
1982 }
1983
1984 return $f($champ, $interval, $unite);
1985 }
1986
1987 /**
1988 * Retourne une expression IN pour le gestionnaire de base de données
1989 *
1990 * Retourne un code à insérer dans une requête SQL pour récupérer
1991 * les éléments d'une colonne qui appartiennent à une liste donnée
1992 *
1993 * @example
1994 * `sql_in('id_rubrique', array(3,4,5))`
1995 * retourne approximativement «id_rubrique IN (3,4,5)» selon ce qu'attend
1996 * le gestionnaire de base de donnée du connecteur en cours.
1997 *
1998 * @api
1999 * @param string $val
2000 * Colonne SQL sur laquelle appliquer le test
2001 * @param string|array $valeurs
2002 * Liste des valeurs possibles (séparés par des virgules si string)
2003 * @param string $not
2004 * - '' sélectionne les éléments correspondant aux valeurs
2005 * - 'NOT' inverse en sélectionnant les éléments ne correspondant pas aux valeurs
2006 * @param string $serveur
2007 * Nom du connecteur
2008 * @param bool|string $option
2009 * Peut avoir 2 valeurs :
2010 *
2011 * - continue -> ne pas echouer en cas de serveur sql indisponible
2012 * - true ou false -> retourne l'expression
2013 * @return string
2014 * Expression de requête SQL
2015 **/
2016 function sql_in($val, $valeurs, $not = '', $serveur = '', $option = true) {
2017 if (is_array($valeurs)) {
2018 $f = sql_serveur('quote', $serveur, true);
2019 if (!is_string($f) or !$f) {
2020 return false;
2021 }
2022 $valeurs = join(',', array_map($f, array_unique($valeurs)));
2023 } elseif (isset($valeurs[0]) and $valeurs[0] === ',') {
2024 $valeurs = substr($valeurs, 1);
2025 }
2026 if (!strlen(trim($valeurs))) {
2027 return ($not ? "0=0" : '0=1');
2028 }
2029
2030 $f = sql_serveur('in', $serveur, $option === 'continue' or $option === false);
2031 if (!is_string($f) or !$f) {
2032 return false;
2033 }
2034
2035 return $f($val, $valeurs, $not, $serveur, $option !== false);
2036 }
2037
2038
2039 /**
2040 * Retourne une expression IN pour le gestionnaire de base de données
2041 * à partir d'une sélection de données
2042 *
2043 * Sélectionne les données (comme sql_select()) et prépare avec l'expression IN
2044 *
2045 * @see sql_select()
2046 * @see sql_in()
2047 * @note
2048 * Penser à dire dans la description du serveur
2049 * s'il accepte les requêtes imbriquées afin d'optimiser ca
2050 *
2051 * @api
2052 * @param string $in
2053 * Colonne SQL sur laquelle appliquer le test
2054 * @param array|string $select
2055 * Liste des champs à récupérer (Select).
2056 * La donnée extraite est le premier élément de la sélection.
2057 * @param array|string $from
2058 * Tables a consulter (From)
2059 * @param array|string $where
2060 * Conditions a remplir (Where)
2061 * @param array|string $groupby
2062 * Critere de regroupement (Group by)
2063 * @param array|string $orderby
2064 * Tableau de classement (Order By)
2065 * @param string $limit
2066 * Critere de limite (Limit)
2067 * @param array $having
2068 * Tableau des des post-conditions a remplir (Having)
2069 * @param string $serveur
2070 * Nom du connecteur
2071 * @return string
2072 * Expression de requête SQL
2073 **/
2074 function sql_in_select(
2075 $in,
2076 $select,
2077 $from = array(),
2078 $where = array(),
2079 $groupby = array(),
2080 $orderby = array(),
2081 $limit = '',
2082 $having = array(),
2083 $serveur = ''
2084 ) {
2085 $liste = array();
2086 $res = sql_select($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur);
2087 while ($r = sql_fetch($res)) {
2088 $liste[] = array_shift($r);
2089 }
2090 sql_free($res);
2091
2092 return sql_in($in, $liste);
2093 }
2094
2095 /**
2096 * Implémentation sécurisée du saut en avant.
2097 *
2098 * Ne dépend pas de la disponibilité de la fonction `sql_seek()`.
2099 * Ne fait rien pour une valeur négative ou nulle de `$saut`.
2100 * Retourne la position après le saut
2101 *
2102 * @see sql_seek()
2103 *
2104 * @param resource $res
2105 * Ressource issue d'une selection sql_select
2106 * @param int $pos
2107 * position courante
2108 * @param int $saut
2109 * saut demande
2110 * @param int $count
2111 * position maximale
2112 * (nombre de resultat de la requete OU position qu'on ne veut pas depasser)
2113 * @param string $serveur
2114 * Nom du connecteur
2115 * @param bool|string $option
2116 * Peut avoir 2 valeurs :
2117 * - true -> executer la requete
2118 * - continue -> ne pas echouer en cas de serveur sql indisponible
2119 *
2120 * @return int
2121 * Position apres le saut.
2122 */
2123 function sql_skip($res, $pos, $saut, $count, $serveur = '', $option = true) {
2124 // pas de saut en arriere qu'on ne sait pas faire sans sql_seek
2125 if (($saut = intval($saut)) <= 0) {
2126 return $pos;
2127 }
2128
2129 $seek = $pos + $saut;
2130 // si le saut fait depasser le maxi, on libere la resource
2131 // et on sort
2132 if ($seek >= $count) {
2133 sql_free($res, $serveur, $option);
2134
2135 return $count;
2136 }
2137
2138 if (sql_seek($res, $seek)) {
2139 $pos = $seek;
2140 } else {
2141 while ($pos < $seek and sql_fetch($res, $serveur, $option)) {
2142 $pos++;
2143 }
2144 }
2145
2146 return $pos;
2147 }
2148
2149
2150 /**
2151 * Teste qu'une description de champ SQL est de type entier
2152 *
2153 * @api
2154 * @see sql_test_date() pour tester les champs de date
2155 *
2156 * @param string $type
2157 * Description de la colonne SQL
2158 * @param string $serveur
2159 * Nom du connecteur
2160 * @param bool $option
2161 * Inutilisé
2162 * @return bool
2163 * True si le champ est de type entier
2164 */
2165 function sql_test_int($type, $serveur = '', $option = true) {
2166 return preg_match('/^(TINYINT|SMALLINT|MEDIUMINT|INT|INTEGER|BIGINT)/i', trim($type));
2167 }
2168
2169 /**
2170 * Teste qu'une description de champ SQL est de type entier
2171 *
2172 * @api
2173 * @see sql_test_int() pour tester les champs d'entiers
2174 *
2175 * @param string $type
2176 * Description de la colonne SQL
2177 * @param string $serveur
2178 * Nom du connecteur
2179 * @param bool $option
2180 * Inutilisé
2181 * @return bool
2182 * True si le champ est de type entier
2183 */
2184 function sql_test_date($type, $serveur = '', $option = true) {
2185 return preg_match('/^(DATE|DATETIME|TIMESTAMP|TIME)/i', trim($type));
2186 }
2187
2188 /**
2189 * Formate une date
2190 *
2191 * Formater une date Y-m-d H:i:s sans passer par mktime
2192 * qui ne sait pas gerer les dates < 1970
2193 *
2194 * @api
2195 * @param int $annee Annee
2196 * @param int $mois Numero du mois
2197 * @param int $jour Numero du jour dans le mois
2198 * @param int $h Heures
2199 * @param int $m Minutes
2200 * @param int $s Secondes
2201 * @param string $serveur
2202 * Le serveur sollicite (pour retrouver la connexion)
2203 * @return string
2204 * La date formatee
2205 */
2206 function sql_format_date($annee = 0, $mois = 0, $jour = 0, $h = 0, $m = 0, $s = 0, $serveur = '') {
2207 $annee = sprintf("%04s", $annee);
2208 $mois = sprintf("%02s", $mois);
2209
2210 if ($annee == "0000") {
2211 $mois = 0;
2212 }
2213 if ($mois == "00") {
2214 $jour = 0;
2215 }
2216
2217 return sprintf("%04u", $annee) . '-' . sprintf("%02u", $mois) . '-'
2218 . sprintf("%02u", $jour) . ' ' . sprintf("%02u", $h) . ':'
2219 . sprintf("%02u", $m) . ':' . sprintf("%02u", $s);
2220 }
2221
2222
2223 /**
2224 * Retourne la description de la table SQL
2225 *
2226 * Retrouve la description de la table SQL en privilegiant
2227 * la structure reelle de la base de donnees.
2228 * En absence, ce qui arrive lors de l'installation, la fonction
2229 * s'appuie sur la declaration des tables SQL principales ou auxiliaires.
2230 *
2231 * @internal Cette fonction devrait disparaître
2232 *
2233 * @param string $nom
2234 * Nom de la table dont on souhait la description
2235 * @param string $serveur
2236 * Nom du connecteur
2237 * @return array|bool
2238 * Description de la table ou false si elle n'est pas trouvee ou declaree.
2239 **/
2240 function description_table($nom, $serveur = '') {
2241
2242 static $trouver_table;
2243
2244 /* toujours utiliser trouver_table
2245 qui renverra la description theorique
2246 car sinon on va se comporter differement selon que la table est declaree
2247 ou non
2248 */
2249 if (!$trouver_table) {
2250 $trouver_table = charger_fonction('trouver_table', 'base');
2251 }
2252 if ($desc = $trouver_table($nom, $serveur)) {
2253 return $desc;
2254 }
2255
2256 // sauf a l'installation :
2257 include_spip('base/serial');
2258 if (isset($GLOBALS['tables_principales'][$nom])) {
2259 return $GLOBALS['tables_principales'][$nom];
2260 }
2261
2262 include_spip('base/auxiliaires');
2263 if (isset($GLOBALS['tables_auxiliaires'][$nom])) {
2264 return $GLOBALS['tables_auxiliaires'][$nom];
2265 }
2266
2267 return false;
2268 }
2269
2270 /**
2271 * Corrige le nom d’une table SQL en utilisant le bon préfixe
2272 *
2273 * Ie: si prefixe 'dev', retournera, pour la table 'spip_articles' : 'dev_articles'.
2274 *
2275 * @param string $table
2276 * @param string $prefixe
2277 * @return string Table sql éventuellement renommée
2278 */
2279 function prefixer_table_spip($table, $prefixe) {
2280 if ($prefixe) {
2281 $table = preg_replace('/^spip_/', $prefixe . '_', $table);
2282 }
2283 return $table;
2284 }