From 446799bc8aa3e37e3ac356a2469b041908a07022 Mon Sep 17 00:00:00 2001
From: Fil <fil@rezo.net>
Date: Sat, 11 Dec 2010 13:35:49 +0000
Subject: [PATCH] introduction d'un iterateur generique a la place de la
 logique SQL des boucles

---
 .gitattributes              |  1 +
 ecrire/public/compiler.php  | 36 +++++++++++++------
 ecrire/public/composer.php  |  1 +
 ecrire/public/criteres.php  |  9 ++---
 ecrire/public/iterateur.php | 69 +++++++++++++++++++++++++++++++++++++
 ecrire/public/quete.php     |  4 +--
 6 files changed, 101 insertions(+), 19 deletions(-)
 create mode 100644 ecrire/public/iterateur.php

diff --git a/.gitattributes b/.gitattributes
index 767bbe93f4..59c27ec16c 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -300,6 +300,7 @@ ecrire/public/aiguiller.php -text
 ecrire/public/decompiler.php -text
 ecrire/public/format_html.php -text
 ecrire/public/index.php -text
+ecrire/public/iterateur.php -text
 ecrire/public/jointures.php -text
 ecrire/public/normaliser.php -text
 ecrire/public/quete.php -text
diff --git a/ecrire/public/compiler.php b/ecrire/public/compiler.php
index 5c77168c40..35b7a0c778 100644
--- a/ecrire/public/compiler.php
+++ b/ecrire/public/compiler.php
@@ -242,13 +242,28 @@ function calculer_boucle_rec($id_boucle, &$boucles, $trace) {
 define('CODE_CORPS_BOUCLE', '%s
 	$t0 = "";
 	// REQUETE
-	$result = calculer_select($select, $from, $type, $where, $join, $groupby, $orderby, $limit, $having, $table, $id, $connect,
-		 array(%s));
-	if ($result) {
+	$iter = new Iter("SQL");
+	$iter->init( array(
+		"select"=>$select,
+		"from"=>$from,
+		"type"=>$type,
+		"where"=>$where,
+		"join"=>$join,
+		"groupby"=>$groupby,
+		"orderby"=>$orderby,
+		"limit"=>$limit,
+		"having"=>$having,
+		"table"=>$table,
+		"id"=>$id,
+		"connect"=>$connect
+		),
+		array(%s)
+	);
+	if ($iter->ok) {
 	%s%s$SP++;
 	// RESULTATS
 	%s
-	%s@sql_free($result%s);
+	%s$iter->free();
 	}%s
 	return $t0;'
 );
@@ -342,9 +357,6 @@ function calculer_boucle_nonrec($id_boucle, &$boucles, $trace) {
 		. $boucle->partie 
 		. $corps;
 
-	$serveur = !$boucle->sql_serveur ? ''
-		: (', ' . _q($boucle->sql_serveur));
-
 	// si le corps est une constante, ne pas appeler le serveur N fois!
 
 	if (preg_match(CODE_MONOTONE,str_replace("\\'",'',$corps), $r)) {
@@ -357,7 +369,7 @@ function calculer_boucle_nonrec($id_boucle, &$boucles, $trace) {
 			$boucle->numrows = true;
 			$corps = "\n\t\$t0 = str_repeat($corps, \$Numrows['$id_boucle']['total']);";
 		}
-	} else $corps = "while (\$Pile[\$SP] = @sql_fetch(\$result$serveur)) {\n$corps\n	}"; 
+	} else $corps = "while (\$Pile[\$SP] = \$iter->next()) {\n$corps\n	}"; 
 
 	$count = '';
 	if (!$boucle->select) {
@@ -374,8 +386,8 @@ function calculer_boucle_nonrec($id_boucle, &$boucles, $trace) {
 
 	if ($boucle->numrows OR $boucle->mode_partie) {
 		if ($count == 'count(*)')
-			$count = "array_shift(sql_fetch(\$result$serveur))";
-		else $count = "sql_count(\$result$serveur)";
+			$count = "array_shift(\$iter->next())";
+		else $count = "\$iter->count()";
 		$nums .= "\$Numrows['$id_boucle']['total'] = @intval($count);"
 		. $boucle->mode_partie
 		. "\n\t";
@@ -389,8 +401,10 @@ function calculer_boucle_nonrec($id_boucle, &$boucles, $trace) {
 	. calculer_requete_sql($boucles[$id_boucle]);
 
 	$contexte = memoriser_contexte_compil($boucle);
+	$a = sprintf(CODE_CORPS_BOUCLE, $init, $contexte, $nums, $init_lang, $corps, $fin_lang, $trace);
 
-	return sprintf(CODE_CORPS_BOUCLE, $init, $contexte, $nums, $init_lang, $corps, $fin_lang, $serveur, $trace);
+#	var_dump($a);exit;
+	return $a;
 }
 
 
diff --git a/ecrire/public/composer.php b/ecrire/public/composer.php
index 1538b2bf7a..ecc139cdcc 100644
--- a/ecrire/public/composer.php
+++ b/ecrire/public/composer.php
@@ -12,6 +12,7 @@
 
 if (!defined("_ECRIRE_INC_VERSION")) return;
 
+include_spip('public/iterateur');
 include_spip('inc/texte');
 include_spip('inc/documents');
 include_spip('inc/distant');
diff --git a/ecrire/public/criteres.php b/ecrire/public/criteres.php
index fd8b097da0..c0265cf7a6 100644
--- a/ecrire/public/criteres.php
+++ b/ecrire/public/criteres.php
@@ -156,11 +156,8 @@ function critere_pagination_dist($idb, &$boucles, $crit) {
 		 // tester si le numero de page demande est de la forme '@yyy'
 		 'isset($Pile[0]['.$debut.']) ? $Pile[0]['.$debut.'] : _request('.$debut.");\n"
 		."\tif(substr(\$debut_boucle,0,1)=='@'){\n"
-		."\t\t".'$debut_boucle = $Pile[0]['. $debut.'] = quete_debut_pagination(\''.$boucle->primary.'\',$Pile[0][\'@'.$boucle->primary.'\'] = substr($debut_boucle,1),'.$pas.',$result,'._q($boucle->sql_serveur).');'."\n"
-		."\t\t".'if (!sql_seek($result,0,'._q($boucle->sql_serveur).")){\n"
-		."\t\t\t".'@sql_free($result,'._q($boucle->sql_serveur).");\n"
-		."\t\t\t".'$result = calculer_select($select, $from, $type, $where, $join, $groupby, $orderby, $limit, $having, $table, $id, $connect);'."\n"
-		."\t\t}\n"
+		."\t\t".'$debut_boucle = $Pile[0]['. $debut.'] = quete_debut_pagination(\''.$boucle->primary.'\',$Pile[0][\'@'.$boucle->primary.'\'] = substr($debut_boucle,1),'.$pas.',$iter);'."\n"
+		."\t\t".'$iter->seek(0);'."\n"
 		."\t}\n"
 		."\t".'$debut_boucle = intval($debut_boucle)';
 
@@ -665,7 +662,7 @@ function calculer_parties(&$boucles, $id_boucle, $debut, $mode) {
 	. '$fin_boucle = min(' . $fin . ", \$Numrows['$id_boucle']['total'] - 1);\n	"
 	. '$Numrows[\''.$id_boucle. "']['grand_total'] = \$Numrows['$id_boucle']['total'];\n	"
 	. '$Numrows[\''.$id_boucle.'\']["total"] = max(0,$fin_boucle - $debut_boucle + 1);'
-	. "\n\tif (\$debut_boucle>0 AND \$debut_boucle < \$Numrows['$id_boucle']['grand_total'] AND sql_seek(\$result,\$debut_boucle,"._q($boucles[$id_boucle]->sql_serveur).",'continue'))\n\t\t\$Numrows['$id_boucle']['compteur_boucle'] = \$debut_boucle;\n\t";
+	. "\n\tif (\$debut_boucle>0 AND \$debut_boucle < \$Numrows['$id_boucle']['grand_total'] AND \$iter->seek(\$debut_boucle,'continue'))\n\t\t\$Numrows['$id_boucle']['compteur_boucle'] = \$debut_boucle;\n\t";
 
 	$boucles[$id_boucle]->partie = "
 		if (\$Numrows['$id_boucle']['compteur_boucle'] <= \$debut_boucle) continue;
diff --git a/ecrire/public/iterateur.php b/ecrire/public/iterateur.php
new file mode 100644
index 0000000000..419b470d49
--- /dev/null
+++ b/ecrire/public/iterateur.php
@@ -0,0 +1,69 @@
+<?php
+
+
+/***************************************************************************\
+ *  SPIP, Systeme de publication pour l'internet                           *
+ *                                                                         *
+ *  Copyright (c) 2001-2010                                                *
+ *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
+ *                                                                         *
+ *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
+ *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
+\***************************************************************************/
+
+
+//
+// Iterateur SQL
+//
+
+class Iter {
+	var $ok = false;
+	var $type;
+	var $command;
+	var $info;
+
+	private $result = false;
+
+
+	public function Iter($type) {
+		$this->type = $type;
+	}
+
+	private function select() {
+		$v = &$this->command;
+		$this->result = calculer_select($v['select'], $v['from'], $v['type'], $v['where'], $v['join'], $v['groupby'], $v['orderby'], $v['limit'], $v['having'], $v['table'], $v['id'], $v['connect'], $this->info);
+		$this->ok = !!$this->result;
+	}
+
+	/*
+	 * array command: les commandes d'initialisation
+	 * array info: les infos sur le squelette
+	 */
+	public function init($command, $info=array()) {
+		$this->command = $command;
+		$this->info = $info;
+		$this->select();
+	}
+	public function seek($n=0, $continue=null) {
+		# SQLite ne sait pas seek(), il faut relancer la query
+		if (!$a = sql_seek($this->result, $this->command['connect'], $n, $continue)) {
+			$this->free();
+			$this->select();
+			return true; # ??
+		}
+		return $a;
+	}
+	public function next(){
+		return sql_fetch($this->result, $this->command['connect']);
+	}
+	public function free(){
+		return sql_free($this->result, $this->command['connect']);
+	}
+	public function count() {
+		return sql_count($this->result, $this->command['connect']);
+	}
+}
+
+
+
+?>
diff --git a/ecrire/public/quete.php b/ecrire/public/quete.php
index 7272421233..900f8b7d95 100644
--- a/ecrire/public/quete.php
+++ b/ecrire/public/quete.php
@@ -254,14 +254,14 @@ function calcul_exposer ($id, $prim, $reference, $parent, $type, $connect='') {
 	return isset($exposer[$m][$prim]) ? isset($exposer[$m][$prim][$id]) : '';
 }
 
-function quete_debut_pagination($primary,$valeur,$pas,$res,$serveur=''){
+function quete_debut_pagination($primary,$valeur,$pas,$iter){
 	// on ne devrait pas arriver ici si la cle primaire est inexistante
 	// ou composee, mais verifions
 	if (!$primary OR preg_match('/[,\s]/',$primary))
 		return 0;
 
 	$pos = 0;
-	while ($row = sql_fetch($res,$serveur) AND $row[$primary]!=$valeur){
+	while ($row = $iter->next() AND $row[$primary]!=$valeur){
 		$pos++;
 	}
 	// si on a pas trouve
-- 
GitLab