erreur thunmbail4
[aidenligne_francais_universite.git] / ecrire / base / db_mysql.php
CommitLineData
c495c100
P
1<?php
2
3/***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2007 *
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
13if (!defined("_ECRIRE_INC_VERSION")) return;
14
15//constantes spip pour spip_fetch_array()
16define('SPIP_BOTH', MYSQL_BOTH);
17define('SPIP_ASSOC', MYSQL_ASSOC);
18define('SPIP_NUM', MYSQL_NUM);
19
20//
21// Appel de requetes SQL
22//
23
24// fonction pour la premiere connexion
25
26// http://doc.spip.org/@base_db_mysql_dist
27function base_db_mysql_dist()
28{
29 // fichier d'init present ?
30 if (!_FILE_CONNECT) {
31 if ($GLOBALS['exec'] != 'install') // est-ce l'installation ?
32 return false; // non, faut faire sans
33 else return 'spip_query_db'; // oui; valeur d'office
34 }
35
36 include_once(_FILE_CONNECT);
37 if (!$GLOBALS['db_ok']) return false;
38
39 // Version courante = 0.3
40 //
41 // les versions 0.1 et 0.2 fonctionnent toujours, meme si :
42 // - la version 0.1 est moins performante que la 0.2
43 // - la 0.2 fait un include_ecrire('inc_db_mysql.php3')
44 // En tout cas on ne force pas la mise a niveau
45 if ($GLOBALS['spip_connect_version'] >= 0.1)
46 return 'spip_query_db';
47
48 // La version 0.0 (non numerotee) doit etre refaite par un admin
49
50 if (!_DIR_RESTREINT) return false;
51
52 include_spip('inc/headers');
53 redirige_par_entete(generer_url_ecrire('upgrade', 'reinstall=oui', true));
54}
55
56// http://doc.spip.org/@spip_query_db
57function spip_query_db($query) {
58
59 $query = traite_query($query);
60
61 $start = (isset($_GET['var_profile'])
62 AND isset($GLOBALS['auteur_session']['statut'])
63 AND ($GLOBALS['auteur_session']['statut'] == '0minirezo')
64 ) ? microtime() : 0;
65
66 return spip_mysql_trace($query,
67 $start,
68 (($GLOBALS['mysql_rappel_connexion'] AND $GLOBALS['spip_mysql_link']) ?
69 mysql_query($query, $GLOBALS['spip_mysql_link']) :
70 mysql_query($query)));
71}
72
73// http://doc.spip.org/@spip_mysql_trace
74function spip_mysql_trace($query, $start, $result)
75{
76 $s = mysql_errno();
77
78 if ($start) spip_mysql_timing($start, microtime(), $query, $result);
79
80 if ($s) {
81 $s .= ' '.mysql_error();
82 if ($GLOBALS['mysql_debug']
83 AND (isset($GLOBALS['auteur_session']['statut']))
84 AND ($GLOBALS['auteur_session']['statut'] == '0minirezo')) {
85 include_spip('public/debug');
86 echo _T('info_erreur_requete'),
87 " ",
88 htmlentities($query),
89 "<br />&laquo; ",
90 htmlentities($result = $s),
91 " &raquo;<p>";
92 }
93 spip_log($GLOBALS['REQUEST_METHOD'].' '.$GLOBALS['REQUEST_URI'], 'mysql');
94 spip_log("$result - $query", 'mysql');
95 spip_log($s, 'mysql');
96 }
97 return $result;
98}
99
100// http://doc.spip.org/@spip_mysql_timing
101function spip_mysql_timing($m1, $m2, $query, $result)
102{
103 static $tt = 0;
104 list($usec, $sec) = explode(" ", $m1);
105 list($usec2, $sec2) = explode(" ", $m2);
106 $dt = $sec2 + $usec2 - $sec - $usec;
107 $tt += $dt;
108 echo "<small>", htmlentities($query), " -> <span style='color: blue'>", sprintf("%3f", $dt),"</span> (", $tt, ")</small> $result<p>\n";
109}
110
111// fonction appelant la precedente specifiquement pour l'espace public
112// c'est une instance de spip_abstract_select, voir ses specs dans abstract.php
113// traite_query pourrait y est fait d'avance, à moindre cout.
114// Les \n et \t sont utiles au debusqueur.
115
116// La parametre sous_requete n'est plus utilise
117
118// http://doc.spip.org/@spip_mysql_select
119function spip_mysql_select($select, $from, $where,
120 $groupby, $orderby, $limit,
121 $sousrequete, $having,
122 $table, $id, $server) {
123
124 $query = (!is_array($select) ? $select : join(", ", $select)) .
125 (!$from ? '' :
126 ("\nFROM " .
127 (!is_array($from) ? $from : spip_select_as($from))))
128 . (!$where ? '' : ("\nWHERE " . (!is_array($where) ? $where : (join("\n\tAND ", array_map('calculer_where', $where))))))
129 . ($groupby ? "\nGROUP BY $groupby" : '')
130 . (!$having ? '' : "\nHAVING " . (!is_array($having) ? $having : (join("\n\tAND ", array_map('calculer_where', $having)))))
131 . ($orderby ? ("\nORDER BY " . join(", ", $orderby)) : '')
132 . ($limit ? "\nLIMIT $limit" : '');
133
134 // Erreur ? C'est du debug de squelette, ou une erreur du serveur
135
136 if (isset($GLOBALS['var_mode']) AND $GLOBALS['var_mode'] == 'debug') {
137 include_spip('public/debug');
138 boucle_debug_resultat($id, 'requete', "SELECT " . $query);
139 }
140
141 if (!($res = @spip_query("SELECT ". $query, $server))) {
142 include_spip('public/debug');
143 erreur_requete_boucle($query, $id, $table,
144 spip_sql_errno(),
145 spip_sql_error());
146 }
147 return $res;
148}
149
150// http://doc.spip.org/@calculer_where
151function calculer_where($v)
152{
153 if (!is_array($v))
154 return $v ;
155
156 $op = array_shift($v);
157 if (!($n=count($v)))
158 return $op;
159 else {
160 $arg = calculer_where(array_shift($v));
161 if ($n==1) {
162 return "$op($arg)";
163 } else {
164 $arg2 = calculer_where(array_shift($v));
165 if ($n==2) {
166 return "($arg $op $arg2)";
167 } else return "($arg $op ($arg2) : $v[0])";
168 }
169 }
170}
171
172// http://doc.spip.org/@spip_select_as
173function spip_select_as($args)
174{
175 $argsas = "";
176 foreach($args as $k => $v) {
177 $argsas .= ', ' . $v . (is_numeric($k) ? '' : " AS `$k`");
178 }
179 return substr($argsas,2);
180}
181
182//
183// Passage d'une requete standardisee
184// Quand tous les appels SQL seront abstraits on pourra l'ameliorer
185
186// http://doc.spip.org/@traite_query
187function traite_query($query) {
188 if ($GLOBALS['table_prefix']) $table_pref = $GLOBALS['table_prefix']."_";
189 else $table_pref = "";
190
191 if ($GLOBALS['mysql_rappel_nom_base'] AND $db = $GLOBALS['spip_mysql_db'])
192 $db = '`'.$db.'`.';
193
194 // changer les noms des tables ($table_prefix)
195 if (preg_match('/\s(SET|VALUES|WHERE)\s/i', $query, $regs)) {
196 $suite = strstr($query, $regs[0]);
197 $query = substr($query, 0, -strlen($suite));
198 } else $suite ='';
199 return preg_replace('/([,\s])spip_/', '\1'.$db.$table_pref, $query) . $suite;
200}
201
202//
203// Fonction appelee uniquement par le fichier FILE_CONNECT cree a l'installation,
204// et comportant les identifants de connexion SQL
205// db_ok est globale, pour test par base_db_mysql_dist ci-dessus
206// Ce serait plus propre de reduire FILE_CONNECT a un fichier de donnees
207// et d'appeler cette fonction a partir de base_db_mysql_dist.
208
209// http://doc.spip.org/@spip_connect_db
210function spip_connect_db($host, $port, $login, $pass, $db) {
211 global $spip_mysql_link, $spip_mysql_db; // pour connexions multiples
212
213 // gerer le fichier tmp/mysql_out
214 ## TODO : ajouter md5(parametres de connexion)
215 if (@file_exists(_DIR_TMP.'mysql_out')
216 AND (time() - @filemtime(_DIR_TMP.'mysql_out') < 30)
217 AND !defined('_ECRIRE_INSTALL'))
218 return $GLOBALS['db_ok'] = false;
219
220 if ($port > 0) $host = "$host:$port";
221 $spip_mysql_link = @mysql_connect($host, $login, $pass);
222 $spip_mysql_db = $db;
223 $ok = @mysql_select_db($db);
224
225 if (defined('_MYSQL_SQL_MODE_TEXT_NOT_NULL'))
226 mysql_query("set sql_mode=''");
227
228 $GLOBALS['db_ok'] = $ok
229 AND !!@spip_num_rows(@spip_query_db('SELECT COUNT(*) FROM spip_meta'));
230
231 // En cas d'erreur marquer le fichier mysql_out
232 if (!$GLOBALS['db_ok']
233 AND !defined('_ECRIRE_INSTALL')) {
234 @touch(_DIR_TMP.'mysql_out');
235 $err = 'Echec connexion MySQL '.spip_sql_errno().' '.spip_sql_error();
236 spip_log($err);
237 spip_log($err, 'mysql');
238 } else $GLOBALS['db_ok'] = 'spip_query_db';
239 return $GLOBALS['db_ok'];
240}
241
242// Fonction de creation d'une table SQL nommee $nom
243// a partir de 2 tableaux PHP :
244// champs: champ => type
245// cles: type-de-cle => champ(s)
246// si $autoinc, c'est une auto-increment (i.e. serial) sur la Primary Key
247// Le nom des caches doit etre inferieur a 64 caracteres
248
249// http://doc.spip.org/@spip_mysql_create
250function spip_mysql_create($nom, $champs, $cles, $autoinc=false, $temporary=false) {
251 $query = ''; $keys = ''; $s = ''; $p='';
252
253 // certains plugins declarent les tables (permet leur inclusion dans le dump)
254 // sans les renseigner (laisse le compilo recuperer la description)
255 if (!is_array($champs) || !is_array($cles))
256 return;
257
258 foreach($cles as $k => $v) {
259 $keys .= "$s\n\t\t$k ($v)";
260 if ($k == "PRIMARY KEY")
261 $p = $v;
262 $s = ",";
263 }
264 $s = '';
265
266 foreach($champs as $k => $v) {
267 $query .= "$s\n\t\t$k $v" .
268 (($autoinc && ($p == $k)) ? " auto_increment" : '');
269 $s = ",";
270 }
271 $temporary = $temporary ? 'TEMPORARY':'';
272 spip_query_db("CREATE $temporary TABLE IF NOT EXISTS $nom ($query" . ($keys ? ",$keys" : '') . ")\n");
273}
274
275// http://doc.spip.org/@spip_mysql_showtable
276function spip_mysql_showtable($nom_table)
277{
278 $a = spip_query("SHOW TABLES LIKE '$nom_table'");
279 if (!$a) return "";
280 if (!spip_fetch_array($a)) return "";
281 list(,$a) = spip_fetch_array(spip_query("SHOW CREATE TABLE $nom_table"),SPIP_NUM);
282 if (!preg_match("/^[^(),]*\((([^()]*\([^()]*\)[^()]*)*)\)[^()]*$/", $a, $r))
283 return "";
284 else {
285 $dec = $r[1];
286 if (preg_match("/^(.*?),([^,]*KEY.*)$/s", $dec, $r)) {
287 $namedkeys = $r[2];
288 $dec = $r[1];
289 }
290 else
291 $namedkeys = "";
292
293 $fields = array();
294 foreach(preg_split("/,\s*`/",$dec) as $v) {
295 preg_match("/^\s*`?([^`]*)`\s*(.*)/",$v,$r);
296 $fields[strtolower($r[1])] = $r[2];
297 }
298 $keys = array();
299
300 foreach(preg_split('/\)\s*,?/',$namedkeys) as $v) {
301 if (preg_match("/^\s*([^(]*)\((.*)$/",$v,$r)) {
302 $k = str_replace("`", '', trim($r[1]));
303 $t = strtolower(str_replace("`", '', $r[2]));
304 if ($k && !isset($keys[$k])) $keys[$k] = $t; else $keys[] = $t;
305 }
306 }
307 return array('field' => $fields, 'key' => $keys);
308 }
309}
310
311//
312// Recuperation des resultats
313//
314
315// interface de abstract_sql.
316
317// http://doc.spip.org/@spip_mysql_fetch
318function spip_mysql_fetch($r, $t=SPIP_ASSOC) {
319 if ($r) return mysql_fetch_array($r, $t);
320}
321
322// http://doc.spip.org/@spip_fetch_array
323function spip_fetch_array($r, $t=SPIP_ASSOC) {
324 if ($r) return mysql_fetch_array($r, $t);
325}
326
327// http://doc.spip.org/@spip_sql_error
328function spip_sql_error() {
329 return mysql_error();
330}
331
332// http://doc.spip.org/@spip_sql_errno
333function spip_sql_errno() {
334 return mysql_errno();
335}
336
337// Interface de abstract_sql
338// http://doc.spip.org/@spip_mysql_count
339function spip_mysql_count($r) {
340 if ($r) return mysql_num_rows($r);
341}
342
343// http://doc.spip.org/@spip_num_rows
344function spip_num_rows($r) {
345 if ($r) return mysql_num_rows($r);
346}
347
348// Interface de abstract_sql (on est sur de l'argument, c'est le compilateur)
349
350// http://doc.spip.org/@spip_mysql_free
351function spip_mysql_free($r) {
352 return mysql_free_result($r);
353}
354
355// Vieux nom a laisser tomber
356// http://doc.spip.org/@spip_free_result
357function spip_free_result($r) {
358 if ($r) return mysql_free_result($r);
359}
360
361// http://doc.spip.org/@spip_mysql_insert
362function spip_mysql_insert($table, $champs, $valeurs) {
363 spip_query("INSERT INTO $table $champs VALUES $valeurs");
364 return mysql_insert_id();
365}
366
367// http://doc.spip.org/@spip_insert_id
368function spip_insert_id() {
369 return mysql_insert_id();
370}
371
372//
373// Poser un verrou local a un SPIP donne
374//
375// http://doc.spip.org/@spip_get_lock
376function spip_get_lock($nom, $timeout = 0) {
377 global $spip_mysql_db, $table_prefix;
378 if ($table_prefix) $nom = "$table_prefix:$nom";
379 if ($spip_mysql_db) $nom = "$spip_mysql_db:$nom";
380
381 // Changer de nom toutes les heures en cas de blocage MySQL (ca arrive)
382 define('_LOCK_TIME', intval(time()/3600-316982));
383 $nom .= _LOCK_TIME;
384
385 $q = spip_query("SELECT GET_LOCK(" . _q($nom) . ", $timeout)");
386 list($lock_ok) = spip_fetch_array($q,SPIP_NUM);
387
388 if (!$lock_ok) spip_log("pas de lock sql pour $nom");
389 return $lock_ok;
390}
391
392// http://doc.spip.org/@spip_release_lock
393function spip_release_lock($nom) {
394 global $spip_mysql_db, $table_prefix;
395 if ($table_prefix) $nom = "$table_prefix:$nom";
396 if ($spip_mysql_db) $nom = "$spip_mysql_db:$nom";
397
398 $nom .= _LOCK_TIME;
399
400 spip_query("SELECT RELEASE_LOCK(" . _q($nom) . ")");
401}
402
403// http://doc.spip.org/@spip_mysql_version
404function spip_mysql_version() {
405 $row = spip_fetch_array(spip_query("SELECT version() AS n"));
406 return ($row['n']);
407}
408
409// http://doc.spip.org/@creer_objet_multi
410function creer_objet_multi ($objet, $lang) {
411 $retour = "(TRIM(IF(INSTR(".$objet.", '<multi>') = 0 , ".
412 " TRIM(".$objet."), ".
413 " CONCAT( ".
414 " LEFT(".$objet.", INSTR(".$objet.", '<multi>')-1), ".
415 " IF( ".
416 " INSTR(TRIM(RIGHT(".$objet.", LENGTH(".$objet.") -(6+INSTR(".$objet.", '<multi>')))),'[".$lang."]') = 0, ".
417 " IF( ".
418 " TRIM(RIGHT(".$objet.", LENGTH(".$objet.") -(6+INSTR(".$objet.", '<multi>')))) REGEXP '^\\[[a-z\_]{2,}\\]', ".
419 " INSERT( ".
420 " TRIM(RIGHT(".$objet.", LENGTH(".$objet.") -(6+INSTR(".$objet.", '<multi>')))), ".
421 " 1, ".
422 " INSTR(TRIM(RIGHT(".$objet.", LENGTH(".$objet.") -(6+INSTR(".$objet.", '<multi>')))), ']'), ".
423 " '' ".
424 " ), ".
425 " TRIM(RIGHT(".$objet.", LENGTH(".$objet.") -(6+INSTR(".$objet.", '<multi>')))) ".
426 " ), ".
427 " TRIM(RIGHT(".$objet.", ( LENGTH(".$objet.") - (INSTR(".$objet.", '[".$lang."]')+ LENGTH('[".$lang."]')-1) ) )) ".
428 " ) ".
429 " ) ".
430 "))) AS multi ";
431
432 return $retour;
433}
434
435
436?>