223 lines
4.5 KiB
PHP
223 lines
4.5 KiB
PHP
|
<?php
|
||
|
|
||
|
/***************************************************************************\
|
||
|
* SPIP, Systeme de publication pour l'internet *
|
||
|
* *
|
||
|
* Copyright (c) 2001-2019 *
|
||
|
* 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. *
|
||
|
\***************************************************************************/
|
||
|
|
||
|
/**
|
||
|
* Gestion de l'itérateur SQL
|
||
|
*
|
||
|
* @package SPIP\Core\Iterateur\SQL
|
||
|
**/
|
||
|
|
||
|
if (!defined('_ECRIRE_INC_VERSION')) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Itérateur SQL
|
||
|
*
|
||
|
* Permet d'itérer sur des données en base de données
|
||
|
*/
|
||
|
class IterateurSQL implements Iterator {
|
||
|
|
||
|
/**
|
||
|
* ressource sql
|
||
|
*
|
||
|
* @var resource|bool
|
||
|
*/
|
||
|
protected $sqlresult = false;
|
||
|
|
||
|
/**
|
||
|
* row sql courante
|
||
|
*
|
||
|
* @var array|null
|
||
|
*/
|
||
|
protected $row = null;
|
||
|
|
||
|
protected $firstseek = false;
|
||
|
|
||
|
/**
|
||
|
* Erreur presente ?
|
||
|
*
|
||
|
* @var bool
|
||
|
**/
|
||
|
public $err = false;
|
||
|
|
||
|
/**
|
||
|
* Calcul du total des elements
|
||
|
*
|
||
|
* @var int|null
|
||
|
**/
|
||
|
public $total = null;
|
||
|
|
||
|
/**
|
||
|
* selectionner les donnees, ie faire la requete SQL
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
protected function select() {
|
||
|
$this->row = null;
|
||
|
$v = &$this->command;
|
||
|
$this->sqlresult = 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->err = !$this->sqlresult;
|
||
|
$this->firstseek = false;
|
||
|
$this->pos = -1;
|
||
|
|
||
|
// pas d'init a priori, le calcul ne sera fait qu'en cas de besoin (provoque une double requete souvent inutile en sqlite)
|
||
|
//$this->total = $this->count();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* array command: les commandes d'initialisation
|
||
|
* array info: les infos sur le squelette
|
||
|
*/
|
||
|
public function __construct($command, $info = array()) {
|
||
|
$this->type = 'SQL';
|
||
|
$this->command = $command;
|
||
|
$this->info = $info;
|
||
|
$this->select();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Rembobiner
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function rewind() {
|
||
|
return ($this->pos > 0)
|
||
|
? $this->seek(0)
|
||
|
: true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Verifier l'etat de l'iterateur
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function valid() {
|
||
|
if ($this->err) {
|
||
|
return false;
|
||
|
}
|
||
|
if (!$this->firstseek) {
|
||
|
$this->next();
|
||
|
}
|
||
|
|
||
|
return is_array($this->row);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Valeurs sur la position courante
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
public function current() {
|
||
|
return $this->row;
|
||
|
}
|
||
|
|
||
|
public function key() {
|
||
|
return $this->pos;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sauter a une position absolue
|
||
|
*
|
||
|
* @param int $n
|
||
|
* @param null|string $continue
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function seek($n = 0, $continue = null) {
|
||
|
if (!sql_seek($this->sqlresult, $n, $this->command['connect'], $continue)) {
|
||
|
// SQLite ne sait pas seek(), il faut relancer la query
|
||
|
// si la position courante est apres la position visee
|
||
|
// il faut relancer la requete
|
||
|
if ($this->pos > $n) {
|
||
|
$this->free();
|
||
|
$this->select();
|
||
|
$this->valid();
|
||
|
}
|
||
|
// et utiliser la methode par defaut pour se deplacer au bon endroit
|
||
|
// (sera fait en cas d'echec de cette fonction)
|
||
|
return false;
|
||
|
}
|
||
|
$this->row = sql_fetch($this->sqlresult, $this->command['connect']);
|
||
|
$this->pos = min($n, $this->count());
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Avancer d'un cran
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
public function next() {
|
||
|
$this->row = sql_fetch($this->sqlresult, $this->command['connect']);
|
||
|
$this->pos++;
|
||
|
$this->firstseek |= true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Avancer et retourner les donnees pour le nouvel element
|
||
|
*
|
||
|
* @return array|bool|null
|
||
|
*/
|
||
|
public function fetch() {
|
||
|
if ($this->valid()) {
|
||
|
$r = $this->current();
|
||
|
$this->next();
|
||
|
} else {
|
||
|
$r = false;
|
||
|
}
|
||
|
|
||
|
return $r;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* liberer les ressources
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function free() {
|
||
|
if (!$this->sqlresult) {
|
||
|
return true;
|
||
|
}
|
||
|
$a = sql_free($this->sqlresult, $this->command['connect']);
|
||
|
$this->sqlresult = null;
|
||
|
|
||
|
return $a;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Compter le nombre de resultats
|
||
|
*
|
||
|
* @return int
|
||
|
*/
|
||
|
public function count() {
|
||
|
if (is_null($this->total)) {
|
||
|
if (!$this->sqlresult) {
|
||
|
$this->total = 0;
|
||
|
} else {
|
||
|
# cas count(*)
|
||
|
if (in_array('count(*)', $this->command['select'])) {
|
||
|
$this->valid();
|
||
|
$s = $this->current();
|
||
|
$this->total = $s['count(*)'];
|
||
|
} else {
|
||
|
$this->total = sql_count($this->sqlresult, $this->command['connect']);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $this->total;
|
||
|
}
|
||
|
}
|