/spip/ecrire/req/sqlite_generique.php
PHP | 1905 lines | 1212 code | 282 blank | 411 comment | 255 complexity | 58633a8144888fc7b3755d4c586ac47f MD5 | raw file
Possible License(s): LGPL-2.1, GPL-3.0
Large files files are truncated, but you can click here to view the full file
- <?php
- /***************************************************************************\
- * SPIP, Systeme de publication pour l'internet *
- * *
- * Copyright (c) 2001-2011 *
- * 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. *
- \***************************************************************************/
- if (!defined('_ECRIRE_INC_VERSION')) return;
- // infos :
- // il ne faut pas avoir de PDO::CONSTANTE dans ce fichier sinon php4 se tue !
- // idem, il ne faut pas de $obj->toto()->toto sinon php4 se tue !
- # todo : get/set_caracteres ?
- /*
- *
- * regroupe le maximum de fonctions qui peuvent cohabiter
- * D'abord les fonctions d'abstractions de SPIP
- *
- */
- // http://doc.spip.org/@req_sqlite_dist
- function req_sqlite_dist($addr, $port, $login, $pass, $db='', $prefixe='', $sqlite_version=''){
- static $last_connect = array();
- // si provient de selectdb
- // un code pour etre sur que l'on vient de select_db()
- if (strpos($db, $code = '@selectdb@')!==false) {
- foreach (array('addr','port','login','pass','prefixe') as $a){
- $$a = $last_connect[$a];
- }
- $db = str_replace($code, '', $db);
- }
- /*
- * En sqlite, seule l'adresse du fichier est importante.
- * Ce sera $db le nom, et le path _DIR_DB
- */
- _sqlite_init();
- // un nom de base demande et impossible d'obtenir la base, on s'en va
- if ($db && !is_file($f = _DIR_DB . $db . '.sqlite') && !is_writable(_DIR_DB))
- return false;
-
- // charger les modules sqlite au besoin
- if (!_sqlite_charger_version($sqlite_version)) {
- spip_log("Impossible de trouver/charger le module SQLite ($sqlite_version)!");
- return false;
- }
- // chargement des constantes
- // il ne faut pas definir les constantes avant d'avoir charge les modules sqlite
- $define = "spip_sqlite".$sqlite_version."_constantes";
- $define();
-
- $ok = false;
- if (!$db){
- // si installation -> base temporaire tant qu'on ne connait pas son vrai nom
- if (defined('_ECRIRE_INSTALL') && _ECRIRE_INSTALL){
- // creation d'une base temporaire pour le debut d'install
- $db = "_sqlite".$sqlite_version."_install";
- $tmp = _DIR_DB . $db . ".sqlite";
- if ($sqlite_version == 3) {
- $ok = $link = new PDO("sqlite:$tmp");
- } else {
- $ok = $link = sqlite_open($tmp, _SQLITE_CHMOD, $err);
- }
- // sinon, on arrete finalement
- } else {
- return false;
- }
- } else {
- // Ouvrir (eventuellement creer la base)
- // si pas de version fourni, on essaie la 3, sinon la 2
- if ($sqlite_version == 3) {
- $ok = $link = new PDO("sqlite:$f");
- } else {
- $ok = $link = sqlite_open($f, _SQLITE_CHMOD, $err);
- }
- }
- if (!$ok){
- spip_log("Impossible d'ouvrir la base de donnee SQLite ($sqlite_version) : $f ");
- return false;
- }
-
- if ($link) {
- $last_connect = array (
- 'addr' => $addr,
- 'port' => $port,
- 'login' => $login,
- 'pass' => $pass,
- 'db' => $db,
- 'prefixe' => $prefixe,
- );
- }
- return array(
- 'db' => $db,
- 'prefixe' => $prefixe ? $prefixe : $db,
- 'link' => $link,
- );
- }
- // Fonction de requete generale, munie d'une trace a la demande
- // http://doc.spip.org/@spip_sqlite_query
- 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 */
- // http://doc.spip.org/@spip_sqlite_alter
- function spip_sqlite_alter($query, $serveur='',$requeter=true){
- $query = spip_sqlite_query("ALTER $query",$serveur,false);
-
- /*
- * la il faut faire les transformations
- * si ALTER TABLE x (DROP|CHANGE) y
- *
- * 1) recuperer "ALTER TABLE table "
- * 2) spliter les sous requetes (,)
- * 3) faire chaque requete independemment
- */
-
- // 1
- if (preg_match("/\s*(ALTER(\s*IGNORE)?\s*TABLE\s*([^\s]*))\s*(.*)?/is", $query, $regs)){
- $debut = $regs[1];
- $table = $regs[3];
- $suite = $regs[4];
- } else {
- spip_log("SQLite : Probleme de ALTER TABLE mal forme dans $query", 'sqlite');
- return false;
- }
- // 2
- // il faudrait une regexp pour eviter de spliter ADD PRIMARY KEY (colA, colB)
- // tout en cassant "ADD PRIMARY KEY (colA, colB), ADD INDEX (chose)"... en deux
- // ou revoir l'api de sql_alter en creant un
- // sql_alter_table($table,array($actions));
- $todo = explode(',', $suite);
- // on remet les morceaux dechires ensembles... que c'est laid !
- $todo2 = array(); $i=0;
- $ouverte = false;
- while ($do = array_shift($todo)) {
- $todo2[$i] = isset($todo2[$i]) ? $todo2[$i] . "," . $do : $do;
- $o=(false!==strpos($do,"("));
- $f=(false!==strpos($do,")"));
- if ($o AND !$f) $ouverte=true;
- elseif ($f) $ouverte=false;
- if (!$ouverte) $i++;
- }
-
- // 3
- $resultats = array();
- foreach ($todo2 as $do){
- $do = trim($do);
- if (!preg_match('/(DROP PRIMARY KEY|DROP INDEX|DROP COLUMN|DROP'
- .'|CHANGE COLUMN|CHANGE|MODIFY|RENAME TO|RENAME'
- .'|ADD PRIMARY KEY|ADD INDEX|ADD COLUMN|ADD'
- .')\s*([^\s]*)\s*(.*)?/', $do, $matches)){
- spip_log("SQLite : Probleme de ALTER TABLE, utilisation non reconnue dans : $do \n(requete d'origine : $query)", 'sqlite');
- return false;
- }
- $cle = strtoupper($matches[1]);
- $colonne_origine = $matches[2];
- $colonne_destination = '';
- $def = $matches[3];
- // eluder une eventuelle clause before|after|first inutilisable
- $defr = rtrim(preg_replace('/(BEFORE|AFTER|FIRST)(.*)$/is','', $def));
- // remplacer les definitions venant de mysql
- $defr = _sqlite_remplacements_definitions_table($defr);
- // reinjecter dans le do
- $do = str_replace($def,$defr,$do);
- $def = $defr;
-
- switch($cle){
- // suppression d'un index
- case 'DROP INDEX':
- $nom_index = $colonne_origine;
- spip_sqlite_drop_index($nom_index, $table, $serveur);
- break;
-
- // suppression d'une pk
- case 'DROP PRIMARY KEY':
- if (!_sqlite_modifier_table(
- $table,
- $colonne_origine,
- array('key'=>array('PRIMARY KEY'=>'')),
- $serveur)){
- return false;
- }
- break;
- // suppression d'une colonne
- case 'DROP COLUMN':
- case 'DROP':
- if (!_sqlite_modifier_table(
- $table,
- array($colonne_origine=>""),
- '',
- $serveur)){
- return false;
- }
- break;
-
- case 'CHANGE COLUMN':
- case 'CHANGE':
- // recuperer le nom de la future colonne
- $def = trim($def);
- $colonne_destination = substr($def, 0, strpos($def,' '));
- $def = substr($def, strlen($colonne_destination)+1);
-
- if (!_sqlite_modifier_table(
- $table,
- array($colonne_origine=>$colonne_destination),
- array('field'=>array($colonne_destination=>$def)),
- $serveur)){
- return false;
- }
- break;
-
- case 'MODIFY':
- if (!_sqlite_modifier_table(
- $table,
- $colonne_origine,
- array('field'=>array($colonne_origine=>$def)),
- $serveur)){
- return false;
- }
- break;
-
- // pas geres en sqlite2
- case 'RENAME':
- $do = "RENAME TO" . substr($do,6);
- case 'RENAME TO':
- if (_sqlite_is_version(3, '', $serveur)){
- $requete = new sqlite_traiter_requete("$debut $do", $serveur);
- if (!$requete->executer_requete()){
- spip_log("SQLite : Erreur ALTER TABLE / RENAME : $query", 'sqlite');
- return false;
- }
- // artillerie lourde pour sqlite2 !
- } else {
- $table_dest = trim(substr($do, 9));
- if (!_sqlite_modifier_table(array($table=>$table_dest), '', '', $serveur)){
- spip_log("SQLite : Erreur ALTER TABLE / RENAME : $query", 'sqlite');
- return false;
- }
- }
- break;
- // ajout d'une pk
- case 'ADD PRIMARY KEY':
- $pk = trim(substr($do,16));
- $pk = ($pk[0]=='(') ? substr($pk,1,-1) : $pk;
- if (!_sqlite_modifier_table(
- $table,
- $colonne_origine,
- array('key'=>array('PRIMARY KEY'=>$pk)),
- $serveur)){
- return false;
- }
- break;
- // ajout d'un index
- case 'ADD INDEX':
- // peut etre "(colonne)" ou "nom_index (colonnes)"
- // bug potentiel si qqn met "(colonne, colonne)"
- //
- // nom_index (colonnes)
- if ($def) {
- $colonnes = substr($def,1,-1);
- $nom_index = $colonne_origine;
- }
- else {
- // (colonne)
- if ($colonne_origine[0] == "(") {
- $colonnes = substr($colonne_origine,1,-1);
- if (false!==strpos(",",$colonnes)) {
- spip_log("SQLite : Erreur, impossible de creer un index sur plusieurs colonnes"
- ." sans qu'il ait de nom ($table, ($colonnes))", 'sqlite');
- break;
- } else {
- $nom_index = $colonnes;
- }
- }
- // nom_index
- else {
- $nom_index = $colonnes = $colonne_origine ;
- }
- }
- spip_sqlite_create_index($nom_index, $table, $colonnes, $serveur);
- break;
-
- // pas geres en sqlite2
- case 'ADD COLUMN':
- $do = "ADD".substr($do, 10);
- case 'ADD':
- default:
- if (_sqlite_is_version(3, '', $serveur)){
- $requete = new sqlite_traiter_requete("$debut $do", $serveur);
- if (!$requete->executer_requete()){
- spip_log("SQLite : Erreur ALTER TABLE / ADD : $query", 'sqlite');
- return false;
- }
- break;
- // artillerie lourde pour sqlite2 !
- } else {
- $def = trim(substr($do, 3));
- $colonne_ajoutee = substr($def, 0, strpos($def,' '));
- $def = substr($def, strlen($colonne_ajoutee)+1);
- if (!_sqlite_modifier_table($table, array($colonne_ajoutee), array('field'=>array($colonne_ajoutee=>$def)), $serveur)){
- spip_log("SQLite : Erreur ALTER TABLE / ADD : $query", 'sqlite');
- return false;
- }
- }
- break;
- }
- // tout est bon, ouf !
- spip_log("SQLite ($serveur) : Changements OK : $debut $do");
- }
- spip_log("SQLite ($serveur) : fin ALTER TABLE OK !");
- return true;
- }
- // Fonction de creation d'une table SQL nommee $nom
- // http://doc.spip.org/@spip_sqlite_create
- 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;
- $res = spip_sqlite_query($query, $serveur, $requeter);
-
- // SQLite ne cree pas les KEY sur les requetes CREATE TABLE
- // il faut donc les faire creer ensuite
- if (!$requeter) return $res;
- $ok = $res ? true : false;
- if ($ok) {
- foreach($cles as $k=>$v) {
- if (strpos($k, "KEY ") === 0) {
- $index = preg_replace("/KEY +/", '',$k);
- $ok &= $res = spip_sqlite_create_index($index, $nom, $v, $serveur);
- }
- }
- }
- return $ok ? true : false;
- }
- /**
- * Fonction pour creer une base de donnees SQLite
- *
- * @param string $nom le nom de la base (sans l'extension de fichier)
- * @param string $serveur le nom de la connexion
- * @param string $option options
- *
- * @return bool true si la base est creee.
- **/
- function spip_sqlite_create_base($nom, $serveur='', $option=true) {
- $f = _DIR_DB . $nom . '.sqlite';
- if (_sqlite_is_version(2, '', $serveur)) {
- $ok = sqlite_open($f, _SQLITE_CHMOD, $err);
- } else {
- $ok = new PDO("sqlite:$f");
- }
- if ($ok) {
- unset($ok);
- return true;
- }
- unset($ok);
- return false;
- }
- // Fonction de creation d'une vue SQL nommee $nom
- // http://doc.spip.org/@spip_sqlite_create_view
- function spip_sqlite_create_view($nom, $query_select, $serveur='',$requeter=true) {
- if (!$query_select) return false;
- // vue deja presente
- if (sql_showtable($nom, false, $serveur)) {
- spip_log("Echec creation d'une vue sql ($nom) car celle-ci existe deja (serveur:$serveur)");
- return false;
- }
-
- $query = "CREATE VIEW $nom AS ". $query_select;
- return spip_sqlite_query($query, $serveur, $requeter);
- }
- /**
- * Fonction de creation d'un INDEX
- *
- * @param string $nom : nom de l'index
- * @param string $table : table sql de l'index
- * @param string/array $champs : liste de champs sur lesquels s'applique l'index
- * @param string $serveur : nom de la connexion sql utilisee
- * @param bool $requeter : true pour executer la requete ou false pour retourner le texte de la requete
- *
- * @return bool ou requete
- */
- function spip_sqlite_create_index($nom, $table, $champs, $serveur='', $requeter=true) {
- if (!($nom OR $table OR $champs)) {
- spip_log("Champ manquant pour creer un index sqlite ($nom, $table, (".join(',',$champs)."))");
- return false;
- }
-
- // SQLite ne differentie pas noms des index en fonction des tables
- // il faut donc creer des noms uniques d'index pour une base sqlite
- $nom = $table.'_'.$nom;
- // enlever d'eventuelles parentheses deja presentes sur champs
- if (!is_array($champs)){
- if ($champs[0]=="(") $champs = substr($champs,1,-1);
- $champs = array($champs);
- }
- $query = "CREATE INDEX $nom ON $table (" . join(',',$champs) . ")";
- $res = spip_sqlite_query($query, $serveur, $requeter);
- if (!$requeter) return $res;
- if ($res)
- return true;
- else
- return false;
- }
- // en PDO/sqlite3, il faut calculer le count par une requete count(*)
- // pour les resultats de SELECT
- // cela est fait sans spip_sqlite_query()
- // http://doc.spip.org/@spip_sqlite_count
- function spip_sqlite_count($r, $serveur='',$requeter=true) {
- if (!$r) return 0;
-
- if (_sqlite_is_version(3, '', $serveur)){
- // select ou autre (insert, update,...) ?
- if (isset($r->spipSqliteRowCount)) {
- // Ce compte est faux s'il y a des limit dans la requete :(
- // il retourne le nombre d'enregistrements sans le limit
- return $r->spipSqliteRowCount;
- } else {
- return $r->rowCount();
- }
- } else {
- return sqlite_num_rows($r);
- }
- }
- // http://doc.spip.org/@spip_sqlite_countsel
- function spip_sqlite_countsel($from = array(), $where = array(), $groupby = '', $having = array(), $serveur='',$requeter=true) {
- $c = !$groupby ? '*' : ('DISTINCT ' . (is_string($groupby) ? $groupby : join(',', $groupby)));
- $r = spip_sqlite_select("COUNT($c)", $from, $where,'', '', '',$having, $serveur, $requeter);
- if ((is_resource($r) or is_object($r)) && $requeter) { // ressource : sqlite2, object : sqlite3
- if (_sqlite_is_version(3,'',$serveur)){
- list($n) = spip_sqlite_fetch($r, SPIP_SQLITE3_NUM, $serveur);
- } else {
- list($n) = spip_sqlite_fetch($r, SPIP_SQLITE2_NUM, $serveur);
- }
- spip_sqlite_free($r,$serveur);
- }
- return $n;
- }
- // http://doc.spip.org/@spip_sqlite_delete
- function spip_sqlite_delete($table, $where='', $serveur='',$requeter=true) {
- $res = spip_sqlite_query(
- _sqlite_calculer_expression('DELETE FROM', $table, ',')
- . _sqlite_calculer_expression('WHERE', $where),
- $serveur, $requeter);
- // renvoyer la requete inerte si demandee
- if (!$requeter) return $res;
-
- if ($res){
- $link = _sqlite_link($serveur);
- if (_sqlite_is_version(3, $link)) {
- return $res->rowCount();
- } else {
- return sqlite_changes($link);
- }
- }
- else
- return false;
- }
- // http://doc.spip.org/@spip_sqlite_drop_table
- function spip_sqlite_drop_table($table, $exist='', $serveur='',$requeter=true) {
- if ($exist) $exist =" IF EXISTS";
-
- /* simuler le IF EXISTS - version 2 */
- if ($exist && _sqlite_is_version(2, '', $serveur)){
- $a = spip_sqlite_showtable($table, $serveur);
- if (!$a) return true;
- $exist = '';
- }
- if (spip_sqlite_query("DROP TABLE$exist $table", $serveur, $requeter))
- return true;
- else
- return false;
- }
- // supprime une vue
- // http://doc.spip.org/@spip_sqlite_drop_view
- function spip_sqlite_drop_view($view, $exist='', $serveur='',$requeter=true) {
- if ($exist) $exist =" IF EXISTS";
-
- /* simuler le IF EXISTS - version 2 */
- if ($exist && _sqlite_is_version(2, '', $serveur)){
- $a = spip_sqlite_showtable($view, $serveur);
- if (!$a) return true;
- $exist = '';
- }
-
- return spip_sqlite_query("DROP VIEW$exist $view", $serveur, $requeter);
- }
- /**
- * Fonction de suppression d'un INDEX
- *
- * @param string $nom : nom de l'index
- * @param string $table : table sql de l'index
- * @param string $serveur : nom de la connexion sql utilisee
- * @param bool $requeter : true pour executer la requete ou false pour retourner le texte de la requete
- *
- * @return bool ou requete
- */
- function spip_sqlite_drop_index($nom, $table, $serveur='', $requeter=true) {
- if (!($nom OR $table)) {
- spip_log("Champ manquant pour supprimer un index sqlite ($nom, $table)");
- return false;
- }
-
- // SQLite ne differentie pas noms des index en fonction des tables
- // il faut donc creer des noms uniques d'index pour une base sqlite
- $index = $table.'_'.$nom;
- $exist =" IF EXISTS";
-
- /* simuler le IF EXISTS - version 2 */
- if (_sqlite_is_version(2, '', $serveur)){
- $a = spip_sqlite_showtable($table, $serveur);
- if (!isset($a['key']['KEY '.$nom])) return true;
- $exist = '';
- }
-
- $query = "DROP INDEX$exist $index";
- return spip_sqlite_query($query, $serveur, $requeter);
- }
- /**
- * Retourne la derniere erreur generee
- *
- * @param $serveur nom de la connexion
- * @return string erreur eventuelle
- **/
- // http://doc.spip.org/@spip_sqlite_error
- function spip_sqlite_error($query='', $serveur='') {
- $link = _sqlite_link($serveur);
-
- if (_sqlite_is_version(3, $link)) {
- $errs = $link->errorInfo();
- $s = '';
- foreach($errs as $n=>$e){
- $s .= "\n$n : $e";
- }
- } elseif ($link) {
- $s = sqlite_error_string(sqlite_last_error($link));
- } else {
- $s = ": aucune ressource sqlite (link)";
- }
- if ($s) spip_log("$s - $query", 'sqlite');
- return $s;
- }
- /**
- * Retourne le numero de la derniere erreur SQL
- * (sauf que SQLite semble ne connaitre que 0 ou 1)
- *
- * @param $serveur nom de la connexion
- * @return int 0 pas d'erreur / 1 une erreur
- **/
- // http://doc.spip.org/@spip_sqlite_errno
- function spip_sqlite_errno($serveur='') {
- $link = _sqlite_link($serveur);
-
- if (_sqlite_is_version(3, $link)){
- $t = $link->errorInfo();
- $s = $t[1];
- } elseif ($link) {
- $s = sqlite_last_error($link);
- } else {
- $s = ": aucune ressource sqlite (link)";
- }
-
- if ($s) spip_log("Erreur sqlite $s");
- return $s ? 1 : 0;
- }
- // http://doc.spip.org/@spip_sqlite_explain
- 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();
- return $r ? spip_sqlite_fetch($r, null, $serveur) : false; // hum ? etrange ca... a verifier
- }
- // http://doc.spip.org/@spip_sqlite_fetch
- function spip_sqlite_fetch($r, $t='', $serveur='',$requeter=true) {
- $link = _sqlite_link($serveur);
- if (!$t) {
- if (_sqlite_is_version(3, $link)) {
- $t = SPIP_SQLITE3_ASSOC;
- } else {
- $t = SPIP_SQLITE2_ASSOC;
- }
- }
- if (_sqlite_is_version(3, $link)){
- if ($r) $retour = $r->fetch($t);
- } elseif ($r) {
- $retour = sqlite_fetch_array($r, $t);
- }
-
- // les version 2 et 3 parfois renvoie des 'table.titre' au lieu de 'titre' tout court ! pff !
- // suppression de 'table.' pour toutes les cles (c'est un peu violent !)
- if ($retour){
- $new = array();
- foreach ($retour as $cle=>$val){
- if (($pos = strpos($cle, '.'))!==false){
- $cle = substr($cle,++$pos);
- }
- $new[$cle] = $val;
- }
- $retour = &$new;
- }
- return $retour;
- }
- function spip_sqlite_seek($r, $row_number, $serveur='',$requeter=true) {
- if ($r){
- $link = _sqlite_link($serveur);
- if (_sqlite_is_version(3, $link)){
- // encore un truc de bien fichu : PDO ne PEUT PAS faire de seek ou de rewind...
- // je me demande si pour sqlite 3 il ne faudrait pas mieux utiliser
- // les nouvelles fonctions sqlite3_xx (mais encore moins presentes...)
- return false;
- }
- else {
- return sqlite_seek($r, $row_number);
- }
- }
- }
- // http://doc.spip.org/@spip_sqlite_free
- function spip_sqlite_free(&$r, $serveur='',$requeter=true) {
- unset($r);
- return true;
- //return sqlite_free_result($r);
- }
- // http://doc.spip.org/@spip_sqlite_get_charset
- 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);
- }
- // http://doc.spip.org/@spip_sqlite_hex
- function spip_sqlite_hex($v){
- return hexdec($v);
- }
- // http://doc.spip.org/@spip_sqlite_in
- function spip_sqlite_in($val, $valeurs, $not='', $serveur='',$requeter=true) {
- $n = $i = 0;
- $in_sql ="";
- while ($n = strpos($valeurs, ',', $n+1)) {
- if ((++$i) >= 255) {
- $in_sql .= "($val $not IN (" .
- substr($valeurs, 0, $n) .
- "))\n" .
- ($not ? "AND\t" : "OR\t");
- $valeurs = substr($valeurs, $n+1);
- $i = $n = 0;
- }
- }
- $in_sql .= "($val $not IN ($valeurs))";
- return "($in_sql)";
- }
- // http://doc.spip.org/@spip_sqlite_insert
- function spip_sqlite_insert($table, $champs, $valeurs, $desc='', $serveur='',$requeter=true) {
- $connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
- $prefixe = $connexion['prefixe'];
- $sqlite = $connexion['link'];
- $db = $connexion['db'];
- if ($prefixe) $table = preg_replace('/^spip/', $prefixe, $table);
- if (isset($_GET['var_profile'])) {
- include_spip('public/tracer');
- $t = trace_query_start();
- } else $t = 0 ;
- $query="INSERT INTO $table ".($champs?"$champs VALUES $valeurs":"DEFAULT VALUES");
-
-
- if ($r = spip_sqlite_query($query, $serveur, $requeter)) {
- if (!$requeter) return $r;
-
- if (_sqlite_is_version(3, $sqlite)) $nb = $sqlite->lastInsertId();
- else $nb = sqlite_last_insert_rowid($sqlite);
- } else $nb = 0;
- $err = spip_sqlite_error($query, $serveur);
- return $t ? trace_query_end($query, $t, $nb, $err, $serveur) : $nb;
- }
- // http://doc.spip.org/@spip_sqlite_insertq
- 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();
- foreach ($couples as $champ => $val) {
- $couples[$champ]= _sqlite_calculer_cite($val, $fields[$champ]);
- }
- // recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
- $couples = _sqlite_ajouter_champs_timestamp($table, $couples, $desc, $serveur);
- // si aucun champ donne pour l'insertion, on en cherche un avec un DEFAULT
- // sinon sqlite3 ne veut pas inserer
- $cles = $valeurs = "";
- if (count($couples)) {
- $cles = "(".join(',',array_keys($couples)).")";
- $valeurs = "(".join(',', $couples).")";
- }
-
- return spip_sqlite_insert($table, $cles , $valeurs , $desc, $serveur, $requeter);
- }
- // http://doc.spip.org/@spip_sqlite_insertq_multi
- function spip_sqlite_insertq_multi($table, $tab_couples=array(), $desc=array(), $serveur='',$requeter=true) {
- foreach ($tab_couples as $couples) {
- $retour = spip_sqlite_insertq($table, $couples, $desc, $serveur, $requeter);
- }
- // renvoie le dernier id d'autoincrement ajoute
- return $retour;
- }
- // http://doc.spip.org/@spip_sqlite_listdbs
- function spip_sqlite_listdbs($serveur='',$requeter=true) {
- _sqlite_init();
-
- if (!is_dir($d = substr(_DIR_DB,0,-1))){
- return array();
- }
-
- include_spip('inc/flock');
- $bases = preg_files($d, $pattern = '(.*)\.sqlite$');
- $bds = array();
- foreach($bases as $b){
- // pas de bases commencant pas sqlite
- // (on s'en sert pour l'installation pour simuler la presence d'un serveur)
- // les bases sont de la forme _sqliteX_tmp_spip_install.sqlite
- if (strpos($b, '_sqlite')) continue;
- $bds[] = preg_replace(";.*/$pattern;iS",'$1', $b);
- }
- return $bds;
- }
- // http://doc.spip.org/@spip_sqlite_multi
- function spip_sqlite_multi ($objet, $lang) {
- $r = "PREG_REPLACE("
- . $objet
- . ",'<multi>.*[\[]"
- . $lang
- . "[\]]([^\[]*).*</multi>', '$1') AS multi";
- return $r;
- }
- /**
- * Optimise une table SQL
- * Note: Sqlite optimise TOUTE un fichier sinon rien.
- * On evite donc 2 traitements sur la meme base dans un hit.
- *
- * @param $table nom de la table a optimiser
- * @param $serveur nom de la connexion
- * @param $requeter effectuer la requete ? sinon retourner son code
- * @return bool|string true / false / requete
- **/
- // http://doc.spip.org/@spip_sqlite_optimize
- function spip_sqlite_optimize($table, $serveur='', $requeter=true) {
- static $do = false;
- if ($requeter and $do) {return true;}
- if ($requeter) { $do = true; }
- return spip_sqlite_query("VACUUM", $serveur, $requeter);
- }
- // avoir le meme comportement que _q()
- function spip_sqlite_quote($v, $type=''){
- if (is_array($v)) return join(",", array_map('spip_sqlite_quote', $v));
- if (is_int($v)) return strval($v);
- if (strncmp($v,'0x',2)==0 AND ctype_xdigit(substr($v,2))) return hexdec(substr($v,2));
- if ($type === 'int' AND !$v) return '0';
- if (function_exists('sqlite_escape_string')) {
- return "'" . sqlite_escape_string($v) . "'";
- }
-
- // trouver un link sqlite3 pour faire l'echappement
- foreach ($GLOBALS['connexions'] as $s) {
- if (_sqlite_is_version(3, $l = $s['link'])){
- return $l->quote($v);
- }
- }
- }
- /**
- * Tester si une date est proche de la valeur d'un champ
- *
- * @param string $champ le nom du champ a tester
- * @param int $interval valeur de l'interval : -1, 4, ...
- * @param string $unite utite utilisee (DAY, MONTH, YEAR, ...)
- * @return string expression SQL
- **/
- function spip_sqlite_date_proche($champ, $interval, $unite)
- {
- $op = $interval > 0 ? '>' : '<';
- return "($champ $op datetime('" . date("Y-m-d H:i:s") . "', '$interval $unite'))";
- }
- // http://doc.spip.org/@spip_sqlite_replace
- function spip_sqlite_replace($table, $couples, $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();
- foreach ($couples as $champ => $val) {
- $couples[$champ]= _sqlite_calculer_cite($val, $fields[$champ]);
- }
-
- // recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
- $couples = _sqlite_ajouter_champs_timestamp($table, $couples, $desc, $serveur);
-
- return spip_sqlite_query("REPLACE INTO $table (" . join(',',array_keys($couples)) . ') VALUES (' .join(',',$couples) . ')', $serveur);
- }
- // http://doc.spip.org/@spip_sqlite_replace_multi
- function spip_sqlite_replace_multi($table, $tab_couples, $desc=array(), $serveur='',$requeter=true) {
-
- // boucler pour trainter chaque requete independemment
- foreach ($tab_couples as $couples){
- $retour = spip_sqlite_replace($table, $couples, $desc, $serveur,$requeter);
- }
- // renvoie le dernier id
- return $retour;
- }
- // http://doc.spip.org/@spip_sqlite_select
- 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);
- // recomposer from
- $from = (!is_array($from) ? $from : _sqlite_calculer_select_as($from));
- $query =
- _sqlite_calculer_expression('SELECT', $select, ', ')
- . _sqlite_calculer_expression('FROM', $from, ', ')
- . _sqlite_calculer_expression('WHERE', $where)
- . _sqlite_calculer_expression('GROUP BY', $groupby, ',')
- . _sqlite_calculer_expression('HAVING', $having)
- . ($orderby ? ("\nORDER BY " . _sqlite_calculer_order($orderby)) :'')
- . ($limit ? "\nLIMIT $limit" : '');
- return spip_sqlite_query($query, $serveur, $requeter);
- }
- // http://doc.spip.org/@spip_sqlite_selectdb
- function spip_sqlite_selectdb($db, $serveur='',$requeter=true) {
- _sqlite_init();
- // interdire la creation d'une nouvelle base,
- // sauf si on est dans l'installation
- if (!is_file($f = _DIR_DB . $db . '.sqlite')
- && (!defined('_ECRIRE_INSTALL') || !_ECRIRE_INSTALL))
- return false;
- // se connecter a la base indiquee
- // avec les identifiants connus
- $index = $serveur ? $serveur : 0;
- if ($link = spip_connect_db('', '', '', '', '@selectdb@' . $db , $serveur, '', '')){
- if (($db==$link['db']) && $GLOBALS['connexions'][$index] = $link)
- return $db;
- } else {
- spip_log("Impossible de selectionner la base $db", 'sqlite');
- return false;
- }
- }
- // http://doc.spip.org/@spip_sqlite_set_charset
- 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 !
- }
- // http://doc.spip.org/@spip_sqlite_showbase
- function spip_sqlite_showbase($match, $serveur='',$requeter=true){
- // type est le type d'entrée : table / index / view
- // on ne retourne que les tables (?) et non les vues...
- # ESCAPE non supporte par les versions sqlite <3
- # return spip_sqlite_query("SELECT name FROM sqlite_master WHERE type='table' AND tbl_name LIKE "._q($match)." ESCAPE '\'", $serveur, $requeter);
- $match = preg_quote($match);
- $match = str_replace("\\\_","[[TIRETBAS]]",$match);
- $match = str_replace("\\\%","[[POURCENT]]",$match);
- $match = str_replace("_",".",$match);
- $match = str_replace("%",".*",$match);
- $match = str_replace("[[TIRETBAS]]","_",$match);
- $match = str_replace("[[POURCENT]]","%",$match);
- $match = "^$match$";
- return spip_sqlite_query("SELECT name FROM sqlite_master WHERE type='table' AND tbl_name REGEXP "._q($match), $serveur, $requeter);
- }
- // http://doc.spip.org/@spip_sqlite_showtable
- function spip_sqlite_showtable($nom_table, $serveur='',$requeter=true){
-
- $query =
- 'SELECT sql, type FROM'
- . ' (SELECT * FROM sqlite_master UNION ALL'
- . ' SELECT * FROM sqlite_temp_master)'
- . " WHERE tbl_name LIKE '$nom_table'"
- . " 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, $requeter);
- if (!$a) return "";
- if (!$requeter) return $a;
- if (!($a = spip_sqlite_fetch($a, null, $serveur))) return "";
- $vue = ($a['type'] == 'view'); // table | vue
- // c'est une table
- // il faut parser le create
- if (!$vue) {
- if (!preg_match("/^[^(),]*\((([^()]*(\([^()]*\))?[^()]*)*)\)[^()]*$/", array_shift($a), $r))
- return "";
- else {
- $dec = $r[1];
- if (preg_match("/^(.*?),([^,]*KEY.*)$/s", $dec, $r)) {
- $namedkeys = $r[2];
- $dec = $r[1];
- }
- else
- $namedkeys = "";
- $fields = array();
- foreach (explode(",",$dec) as $v) {
- preg_match("/^\s*([^\s]+)\s+(.*)/",$v,$r);
- // trim car 'Sqlite Manager' (plugin Firefox) utilise des guillemets
- // lorsqu'on modifie une table avec cet outil.
- // possible que d'autres fassent de meme.
- $fields[ trim(strtolower($r[1]),'"') ] = $r[2];
- }
- // key inclues dans la requete
- $keys = array();
- foreach(preg_split('/\)\s*,?/',$namedkeys) as $v) {
- if (preg_match("/^\s*([^(]*)\((.*)$/",$v,$r)) {
- $k = str_replace("`", '', trim($r[1]));
- $t = trim(strtolower(str_replace("`", '', $r[2])), '"');
- if ($k && !isset($keys[$k])) $keys[$k] = $t; else $keys[] = $t;
- }
- }
- // sinon ajouter les key index
- $query =
- 'SELECT name,sql FROM'
- . ' (SELECT * FROM sqlite_master UNION ALL'
- . ' SELECT * FROM sqlite_temp_master)'
- . " WHERE tbl_name LIKE '$nom_table'"
- . " AND type='index' AND name NOT LIKE 'sqlite_%'"
- . 'ORDER BY substr(type,2,1), name';
- $a = spip_sqlite_query($query, $serveur, $requeter);
- while ($r = spip_sqlite_fetch($a, null, $serveur)) {
- $key = str_replace($nom_table.'_','',$r['name']); // enlever le nom de la table ajoute a l'index
- $colonnes = preg_replace(',.*\((.*)\).*,','$1',$r['sql']);
- $keys['KEY '.$key] = $colonnes;
- }
- }
- // c'est une vue, on liste les champs disponibles simplement
- } else {
- if ($res = sql_fetsel('*',$nom_table,'','','','1','',$serveur)){ // limit 1
- $fields = array();
- foreach($res as $c=>$v) $fields[$c]='';
- $keys = array();
- } else {
- return "";
- }
- }
- return array('field' => $fields, 'key' => $keys);
-
- }
- // http://doc.spip.org/@spip_sqlite_update
- function spip_sqlite_update($table, $champs, $where='', $desc='', $serveur='',$requeter=true) {
- // recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
- $champs = _sqlite_ajouter_champs_timestamp($table, $champs, $desc, $serveur);
-
- $set = array();
- foreach ($champs as $champ => $val)
- $set[] = $champ . "=$val";
- if (!empty($set))
- return spip_sqlite_query(
- _sqlite_calculer_expression('UPDATE', $table, ',')
- . _sqlite_calculer_expression('SET', $set, ',')
- . _sqlite_calculer_expression('WHERE', $where),
- $serveur, $requeter);
- }
- // http://doc.spip.org/@spip_sqlite_updateq
- function spip_sqlite_updateq($table, $champs, $where='', $desc=array(), $serveur='',$requeter=true) {
- if (!$champs) return;
- if (!$desc) $desc = description_table($table);
- if (!$desc) die("$table insertion sans description");
- $fields = $desc['field'];
-
- // recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
- $champs = _sqlite_ajouter_champs_timestamp($table, $champs, $desc, $serveur);
-
- $set = array();
- foreach ($champs as $champ => $val) {
- $set[] = $champ . '=' . _sqlite_calculer_cite($val, $fields[$champ]);
- }
- return spip_sqlite_query(
- _sqlite_calculer_expression('UPDATE', $table, ',')
- . _sqlite_calculer_expression('SET', $set, ',')
- . _sqlite_calculer_expression('WHERE', $where),
- $serveur, $requeter);
- }
- /*
- *
- * Ensuite les fonctions non abstraites
- * crees pour l'occasion de sqlite
- *
- */
- // fonction pour la premiere connexion a un serveur SQLite
- // http://doc.spip.org/@_sqlite_init
- function _sqlite_init(){
- if (!defined('_DIR_DB')) define('_DIR_DB', _DIR_ETC . 'bases/');
- if (!defined('_SQLITE_CHMOD')) define('_SQLITE_CHMOD', _SPIP_CHMOD);
-
- if (!is_dir($d = _DIR_DB)){
- include_spip('inc/flock');
- sous_repertoire($d);
- }
- }
- // teste la version sqlite du link en cours
- // http://doc.spip.org/@_sqlite_is_version
- function _sqlite_is_version($version='', $link='', $serveur='',$requeter=true){
- if ($link==='') $link = _sqlite_link($serveur);
- if (!$link) return false;
- if (is_a($link, 'PDO')){
- $v = 3;
- } else {
- $v = 2;
- }
-
- if (!$version) return $v;
- return ($version == $v);
- }
- // retrouver un link (et definir les fonctions externes sqlite->php)
- // $recharger devient inutile (a supprimer ?)
- // http://doc.spip.org/@_sqlite_link
- function _sqlite_link($serveur = '', $recharger = false){
- static $charge = array();
- if ($recharger) $charge[$serveur] = false;
-
- $link = &$GLOBALS['connexions'][$serveur ? $serveur : 0]['link'];
- if ($link && !$charge[$serveur]){
- include_spip('req/sqlite_fonctions');
- _sqlite_init_functions($link);
- $charge[$serveur] = true;
- }
- return $link;
- }
- /* ordre alphabetique pour les autres */
- // renvoie les bons echappements (pas sur les fonctions now())
- // http://doc.spip.org/@_sqlite_calculer_cite
- function _sqlite_calculer_cite($v, $type) {
- if (sql_test_date($type) AND preg_match('/^\w+\(/', $v))
- return $v;
- if (sql_test_int($type)) {
- if (is_numeric($v))
- return $v;
- if (ctype_xdigit(substr($v,2)) AND strncmp($v,'0x',2)==0)
- return hexdec(substr($v,2));
- }
- //else return ("'" . spip_sqlite_quote($v) . "'");
- return (spip_sqlite_quote($v));
- }
- // renvoie grosso modo "$expression join($join, $v)"
- // http://doc.spip.org/@_sqlite_calculer_expression
- function _sqlite_calculer_expression($expression, $v, $join = 'AND'){
- if (empty($v))
- return '';
-
- $exp = "\n$expression ";
-
- if (!is_array($v)) {
- return $exp . $v;
- } else {
- if (strtoupper($join) === 'AND')
- return $exp . join("\n\t$join ", array_map('_sqlite_calculer_where', $v));
- else
- return $exp . join($join, $v);
- }
- }
- // pour conversion 0+x ? (pas la peine en sqlite)
- // http://doc.spip.org/@_sqlite_calculer_order
- function _sqlite_calculer_order($orderby) {
- return (is_array($orderby)) ? join(", ", $orderby) : $orderby;
- }
- // renvoie des 'nom AS alias'
- // http://doc.spip.org/@_sqlite_calculer_select_as
- function _sqlite_calculer_select_as($args){
- $res = '';
- foreach($args as $k => $v) {
- if (substr($k,-1)=='@') {
- // c'est une jointure qui se refere au from precedent
- // pas de virgule
- $res .= ' ' . $v ;
- }
- else {
- if (!is_numeric($k)) {
- $p = strpos($v, " ");
- if ($p)
- $v = substr($v,0,$p) . " AS '$k'" . substr($v,$p);
- else $v .= " AS '$k'";
- }
- $res .= ', ' . $v ;
- }
- }
- return substr($res,2) . $join;
- }
- // renvoie les bonnes parentheses pour des where imbriquees
- // http://doc.spip.org/@_sqlite_calculer_where
- function _sqlite_calculer_where($v){
- if (!is_array($v))
- return $v ;
- $op = array_shift($v);
- if (!($n=count($v)))
- return $op;
- else {
- $arg = _sqlite_calculer_where(array_shift($v));
- if ($n==1) {
- return "$op($arg)";
- } else {
- $arg2 = _sqlite_calculer_where(array_shift($v));
- if ($n==2) {
- return "($arg $op $arg2)";
- } else return "($arg $op ($arg2) : $v[0])";
- }
- }
- }
- /*
- * Charger les modules sqlite (si possible) (juste la version demandee),
- * ou, si aucune version, renvoie les versions sqlite dispo
- * sur ce serveur dans un array
- */
- // http://doc.spip.org/@_sqlite_charger_version
- function _sqlite_charger_version($version=''){
- $versions = array();
-
- // version 2
- if (!$version || $version == 2){
- if (charger_php_extension('sqlite')) {
- $versions[]=2;
- }
- }
-
- // version 3
- if (!$version || $version == 3){
- if (charger_php_extension('pdo') && charger_php_extension('pdo_sqlite')) {
- $versions[]=3;
- }
- }
- if ($version) return in_array($version, $versions);
- return $versions;
- }
- /**
- * Gestion des requetes ALTER non reconnues de SQLite :
- * ALTER TABLE table DROP column
- * ALTER TABLE table CHANGE [COLUMN] columnA columnB definition
- * ALTER TABLE table MODIFY column definition
- * ALTER TABLE table ADD|DROP PRIMARY KEY
- *
- * (MODIFY transforme en CHANGE columnA columnA) par spip_sqlite_alter()
- *
- * 1) creer une table B avec le nouveau format souhaite
- * 2) copier la table d'origine A vers B
- * 3) supprimer la table A
- * 4) renommer la table B en A
- * 5) remettre les index (qui sont supprimes avec la table A)
- *
- * @param string/array $table : nom_table, array(nom_table=>nom_futur)
- * @param string/array $col : nom_colonne, array(nom_colonne=>nom_futur)
- * @param array $opt : options comme les tables spip, qui sera merge a la table creee : array('field'=>array('nom'=>'syntaxe', ...), 'key'=>array('KEY nom'=>'colonne', ...))
- * @param string $serveur : nom de la connexion sql en cours
- *
- */
- // http://doc.spip.org/@_sqlite_modifier_table
- function _sqlite_modifier_table($table, $colonne, $opt=array(), $serveur=''){
- if (is_array($table)) {
- $table_origine = array_shift(array_keys($table));
- $table_destination = array_shift($table);
- } else {
- $table_origine = $table_destination = $table;
- }
- // ne prend actuellement qu'un changement
- // mais pourra etre adapte pour changer plus qu'une colonne a la fois
- if (is_array($colonne)) {
- $colonne_origine = array_shift(array_keys($colonne));
- $colonne_destination = array_shift($colonne);
- } else {
- $colonne_origine = $colonne_destination = $colonne;
- }
- if (!isset($opt['field'])) $opt['field'] = array();
- if (!isset($opt['key'])) $opt['key'] = array();
-
- // si les noms de tables sont differents, pas besoin de table temporaire
- // on prendra directement le nom de la future table
- $meme_table = ($table_origine == $table_destination);
-
- $def_origine = sql_showtable($table_origine, false, $serveur);
- $table_tmp = $table_origine . '_tmp';
- // 1) creer une table temporaire avec les modifications
- // - DROP : suppression de la colonne
- // - CHANGE : modification de la colonne
- // (foreach pour conserver l'ordre des champs)
-
- // field
- $fields = array();
- // pour le INSERT INTO plus loin
- // stocker la correspondance nouvelles->anciennes colonnes
- $fields_correspondances = array();
- foreach ($def_origine['field'] as $c=>$d){
- if ($colonne_origine && ($c == $colonne_origine)) {
- // si pas DROP
- if ($colonne_destination){
- $fields[$colonne_destination] = $opt['field'][$colonne_destination];
- $fields_correspondances[$colonne_destination] = $c;
- }
- } else {
- $fields[$c] = $d;
- $fields_correspondances[$c] = $c;
- }
- }
- // cas de ADD sqlite2 (ajout du champ en fin de table):
- if (!$colonne_origine && $colonne_destination){
- $fields[$colonne_destination] = $opt['field'][$colonne_destination];
- }
-
- // key...
- $keys = array();
- foreach ($def_origine['key'] as $c=>$d){
- $c = str_replace($colonne_origine,$colonne_destination,$c);
- $d = str_replace($colonne_origine,$colonne_destination,$d);
- // seulement si on ne supprime pas la colonne !
- if ($d)
- $keys[$c] = $d;
- }
- // autres keys, on merge
- $keys = array_merge($keys,$opt['key']);
- $queries = array();
- $queries[] = 'BEGIN TRANSACTION';
-
- // copier dans destination (si differente de origine), sinon tmp
- $table_copie = ($meme_table) ? $table_tmp : $table_destination;
-
- if ($q = _sqlite_requete_create(
- $table_copie,
- $fields,
- $keys,
- $autoinc=false,
- $temporary=false,
- $ifnotexists=true,
- $serveur)){
- $queries[] = $q;
- }
-
- // 2) y copier les champs qui vont bien
- $champs_dest = join(', ', array_keys($fields_correspondances));
- $champs_ori = join(', ', $fields_correspondances);
- $queries[] = "INSERT INTO $table_copie ($champs_dest) SELECT $champs_ori FROM $table_origine";
-
- // 3) supprimer la table d'origine
- $queries[] = "DROP TABLE $table_origine";
-
- // 4) renommer la table temporaire
- // avec le nom de la table destination
- // si necessaire
- if ($meme_table){
- if (_sqlite_is_version(3, '', $serveur)){
- $queries[] = "ALTER TABLE $table_copie RENAME TO $table_destination";
- } else {
- $queries[] = _sqlite_requete_create(
- $table_destination,
- $fields,
- $keys,
- $autoinc=false,
- $temporary=false,
- $ifnotexists=false, // la table existe puisqu'on est dans une transaction
- $serveur);
- $queries[] = "INSERT INTO $table_destination SELECT * FROM $table_copie";
- $queries[] = "DROP TABLE $table_copie";
- }
- }
-
- // 5) remettre les index !
- foreach ($keys as $k=>$v) {
- if ($k=='PRIMARY KEY'){}
- else {
- // enlever KEY
- $k = substr($k,4);
- $queries[] = "CREATE INDEX $table_destination"."_$k ON $table_destination ($v)";
- }
- }
-
- $queries[] = "COMMIT";
-
- // il faut les faire une par une car $query = join('; ', $queries).";"; ne fonctionne pas
- foreach ($queries as $q){
- $req = new sqlite_traiter_requete($q, $serveur);
- if (!$req->executer_requete()){
- spip_log("SQLite : ALTER TABLE table :"
- ." Erreur a l'execution de la requete : $q",'sqlite');
- return false;
- }
- }
- return true;
- }
- /*
- * Nom des fonctions
- */
- // http://doc.spip.org/@_sqlite_ref_fonctions
- function _sqlite_ref_fonctions(){
- $fonctions = array(
- 'alter' => 'spip_sqlite_alter',
- 'count' => 'spip_sqlite_count',
- 'countsel' => 'spip_sqlite_countsel',
- 'create' => 'spip_sqlite_create',
- 'create_base' => 'spip_sqlite_create_base',
- 'create_view' => 'spip_sqlite_create_view',
- 'date_proche' => 'spip_sqlite_date_proche',
- 'delete' => 'spip_sqlite_delete',
- 'drop_table' => 'spip_sqlite_drop_table',
- 'drop_view' => 'spip_sqlite_drop_view',
- 'errno' => 'spip_sqlite_errno',
- 'error' => 'spip_sqlite_error',
- 'explain' => 'spip_sqlite_explain',
- 'fetch' => 'spip_sqlite_fetch',
- 'seek' => 'spip_sqlite_seek',
- 'free' => 'spip_sqlite_free',
- 'hex' => 'spip_sqlite_hex',
- 'in' => 'spip_sqlite_in',
- 'insert' => 'spip_sqlite_insert',
- 'insertq' => 'spip_sqlite_insertq',
- 'insertq_multi' => 'spip_sqlite_insertq_multi',
- 'listdbs' => 'spip_sqlite_listdbs',
- 'multi' => 'spip_sqlite_multi',
- 'optimize' => 'spip_sqlite_optimize',
- 'query' => 'spip_sqlite_query',
- 'quote' => 'spip_sqlite_quote',
- 'replace' => 'spip_sqlite_replace',
- 'replace_multi' => 'spip_sqlite_replace_multi',
- 'select' => 'spip_sqlite_select',
- 'selectdb' => 'spip_sqlite_selectdb',
- 'set_charset' => 'spip_sqlite_set_charset',
- 'get_charset' => 'spip_sqlite_get_charset',
- 'showbase' => 'spip_sqlite_showbase',
- 'showtable' => 'spip_sqlite_showtable',
- 'update' => 'spip_sqlite_update',
- 'updateq' => 'spip_sqlite_updateq',
- );
-
- // association de chaque nom http d'un charset aux couples sqlite
- // SQLite supporte utf-8 et utf-16 uniquement.
- $charsets = array(
- 'utf-8'=>array('charset'=>'utf8','collation'=>'utf8_general_ci'),
- //'utf-16be'=>array('charset'=>'utf16be','collation'=>'UTF-16BE'),// aucune idee de quoi il faut remplir dans es champs la
- //'utf-16le'=>array('charset'=>'utf16le','collation'=>'UTF-16LE')
- );
-
- $fonctions['charsets'] = $charsets;
-
- return $fonctions;
- }
- // $query est une requete ou une liste de champs
- // http://doc.spip.org/@_sqlite_remplacements_definitions_table
- function _sqlite_remplacements_definitions_table($query,$autoinc=false){
- // quelques remplacements
- $num = "(\s*\([0-9]*\))?";
- $enum = "(\s*\([^\)]*\))?";
-
- $remplace = array(
- '/enum'.$enum.'/is' => 'VARCHAR',
- '/binary/is' => '',
- '/COLLATE \w+_bin/is' => '',
- '/auto_increment/is' => '',
- '/(timestamp .* )ON .*$/is' => '\\1',
- '/character set \w+/is' => '',
- '/((big|small|medium|tiny)?int(eger)?)'.$num.'\s*unsigned/is' => '\\1 UNSIGNED',
- '/(text\s+not\s+null)\s*$/is' => "\\1 DEFAULT ''",
- );
- // pour l'autoincrement, il faut des INTEGER NOT NULL PRIMARY KEY
- if ($autoinc)
- $remplace['/(big|small|medium|tiny)?int(eger)?'.$num.'/is'] = 'INTEGER';
- return preg_replace(array_keys($remplace), $remplace, $query);
- }
- /*
- * Creer la requete pour la creation d'une table
- * retourne la requete pour utilisation par sql_create() et sql_alter()
- */
- // http://doc.spip.org/@_sqlite_requete_create
- 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)
- // sans les renseigner (laisse le compilo recuperer la description)
- if (!is_array($champs) || !is_array($cles))
- return;
- // sqlite ne gere pas KEY tout court dans une requete CREATE TABLE
- // il faut passer par des create index
- // Il gere par contre primary key !
- // Soit la PK est definie dans les cles, soit dans un champs
- if (!$c = $cles[$pk = "PRIMARY KEY"]) {
- foreach($champs as $k => $v) {
- if (false !== stripos($v,$pk)) {
- $c = $k;
- // on n'en a plus besoin dans field, vu que defini dans key
- $champs[$k] = preg_replace("/$pk/is", '', $champs[$k]);
- break;
- }
- }
- }
- if ($c) $keys = "\n\t\t$pk ($c)";
-
- $champs = _sqlite_remplacements_definitions_table($champs, $autoinc);
- foreach($champs as $k => $v) {
- $query .= "$s\n\t\t$k $v";
- $s = ",";
- }
- $ifnotexists = "";
- if ($_ifnotexists) {
- // simuler le IF NOT EXISTS - version 2
- if (_sqlite_is_version(2, '', $serveur)){
- $a = spip_sqlite_showtable($nom, $serveur);
- if ($a) return false;
- }
- // sinon l'ajouter en version 3
- else {
- $ifnotexists = ' IF NOT EXISTS';
- }
- }
- $temporary = $temporary ? ' TEMPORARY':'';
- $q = "CREATE$temporary TABLE$ifnotexists $nom ($query" . ($keys ? ",$keys" : '') . ")\n";
- return $q;
- }
-
- /*
- * Retrouver les champs 'timestamp'
- * pour les ajouter aux 'insert' ou 'replace'
- * afin de simuler le fonctionnement de mysql
- *
- * stocke le resultat pour ne pas faire
- * de requetes showtable intempestives
- */
- // http://doc.spip.org/@_sqlite_ajouter_champs_timestamp
- function _sqlite_ajouter_champs_timestamp($table, $couples, $desc='', $serveur=''){
- static $tables = array();
-
- if (!isset($tables[$table])){
-
- if (!$desc){
- $f = charger_fonction('trouver_table', 'base');
- $desc = $f($table, $serveur);
- // si pas de description, on ne fait rien, ou on die() ?
- if (!$desc OR !$desc['field']) return $couples;
- }
-
- // recherche des champs avec simplement 'TIMESTAMP'
- // cependant, il faudra peut etre etendre
- // avec la gestion de DEFAULT et ON UPDATE
- // mais ceux-ci ne sont pas utilises dans le core
- $tables[$table] = array();
- foreach ($desc['field'] as $k=>$v){
- if (strpos(strtolower(ltrim($v)), 'timestamp')===0)
- $tables[$table][] = $k;
- }
- }
-
- // ajout des champs type 'timestamp' absents
- foreach ($tables[$table] as $maj){
- if (!array_key_exists($maj, $couples))
- $couples[$maj] = "datetime('now')";
- }
- return $couples;
- }
-
-
- /*
- * renvoyer la liste des versions sqlite disponibles
- * sur le serveur
- */
- // http://doc.spip.org/@spip_versions_sqlite
- function spip_versions_sqlite(){
- return _sqlite_charger_version();
- }
- /*
- * Classe pour partager les lancements de requete
- * - peut corriger la syntaxe des requetes pour la conformite a sqlite
- * - peut tracer les requetes
- *
- * Cette classe est presente essentiellement pour un preg_replace_callback
- * avec des parametres dans la fonction appelee que l'on souhaite incrementer
- * (fonction pour proteger les textes)
- *
- */
- class sqlite_traiter_requete{
- var $query = ''; // la requete
- var $queryCount = ''; // la requete pour compter
- var $serveur = ''; // le serveur
- var $link = ''; // le link (ressource) sqlite
- var $prefixe = ''; // le prefixe des tables
- var $db = ''; // le nom de la base
- var $tracer = false; // doit-on tracer les requetes (var_profile)
-
- var $sqlite_version = ''; // Version de sqlite (2 ou 3)
-
- // Pour les corrections a effectuer sur les requetes :
- var $textes = array(); // array(code=>'texte') trouvé
- var $codeEchappements = "%@##@%";
-
-
- // constructeur
- // http://doc.spip.org/@sqlite_traiter_requete
- function sqlite_traiter_requete($query, $serveur = ''){
- $this->query = $query;
- $this->serveur = strtolower($serveur);
-
- if (!($this->link = _sqlite_link($this->serveur)) && (!defined('_ECRIRE_INSTALL') || !_ECRIRE_INSTALL)){
- spip_log("Aucune connexion sqlite (link)");
- return false;
- }
- $this->sqlite_version =_sqlite_is_version('', $this->link);
-
- $…
Large files files are truncated, but you can click here to view the full file