From 9b124538ed0f9058f59e789d417d456684bfefe6 Mon Sep 17 00:00:00 2001
From: Cerdic <cedric@yterium.com>
Date: Tue, 29 Jan 2008 23:44:55 +0000
Subject: [PATCH] etendre le prototype des fonctions d'abstraction sql avec un
 parametre $requeter par defaut a true lorsque le parametre est passe a false,
 les fonctions renvoient la requete textuelle sans l'evaluer

application experimentale a la construction de sous requete pour l'ecriture
{!id_mot=2} traduit comme (n'est pas dans l'ensemble des elements lies au mot 2)
il manque encore le left join pour recuperer aussi les elements lies a aucun mot
les sous requetes necessitent mysql 4.1

au passage, un bug corrige sur argument manquant dans sql_countsel
---
 ecrire/base/abstract_sql.php    | 178 ++++++++++++++++----------------
 ecrire/public/composer.php      |  43 +++++++-
 ecrire/public/criteres.php      |  11 +-
 ecrire/public/phraser_html.php  |  14 +--
 ecrire/req/mysql.php            |  88 ++++++++--------
 ecrire/req/pg.php               |  77 +++++++-------
 ecrire/req/sqlite_generique.php |  99 +++++++++---------
 7 files changed, 283 insertions(+), 227 deletions(-)

diff --git a/ecrire/base/abstract_sql.php b/ecrire/base/abstract_sql.php
index 6e8cf39957..f258ac9090 100644
--- a/ecrire/base/abstract_sql.php
+++ b/ecrire/base/abstract_sql.php
@@ -27,20 +27,20 @@ define('sql_ABSTRACT_VERSION', 1);
 // Erreur fatale si la fonctionnalite est absente sauf si le 3e arg <> false
 
 // http://doc.spip.org/@sql_serveur
