[SPIP] ~2.1.12 -->2.1.25
[velocampus/web/www.git] / www / ecrire / req / mysql.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2014 *
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 if (!defined('_ECRIRE_INC_VERSION')) return;
14
15 // fonction pour la premiere connexion a un serveur MySQL
16
17 // http://doc.spip.org/@req_mysql_dist
18 function req_mysql_dist($host, $port, $login, $pass, $db='', $prefixe='') {
19 if (!charger_php_extension('mysql')) return false;
20 if ($port > 0) $host = "$host:$port";
21 $link = @mysql_connect($host, $login, $pass, true);
22 if (!$link) {
23 spip_log('Echec mysql_connect. Erreur : ' . mysql_error(),'mysql');
24 return false;
25 }
26 $last = '';
27 if (!$db) {
28 $ok = $link;
29 $db = 'spip';
30 } else {
31 $ok = spip_mysql_selectdb($db);
32 if (defined('_MYSQL_SET_SQL_MODE')
33 OR defined('_MYSQL_SQL_MODE_TEXT_NOT_NULL') // compatibilite
34 )
35 mysql_query($last = "set sql_mode=''");
36 }
37 # spip_log("Connexion vers $host, base $db, prefixe $prefixe "
38 # . ($ok ? "operationnelle sur $link" : 'impossible'));
39
40 return !$ok ? false : array(
41 'db' => $db,
42 'last' => $last,
43 'prefixe' => $prefixe ? $prefixe : $db,
44 'link' => $GLOBALS['mysql_rappel_connexion'] ? $link : false,
45 );
46 }
47
48 $GLOBALS['spip_mysql_functions_1'] = array(
49 'alter' => 'spip_mysql_alter',
50 'count' => 'spip_mysql_count',
51 'countsel' => 'spip_mysql_countsel',
52 'create' => 'spip_mysql_create',
53 'create_base' => 'spip_mysql_create_base',
54 'create_view' => 'spip_mysql_create_view',
55 'date_proche' => 'spip_mysql_date_proche',
56 'delete' => 'spip_mysql_delete',
57 'drop_table' => 'spip_mysql_drop_table',
58 'drop_view' => 'spip_mysql_drop_view',
59 'errno' => 'spip_mysql_errno',
60 'error' => 'spip_mysql_error',
61 'explain' => 'spip_mysql_explain',
62 'fetch' => 'spip_mysql_fetch',
63 'seek' => 'spip_mysql_seek',
64 'free' => 'spip_mysql_free',
65 'hex' => 'spip_mysql_hex',
66 'in' => 'spip_mysql_in',
67 'insert' => 'spip_mysql_insert',
68 'insertq' => 'spip_mysql_insertq',
69 'insertq_multi' => 'spip_mysql_insertq_multi',
70 'listdbs' => 'spip_mysql_listdbs',
71 'multi' => 'spip_mysql_multi',
72 'optimize' => 'spip_mysql_optimize',
73 'query' => 'spip_mysql_query',
74 'quote' => 'spip_mysql_quote',
75 'replace' => 'spip_mysql_replace',
76 'replace_multi' => 'spip_mysql_replace_multi',
77 'repair' => 'spip_mysql_repair',
78 'select' => 'spip_mysql_select',
79 'selectdb' => 'spip_mysql_selectdb',
80 'set_charset' => 'spip_mysql_set_charset',
81 'get_charset' => 'spip_mysql_get_charset',
82 'showbase' => 'spip_mysql_showbase',
83 'showtable' => 'spip_mysql_showtable',
84 'update' => 'spip_mysql_update',
85 'updateq' => 'spip_mysql_updateq',
86
87 // association de chaque nom http d'un charset aux couples MySQL
88 'charsets' => array(
89 'cp1250'=>array('charset'=>'cp1250','collation'=>'cp1250_general_ci'),
90 'cp1251'=>array('charset'=>'cp1251','collation'=>'cp1251_general_ci'),
91 'cp1256'=>array('charset'=>'cp1256','collation'=>'cp1256_general_ci'),
92 'iso-8859-1'=>array('charset'=>'latin1','collation'=>'latin1_swedish_ci'),
93 //'iso-8859-6'=>array('charset'=>'latin1','collation'=>'latin1_swedish_ci'),
94 'iso-8859-9'=>array('charset'=>'latin5','collation'=>'latin5_turkish_ci'),
95 //'iso-8859-15'=>array('charset'=>'latin1','collation'=>'latin1_swedish_ci'),
96 'utf-8'=>array('charset'=>'utf8','collation'=>'utf8_general_ci'))
97 );
98
99 // http://doc.spip.org/@spip_mysql_set_charset
100 function spip_mysql_set_charset($charset, $serveur='',$requeter=true,$requeter=true){
101 $connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
102 #spip_log("changement de charset sql : "."SET NAMES "._q($charset));
103 return mysql_query($connexion['last'] = "SET NAMES "._q($charset));
104 }
105
106 // http://doc.spip.org/@spip_mysql_get_charset
107 function spip_mysql_get_charset($charset=array(), $serveur='',$requeter=true){
108 $connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
109 $connexion['last'] = $c = "SHOW CHARACTER SET"
110 . (!$charset ? '' : (" LIKE "._q($charset['charset'])));
111
112 return spip_mysql_fetch(mysql_query($c), NULL, $serveur);
113 }
114
115 // obsolete, ne plus utiliser
116 // http://doc.spip.org/@spip_query_db
117 function spip_query_db($query, $serveur='',$requeter=true) {
118 return spip_mysql_query($query, $serveur, $requeter);
119 }
120
121 // Fonction de requete generale, munie d'une trace a la demande
122
123 // http://doc.spip.org/@spip_mysql_query
124 function spip_mysql_query($query, $serveur='',$requeter=true) {
125
126 $connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
127 $prefixe = $connexion['prefixe'];
128 $link = $connexion['link'];
129 $db = $connexion['db'];
130
131 $query = traite_query($query, $db, $prefixe);
132
133 // renvoyer la requete inerte si demandee
134 if (!$requeter) return $query;
135
136 if (isset($_GET['var_profile'])) {
137 include_spip('public/tracer');
138 $t = trace_query_start();
139 } else $t = 0 ;
140
141 $connexion['last'] = $query;
142
143 // ajouter un debug utile dans log/mysql-slow.log ?
144 $debug = (!defined('_DEBUG_SLOW_QUERIES') || !_DEBUG_SLOW_QUERIES)
145 ? ''
146 : ' /* '
147 .str_replace('*/','@/',
148 $_SERVER['REQUEST_URI'].' + '.$GLOBALS['ip']
149 )
150 .' */';
151
152 $r = $link ? mysql_query($query.$debug, $link) : mysql_query($query.$debug);
153
154 if ($e = spip_mysql_errno($serveur)) // Log de l'erreur eventuelle
155 $e .= spip_mysql_error($query, $serveur); // et du fautif
156 return $t ? trace_query_end($query, $t, $r, $e, $serveur) : $r;
157 }
158
159 // http://doc.spip.org/@spip_mysql_alter
160 function spip_mysql_alter($query, $serveur='',$requeter=true){
161 return spip_mysql_query("ALTER ".$query, $serveur, $requeter); # i.e. que PG se debrouille
162 }
163
164 // http://doc.spip.org/@spip_mysql_optimize
165 function spip_mysql_optimize($table, $serveur='',$requeter=true){
166 spip_mysql_query("OPTIMIZE TABLE ". $table);
167 return true;
168 }
169
170 // http://doc.spip.org/@spip_mysql_explain
171 function spip_mysql_explain($query, $serveur='',$requeter=true){
172 if (strpos(ltrim($query), 'SELECT') !== 0) return array();
173 $connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
174 $prefixe = $connexion['prefixe'];
175 $link = $connexion['link'];
176 $db = $connexion['db'];
177
178 $query = 'EXPLAIN ' . traite_query($query, $db, $prefixe);
179 $r = $link ? mysql_query($query, $link) : mysql_query($query);
180 return spip_mysql_fetch($r, NULL, $serveur);
181 }
182 // fonction instance de sql_select, voir ses specs dans abstract.php
183 // traite_query pourrait y etre fait d'avance ce serait moins cher
184 // Les \n et \t sont utiles au debusqueur.
185
186
187 // http://doc.spip.org/@spip_mysql_select
188 function spip_mysql_select($select, $from, $where='',
189 $groupby='', $orderby='', $limit='', $having='',
190 $serveur='',$requeter=true) {
191
192
193 $from = (!is_array($from) ? $from : spip_mysql_select_as($from));
194 $query =
195 calculer_mysql_expression('SELECT', $select, ', ')
196 . calculer_mysql_expression('FROM', $from, ', ')
197 . calculer_mysql_expression('WHERE', $where)
198 . calculer_mysql_expression('GROUP BY', $groupby, ',')
199 . calculer_mysql_expression('HAVING', $having)
200 . ($orderby ? ("\nORDER BY " . spip_mysql_order($orderby)) :'')
201 . ($limit ? "\nLIMIT $limit" : '');
202
203 // renvoyer la requete inerte si demandee
204 if ($requeter === false) return $query;
205 $r = spip_mysql_query($query, $serveur, $requeter);
206 return $r ? $r : $query;
207 }
208
209 // 0+x avec un champ x commencant par des chiffres est converti par MySQL
210 // en le nombre qui commence x.
211 // Pas portable malheureusement, on laisse pour le moment.
212
213 // http://doc.spip.org/@spip_mysql_order
214 function spip_mysql_order($orderby)
215 {
216 return (is_array($orderby)) ? join(", ", $orderby) : $orderby;
217 }
218
219
220 // http://doc.spip.org/@calculer_mysql_where
221 function calculer_mysql_where($v)
222 {
223 if (!is_array($v))
224 return $v ;
225
226 $op = array_shift($v);
227 if (!($n=count($v)))
228 return $op;
229 else {
230 $arg = calculer_mysql_where(array_shift($v));
231 if ($n==1) {
232 return "$op($arg)";
233 } else {
234 $arg2 = calculer_mysql_where(array_shift($v));
235 if ($n==2) {
236 return "($arg $op $arg2)";
237 } else return "($arg $op ($arg2) : $v[0])";
238 }
239 }
240 }
241
242 // http://doc.spip.org/@calculer_mysql_expression
243 function calculer_mysql_expression($expression, $v, $join = 'AND'){
244 if (empty($v))
245 return '';
246
247 $exp = "\n$expression ";
248
249 if (!is_array($v)) {
250 return $exp . $v;
251 } else {
252 if (strtoupper($join) === 'AND')
253 return $exp . join("\n\t$join ", array_map('calculer_mysql_where', $v));
254 else
255 return $exp . join($join, $v);
256 }
257 }
258
259 // http://doc.spip.org/@spip_mysql_select_as
260 function spip_mysql_select_as($args)
261 {
262 $res = '';
263 foreach($args as $k => $v) {
264 if (substr($k,-1)=='@') {
265 // c'est une jointure qui se refere au from precedent
266 // pas de virgule
267 $res .= ' ' . $v ;
268 }
269 else {
270 if (!is_numeric($k)) {
271 $p = strpos($v, " ");
272 if ($p)
273 $v = substr($v,0,$p) . " AS `$k`" . substr($v,$p);
274 else $v .= " AS `$k`";
275 }
276
277 $res .= ', ' . $v ;
278 }
279 }
280 return substr($res,2);
281 }
282
283 //
284 // Changer les noms des tables ($table_prefix)
285 // Quand tous les appels SQL seront abstraits on pourra l'ameliorer
286
287 define('_SQL_PREFIXE_TABLE', '/([,\s])spip_/S');
288
289 // http://doc.spip.org/@traite_query
290 function traite_query($query, $db='', $prefixe='') {
291
292 if ($GLOBALS['mysql_rappel_nom_base'] AND $db)
293 $pref = '`'. $db.'`.';
294 else $pref = '';
295
296 if ($prefixe)
297 $pref .= $prefixe . "_";
298
299 if (!preg_match('/\s(SET|VALUES|WHERE|DATABASE)\s/i', $query, $regs)) {
300 $suite ='';
301 } else {
302 $suite = strstr($query, $regs[0]);
303 $query = substr($query, 0, -strlen($suite));
304 // propager le prefixe en cas de requete imbriquee
305 // il faut alors echapper les chaine avant de le faire, pour ne pas risquer de
306 // modifier une requete qui est en fait juste du texte dans un champ
307 if (strpos(strtoupper($suite),"SELECT")!==false) {
308 list($suite,$textes) = query_echappe_textes($suite);
309 if (preg_match('/^(.*?)([(]\s*SELECT\b.*)$/si', $suite, $r))
310 $suite = $r[1] . traite_query($r[2], $db, $prefixe);
311 $suite = query_reinjecte_textes($suite, $textes);
312 }
313 }
314 $r = preg_replace(_SQL_PREFIXE_TABLE, '\1'.$pref, $query) . $suite;
315 # spip_log("traite_query: " . substr($r,0, 50) . ".... $db, $prefixe");
316 return $r;
317 }
318
319 // http://doc.spip.org/@spip_mysql_selectdb
320 function spip_mysql_selectdb($db) {
321 $ok = mysql_select_db($db);
322 if (!$ok)
323 spip_log('Echec mysql_selectdb. Erreur : ' . mysql_error(),'mysql');
324 return $ok;
325 }
326
327
328 // Retourne les bases accessibles
329 // Attention on n'a pas toujours les droits
330
331 // http://doc.spip.org/@spip_mysql_listdbs
332 function spip_mysql_listdbs($serveur='',$requeter=true) {
333 $res = spip_mysql_query("SHOW DATABASES");
334 return $res;
335 }
336
337 // Fonction de creation d'une table SQL nommee $nom
338 // a partir de 2 tableaux PHP :
339 // champs: champ => type
340 // cles: type-de-cle => champ(s)
341 // si $autoinc, c'est une auto-increment (i.e. serial) sur la Primary Key
342 // Le nom des caches doit etre inferieur a 64 caracteres
343
344 // http://doc.spip.org/@spip_mysql_create
345 function spip_mysql_create($nom, $champs, $cles, $autoinc=false, $temporary=false, $serveur='',$requeter=true) {
346
347 $query = ''; $keys = ''; $s = ''; $p='';
348
349 // certains plugins declarent les tables (permet leur inclusion dans le dump)
350 // sans les renseigner (laisse le compilo recuperer la description)
351 if (!is_array($champs) || !is_array($cles))
352 return;
353
354 $res = spip_mysql_query("SELECT version() as v");
355 if ($row = mysql_fetch_array($res)
356 && (version_compare($row['v'],'5.0','>=')))
357 spip_mysql_query("SET sql_mode=''");
358
359 foreach($cles as $k => $v) {
360 $keys .= "$s\n\t\t$k ($v)";
361 if ($k == "PRIMARY KEY")
362 $p = $v;
363 $s = ",";
364 }
365 $s = '';
366
367 $character_set = "";
368 if (@$GLOBALS['meta']['charset_sql_base'])
369 $character_set .= " CHARACTER SET ".$GLOBALS['meta']['charset_sql_base'];
370 if (@$GLOBALS['meta']['charset_collation_sql_base'])
371 $character_set .= " COLLATE ".$GLOBALS['meta']['charset_collation_sql_base'];
372
373 foreach($champs as $k => $v) {
374 if (preg_match(',([a-z]*\s*(\(\s*[0-9]*\s*\))?(\s*binary)?),i',$v,$defs)){
375 if (preg_match(',(char|text),i',$defs[1]) AND !preg_match(',binary,i',$defs[1]) ){
376 $v = $defs[1] . $character_set . ' ' . substr($v,strlen($defs[1]));
377 }
378 }
379
380 $query .= "$s\n\t\t$k $v"
381 . (($autoinc && ($p == $k) && preg_match(',\b(big|small|medium)?int\b,i', $v))
382 ? " auto_increment"
383 : ''
384 );
385 $s = ",";
386 }
387 $temporary = $temporary ? 'TEMPORARY':'';
388 $q = "CREATE $temporary TABLE IF NOT EXISTS $nom ($query" . ($keys ? ",$keys" : '') . ")".
389 ($character_set?" DEFAULT $character_set":"")
390 ."\n";
391 return spip_mysql_query($q, $serveur);
392 }
393
394 function spip_mysql_create_base($nom, $serveur='',$requeter=true) {
395 return spip_mysql_query("CREATE DATABASE `$nom`", $serveur, $requeter);
396 }
397
398 // Fonction de creation d'une vue SQL nommee $nom
399 // http://doc.spip.org/@spip_mysql_create_view
400 function spip_mysql_create_view($nom, $query_select, $serveur='',$requeter=true) {
401 if (!$query_select) return false;
402 // vue deja presente
403 if (sql_showtable($nom, false, $serveur)) {
404 spip_log("Echec creation d'une vue sql ($nom) car celle-ci existe deja (serveur:$serveur)");
405 return false;
406 }
407
408 $query = "CREATE VIEW $nom AS ". $query_select;
409 return spip_mysql_query($query, $serveur, $requeter);
410 }
411
412
413 // http://doc.spip.org/@spip_mysql_drop_table
414 function spip_mysql_drop_table($table, $exist='', $serveur='',$requeter=true)
415 {
416 if ($exist) $exist =" IF EXISTS";
417 if (!preg_match('@^\w+$@', $table)) $table = "`$table`";
418 return spip_mysql_query("DROP TABLE$exist $table", $serveur, $requeter);
419 }
420
421 // supprime une vue
422 // http://doc.spip.org/@spip_mysql_drop_view
423 function spip_mysql_drop_view($view, $exist='', $serveur='',$requeter=true) {
424 if ($exist) $exist =" IF EXISTS";
425 return spip_mysql_query("DROP VIEW$exist `$view`", $serveur, $requeter);
426 }
427
428 // http://doc.spip.org/@spip_mysql_showbase
429 function spip_mysql_showbase($match, $serveur='',$requeter=true)
430 {
431 return spip_mysql_query("SHOW TABLES LIKE " . _q($match), $serveur, $requeter);
432 }
433
434 // http://doc.spip.org/@spip_mysql_repair
435 function spip_mysql_repair($table, $serveur='',$requeter=true)
436 {
437 if (!preg_match('@^\w+$@', $table)) $table = "`$table`";
438 return spip_mysql_query("REPAIR TABLE $table", $serveur, $requeter);
439 }
440
441 // Recupere la definition d'une table ou d'une vue MySQL
442 // colonnes, indexes, etc.
443 // au meme format que la definition des tables de SPIP
444 // http://doc.spip.org/@spip_mysql_showtable
445 function spip_mysql_showtable($nom_table, $serveur='',$requeter=true)
446 {
447 $s = spip_mysql_query("SHOW CREATE TABLE `$nom_table`", $serveur, $requeter);
448 if (!$s) return '';
449 if (!$requeter) return $s;
450
451 list(,$a) = mysql_fetch_array($s ,MYSQL_NUM);
452 if (preg_match("/^[^(),]*\((([^()]*\([^()]*\)[^()]*)*)\)[^()]*$/", $a, $r)){
453 $dec = $r[1];
454 if (preg_match("/^(.*?),([^,]*KEY.*)$/s", $dec, $r)) {
455 $namedkeys = $r[2];
456 $dec = $r[1];
457 }
458 else
459 $namedkeys = "";
460
461 $fields = array();
462 foreach(preg_split("/,\s*`/",$dec) as $v) {
463 preg_match("/^\s*`?([^`]*)`\s*(.*)/",$v,$r);
464 $fields[strtolower($r[1])] = $r[2];
465 }
466 $keys = array();
467
468 foreach(preg_split('/\)\s*,?/',$namedkeys) as $v) {
469 if (preg_match("/^\s*([^(]*)\((.*)$/",$v,$r)) {
470 $k = str_replace("`", '', trim($r[1]));
471 $t = strtolower(str_replace("`", '', $r[2]));
472 if ($k && !isset($keys[$k])) $keys[$k] = $t; else $keys[] = $t;
473 }
474 }
475 spip_mysql_free($s);
476 return array('field' => $fields, 'key' => $keys);
477 }
478
479 $res = spip_mysql_query("SHOW COLUMNS FROM `$nom_table`", $serveur);
480 if($res) {
481 $nfields = array();
482 $nkeys = array();
483 while($val = spip_mysql_fetch($res)) {
484 $nfields[$val["Field"]] = $val['Type'];
485 if($val['Null']=='NO') {
486 $nfields[$val["Field"]] .= ' NOT NULL';
487 }
488 if($val['Default'] === '0' || $val['Default']) {
489 if(preg_match('/[A-Z_]/',$val['Default'])) {
490 $nfields[$val["Field"]] .= ' DEFAULT '.$val['Default'];
491 } else {
492 $nfields[$val["Field"]] .= " DEFAULT '".$val['Default']."'";
493 }
494 }
495 if($val['Extra'])
496 $nfields[$val["Field"]] .= ' '.$val['Extra'];
497 if($val['Key'] == 'PRI') {
498 $nkeys['PRIMARY KEY'] = $val["Field"];
499 } else if($val['Key'] == 'MUL') {
500 $nkeys['KEY '.$val["Field"]] = $val["Field"];
501 } else if($val['Key'] == 'UNI') {
502 $nkeys['UNIQUE KEY '.$val["Field"]] = $val["Field"];
503 }
504 }
505 spip_mysql_free($res);
506 return array('field' => $nfields, 'key' => $nkeys);
507 }
508 return "";
509 }
510
511 //
512 // Recuperation des resultats
513 //
514
515 // http://doc.spip.org/@spip_mysql_fetch
516 function spip_mysql_fetch($r, $t='', $serveur='',$requeter=true) {
517 if (!$t) $t = MYSQL_ASSOC;
518 if ($r) return mysql_fetch_array($r, $t);
519 }
520
521 function spip_mysql_seek($r, $row_number, $serveur='',$requeter=true) {
522 if ($r) return mysql_data_seek($r,$row_number);
523 }
524
525
526 // http://doc.spip.org/@spip_mysql_countsel
527 function spip_mysql_countsel($from = array(), $where = array(),
528 $groupby = '', $having = array(), $serveur='',$requeter=true)
529 {
530 $c = !$groupby ? '*' : ('DISTINCT ' . (is_string($groupby) ? $groupby : join(',', $groupby)));
531
532 $r = spip_mysql_select("COUNT($c)", $from, $where,'', '', '', $having, $serveur, $requeter);
533
534 if (!$requeter) return $r;
535 if (!is_resource($r)) return 0;
536 list($c) = mysql_fetch_array($r, MYSQL_NUM);
537 mysql_free_result($r);
538 return $c;
539 }
540
541 // Bien specifier le serveur auquel on s'adresse,
542 // mais a l'install la globale n'est pas encore completement definie
543 // http://doc.spip.org/@spip_mysql_error
544 function spip_mysql_error($query='', $serveur='',$requeter=true) {
545 $link = $GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0]['link'];
546 $s = $link ? mysql_error($link) : mysql_error();
547 if ($s) spip_log("$s - $query", 'mysql');
548 return $s;
549 }
550
551 // A transposer dans les portages
552 // http://doc.spip.org/@spip_mysql_errno
553 function spip_mysql_errno($serveur='',$requeter=true) {
554 $link = $GLOBALS['connexions'][$serveur ? $serveur : 0]['link'];
555 $s = $link ? mysql_errno($link) : mysql_errno();
556 // 2006 MySQL server has gone away
557 // 2013 Lost connection to MySQL server during query
558 if (in_array($s, array(2006,2013)))
559 define('spip_interdire_cache', true);
560 if ($s) spip_log("Erreur mysql $s");
561 return $s;
562 }
563
564 // Interface de abstract_sql
565 // http://doc.spip.org/@spip_mysql_count
566 function spip_mysql_count($r, $serveur='',$requeter=true) {
567 if ($r) return mysql_num_rows($r);
568 }
569
570
571 // http://doc.spip.org/@spip_mysql_free
572 function spip_mysql_free($r, $serveur='',$requeter=true) {
573 return mysql_free_result($r);
574 }
575
576 // http://doc.spip.org/@spip_mysql_insert
577 function spip_mysql_insert($table, $champs, $valeurs, $desc='', $serveur='',$requeter=true) {
578
579 $connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
580 $prefixe = $connexion['prefixe'];
581 $link = $connexion['link'];
582 $db = $connexion['db'];
583
584 if ($prefixe) $table = preg_replace('/^spip/', $prefixe, $table);
585
586 $query ="INSERT INTO $table $champs VALUES $valeurs";
587 if (!$requeter) return $query;
588
589 if (isset($_GET['var_profile'])) {
590 include_spip('public/tracer');
591 $t = trace_query_start();
592 } else $t = 0 ;
593
594 $connexion['last'] = $query;
595 # spip_log($query);
596 if (mysql_query($query, $link))
597 $r = mysql_insert_id($link);
598 else {
599 if ($e = spip_mysql_errno($serveur)) // Log de l'erreur eventuelle
600 $e .= spip_mysql_error($query, $serveur); // et du fautif
601 }
602 return $t ? trace_query_end($query, $t, $r, $e, $serveur) : $r;
603
604 // return $r ? $r : (($r===0) ? -1 : 0); pb avec le multi-base.
605 }
606
607 // http://doc.spip.org/@spip_mysql_insertq
608 function spip_mysql_insertq($table, $couples=array(), $desc=array(), $serveur='',$requeter=true) {
609
610 if (!$desc) $desc = description_table($table);
611 if (!$desc) $couples = array();
612 $fields = isset($desc['field'])?$desc['field']:array();
613
614 foreach ($couples as $champ => $val) {
615 $couples[$champ]= spip_mysql_cite($val, $fields[$champ]);
616 }
617
618 return spip_mysql_insert($table, "(".join(',',array_keys($couples)).")", "(".join(',', $couples).")", $desc, $serveur, $requeter);
619 }
620
621
622 // http://doc.spip.org/@spip_mysql_insertq_multi
623 function spip_mysql_insertq_multi($table, $tab_couples=array(), $desc=array(), $serveur='',$requeter=true) {
624
625 if (!$desc) $desc = description_table($table);
626 if (!$desc) $tab_couples = array();
627 $fields = isset($desc['field'])?$desc['field']:array();
628
629 $cles = "(" . join(',',array_keys($tab_couples[0])) . ')';
630 $valeurs = array();
631 foreach ($tab_couples as $couples) {
632 foreach ($couples as $champ => $val){
633 $couples[$champ]= spip_mysql_cite($val, $fields[$champ]);
634 }
635 $valeurs[] = '(' .join(',', $couples) . ')';
636 }
637
638 // Inserer par groupes de 100 max pour eviter un debordement de pile
639 $r = false;
640 do {
641 $ins = array_slice($valeurs,0,100);
642 $valeurs = array_slice($valeurs,100);
643 $r = spip_mysql_insert($table, $cles, join(', ', $ins), $desc, $serveur, $requeter);
644 } while (count($valeurs));
645
646 return $r; // dans le cas d'une table auto_increment, le dernier insert_id
647 }
648
649 // http://doc.spip.org/@spip_mysql_update
650 function spip_mysql_update($table, $champs, $where='', $desc='', $serveur='',$requeter=true) {
651 $set = array();
652 foreach ($champs as $champ => $val)
653 $set[] = $champ . "=$val";
654 if (!empty($set))
655 return spip_mysql_query(
656 calculer_mysql_expression('UPDATE', $table, ',')
657 . calculer_mysql_expression('SET', $set, ',')
658 . calculer_mysql_expression('WHERE', $where),
659 $serveur, $requeter);
660 }
661
662 // idem, mais les valeurs sont des constantes a mettre entre apostrophes
663 // sauf les expressions de date lorsqu'il s'agit de fonctions SQL (NOW etc)
664 // http://doc.spip.org/@spip_mysql_updateq
665 function spip_mysql_updateq($table, $champs, $where='', $desc=array(), $serveur='',$requeter=true) {
666
667 if (!$champs) return;
668 if (!$desc) $desc = description_table($table);
669 if (!$desc) $champs = array(); else $fields = $desc['field'];
670 $set = array();
671 foreach ($champs as $champ => $val) {
672 $set[] = $champ . '=' . spip_mysql_cite($val, $fields[$champ]);
673 }
674 return spip_mysql_query(
675 calculer_mysql_expression('UPDATE', $table, ',')
676 . calculer_mysql_expression('SET', $set, ',')
677 . calculer_mysql_expression('WHERE', $where),
678 $serveur, $requeter);
679 }
680
681 // http://doc.spip.org/@spip_mysql_delete
682 function spip_mysql_delete($table, $where='', $serveur='',$requeter=true) {
683 $res = spip_mysql_query(
684 calculer_mysql_expression('DELETE FROM', $table, ',')
685 . calculer_mysql_expression('WHERE', $where),
686 $serveur, $requeter);
687 if (!$requeter) return $res;
688 if ($res){
689 $connexion = &$GLOBALS['connexions'][$serveur ? $serveur : 0];
690 $link = $connexion['link'];
691 return $link ? mysql_affected_rows($link) : mysql_affected_rows();
692 }
693 else
694 return false;
695 }
696
697 // http://doc.spip.org/@spip_mysql_replace
698 function spip_mysql_replace($table, $couples, $desc=array(), $serveur='',$requeter=true) {
699 return spip_mysql_query("REPLACE $table (" . join(',',array_keys($couples)) . ') VALUES (' .join(',',array_map('_q', $couples)) . ')', $serveur, $requeter);
700 }
701
702
703 // http://doc.spip.org/@spip_mysql_replace_multi
704 function spip_mysql_replace_multi($table, $tab_couples, $desc=array(), $serveur='',$requeter=true) {
705 $cles = "(" . join(',',array_keys($tab_couples[0])). ')';
706 $valeurs = array();
707 foreach ($tab_couples as $couples) {
708 $valeurs[] = '(' .join(',',array_map('_q', $couples)) . ')';
709 }
710 $valeurs = implode(', ',$valeurs);
711 return spip_mysql_query("REPLACE $table $cles VALUES $valeurs", $serveur, $requeter);
712 }
713
714
715 // http://doc.spip.org/@spip_mysql_multi
716 function spip_mysql_multi ($objet, $lang) {
717 $lengthlang = strlen("[$lang]");
718 $posmulti = "INSTR(".$objet.", '<multi>')";
719 $posfinmulti = "INSTR(".$objet.", '</multi>')";
720 $debutchaine = "LEFT(".$objet.", $posmulti-1)";
721 $finchaine = "RIGHT(".$objet.", CHAR_LENGTH(".$objet.") -(7+$posfinmulti))";
722 $chainemulti = "TRIM(SUBSTRING(".$objet.", $posmulti+7, $posfinmulti -(7+$posmulti)))";
723 $poslang = "INSTR($chainemulti,'[".$lang."]')";
724 $poslang = "IF($poslang=0,INSTR($chainemulti,']')+1,$poslang+$lengthlang)";
725 $chainelang = "TRIM(SUBSTRING(".$objet.", $posmulti+7+$poslang-1,$posfinmulti -($posmulti+7+$poslang-1) ))";
726 $posfinlang = "INSTR(".$chainelang.", '[')";
727 $chainelang = "IF($posfinlang>0,LEFT($chainelang,$posfinlang-1),$chainelang)";
728 //$chainelang = "LEFT($chainelang,$posfinlang-1)";
729 $retour = "(TRIM(IF($posmulti = 0 , ".
730 " TRIM(".$objet."), ".
731 " CONCAT( ".
732 " $debutchaine, ".
733 " IF( ".
734 " $poslang = 0, ".
735 " $chainemulti, ".
736 " $chainelang".
737 " ), ".
738 " $finchaine".
739 " ) ".
740 "))) AS multi";
741
742 return $retour;
743 }
744
745 // http://doc.spip.org/@spip_mysql_hex
746 function spip_mysql_hex($v)
747 {
748 return "0x" . $v;
749 }
750
751 function spip_mysql_quote($v, $type='')
752 {
753 return ($type === 'int' AND !$v) ? '0' : _q($v);
754 }
755
756 function spip_mysql_date_proche($champ, $interval, $unite)
757 {
758 return '('
759 . $champ
760 . (($interval <= 0) ? '>' : '<')
761 . (($interval <= 0) ? 'DATE_SUB' : 'DATE_ADD')
762 . '('
763 . sql_quote(date('Y-m-d H:i:s'))
764 . ', INTERVAL '
765 . (($interval > 0) ? $interval : (0-$interval))
766 . ' '
767 . $unite
768 . '))';
769 }
770
771 //
772 // IN (...) est limite a 255 elements, d'ou cette fonction assistante
773 //
774 // http://doc.spip.org/@spip_mysql_in
775 function spip_mysql_in($val, $valeurs, $not='', $serveur='',$requeter=true) {
776 $n = $i = 0;
777 $in_sql ="";
778 while ($n = strpos($valeurs, ',', $n+1)) {
779 if ((++$i) >= 255) {
780 $in_sql .= "($val $not IN (" .
781 substr($valeurs, 0, $n) .
782 "))\n" .
783 ($not ? "AND\t" : "OR\t");
784 $valeurs = substr($valeurs, $n+1);
785 $i = $n = 0;
786 }
787 }
788 $in_sql .= "($val $not IN ($valeurs))";
789
790 return "($in_sql)";
791 }
792
793 // pour compatibilite. Ne plus utiliser.
794 // http://doc.spip.org/@calcul_mysql_in
795 function calcul_mysql_in($val, $valeurs, $not='') {
796 if (is_array($valeurs))
797 $valeurs = join(',', array_map('_q', $valeurs));
798 elseif ($valeurs[0]===',') $valeurs = substr($valeurs,1);
799 if (!strlen(trim($valeurs))) return ($not ? "0=0" : '0=1');
800 return spip_mysql_in($val, $valeurs, $not);
801 }
802
803 // http://doc.spip.org/@spip_mysql_cite
804 function spip_mysql_cite($v, $type) {
805 if (sql_test_date($type) AND preg_match('/^\w+\(/', $v)
806 OR (sql_test_int($type)
807 AND (is_numeric($v)
808 OR (ctype_xdigit(substr($v,2))
809 AND $v[0]=='0' AND $v[1]=='x'))))
810 return $v;
811 else return ("'" . addslashes($v) . "'");
812 }
813
814 // Ces deux fonctions n'ont pas d'equivalent exact PostGres
815 // et ne sont la que pour compatibilite avec les extensions de SPIP < 1.9.3
816
817 //
818 // Poser un verrou local a un SPIP donne
819 // Changer de nom toutes les heures en cas de blocage MySQL (ca arrive)
820 //
821 // http://doc.spip.org/@spip_get_lock
822 function spip_get_lock($nom, $timeout = 0) {
823
824 define('_LOCK_TIME', intval(time()/3600-316982));
825
826 $connexion = &$GLOBALS['connexions'][0];
827 $prefixe = $connexion['prefixe'];
828 $nom = "$bd:$prefix:$nom" . _LOCK_TIME;
829
830 $connexion['last'] = $q = "SELECT GET_LOCK(" . _q($nom) . ", $timeout) AS n";
831 $q = @sql_fetch(mysql_query($q));
832 if (!$q) spip_log("pas de lock sql pour $nom");
833 return $q['n'];
834 }
835
836 // http://doc.spip.org/@spip_release_lock
837 function spip_release_lock($nom) {
838
839 $connexion = &$GLOBALS['connexions'][0];
840 $prefixe = $connexion['prefixe'];
841 $nom = "$bd:$prefix:$nom" . _LOCK_TIME;
842
843 $connexion['last'] = $q = "SELECT RELEASE_LOCK(" . _q($nom) . ")";
844 @mysql_query($q);
845 }
846
847 // Renvoie false si on n'a pas les fonctions mysql (pour l'install)
848 // http://doc.spip.org/@spip_versions_mysql
849 function spip_versions_mysql() {
850 charger_php_extension('mysql');
851 return function_exists('mysql_query');
852 }
853
854 // Tester si mysql ne veut pas du nom de la base dans les requetes
855
856 // http://doc.spip.org/@test_rappel_nom_base_mysql
857 function test_rappel_nom_base_mysql($server_db)
858 {
859 $GLOBALS['mysql_rappel_nom_base'] = true;
860 sql_delete('spip_meta', "nom='mysql_rappel_nom_base'", $server_db);
861 $ok = spip_query("INSERT INTO spip_meta (nom,valeur) VALUES ('mysql_rappel_nom_base', 'test')", $server_db);
862
863 if ($ok) {
864 sql_delete('spip_meta', "nom='mysql_rappel_nom_base'", $server_db);
865 return '';
866 } else {
867 $GLOBALS['mysql_rappel_nom_base'] = false;
868 return "\$GLOBALS['mysql_rappel_nom_base'] = false; ".
869 "/* echec de test_rappel_nom_base_mysql a l'installation. */\n";
870 }
871 }
872
873 // http://doc.spip.org/@test_sql_mode_mysql
874 function test_sql_mode_mysql($server_db){
875 $res = sql_select("version() as v",'','','','','','',$server_db);
876 $row = sql_fetch($res,$server_db);
877 if (version_compare($row['v'],'5.0.0','>=')){
878 define('_MYSQL_SET_SQL_MODE',true);
879 return "define('_MYSQL_SET_SQL_MODE',true);\n";
880 }
881 return '';
882 }
883
884 ?>