-function sql_serveur($ins_sql='', $serveur='', $continue=false) {
+function sql_serveur($ins_sql='', $serveur='',$requeter=true, $continue=false) {
 	return spip_connect_sql(sql_ABSTRACT_VERSION, $ins_sql, $serveur, $continue);
 }
 
 // Demande si un charset est disponible. 
 // http://doc.spip.org/@sql_get_charset
-function sql_get_charset($charset, $serveur=''){
+function sql_get_charset($charset, $serveur='',$requeter=true){
   // le nom http du charset differe parfois du nom SQL utf-8 ==> utf8 etc.
 	$desc = sql_serveur('', $serveur, true);
 	$desc = $desc[sql_ABSTRACT_VERSION];
 	$c = $desc['charsets'][$charset];
 	if ($c) {
 		if (function_exists($f=@$desc['get_charset'])) 
-			if ($f($c, $serveur)) return $c;
+			if ($f($c, $serveur, $requeter)) return $c;
 	}
 	spip_log("SPIP ne connait pas les Charsets disponibles sur le serveur $serveur. Le serveur choisira seul.");
 	return false;
@@ -49,9 +49,9 @@ function sql_get_charset($charset, $serveur=''){
 // Regler le codage de connexion
 
 // http://doc.spip.org/@sql_set_charset
-function sql_set_charset($charset,$serveur=''){
-	$f = sql_serveur('set_charset', $serveur);
-	return $f($charset, $serveur);
+function sql_set_charset($charset,$serveur='',$requeter=true){
+	$f = sql_serveur('set_charset', $serveur, $requeter);
+	return $f($charset, $serveur, $requeter);
 }
 
 // Fonction pour SELECT, retournant la ressource interrogeable par sql_fetch.
@@ -69,10 +69,10 @@ function sql_set_charset($charset,$serveur=''){
 function sql_select (
 	$select = array(), $from = array(), $where = array(),
 	$groupby = array(), $orderby = array(), $limit = '', $having = array(),
-	$serveur='') {
+	$serveur='',$requeter=true) {
 
-	$f = sql_serveur('select', $serveur);
-	return $f($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur);
+	$f = sql_serveur('select', $serveur, $requeter);
+	return $f($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur, $requeter);
 }
 
 // Comme ci-dessus, mais ramene seulement et tout de suite le nombre de lignes
@@ -80,47 +80,47 @@ function sql_select (
 // http://doc.spip.org/@sql_countsel
 function sql_countsel($from = array(), $where = array(),
 		      $groupby = array(), $limit = '', $having = array(),
-	$serveur='') {
-  	$f = sql_serveur('countsel', $serveur);
-	return $f($from, $where, $groupby, $limit, $having, $serveur);
+	$serveur='',$requeter=true) {
+  	$f = sql_serveur('countsel', $serveur, $requeter);
+	return $f($from, $where, $groupby, $limit, '', $having, $serveur, $requeter);
 }
 
 // http://doc.spip.org/@sql_alter
-function sql_alter($q, $serveur='') {
-	$f = sql_serveur('alter', $serveur);
-	return $f($q, $serveur);
+function sql_alter($q, $serveur='',$requeter=true) {
+	$f = sql_serveur('alter', $serveur, $requeter);
+	return $f($q, $serveur, $requeter);
 }
 
 // http://doc.spip.org/@sql_fetch
-function sql_fetch($res, $serveur='') {
-	$f = sql_serveur('fetch', $serveur);
-	return $f($res, NULL, $serveur);
+function sql_fetch($res, $serveur='',$requeter=true) {
+	$f = sql_serveur('fetch', $serveur, $requeter);
+	return $f($res, NULL, $serveur, $requeter);
 }
 
 // http://doc.spip.org/@sql_listdbs
-function sql_listdbs($serveur='') {
-  	$f = sql_serveur('listdbs', $serveur);
+function sql_listdbs($serveur='',$requeter=true) {
+  	$f = sql_serveur('listdbs', $serveur, $requeter);
 	return $f($serveur);
 }
 
 // http://doc.spip.org/@sql_selectdb
-function sql_selectdb($res, $serveur='')
+function sql_selectdb($res, $serveur='',$requeter=true)
 {
-	$f = sql_serveur('selectdb', $serveur);
-	return $f($res, $serveur);
+	$f = sql_serveur('selectdb', $serveur, $requeter);
+	return $f($res, $serveur, $requeter);
 }
 
 // http://doc.spip.org/@sql_count
-function sql_count($res, $serveur='')
+function sql_count($res, $serveur='',$requeter=true)
 {
-	$f = sql_serveur('count', $serveur);
-	return $f($res, $serveur);
+	$f = sql_serveur('count', $serveur, $requeter);
+	return $f($res, $serveur, $requeter);
 }
 
 // http://doc.spip.org/@sql_free
-function sql_free($res, $serveur='')
+function sql_free($res, $serveur='',$requeter=true)
 {
-	$f = sql_serveur('free', $serveur);
+	$f = sql_serveur('free', $serveur, $requeter);
 	return $f($res);
 }
 
@@ -129,71 +129,71 @@ function sql_free($res, $serveur='')
 // Elle est fournie pour permettre l'actualisation de vieux codes 
 // par un Sed brutal qui peut donner des resultats provisoirement acceptables
 // http://doc.spip.org/@sql_insert
-function sql_insert($table, $noms, $valeurs, $desc=array(), $serveur='')
+function sql_insert($table, $noms, $valeurs, $desc=array(), $serveur='',$requeter=true)
 {
-	$f = sql_serveur('insert', $serveur);
-	return $f($table, $noms, $valeurs, $desc, $serveur);
+	$f = sql_serveur('insert', $serveur, $requeter);
+	return $f($table, $noms, $valeurs, $desc, $serveur, $requeter);
 }
 
 // http://doc.spip.org/@sql_insertq
-function sql_insertq($table, $couples=array(), $desc=array(), $serveur='')
+function sql_insertq($table, $couples=array(), $desc=array(), $serveur='',$requeter=true)
 {
-	$f = sql_serveur('insertq', $serveur);
-	return $f($table, $couples, $desc, $serveur);
+	$f = sql_serveur('insertq', $serveur, $requeter);
+	return $f($table, $couples, $desc, $serveur, $requeter);
 }
 
 // http://doc.spip.org/@sql_update
-function sql_update($table, $exp, $where='', $desc=array(), $serveur='')
+function sql_update($table, $exp, $where='', $desc=array(), $serveur='',$requeter=true)
 {
-	$f = sql_serveur('update', $serveur);
-	return $f($table, $exp, $where, $desc, $serveur);
+	$f = sql_serveur('update', $serveur, $requeter);
+	return $f($table, $exp, $where, $desc, $serveur, $requeter);
 }
 
 // Update est presque toujours appelee sur des constantes ou des dates
 // Cette fonction est donc plus utile que la precedente,d'autant qu'elle
 // permet de gerer les differences de representation des constantes.
 // http://doc.spip.org/@sql_updateq
-function sql_updateq($table, $exp, $where='', $desc=array(), $serveur='')
+function sql_updateq($table, $exp, $where='', $desc=array(), $serveur='',$requeter=true)
 {
-	$f = sql_serveur('updateq', $serveur);
-	return $f($table, $exp, $where, $desc, $serveur);
+	$f = sql_serveur('updateq', $serveur, $requeter);
+	return $f($table, $exp, $where, $desc, $serveur, $requeter);
 }
 
 // http://doc.spip.org/@sql_delete
-function sql_delete($table, $where='', $serveur='')
+function sql_delete($table, $where='', $serveur='',$requeter=true)
 {
-	$f = sql_serveur('delete', $serveur);
-	return $f($table, $where, $serveur);
+	$f = sql_serveur('delete', $serveur, $requeter);
+	return $f($table, $where, $serveur, $requeter);
 }
 
 // http://doc.spip.org/@sql_replace
-function sql_replace($table, $values, $desc=array(), $serveur='')
+function sql_replace($table, $values, $desc=array(), $serveur='',$requeter=true)
 {
-	$f = sql_serveur('replace', $serveur);
-	return $f($table, $values, $desc, $serveur);
+	$f = sql_serveur('replace', $serveur, $requeter);
+	return $f($table, $values, $desc, $serveur, $requeter);
 }
 
 // http://doc.spip.org/@sql_drop_table
-function sql_drop_table($table, $exist='', $serveur='')
+function sql_drop_table($table, $exist='', $serveur='',$requeter=true)
 {
-	$f = sql_serveur('drop_table', $serveur);
-	return $f($table, $exist, $serveur);
+	$f = sql_serveur('drop_table', $serveur, $requeter);
+	return $f($table, $exist, $serveur, $requeter);
 }
 
 // http://doc.spip.org/@sql_showbase
-function sql_showbase($spip=NULL, $serveur='')
+function sql_showbase($spip=NULL, $serveur='',$requeter=true)
 {
 	if ($spip == NULL){
 		$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
 		$spip = $connexion['prefixe'] . '%';
 	}
 	
-	$f = sql_serveur('showbase', $serveur);
-	return $f($spip, $serveur);
+	$f = sql_serveur('showbase', $serveur, $requeter);
+	return $f($spip, $serveur, $requeter);
 }
 
 // http://doc.spip.org/@sql_showtable
-function sql_showtable($table, $table_spip = false, $serveur='')
+function sql_showtable($table, $table_spip = false, $serveur='',$requeter=true)
 {
 	if ($table_spip){
 		$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
@@ -201,8 +201,8 @@ function sql_showtable($table, $table_spip = false, $serveur='')
 		$table = preg_replace('/^spip/', $prefixe, $table);
 	}
 	
-	$f = sql_serveur('showtable', $serveur);
-	$f = $f($table, $serveur);
+	$f = sql_serveur('showtable', $serveur, $requeter);
+	$f = $f($table, $serveur, $requeter);
 	if (!$f) return array();
 	if (isset($GLOBALS['tables_principales'][$table]['join']))
 		$f['join'] = $GLOBALS['tables_principales'][$table]['join'];
@@ -212,55 +212,55 @@ function sql_showtable($table, $table_spip = false, $serveur='')
 }
 
 // http://doc.spip.org/@sql_create
-function sql_create($nom, $champs, $cles=array(), $autoinc=false, $temporary=false, $serveur='') {
-	$f = sql_serveur('create', $serveur);
-	return $f($nom, $champs, $cles, $autoinc, $temporary, $serveur);
+function sql_create($nom, $champs, $cles=array(), $autoinc=false, $temporary=false, $serveur='',$requeter=true) {
+	$f = sql_serveur('create', $serveur, $requeter);
+	return $f($nom, $champs, $cles, $autoinc, $temporary, $serveur, $requeter);
 }
 
 // http://doc.spip.org/@sql_multi
-function sql_multi($sel, $lang, $serveur='')
+function sql_multi($sel, $lang, $serveur='',$requeter=true)
 {
-  	$f = sql_serveur('multi', $serveur);
+  	$f = sql_serveur('multi', $serveur, $requeter);
 	return $f($sel, $lang);
 }
 
 // http://doc.spip.org/@sql_error
-function sql_error($query='requete inconnue', $serveur='') {
-  	$f = sql_serveur('error', $serveur);
-	return $f($query, $serveur);
+function sql_error($query='requete inconnue', $serveur='',$requeter=true) {
+  	$f = sql_serveur('error', $serveur, $requeter);
+	return $f($query, $serveur, $requeter);
 }
 
 // http://doc.spip.org/@sql_errno
-function sql_errno($serveur='') {
-  	$f = sql_serveur('errno', $serveur);
+function sql_errno($serveur='',$requeter=true) {
+  	$f = sql_serveur('errno', $serveur, $requeter);
 	return $f($serveur);
 }
 
 // http://doc.spip.org/@sql_explain
-function sql_explain($q, $serveur='') {
+function sql_explain($q, $serveur='',$requeter=true) {
 	$f = sql_serveur('explain', $serveur, true);
-	return @function_exists($f) ? $f($q, $serveur) : false;
+	return @function_exists($f) ? $f($q, $serveur, $requeter) : false;
 }
 
 // http://doc.spip.org/@sql_optimize
-function sql_optimize($q, $serveur='') {
+function sql_optimize($q, $serveur='',$requeter=true) {
 	$f = sql_serveur('optimize', $serveur, true);
-	return @function_exists($f) ? $f($q, $serveur) : false;
+	return @function_exists($f) ? $f($q, $serveur, $requeter) : false;
 }
 
 // http://doc.spip.org/@sql_repair
-function sql_repair($q, $serveur='') {
+function sql_repair($q, $serveur='',$requeter=true) {
 	$f = sql_serveur('repair', $serveur, true);
-	return @function_exists($f) ? $f($q, $serveur) : false;
+	return @function_exists($f) ? $f($q, $serveur, $requeter) : false;
 }
 
 // Fonction la plus generale ... et la moins portable
 // A n'utiliser qu'en derniere extremite
 
 // http://doc.spip.org/@sql_query
-function sql_query($ins, $serveur='') {
-  	$f = sql_serveur('query', $serveur);
-	return $f($ins, $serveur);
+function sql_query($ins, $serveur='',$requeter=true) {
+  	$f = sql_serveur('query', $serveur, $requeter);
+	return $f($ins, $serveur, $requeter);
 }
 
 # une composition tellement frequente...
@@ -268,21 +268,21 @@ function sql_query($ins, $serveur='') {
 function sql_fetsel(
 	$select = array(), $from = array(), $where = array(),
 	$groupby = array(), $orderby = array(), $limit = '',
-	$having = array(), $serveur='') {
-	return sql_fetch(sql_select($select, $from, $where,	$groupby, $orderby, $limit, $having, $serveur), $serveur);
+	$having = array(), $serveur='',$requeter=true) {
+	return sql_fetch(sql_select($select, $from, $where,	$groupby, $orderby, $limit, $having, $serveur, $requeter), $serveur, $requeter);
 }
 
 # Retourne l'unique champ demande dans une requete Select a resultat unique
 // http://doc.spip.org/@sql_getfetsel
 function sql_getfetsel(
 		       $select, $from = array(), $where = array(), $groupby = array(), 
-	$orderby = array(), $limit = '', $having = array(), $serveur='') {
-	$r = sql_fetch(sql_select($select, $from, $where,	$groupby, $orderby, $limit, $having, $serveur), $serveur);
+	$orderby = array(), $limit = '', $having = array(), $serveur='',$requeter=true) {
+	$r = sql_fetch(sql_select($select, $from, $where,	$groupby, $orderby, $limit, $having, $serveur, $requeter), $serveur, $requeter);
 	return $r ? $r[$select] : NULL;
 }
 
 // http://doc.spip.org/@sql_version
-function sql_version($serveur='') {
+function sql_version($serveur='',$requeter=true) {
 	$row = sql_fetsel("version() AS n", '','','','','','',$serveur);
 	return ($row['n']);
 }
@@ -291,34 +291,34 @@ function sql_version($serveur='') {
 // et retourne sa representation numerique:
 // FF ==> 0xFF en MySQL mais x'FF' en PG
 // http://doc.spip.org/@sql_hex
-function sql_hex($val, $serveur='')
+function sql_hex($val, $serveur='',$requeter=true)
 {
-	$f = sql_serveur('hex', $serveur);
+	$f = sql_serveur('hex', $serveur, $requeter);
 	return $f($val);
 }
 
 // http://doc.spip.org/@sql_quote
-function sql_quote($val, $serveur='')
+function sql_quote($val, $serveur='',$requeter=true)
 {
-	$f = sql_serveur('quote', $serveur);
+	$f = sql_serveur('quote', $serveur, $requeter);
 	return $f($val);
 }
 
 // http://doc.spip.org/@sql_in
-function sql_in($val, $valeurs, $not='', $serveur='') {
+function sql_in($val, $valeurs, $not='', $serveur='',$requeter=true) {
 	if (is_array($valeurs)) {
-		$f = sql_serveur('quote', $serveur);
+		$f = sql_serveur('quote', $serveur, $requeter);
 		$valeurs = join(',', array_map($f, array_unique($valeurs)));
 	} elseif ($valeurs[0]===',') $valeurs = substr($valeurs,1);
 	if (!strlen(trim($valeurs))) return ($not ? "0=0" : '0=1');
 
-	$f = sql_serveur('in', $serveur);
-	return $f($val, $valeurs, $not, $serveur);
+	$f = sql_serveur('in', $serveur, $requeter);
+	return $f($val, $valeurs, $not, $serveur, $requeter);
 }
 
 
 // http://doc.spip.org/@sql_test_int
-function sql_test_int($type, $serveur='')
+function sql_test_int($type, $serveur='',$requeter=true)
 {
   return (preg_match('/^bigint/i',$type)
 	  OR preg_match('/^int/i',$type)
@@ -326,7 +326,7 @@ function sql_test_int($type, $serveur='')
 }
 
 // http://doc.spip.org/@sql_test_date
-function sql_test_date($type, $serveur='')
+function sql_test_date($type, $serveur='',$requeter=true)
 {
   return (preg_match('/^datetime/i',$type)
 	  OR preg_match('/^timestamp/i',$type));
diff --git a/ecrire/public/composer.php b/ecrire/public/composer.php
index f1c55b5665..d042280183 100644
--- a/ecrire/public/composer.php
+++ b/ecrire/public/composer.php
@@ -484,6 +484,34 @@ function lang_parametres_forum($qs, $lang) {
 	return $qs;
 }
 
+
+function match_self($w){
+	if (is_string($w)) return false;
+	if (is_array($w)) {
+		if (reset($w)=="SELF") return $w;
+		foreach($w as $sw)
+			if ($m=match_self($sw)) return $m;
+	}
+	return false;
+}
+function remplace_sous_requete($w,$sousrequete){
+	if (is_array($w)) {
+		if (reset($w)=="SELF") return $sousrequete;
+		foreach($w as $k=>$sw)
+			$w[$k] = remplace_sous_requete($sw,$sousrequete);
+	}
+	return $w;
+}
+function trouver_sous_requetes($where){
+	$where_simples = array();
+	$where_sous = array();
+	foreach($where as $k=>$w){
+		if (match_self($w)) $where_sous[$k] = $w;
+		else $where_simples[$k] = $w;
+	}
+	return array($where_simples,$where_sous);
+}
+
 // La fonction presente dans les squelettes compiles
 
 // http://doc.spip.org/@calculer_select
@@ -491,7 +519,7 @@ function calculer_select ($select = array(), $from = array(),
 			$from_type = array(),
       $where = array(), $join=array(),
 			$groupby = array(), $orderby = array(), $limit = '',
-			$having=array(), $table = '', $id = '', $serveur='') {
+			$having=array(), $table = '', $id = '', $serveur='', $requeter=true) {
 
 // retirer les criteres vides:
 // {X ?} avec X absent de l'URL
@@ -506,6 +534,17 @@ function calculer_select ($select = array(), $from = array(),
 			$menage = true;
 		}
 	}
+	// remplacer les sous requetes recursives au calcul
+	list($where_simples,$where_sous) = trouver_sous_requetes($where);
+	//var_dump($where_sous);
+	foreach($where_sous as $k=>$w) {
+		// on recupere la sous requete 
+		$sous = match_self($w);
+		array_push($where_simples,$sous[2]);
+		$where[$k] = remplace_sous_requete($w,"(".calculer_select($sous[1],$from,$from_type,$where_simples,$join,$groupby,$orderby,'',$having,$table,$id,$serveur,false).")");
+		array_pop($where_simples);
+	}
+	//var_dump($where);
 
 	foreach($having as $k => $v) { 
 		if ((!$v) OR ($v==1) OR ($v=='0=0')) {
@@ -564,7 +603,7 @@ function calculer_select ($select = array(), $from = array(),
 	$GLOBALS['debug']['aucasou'] = array ($table, $id, $serveur);
 
 	$r = sql_select($select, $from, $where,
-		$groupby, array_filter($orderby), $limit, $having, $serveur);
+		$groupby, array_filter($orderby), $limit, $having, $serveur, $requeter);
 	unset($GLOBALS['debug']['aucasou']);
 	return $r;
 }
diff --git a/ecrire/public/criteres.php b/ecrire/public/criteres.php
index 04760179dc..9a860c788e 100644
--- a/ecrire/public/criteres.php
+++ b/ecrire/public/criteres.php
@@ -685,7 +685,12 @@ function calculer_critere_DEFAUT($idb, &$boucles, $crit)
 
 	// inserer la negation (cf !...)
 
-	if ($crit->not) $where = array("'NOT'", $where);
+	if ($crit->not) 
+		if (!preg_match(",^L[0-9]+[.],",$arg))
+			$where = array("'NOT'", $where);
+		else
+			// un not sur un critere de jointure se traduit comme un NOT IN avec une sous requete
+			$where = array("'NOT'",array("'IN'","'".$boucles[$idb]->id_table.".".$boucles[$idb]->primary."'" ,array("'SELF'","'".$boucles[$idb]->id_table.".".$boucles[$idb]->primary."'",$where)));
 
 	// inserer la condition (cf {lang?})
 	// traiter a part la date, elle est mise d'office par SPIP,
@@ -718,7 +723,7 @@ function calculer_critere_infixe($idb, &$boucles, $crit) {
 	list($fct, $col, $op, $val, $args_sql) =
 	  calculer_critere_infixe_ops($idb, $boucles, $crit);
 	$col_alias = $col;
-
+//var_dump(array($fct, $col, $op, $val, $args_sql));
 	// Cas particulier : id_enfant => utiliser la colonne id_objet
 	if ($col == 'id_enfant')
 	  $col = $boucle->primary;
@@ -941,7 +946,7 @@ function calculer_critere_infixe_ops($idb, &$boucles, $crit)
 	  }
 	  $args_sql .= $a[2];;
 	}
-
+//var_dump(array($fct,$col,$op,$val,$args_sql));
 	return array($fct, $col, $op, $val, $args_sql);
 }
 
diff --git a/ecrire/public/phraser_html.php b/ecrire/public/phraser_html.php
index c718d1bf6d..080a1a0d08 100644
--- a/ecrire/public/phraser_html.php
+++ b/ecrire/public/phraser_html.php
@@ -408,6 +408,7 @@ function phraser_criteres($params, &$result) {
 			  $not = "";
 			} else {
 			  preg_match("/^([!]?)([a-zA-Z][a-zA-Z0-9]*)[[:space:]]*(.*)$/ms", $param, $m);
+
 			  $op = $m[2];
 			  $not = $m[1];
 			  if ($m[3]) $v[1][0]->texte = $m[3]; else array_shift($v[1]);
@@ -450,7 +451,7 @@ function phraser_criteres($params, &$result) {
 				$result->modificateur['tout'] = true;
 			elseif (($type == 'hierarchie') && ($param == 'id_rubrique'))
 				{;}
-			else { 
+			else {
 			  // pas d'emplacement statique, faut un dynamique
 			  /// mais il y a 2 cas qui ont les 2 !
 			  if (($param == 'unique') || (preg_match(',^!?doublons *,', $param)))
@@ -465,14 +466,15 @@ function phraser_criteres($params, &$result) {
 			      $result->hash = true;
 			  if (preg_match(',^ *([0-9-]+) *(/) *(.+) *$,', $param, $m)) {
 			    $crit = phraser_critere_infixe($m[1], $m[3],$v, '/', '', '');
-			  } elseif (preg_match(',^(' . CHAMP_SQL_PLUS_FONC . 
+			  } elseif (preg_match(',^([!]?)(' . CHAMP_SQL_PLUS_FONC . 
 					 ')[[:space:]]*(\??)(!?)(<=?|>=?|==?|\b(?:IN|LIKE)\b)(.*)$,is', $param, $m)) {
-			    $a2 = trim($m[7]);
+			    $a2 = trim($m[8]);
 			    if ($a2 AND ($a2[0]=="'" OR $a2[0]=='"') AND ($a2[0]==substr($a2,-1)))
 			      $a2 = substr($a2,1,-1);
-			    $crit = phraser_critere_infixe($m[1], $a2, $v,
-							   (($m[1] == 'lang_select') ? $m[1] : $m[6]),
-							   $m[5], $m[4]);
+			    $crit = phraser_critere_infixe($m[2], $a2, $v,
+							   (($m[2] == 'lang_select') ? $m[2] : $m[7]),
+							   $m[6], $m[5]);
+					$crit->not = $m[1];
 			  } elseif (preg_match("/^([!]?)\s*(" .
 					       CHAMP_SQL_PLUS_FONC .
 					       ")\s*(\??)(.*)$/is", $param, $m)) {
diff --git a/ecrire/req/mysql.php b/ecrire/req/mysql.php
index 65e644dbda..84e99c4cf4 100644
--- a/ecrire/req/mysql.php
+++ b/ecrire/req/mysql.php
@@ -85,27 +85,27 @@ $GLOBALS['spip_mysql_functions_1'] = array(
 		);
 
 // http://doc.spip.org/@spip_mysql_set_charset
-function spip_mysql_set_charset($charset, $serveur=''){
+function spip_mysql_set_charset($charset, $serveur='',$requeter=true,$requeter=true){
 	#spip_log("changement de charset sql : "."SET NAMES "._q($charset));
 	return mysql_query("SET NAMES "._q($charset));
 }
 
 // http://doc.spip.org/@spip_mysql_get_charset
-function spip_mysql_get_charset($charset=array(), $serveur=''){
+function spip_mysql_get_charset($charset=array(), $serveur='',$requeter=true){
 	$c = !$charset ? '' : (" LIKE "._q($charset['charset']));
 	return spip_mysql_fetch(mysql_query("SHOW CHARACTER SET$c"), NULL, $serveur);
 }
 
 // obsolete, ne plus utiliser
 // http://doc.spip.org/@spip_query_db
-function spip_query_db($query, $serveur='') {
-	return spip_mysql_query($query, $serveur);
+function spip_query_db($query, $serveur='',$requeter=true) {
+	return spip_mysql_query($query, $serveur, $requeter);
 }
 
 // Fonction de requete generale, munie d'une trace a la demande
 
 // http://doc.spip.org/@spip_mysql_query
-function spip_mysql_query($query, $serveur='') {
+function spip_mysql_query($query, $serveur='',$requeter=true) {
 
 	$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
 	$prefixe = $connexion['prefixe'];
@@ -114,6 +114,9 @@ function spip_mysql_query($query, $serveur='') {
 
 	$query = traite_query($query, $db, $prefixe);
 
+	// renvoyer la requete inerte si demandee
+	if (!$requeter) return $query;
+
 	$t = !isset($_GET['var_profile']) ? 0 : trace_query_start();
 	$r = $link ? mysql_query($query, $link) : mysql_query($query);
 
@@ -123,18 +126,18 @@ function spip_mysql_query($query, $serveur='') {
 }
 
 // http://doc.spip.org/@spip_mysql_alter
-function spip_mysql_alter($query, $serveur=''){
-	return spip_mysql_query("ALTER ".$query); # i.e. que PG se debrouille
+function spip_mysql_alter($query, $serveur='',$requeter=true){
+	return spip_mysql_query("ALTER ".$query, $serveur, $requeter); # i.e. que PG se debrouille
 }
 
 // http://doc.spip.org/@spip_mysql_optimize
-function spip_mysql_optimize($table, $serveur=''){
+function spip_mysql_optimize($table, $serveur='',$requeter=true){
 	spip_mysql_query("OPTIMIZE TABLE ". $table);
 	return true;
 }
 
 // http://doc.spip.org/@spip_mysql_explain
-function spip_mysql_explain($query, $serveur=''){
+function spip_mysql_explain($query, $serveur='',$requeter=true){
 	if (strpos(ltrim($query), 'SELECT') !== 0) return array();
 	$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
 	$prefixe = $connexion['prefixe'];
@@ -153,7 +156,7 @@ function spip_mysql_explain($query, $serveur=''){
 // http://doc.spip.org/@spip_mysql_select
 function spip_mysql_select($select, $from, $where='',
 			   $groupby='', $orderby='', $limit='', $having='',
-			   $serveur='') {
+			   $serveur='',$requeter=true) {
 
 
 	$from = (!is_array($from) ? $from : spip_mysql_select_as($from));
@@ -168,12 +171,12 @@ function spip_mysql_select($select, $from, $where='',
 
 	// Erreur ? C'est du debug de squelette, ou une erreur du serveur
 
-	if (isset($GLOBALS['var_mode']) AND $GLOBALS['var_mode'] == 'debug') {
+	if (isset($GLOBALS['var_mode']) AND $GLOBALS['var_mode'] == 'debug' AND $requeter) {
 		include_spip('public/debug');
 		boucle_debug_requete($query);
 	}
-
-	if (!($res = spip_mysql_query($query, $serveur))) {
+	
+	if (!($res = spip_mysql_query($query, $serveur, $requeter))) {
 		include_spip('public/debug');
 		erreur_requete_boucle(substr($query, 7),
 				      spip_mysql_errno(),
@@ -287,7 +290,7 @@ function spip_mysql_selectdb($db) {
 // Attention on n'a pas toujours les droits
 
 // http://doc.spip.org/@spip_mysql_listdbs
-function spip_mysql_listdbs($serveur='') {
+function spip_mysql_listdbs($serveur='',$requeter=true) {
 	return @mysql_list_dbs();
 }
 
@@ -299,7 +302,7 @@ function spip_mysql_listdbs($serveur='') {
 // Le nom des caches doit etre inferieur a 64 caracteres
 
 // http://doc.spip.org/@spip_mysql_create
-function spip_mysql_create($nom, $champs, $cles, $autoinc=false, $temporary=false, $serveur='') {
+function spip_mysql_create($nom, $champs, $cles, $autoinc=false, $temporary=false, $serveur='',$requeter=true) {
 
 	$query = ''; $keys = ''; $s = ''; $p='';
 
@@ -349,29 +352,30 @@ function spip_mysql_create($nom, $champs, $cles, $autoinc=false, $temporary=fals
 }
 
 // http://doc.spip.org/@spip_mysql_drop_table
-function spip_mysql_drop_table($table, $exist='', $serveur='')
+function spip_mysql_drop_table($table, $exist='', $serveur='',$requeter=true)
 {
 	if ($exist) $exist =" IF EXISTS";
-	return spip_mysql_query("DROP TABLE$exist $table", $serveur);
+	return spip_mysql_query("DROP TABLE$exist $table", $serveur, $requeter);
 }
 
 // http://doc.spip.org/@spip_mysql_showbase
-function spip_mysql_showbase($match, $serveur='')
+function spip_mysql_showbase($match, $serveur='',$requeter=true)
 {
-	return spip_mysql_query("SHOW TABLES LIKE '$match'", $serveur);
+	return spip_mysql_query("SHOW TABLES LIKE '$match'", $serveur, $requeter);
 }
 
 // http://doc.spip.org/@spip_mysql_repair
-function spip_mysql_repair($table, $serveur='')
+function spip_mysql_repair($table, $serveur='',$requeter=true)
 {
-	return spip_mysql_query("REPAIR TABLE $table", $serveur);
+	return spip_mysql_query("REPAIR TABLE $table", $serveur, $requeter);
 }
 
 // http://doc.spip.org/@spip_mysql_showtable
-function spip_mysql_showtable($nom_table, $serveur='')
+function spip_mysql_showtable($nom_table, $serveur='',$requeter=true)
 {
-	$a = spip_mysql_query("SHOW TABLES LIKE '$nom_table'", $serveur);
+	$a = spip_mysql_query("SHOW TABLES LIKE '$nom_table'", $serveur, $requeter);
 	if (!$a) return "";
+	if (!$requeter) return $a;
 	if (!mysql_fetch_array($a)) return "";
 	list(,$a) = mysql_fetch_array(spip_mysql_query("SHOW CREATE TABLE $nom_table", $serveur),MYSQL_NUM);
 	if (!preg_match("/^[^(),]*\((([^()]*\([^()]*\)[^()]*)*)\)[^()]*$/", $a, $r))
@@ -408,7 +412,7 @@ function spip_mysql_showtable($nom_table, $serveur='')
 //
 
 // http://doc.spip.org/@spip_mysql_fetch
-function spip_mysql_fetch($r, $t='', $serveur='') {
+function spip_mysql_fetch($r, $t='', $serveur='',$requeter=true) {
 	if (!$t) $t = MYSQL_ASSOC;
 	if ($r) return mysql_fetch_array($r, $t);
 }
@@ -416,16 +420,16 @@ function spip_mysql_fetch($r, $t='', $serveur='') {
 
 // http://doc.spip.org/@spip_mysql_countsel
 function spip_mysql_countsel($from = array(), $where = array(),
-			     $groupby = '', $limit = '', $sousrequete = '', $having = array(), $serveur='')
+			     $groupby = '', $limit = '', $sousrequete = '', $having = array(), $serveur='',$requeter=true)
 {
 	$r = spip_mysql_select('COUNT(*)', $from, $where,$groupby, '', $limit,
-			$having, $serveur);
-	if ($r) list($r) = mysql_fetch_array($r, MYSQL_NUM);
+			$having, $serveur, $requeter);
+	if ($r && $requeter) list($r) = mysql_fetch_array($r, MYSQL_NUM);
 	return $r;
 }
 
 // http://doc.spip.org/@spip_mysql_error
-function spip_mysql_error($query='', $serveur='') {
+function spip_mysql_error($query='', $serveur='',$requeter=true) {
 	$s = mysql_error();
 	if ($s) spip_log("$s - $query", 'mysql');
 	return $s;
@@ -433,7 +437,7 @@ function spip_mysql_error($query='', $serveur='') {
 
 // A transposer dans les portages
 // http://doc.spip.org/@spip_mysql_errno
-function spip_mysql_errno($serveur='') {
+function spip_mysql_errno($serveur='',$requeter=true) {
 	$s = mysql_errno();
 	// 2006 MySQL server has gone away
 	// 2013 Lost connection to MySQL server during query
@@ -445,18 +449,18 @@ function spip_mysql_errno($serveur='') {
 
 // Interface de abstract_sql
 // http://doc.spip.org/@spip_mysql_count
-function spip_mysql_count($r, $serveur='') {
+function spip_mysql_count($r, $serveur='',$requeter=true) {
 	if ($r)	return mysql_num_rows($r);
 }
 
 
 // http://doc.spip.org/@spip_mysql_free
-function spip_mysql_free($r, $serveur='') {
+function spip_mysql_free($r, $serveur='',$requeter=true) {
 	return mysql_free_result($r);
 }
 
 // http://doc.spip.org/@spip_mysql_insert
-function spip_mysql_insert($table, $champs, $valeurs, $desc='', $serveur='') {
+function spip_mysql_insert($table, $champs, $valeurs, $desc='', $serveur='',$requeter=true) {
 
 	$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
 	$prefixe = $connexion['prefixe'];
@@ -480,7 +484,7 @@ function spip_mysql_insert($table, $champs, $valeurs, $desc='', $serveur='') {
 }
 
 // http://doc.spip.org/@spip_mysql_insertq
-function spip_mysql_insertq($table, $couples=array(), $desc=array(), $serveur='') {
+function spip_mysql_insertq($table, $couples=array(), $desc=array(), $serveur='',$requeter=true) {
 
 	if (!$desc) $desc = description_table($table);
 	if (!$desc) die("$table insertion sans description");
@@ -494,7 +498,7 @@ function spip_mysql_insertq($table, $couples=array(), $desc=array(), $serveur=''
 }
 
 // http://doc.spip.org/@spip_mysql_update
-function spip_mysql_update($table, $champs, $where='', $desc='', $serveur='') {
+function spip_mysql_update($table, $champs, $where='', $desc='', $serveur='',$requeter=true) {
 	$set = array();
 	foreach ($champs as $champ => $val)
 		$set[] = $champ . "=$val";
@@ -503,13 +507,13 @@ function spip_mysql_update($table, $champs, $where='', $desc='', $serveur='') {
 			  calculer_mysql_expression('UPDATE', $table, ',')
 			. calculer_mysql_expression('SET', $set, ',')
 			. calculer_mysql_expression('WHERE', $where), 
-			$serveur);
+			$serveur, $requeter);
 }
 
 // idem, mais les valeurs sont des constantes a mettre entre apostrophes
 // sauf les expressions de date lorsqu'il s'agit de fonctions SQL (NOW etc)
 // http://doc.spip.org/@spip_mysql_updateq
-function spip_mysql_updateq($table, $champs, $where='', $desc=array(), $serveur='') {
+function spip_mysql_updateq($table, $champs, $where='', $desc=array(), $serveur='',$requeter=true) {
 
 	if (!$champs) return;
 	if (!$desc) $desc = description_table($table);
@@ -523,20 +527,20 @@ function spip_mysql_updateq($table, $champs, $where='', $desc=array(), $serveur=
 			  calculer_mysql_expression('UPDATE', $table, ',')
 			. calculer_mysql_expression('SET', $set, ',')
 			. calculer_mysql_expression('WHERE', $where),
-			$serveur);
+			$serveur, $requeter);
 }
 
 // http://doc.spip.org/@spip_mysql_delete
-function spip_mysql_delete($table, $where='', $serveur='') {
+function spip_mysql_delete($table, $where='', $serveur='',$requeter=true) {
 	return spip_mysql_query(
 			  calculer_mysql_expression('DELETE FROM', $table, ',')
 			. calculer_mysql_expression('WHERE', $where),
-			$serveur);
+			$serveur, $requeter);
 }
 
 // http://doc.spip.org/@spip_mysql_replace
-function spip_mysql_replace($table, $values, $keys=array(), $serveur='') {
-	return spip_mysql_query("REPLACE $table (" . join(',',array_keys($values)) . ') VALUES (' .join(',',array_map('_q', $values)) . ')', $serveur);
+function spip_mysql_replace($table, $values, $keys=array(), $serveur='',$requeter=true) {
+	return spip_mysql_query("REPLACE $table (" . join(',',array_keys($values)) . ') VALUES (' .join(',',array_map('_q', $values)) . ')', $serveur, $requeter);
 }
 
 // http://doc.spip.org/@spip_mysql_multi
@@ -578,7 +582,7 @@ function spip_mysql_quote($v)
 //
 // IN (...) est limite a 255 elements, d'ou cette fonction assistante
 //
-function spip_mysql_in($val, $valeurs, $not='', $serveur='') {
+function spip_mysql_in($val, $valeurs, $not='', $serveur='',$requeter=true) {
 	$n = $i = 0;
 	$in_sql ="";
 	while ($n = strpos($valeurs, ',', $n+1)) {
diff --git a/ecrire/req/pg.php b/ecrire/req/pg.php
index dc3bb8c822..385c2888cf 100644
--- a/ecrire/req/pg.php
+++ b/ecrire/req/pg.php
@@ -98,7 +98,7 @@ $GLOBALS['spip_pg_functions_1'] = array(
 
 // Par ou ca passe une fois les traductions faites
 // http://doc.spip.org/@spip_pg_trace_query
-function spip_pg_trace_query($query, $serveur='')
+function spip_pg_trace_query($query, $serveur='',$requeter=true)
 {
 	$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
 	$prefixe = $connexion['prefixe'];
@@ -117,7 +117,7 @@ function spip_pg_trace_query($query, $serveur='')
 // Elle change juste le noms des tables ($table_prefix) dans le FROM etc
 
 // http://doc.spip.org/@spip_pg_query
-function spip_pg_query($query, $serveur='')
+function spip_pg_query($query, $serveur='',$requeter=true)
 {
 	$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
 	$prefixe = $connexion['prefixe'];
@@ -129,12 +129,16 @@ function spip_pg_query($query, $serveur='')
 		$query = substr($query, 0, -strlen($suite));
 	} else $suite ='';
 	$query = preg_replace('/([,\s])spip_/', '\1'.$prefixe.'_', $query) . $suite;
+	
+	// renvoyer la requete inerte si demandee
+	if (!$requeter) return $query;
+
 	return spip_pg_trace_query($query, $serveur);
 }
 
 // Alter en PG ne traite pas les index
 // http://doc.spip.org/@spip_pg_alter
-function spip_pg_alter($query, $serveur='') {
+function spip_pg_alter($query, $serveur='',$requeter=true) {
 
 	if (!preg_match('/^\s*(IGNORE\s*)?TABLE\s+(\w+)\s+(ADD|DROP|CHANGE)\s*([^,]*)(.*)$/is', $query, $r)) {
 	  spip_log("$query incompris", 'pg');
@@ -151,7 +155,7 @@ function spip_pg_alter($query, $serveur='') {
 }
 	      
 // http://doc.spip.org/@spip_pg_alter_change
-function spip_pg_alter_change($table, $arg, $serveur='')
+function spip_pg_alter_change($table, $arg, $serveur='',$requeter=true)
 {
 	if (!preg_match('/^`?(\w+)`?\s+`?(\w+)`?\s+(.*?)\s*(DEFAULT .*?)?(NOT\s+NULL)?\s*(DEFAULT .*?)?$/i',$arg, $r)) {
 	  spip_log("alter change: $arg  incompris", 'pg');
@@ -176,7 +180,7 @@ function spip_pg_alter_change($table, $arg, $serveur='')
 }
 
 // http://doc.spip.org/@spip_pg_alter_add
-function spip_pg_alter_add($table, $arg, $serveur='') {
+function spip_pg_alter_add($table, $arg, $serveur='',$requeter=true) {
 	if (!preg_match('/^(INDEX|KEY|PRIMARY\s+KEY|)\s*(.*)$/', $arg, $r)) {
 		spip_log("alter add $arg  incompris", 'pg');
 		return NULL;
@@ -194,7 +198,7 @@ function spip_pg_alter_add($table, $arg, $serveur='') {
 }
 
 // http://doc.spip.org/@spip_pg_alter_drop
-function spip_pg_alter_drop($table, $arg, $serveur='') {
+function spip_pg_alter_drop($table, $arg, $serveur='',$requeter=true) {
 	if (!preg_match('/^(INDEX|KEY|PRIMARY\s+KEY|)\s*`?(\w*)`?/', $arg, $r))
 	  spip_log("alter drop: $arg  incompris", 'pg');
 	else {
@@ -209,7 +213,7 @@ function spip_pg_alter_drop($table, $arg, $serveur='') {
 }
 
 // http://doc.spip.org/@spip_pg_explain
-function spip_pg_explain($query, $serveur=''){
+function spip_pg_explain($query, $serveur='',$requeter=true){
 	if (strpos(ltrim($query), 'SELECT') !== 0) return array();
 	$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
 	$prefixe = $connexion['prefixe'];
@@ -220,12 +224,13 @@ function spip_pg_explain($query, $serveur=''){
 	} else $suite ='';
 	$query = 'EXPLAIN ' . preg_replace('/([,\s])spip_/', '\1'.$prefixe.'_', $query) . $suite;
 
-	$r = pg_query($link,$query);
+	$r = pg_query($link,$query,$requeter);
+	if (!$requeter) return $r;
 	return spip_pg_fetch($r, NULL, $serveur);
 }
 
 // http://doc.spip.org/@spip_pg_selectdb
-function spip_pg_selectdb($db, $serveur='') {
+function spip_pg_selectdb($db, $serveur='',$requeter=true) {
 	// se connecter a la base indiquee
 	// avec les identifiants connus
 	$index = $serveur ? $serveur : 0;
@@ -247,7 +252,7 @@ function spip_pg_listdbs() {
 // http://doc.spip.org/@spip_pg_select
 function spip_pg_select($select, $from, $where='',
 			$groupby=array(), $orderby='', $limit='',
-                           $having='', $serveur=''){
+                           $having='', $serveur='',$requeter=true){
 
 	$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
 	$prefixe = $connexion['prefixe'];
@@ -281,12 +286,12 @@ function spip_pg_select($select, $from, $where='',
 	// il faudrait mettre ici le d�clenchement du message SQL
 	// actuellement dans erreur_requete_boucle
 
-	if ($GLOBALS['var_mode'] == 'debug') {
+	if ($requeter && $GLOBALS['var_mode'] == 'debug') {
 		include_spip('public/debug');
 		boucle_debug_requete($q);
 	}
 
-	if (!($res = spip_pg_trace_query($q, $serveur))) {
+	if (!($res = spip_pg_trace_query($q, $serveur, $requeter))) {
 	  include_spip('public/debug');
 	  erreur_requete_boucle($q, 0, 0);
 	}
@@ -507,7 +512,7 @@ function spip_pg_select_as($args)
 }
 
 // http://doc.spip.org/@spip_pg_fetch
-function spip_pg_fetch($res, $t='', $serveur='') {
+function spip_pg_fetch($res, $t='', $serveur='',$requeter=true) {
 
 	if ($res) $res = pg_fetch_array($res, NULL, PGSQL_ASSOC);
 	return $res;
@@ -515,26 +520,26 @@ function spip_pg_fetch($res, $t='', $serveur='') {
  
 // http://doc.spip.org/@spip_pg_countsel
 function spip_pg_countsel($from = array(), $where = array(),
-			  $groupby=array(), $limit='', $having = array(), $serveur='')
+			  $groupby=array(), $limit='', $having = array(), $serveur='',$requeter=true)
 {
 	$r = spip_pg_select('COUNT(*)', $from, $where,
-			    $groupby, '', $limit, $sousrequete, $having, '','', $serveur);
-	if ($r) list($r) = pg_fetch_array($r, NULL, PGSQL_NUM);
+			    $groupby, '', $limit, $sousrequete, $having, '','', $serveur, $requeter);
+	if ($r && $requeter) list($r) = pg_fetch_array($r, NULL, PGSQL_NUM);
 	return $r;
 }
 
 // http://doc.spip.org/@spip_pg_count
-function spip_pg_count($res, $serveur='') {
+function spip_pg_count($res, $serveur='',$requeter=true) {
 	return !$res ? 0 : pg_numrows($res);
 }
   
 // http://doc.spip.org/@spip_pg_free
-function spip_pg_free($res, $serveur='') {
+function spip_pg_free($res, $serveur='',$requeter=true) {
   // rien � faire en postgres
 }
 
 // http://doc.spip.org/@spip_pg_delete
-function spip_pg_delete($table, $where='', $serveur='') {
+function spip_pg_delete($table, $where='', $serveur='',$requeter=true) {
 
 	$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
 	$prefixe = $connexion['prefixe'];
@@ -544,11 +549,11 @@ function spip_pg_delete($table, $where='', $serveur='') {
 	return spip_pg_trace_query(
 			  calculer_pg_expression('DELETE FROM', $table, ',')
 			. calculer_pg_expression('WHERE', $where, 'AND'), 
-			$serveur);
+			$serveur, $requeter);
 }
 
 // http://doc.spip.org/@spip_pg_insert
-function spip_pg_insert($table, $champs, $valeurs, $desc=array(), $serveur='') {
+function spip_pg_insert($table, $champs, $valeurs, $desc=array(), $serveur='',$requeter=true) {
 	$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
 	$prefixe = $connexion['prefixe'];
 	$link = $connexion['link'];
@@ -579,7 +584,7 @@ function spip_pg_insert($table, $champs, $valeurs, $desc=array(), $serveur='') {
 }
 
 // http://doc.spip.org/@spip_pg_insertq
-function spip_pg_insertq($table, $couples=array(), $desc=array(), $serveur='') {
+function spip_pg_insertq($table, $couples=array(), $desc=array(), $serveur='',$requeter=true) {
 
 	if (!$desc) $desc = description_table($table);
 	if (!$desc) die("$table insertion sans description");
@@ -589,11 +594,11 @@ function spip_pg_insertq($table, $couples=array(), $desc=array(), $serveur='') {
 		$couples[$champ]=  spip_pg_cite($val, $fields[$champ]);
 	}
 
-	return spip_pg_insert($table, "(".join(',',array_keys($couples)).")", "(".join(',', $couples).")", $desc, $serveur);
+	return spip_pg_insert($table, "(".join(',',array_keys($couples)).")", "(".join(',', $couples).")", $desc, $serveur, $requeter);
 }
 
 // http://doc.spip.org/@spip_pg_update
-function spip_pg_update($table, $champs, $where='', $desc='', $serveur='') {
+function spip_pg_update($table, $champs, $where='', $desc='', $serveur='',$requeter=true) {
 
 	if (!$champs) return;
 	$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
@@ -610,13 +615,13 @@ function spip_pg_update($table, $champs, $where='', $desc='', $serveur='') {
 		  calculer_pg_expression('UPDATE', $table, ',')
 		. calculer_pg_expression('SET', $set, ',')
 		. calculer_pg_expression('WHERE', $where, 'AND'), 
-		$serveur);
+		$serveur, $requeter);
 }
 
 // idem, mais les valeurs sont des constantes a mettre entre apostrophes
 // sauf les expressions de date lorsqu'il s'agit de fonctions SQL (NOW etc)
 // http://doc.spip.org/@spip_pg_updateq
-function spip_pg_updateq($table, $champs, $where='', $desc=array(), $serveur='') {
+function spip_pg_updateq($table, $champs, $where='', $desc=array(), $serveur='',$requeter=true) {
 	if (!$champs) return;
 	if (!$desc) $desc = description_table($table);
 	$fields = $desc['field'];
@@ -624,12 +629,12 @@ function spip_pg_updateq($table, $champs, $where='', $desc=array(), $serveur='')
 		$champs[$k] = spip_pg_cite($val, $fields[$k]);
 	}
 
-	return spip_pg_update($table, $champs, $where, $desc, $serveur);
+	return spip_pg_update($table, $champs, $where, $desc, $serveur, $requeter);
 }
 
 
 // http://doc.spip.org/@spip_pg_replace
-function spip_pg_replace($table, $values, $desc, $serveur='') {
+function spip_pg_replace($table, $values, $desc, $serveur='',$requeter=true) {
 
 	if (!$values) {spip_log("replace vide $table"); return 0;}
 	$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
@@ -773,28 +778,28 @@ function spip_pg_in($val, $valeurs, $not='', $serveur) {
 }
 
 // http://doc.spip.org/@spip_pg_error
-function spip_pg_error($query, $serveur='') {
+function spip_pg_error($query, $serveur='',$requeter=true) {
 	$s = str_replace('ERROR', 'errcode: 1000 ', pg_last_error());
 	if ($s) spip_log("$s - $query", 'pg');
 	return $s;
 }
 
 // http://doc.spip.org/@spip_pg_errno
-function spip_pg_errno($serveur='') {
+function spip_pg_errno($serveur='',$requeter=true) {
 	$s = pg_last_error(); 
 	if ($s) spip_log("Erreur PG $s");
 	return $s ? 1 : 0;
 }
 
 // http://doc.spip.org/@spip_pg_drop_table
-function spip_pg_drop_table($table, $exist='', $serveur='')
+function spip_pg_drop_table($table, $exist='', $serveur='',$requeter=true)
 {
 	if ($exist) $exist =" IF EXISTS";
-	return spip_pg_query("DROP TABLE$exist $table", $serveur);
+	return spip_pg_query("DROP TABLE$exist $table", $serveur, $requeter);
 }
 
 // http://doc.spip.org/@spip_pg_showbase
-function spip_pg_showbase($match, $serveur='')
+function spip_pg_showbase($match, $serveur='',$requeter=true)
 {
 	$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
 	$link = $connexion['link'];
@@ -803,7 +808,7 @@ function spip_pg_showbase($match, $serveur='')
 }
 
 // http://doc.spip.org/@spip_pg_showtable
-function spip_pg_showtable($nom_table, $serveur='')
+function spip_pg_showtable($nom_table, $serveur='',$requeter=true)
 {
 	$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
 	$link = $connexion['link'];
@@ -837,7 +842,7 @@ function spip_pg_showtable($nom_table, $serveur='')
 // si $autoinc, c'est une auto-increment (i.e. serial) sur la Primary Key
 // Le nom des index est prefixe par celui de la table pour eviter les conflits
 // http://doc.spip.org/@spip_pg_create
-function spip_pg_create($nom, $champs, $cles, $autoinc=false, $temporary=false, $serveur='') {
+function spip_pg_create($nom, $champs, $cles, $autoinc=false, $temporary=false, $serveur='',$requeter=true) {
 
 	$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
 	$prefixe = $connexion['prefixe'];
@@ -906,7 +911,7 @@ function spip_pg_create($nom, $champs, $cles, $autoinc=false, $temporary=false,
 }
 
 // http://doc.spip.org/@spip_pg_set_connect_charset
-function spip_pg_set_connect_charset($charset, $serveur=''){
+function spip_pg_set_connect_charset($charset, $serveur='',$requeter=true){
 	spip_log("changement de charset sql a ecrire en PG");
 }
 
diff --git a/ecrire/req/sqlite_generique.php b/ecrire/req/sqlite_generique.php
index 8a7f2ee883..b83e851260 100644
--- a/ecrire/req/sqlite_generique.php
+++ b/ecrire/req/sqlite_generique.php
@@ -111,31 +111,29 @@ function req_sqlite_dist($addr, $port, $login, $pass, $db='', $prefixe='', $ldap
 
 // obsolete, ne plus utiliser
 /*
-function spip_query_db($query, $serveur='') {
+function spip_query_db($query, $serveur='',$requeter=true) {
 	return spip_sqlite_query($query, $serveur);
 }
 */
 
 // Fonction de requete generale, munie d'une trace a la demande
-function spip_sqlite_query($query, $serveur='') {
+function spip_sqlite_query($query, $serveur='',$requeter=true) {
 #spip_log("spip_sqlite_query() > $query");
 	_sqlite_init();
 	
 	$requete = new sqlite_traiter_requete($query, $serveur);
 	$requete->traduire_requete(); // mysql -> sqlite
+	if (!$requeter) return $requete->query;
 	return $requete->executer_requete();
 }
 
 
 /* ordre alphabetique pour les autres */
 
-function spip_sqlite_alter($query, $serveur=''){
+function spip_sqlite_alter($query, $serveur='',$requeter=true){
 
 	$query = _sqlite_remplacements_definitions_table($query);
-
-	$requete = new sqlite_traiter_requete("ALTER $query", $serveur);
-	$requete->traduire_requete(); // mysql -> sqlite
-	$query = $requete->query;
+	$query = spip_sqlite_query("ALTER $query",$serveur,false);
 	
 	/* 
 	 * la il faut faire les transformations
@@ -276,17 +274,17 @@ function spip_sqlite_alter($query, $serveur=''){
 
 
 // Fonction de creation d'une table SQL nommee $nom
-function spip_sqlite_create($nom, $champs, $cles, $autoinc=false, $temporary=false, $serveur='') {
-	$query = _sqlite_requete_create($nom, $champs, $cles, $autoinc, $temporary, $ifnotexists=true, $serveur);
+function spip_sqlite_create($nom, $champs, $cles, $autoinc=false, $temporary=false, $serveur='',$requeter=true) {
+	$query = _sqlite_requete_create($nom, $champs, $cles, $autoinc, $temporary, $ifnotexists=true, $serveur, $requeter);
 	if (!$query) return false;
-	return spip_sqlite_query($query, $serveur);
+	return spip_sqlite_query($query, $serveur, $requeter);
 }
 
 
 // en PDO/sqlite3, il faut calculer le count par une requete count(*)
 // pour les resultats de SELECT
 // cela est fait sans spip_sqlite_query()
-function spip_sqlite_count($r, $serveur='') {
+function spip_sqlite_count($r, $serveur='',$requeter=true) {
 	if (!$r) return 0;
 		
 	if (_sqlite_is_version(3, '', $serveur)){
@@ -304,11 +302,11 @@ function spip_sqlite_count($r, $serveur='') {
 }
 
 
-function spip_sqlite_countsel($from = array(), $where = array(), $groupby = '', $limit = '', $sousrequete = '', $having = array(), $serveur='') {
+function spip_sqlite_countsel($from = array(), $where = array(), $groupby = '', $limit = '', $sousrequete = '', $having = array(), $serveur='',$requeter=true) {
 	$r = spip_sqlite_select('COUNT(*)', $from, $where,$groupby, '', $limit,
-			$having, $serveur);
+			$having, $serveur, $requeter);
 	
-	if ($r) {
+	if ($r && $requeter) {
 		if (_sqlite_is_version(3,'',$serveur)){
 			list($r) = spip_sqlite_fetch($r, SPIP_SQLITE3_NUM, $serveur);
 		} else {
@@ -321,15 +319,15 @@ function spip_sqlite_countsel($from = array(), $where = array(), $groupby = '',
 
 
 
-function spip_sqlite_delete($table, $where='', $serveur='') {
+function spip_sqlite_delete($table, $where='', $serveur='',$requeter=true) {
 	return spip_sqlite_query(
 			  _sqlite_calculer_expression('DELETE FROM', $table, ',')
 			. _sqlite_calculer_expression('WHERE', $where),
-			$serveur);
+			$serveur, $requeter);
 }
 
 
-function spip_sqlite_drop_table($table, $exist='', $serveur='') {
+function spip_sqlite_drop_table($table, $exist='', $serveur='',$requeter=true) {
 	if ($exist) $exist =" IF EXISTS";
 	
 	/* simuler le IF EXISTS - version 2 */
@@ -339,11 +337,11 @@ function spip_sqlite_drop_table($table, $exist='', $serveur='') {
 		$exist = '';
 	}
 	
-	return spip_sqlite_query("DROP TABLE$exist $table", $serveur);
+	return spip_sqlite_query("DROP TABLE$exist $table", $serveur, $requeter);
 }
 
 
-function spip_sqlite_error($query='', $serveur='') {
+function spip_sqlite_error($query='', $serveur='',$requeter=true) {
 	$link  = _sqlite_link($serveur);
 	
 	if (_sqlite_is_version(3, $link)){
@@ -363,7 +361,7 @@ function spip_sqlite_error($query='', $serveur='') {
 }
 
 
-function spip_sqlite_errno($serveur='') {
+function spip_sqlite_errno($serveur='',$requeter=true) {
 	$link  = _sqlite_link($serveur);
 	
 	if (_sqlite_is_version(3, $link)){
@@ -382,12 +380,13 @@ function spip_sqlite_errno($serveur='') {
 }
 
 
-function spip_sqlite_explain($query, $serveur=''){
+function spip_sqlite_explain($query, $serveur='',$requeter=true){
 	if (strpos(ltrim($query), 'SELECT') !== 0) return array();
 
 	$requete = new sqlite_traiter_requete("$query", $serveur);
 	$requete->traduire_requete(); // mysql -> sqlite
 	$requete->query = 'EXPLAIN ' . $requete->query;
+	if (!$requeter) return $requete;
 	// on ne trace pas ces requetes, sinon on obtient un tracage sans fin...
 	$requete->tracer = false; 
 	$r = $requete->executer_requete();
@@ -396,7 +395,7 @@ function spip_sqlite_explain($query, $serveur=''){
 }
 
 
-function spip_sqlite_fetch($r, $t='', $serveur='') {
+function spip_sqlite_fetch($r, $t='', $serveur='',$requeter=true) {
 
 	$link = _sqlite_link($serveur);
 	if (!$t) {
@@ -432,12 +431,12 @@ function spip_sqlite_fetch($r, $t='', $serveur='') {
 }
 
 
-function spip_sqlite_free($r, $serveur='') {
+function spip_sqlite_free($r, $serveur='',$requeter=true) {
 	//return sqlite_free_result($r);
 }
 
 
-function spip_sqlite_get_charset($charset=array(), $serveur=''){
+function spip_sqlite_get_charset($charset=array(), $serveur='',$requeter=true){
 	//$c = !$charset ? '' : (" LIKE "._q($charset['charset']));
 	//return spip_sqlite_fetch(sqlite_query(_sqlite_link($serveur), "SHOW CHARACTER SET$c"), NULL, $serveur);
 }
@@ -448,7 +447,7 @@ function spip_sqlite_hex($v){
 }
 
 
-function spip_sqlite_in($val, $valeurs, $not='', $serveur='') {
+function spip_sqlite_in($val, $valeurs, $not='', $serveur='',$requeter=true) {
 	$n = $i = 0;
 	$in_sql ="";
 	while ($n = strpos($valeurs, ',', $n+1)) {
@@ -467,7 +466,7 @@ function spip_sqlite_in($val, $valeurs, $not='', $serveur='') {
 }
 
 
-function spip_sqlite_insert($table, $champs, $valeurs, $desc='', $serveur='') {
+function spip_sqlite_insert($table, $champs, $valeurs, $desc='', $serveur='',$requeter=true) {
 
 	$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
 	$prefixe = $connexion['prefixe'];
@@ -480,7 +479,8 @@ function spip_sqlite_insert($table, $champs, $valeurs, $desc='', $serveur='') {
 	$t = !isset($_GET['var_profile']) ? 0 : trace_query_start();
 
 	$query="INSERT OR REPLACE INTO $table $champs VALUES $valeurs";
-
+	if (!$requeter) return $query;
+	
 	if ($r = spip_sqlite_query($query, $serveur)) {
 		if (_sqlite_is_version(3, $sqlite)) $nb = $sqlite->lastInsertId();
 		else $nb = sqlite_last_insert_rowid($sqlite);
@@ -493,7 +493,7 @@ function spip_sqlite_insert($table, $champs, $valeurs, $desc='', $serveur='') {
 }
 
 
-function spip_sqlite_insertq($table, $couples=array(), $desc=array(), $serveur='') {
+function spip_sqlite_insertq($table, $couples=array(), $desc=array(), $serveur='',$requeter=true) {
 	if (!$desc) $desc = description_table($table);
 	if (!$desc) die("$table insertion sans description");
 	$fields =  isset($desc['field'])?$desc['field']:array();
@@ -502,11 +502,11 @@ function spip_sqlite_insertq($table, $couples=array(), $desc=array(), $serveur='
 		$couples[$champ]= _sqlite_calculer_cite($val, $fields[$champ]);
 	}
 	
-	return spip_sqlite_insert($table, "(".join(',',array_keys($couples)).")", "(".join(',', $couples).")", $desc, $serveur);
+	return spip_sqlite_insert($table, "(".join(',',array_keys($couples)).")", "(".join(',', $couples).")", $desc, $serveur, $requeter);
 }
 
 
-function spip_sqlite_listdbs($serveur='') {
+function spip_sqlite_listdbs($serveur='',$requeter=true) {
 	_sqlite_init();
 	
 	if (!is_dir($d = substr(_DIR_DB,0,-1))){
@@ -539,7 +539,7 @@ function spip_sqlite_multi ($objet, $lang) {
 }
 
 
-function spip_sqlite_optimize($table, $serveur=''){
+function spip_sqlite_optimize($table, $serveur='',$requeter=true){
 	spip_sqlite_query("OPTIMIZE TABLE ". $table, $serveur); // <- a verifier mais ca doit pas etre ca !
 	return true;
 }
@@ -563,17 +563,17 @@ function spip_sqlite_quote($v){
 }
 
 
-function spip_sqlite_repair($table, $serveur=''){
-	return spip_sqlite_query("REPAIR TABLE $table", $serveur); // <- ca m'ettonerait aussi ca !
+function spip_sqlite_repair($table, $serveur='',$requeter=true){
+	return spip_sqlite_query("REPAIR TABLE $table", $serveur, $requeter); // <- ca m'ettonerait aussi ca !
 }
 
 
-function spip_sqlite_replace($table, $values, $keys=array(), $serveur='') {
+function spip_sqlite_replace($table, $values, $keys=array(), $serveur='',$requeter=true) {
 	return spip_sqlite_query("REPLACE INTO $table (" . join(',',array_keys($values)) . ') VALUES (' .join(',',array_map('spip_sqlite_quote', $values)) . ')', $serveur);
 }
 
 
-function spip_sqlite_select($select, $from, $where='', $groupby='', $orderby='', $limit='', $having='', $serveur='') {	
+function spip_sqlite_select($select, $from, $where='', $groupby='', $orderby='', $limit='', $having='', $serveur='',$requeter=true) {	
 	// version() n'est pas connu de sqlite
 	$select = str_replace('version()', 'sqlite_version()',$select);
 
@@ -596,7 +596,7 @@ function spip_sqlite_select($select, $from, $where='', $groupby='', $orderby='',
 		boucle_debug_requete($query);
 	}
 
-	if (!($res = spip_sqlite_query($query, $serveur))) {
+	if (!($res = spip_sqlite_query($query, $serveur, $requeter))) {
 		include_spip('public/debug');
 		
 		erreur_requete_boucle(substr($query, 7),
@@ -608,7 +608,7 @@ function spip_sqlite_select($select, $from, $where='', $groupby='', $orderby='',
 }
 
 
-function spip_sqlite_selectdb($db, $serveur='') {
+function spip_sqlite_selectdb($db, $serveur='',$requeter=true) {
 	_sqlite_init();
 
 	// interdire la creation d'une nouvelle base, 
@@ -632,18 +632,18 @@ function spip_sqlite_selectdb($db, $serveur='') {
 }
 
 
-function spip_sqlite_set_charset($charset, $serveur=''){
+function spip_sqlite_set_charset($charset, $serveur='',$requeter=true){
 	#spip_log("changement de charset sql : "."SET NAMES "._q($charset));
 	# return spip_sqlite_query("SET NAMES ". spip_sqlite_quote($charset), $serveur); //<-- Passe pas !
 }
 
 
-function spip_sqlite_showbase($match, $serveur=''){
-	return spip_sqlite_query('SELECT name FROM sqlite_master WHERE type LIKE "'.$match.'"', $serveur);
+function spip_sqlite_showbase($match, $serveur='',$requeter=true){
+	return spip_sqlite_query('SELECT name FROM sqlite_master WHERE type LIKE "'.$match.'"', $serveur, $requeter);
 }
 
 
-function spip_sqlite_showtable($nom_table, $serveur=''){
+function spip_sqlite_showtable($nom_table, $serveur='',$requeter=true){
 
 	$query = 
 			'SELECT sql FROM'
@@ -653,8 +653,9 @@ function spip_sqlite_showtable($nom_table, $serveur=''){
 			. " AND type!='meta' AND sql NOT NULL AND name NOT LIKE 'sqlite_%'"
 			. 'ORDER BY substr(type,2,1), name';
 	
-	$a = spip_sqlite_query($query, $serveur);
+	$a = spip_sqlite_query($query, $serveur, $requeter);
 	if (!$a) return "";
+	if (!$requeter) return $a;
 	if (!($a = spip_sqlite_fetch($a, null, $serveur))) return "";
 	$a = array_shift($a); 
 	if (!preg_match("/^[^(),]*\((([^()]*(\([^()]*\))?[^()]*)*)\)[^()]*$/", $a, $r))
@@ -691,7 +692,7 @@ function spip_sqlite_showtable($nom_table, $serveur=''){
 }
 
 
-function spip_sqlite_update($table, $champs, $where='', $desc='', $serveur='') {
+function spip_sqlite_update($table, $champs, $where='', $desc='', $serveur='',$requeter=true) {
 	$set = array();
 	foreach ($champs as $champ => $val)
 		$set[] = $champ . "=$val";
@@ -700,11 +701,11 @@ function spip_sqlite_update($table, $champs, $where='', $desc='', $serveur='') {
 			  _sqlite_calculer_expression('UPDATE', $table, ',')
 			. _sqlite_calculer_expression('SET', $set, ',')
 			. _sqlite_calculer_expression('WHERE', $where), 
-			$serveur);
+			$serveur, $requeter);
 }
 
 
-function spip_sqlite_updateq($table, $champs, $where='', $desc=array(), $serveur='') {
+function spip_sqlite_updateq($table, $champs, $where='', $desc=array(), $serveur='',$requeter=true) {
 
 	if (!$champs) return;
 	if (!$desc) $desc = description_table($table);
@@ -718,7 +719,7 @@ function spip_sqlite_updateq($table, $champs, $where='', $desc=array(), $serveur
 			  _sqlite_calculer_expression('UPDATE', $table, ',')
 			. _sqlite_calculer_expression('SET', $set, ',')
 			. _sqlite_calculer_expression('WHERE', $where),
-			$serveur);
+			$serveur, $requeter);
 }
 
 
@@ -744,7 +745,7 @@ function _sqlite_init(){
 
 
 // teste la version sqlite du link en cours
-function _sqlite_is_version($version='', $link='', $serveur=''){
+function _sqlite_is_version($version='', $link='', $serveur='',$requeter=true){
 	if ($link==='') $link = _sqlite_link($serveur);
 	if (!$link) return false;
 	if (is_a($link, 'PDO')){
@@ -912,7 +913,7 @@ function _sqlite_charger_version($version=''){
  * 4) renommer la table B en A
  * 
  */
-function _sqlite_modifier_table($table_origine, $table_destination, $colonne_origine='', $colonne_destination='', $def_col_destination='', $serveur=''){
+function _sqlite_modifier_table($table_origine, $table_destination, $colonne_origine='', $colonne_destination='', $def_col_destination='', $serveur='',$requeter=true){
 	
 	// si les noms de tables sont differents, pas besoin de table temporaire
 	// on prendra directement le nom de la future table
@@ -1103,7 +1104,7 @@ function _sqlite_remplacements_definitions_table($query){
  * Creer la requete pour la creation d'une table
  * retourne la requete pour utilisation par sql_create() et sql_alter()
  */
-function _sqlite_requete_create($nom, $champs, $cles, $autoinc=false, $temporary=false, $_ifnotexists=true, $serveur='') {
+function _sqlite_requete_create($nom, $champs, $cles, $autoinc=false, $temporary=false, $_ifnotexists=true, $serveur='',$requeter=true) {
 	$query = $keys = $s = $p = '';
 
 	// certains plugins declarent les tables  (permet leur inclusion dans le dump)
-- 
GitLab