From ece300e2c76d5426f2c344967a817bdd94e3c393 Mon Sep 17 00:00:00 2001 From: "Committo,Ergo:sum" <esj@rezo.net> Date: Wed, 1 Aug 2007 18:15:13 +0000 Subject: [PATCH] (#209): Introduction d'un jeu de fonctions permettant d'installer SPIP sur un serveur Postgres. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ATTENTION: actuellement en PG seule l'installation fonctionne, il n'est pas possible de créer quoi que ce soit (article, auteur, etc). La version MySQL quant à elle reste opérationnelle bien entendu. exec/accueil : standardisation SQL inc/auth : standardisation SQL inc/agenda: standardisation SQL inc/boutons: standardisation SQL inc/meta: remplacement de REPLACE (!) base/db_pg: clone de db_mysql, à compléter. --- .gitattributes | 1 + ecrire/base/db_pg.php | 314 ++++++++++++++++++++++++++++++++++++++++ ecrire/exec/accueil.php | 8 +- ecrire/inc/agenda.php | 8 +- ecrire/inc/auth.php | 8 +- ecrire/inc/boutons.php | 2 +- ecrire/inc/meta.php | 12 +- 7 files changed, 337 insertions(+), 16 deletions(-) create mode 100644 ecrire/base/db_pg.php diff --git a/.gitattributes b/.gitattributes index 401fd8887e..b990601168 100644 --- a/.gitattributes +++ b/.gitattributes @@ -400,6 +400,7 @@ ecrire/balise/index.php -text ecrire/base/admin_repair.php -text ecrire/base/convert_sql_utf8.php -text ecrire/base/convert_utf8.php -text +ecrire/base/db_pg.php -text ecrire/base/delete_all.php -text ecrire/base/import_all.php -text ecrire/base/index.php -text diff --git a/ecrire/base/db_pg.php b/ecrire/base/db_pg.php new file mode 100644 index 0000000000..7622210758 --- /dev/null +++ b/ecrire/base/db_pg.php @@ -0,0 +1,314 @@ +<?php + +/***************************************************************************\ + * SPIP, Systeme de publication pour l'internet * + * * + * Copyright (c) 2001-2007 * + * 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; + +//constantes spip pour spip_fetch_array() +define('SPIP_BOTH', PGSQL_BOTH); +define('SPIP_ASSOC', PGSQL_ASSOC); +define('SPIP_NUM', PGSQL_NUM); + +// Se connecte et retourne le nom de la fonction a connexion persistante + +function base_db_pg_dist($addr, $port, $login, $pass, $db='') { + global $spip_pg_link; + + @list($host, $p) = split(';', $addr); + if ($p >0) $port = " port=$p" ; else $port = ''; + if ($db) $db= " dbname=$db"; + $spip_pg_link = pg_connect("host=$host$port$db user=$login password=$pass"); + if ($spip_pg_link) return 'spip_pg_query'; + + spip_log("pas d'acces vers $host:$port sur $db pour $login"); + return false; +} + +// Fonction de requete generale. +// Passe la main pour les idiosyncrasies MySQL a traduire + +function spip_pg_query($query) +{ + global $spip_pg_link, $table_prefix; + + if (strpos($query, 'REPLACE') ===0) + return spip_pg_replace($query); + // changer les noms des tables ($table_prefix) + if (preg_match('/\s(SET|VALUES|WHERE)\s/i', $query, $regs)) { + $suite = strstr($query, $regs[0]); + $query = substr($query, 0, -strlen($suite)); + } else $suite =''; + $query = preg_replace('/([,\s])spip_/', '\1'.$table_prefix.'_', $query) . $suite; + + $r = pg_query($spip_pg_link, $query); + + return $r; +} + + +function spip_pg_replace($query) { + spip_log("REPLACE a implementer en postgres"); +} + + +// Qu'une seule base pour le moment + +function spip_pg_selectdb($db) { + return pg_dbname(); +} + +// Qu'une seule base pour le moment + +function spip_pg_listdbs() { + return array(); +} + +function spip_pg_select($select, $from, $where, + $groupby, $orderby, $limit, + $sousrequete, $having, + $table, $id, $serveur){ + global $spip_pg_link; + if (eregi("^([0-9]+), *([0-9]+)$", $limit,$match)) + { + $offset = $match[1]; + $count = $match[2]; + } + + $q = (!is_array($select) ? $select : join(", ", $select)) . + (!$from ? '' : + ("\nFROM " . + (!is_array($from) ? $from : spip_pg_select_as($from)))) + . (!$where ? '' : ("\nWHERE " . (!is_array($where) ? $where : (join("\n\tAND ", array_map('calculer_pg_where', $where)))))) + . ($groupby ? "\nGROUP BY $groupby" : '') + . (!$having ? '' : "\nHAVING " . (!is_array($having) ? $having : (join("\n\tAND ", array_map('calculer_where', $having))))) + . ($orderby ? ("\nORDER BY " . join(", ", $orderby)) : '') + . (!$limit ? '' : (" LIMIT $count" . (!$offset ? '' : " OFFSET $offset"))); + $q = " SELECT ". $q; + + // Erreur ? C'est du debug, ou une erreur du serveur + // il faudrait mettre ici le déclenchement du message SQL + // actuellement dans erreur_requete_boucle + + if ($GLOBALS['var_mode'] == 'debug') { + boucle_debug_resultat($id, '', $q); + } + + if (!($res = spip_pg_query($q))) { + include_spip('inc/debug_sql.php'); + erreur_requete_boucle($q, $id, $table, + spip_pg_errno(), + spip_pg_error()); + } +# spip_log("selectabs $q" . pg_numrows($res)); + return $res; +} + + +function calculer_pg_where($v) +{ + if (!is_array($v)) + return $v ; + + $op = array_shift($v); + if (!($n=count($v))) + return $op; + else { + $arg = calculer_pg_where(array_shift($v)); + if ($n==1) { + return "$op($arg)"; + } else { + $arg2 = calculer_pg_where(array_shift($v)); + if ($n==2) { + return "($arg $op $arg2)"; + } else return "($arg $op ($arg2) : $v[0])"; + } + } +} + +function spip_pg_select_as($args) +{ + $argsas = ""; + foreach($args as $k => $v) { + $argsas .= ', ' . $v . ((is_numeric($k) OR $v==$k) ? '' : " AS $k"); + } + return substr($argsas,2); +} + +function spip_pg_fetch($res, $extra='') { + static $n = array(); + if ($extra) spip_log("fetch argument 2: $extra a revoir"); + if ($res) $res = pg_fetch_array($res, $n[$res]++, PGSQL_ASSOC); + return $res; +} + +// http://doc.spip.org/@spip_fetch_array +function spip_fetch_array($r, $extra='') { + if ($extra) spip_log("fetch argument 2: $extra a revoir"); + if ($r) return pg_fetch_array($r); +} + +function spip_pg_count($res, $serveur='') { + return !$res ? 0 : pg_numrows($res); +} + +function spip_pg_free($res, $serveur='') { + // rien à faire en postgres +} + +function spip_pg_insert($table, $champs, $valeurs, $ignore='') { + global $tables_principales; + global $spip_pg_link, $table_prefix; + include_spip('base/serial.php'); + if (isset($tables_principales[$table]['key']["PRIMARY KEY"])) + $ret = " RETURNING " + . $tables_principales[$table]['key']["PRIMARY KEY"]; + else $ret = ''; + if ($GLOBALS['table_prefix']) + $table = preg_replace('/^spip/', + $GLOBALS['table_prefix'], + $table); + $r = pg_query($spip_pg_link, "INSERT INTO $table $champs VALUES $valeurs $ret"); + if (!$r) return 0; + if (!$ret) return -1; + $r = pg_fetch_array($r, 0, PGSQL_NUM); + + return $r[0]; +} + +function spip_pg_update($table, $exp, $where='') { + global $spip_pg_link, $table_prefix; + if ($GLOBALS['table_prefix']) + $table = preg_replace('/^spip/', + $GLOBALS['table_prefix'], + $table); + pg_query($spip_pg_link, "UPDATE $table SET $exp" . ($where ? " WHERE $where" : '')); +} + + +function spip_pg_error() { + return pg_last_error(); +} + +function spip_pg_errno() { + return pg_last_error() ? 1 : 0; +} + +function spip_pg_showtable($nom_table) +{ + spip_log("spip_pg_showtable('$nom_table') a definir"); +} + +function calcul_pg_in($val, $valeurs, $not='') { +// +// IN (...) souvent limite a 255 elements, d'ou cette fonction assistante +// + if (!$valeurs) return '0=0'; + $s = split(',', $valeurs, 255); + if (count($s) < 255) { + return ("($val $not IN ($valeurs))"); + } else { + $valeurs = array_pop($s); + return ("($val $not IN (" . join(',',$s) . "))\n" . + ($not ? "AND\t" : "OR\t") . + calcul_pgsql_in($val, $valeurs, $not)); + } +} + +// Fonction de creation d'une table SQL nommee $nom +// a partir de 2 tableaux PHP : +// champs: champ => type +// cles: type-de-cle => champ(s) +// si $autoinc, c'est une auto-increment (i.e. serial) sur la Primary Key +// Le nom des caches doit etre inferieur a 64 caracteres +function spip_pg_create($nom, $champs, $cles, $autoinc=false, $temporary=false) { + global $spip_pg_link; + if ($GLOBALS['table_prefix']) + $nom = preg_replace('/^spip/', + $GLOBALS['table_prefix'], + $nom); + $query = $prim = $s = $p=''; + $keys = array(); + + // 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; + + foreach($cles as $k => $v) { + if (strpos($k, "KEY ") === 0) { + $n = str_replace('`','',$k); + $v = str_replace('`','"',$v); + $i = $nom . preg_replace("/KEY +/", '_',$n); + if ($k != $n) $i = "\"$i\""; + $keys[] = "CREATE INDEX $i ON $nom ($v);"; + } else $prim .= "$s\n\t\t" . str_replace('`','"',$k) ." ($v)"; + if ($k == "PRIMARY KEY") + $p = $v; + $s = ","; + } + $s = ''; + + $character_set = ""; + if (@$GLOBALS['meta']['charset_sql_base']) + $character_set .= " CHARACTER SET ".$GLOBALS['meta']['charset_sql_base']; + if (@$GLOBALS['meta']['charset_collation_sql_base']) + $character_set .= " COLLATE ".$GLOBALS['meta']['charset_collation_sql_base']; + + foreach($champs as $k => $v) { + $k = str_replace('`','"',$k); + if (preg_match(',([a-z]*\s*(\(\s*[0-9]*\s*\))?(\s*binary)?),i',$v,$defs)){ + if (preg_match(',(char|text),i',$defs[1]) AND !preg_match(',binary,i',$defs[1]) ){ + $v = $defs[1] . $character_set . ' ' . substr($v,strlen($defs[1])); + } + } + + $query .= "$s\n\t\t$k " + . (($autoinc && ($p == $k) && preg_match(',\b(big)?int\b,i', $v)) + ? " bigserial" + : mysql2pg_type($v) + ); + $s = ","; + } + $temporary = $temporary ? 'TEMPORARY':''; + + // controler si la table existe deja serait pas mal + + $q = "CREATE $temporary TABLE $nom ($query" . ($prim ? ",$prim" : '') . ")". + ($character_set?" DEFAULT $character_set":"") + ."\n"; + + pg_query($spip_pg_link, $q); + foreach($keys as $index) {pg_query($spip_pg_link, $index);} +} + +// Palanquee d'idiosyncrasies MySQL dans les creations de table +// A completer par les autres, mais essayer de reduire en amont. + +function mysql2pg_type($v) +{ + return preg_replace('/bigint\s*[(]\d+[)]/i', 'bigint', + preg_replace("/longtext/i", 'text', + str_replace("mediumtext", 'text', + preg_replace("/tinytext/i", 'text', + str_replace("longblob", 'text', + str_replace("datetime", 'timestamp', + str_replace("0000-00-00",'1970-01-01', + preg_replace("/unsigned/i", '', + preg_replace("/double/i", 'double precision', + preg_replace("/tinyint/i", 'int', + str_replace("VARCHAR(255) BINARY", 'bytea', + preg_replace("/ENUM *[(][^)]*[)]/", "varchar(255)", + $v + )))))))))))); +} + +?> diff --git a/ecrire/exec/accueil.php b/ecrire/exec/accueil.php index 4c351dbd5f..3928879a59 100644 --- a/ecrire/exec/accueil.php +++ b/ecrire/exec/accueil.php @@ -295,7 +295,7 @@ function etat_base_accueil() $res .= propre($GLOBALS['meta']["descriptif_site"]); - $q = spip_query("SELECT COUNT(*) AS cnt, statut FROM spip_articles GROUP BY statut HAVING cnt <>0"); + $q = spip_query("SELECT COUNT(*) AS cnt, statut FROM spip_articles GROUP BY statut HAVING COUNT(*)<>0"); $cpt = array(); $cpt2 = array(); @@ -320,7 +320,7 @@ function etat_base_accueil() $res .= "</ul>"; } - $q = spip_query("SELECT COUNT(*) AS cnt, statut FROM spip_breves GROUP BY statut HAVING cnt <>0"); + $q = spip_query("SELECT COUNT(*) AS cnt, statut FROM spip_breves GROUP BY statut HAVING COUNT(*)<>0"); $cpt = array(); $cpt2 = array(); @@ -345,7 +345,7 @@ function etat_base_accueil() $res .= "</ul>"; } - $q = spip_query("SELECT COUNT(*) AS cnt, statut FROM spip_forum WHERE statut IN ('publie', 'prop') GROUP BY statut HAVING cnt <>0"); + $q = spip_query("SELECT COUNT(*) AS cnt, statut FROM spip_forum WHERE statut IN ('publie', 'prop') GROUP BY statut HAVING COUNT(*)<>0"); $cpt = array(); $cpt2 = array(); @@ -387,7 +387,7 @@ function accueil_liste_participants() { global $spip_lang_left; - $q = spip_query("SELECT COUNT(*) AS cnt, statut FROM spip_auteurs GROUP BY statut HAVING cnt <>0 AND statut IN (". _q($GLOBALS['liste_des_statuts']) . ")"); + $q = spip_query("SELECT COUNT(*) AS cnt, statut FROM spip_auteurs GROUP BY statut HAVING COUNT(*)<>0 AND statut IN (". _q($GLOBALS['liste_des_statuts']) . ")"); $cpt = array(); while($row=spip_fetch_array($q)) $cpt[$row['statut']] = $row['cnt']; diff --git a/ecrire/inc/agenda.php b/ecrire/inc/agenda.php index cdc450917d..ced445bcfd 100644 --- a/ecrire/inc/agenda.php +++ b/ecrire/inc/agenda.php @@ -1435,7 +1435,7 @@ function sql_calendrier_interval_rv($avant, $apres) { global $connect_id_auteur; $evenements= array(); if (!$connect_id_auteur) return $evenements; - $result=spip_query("SELECT messages.id_message, messages.titre, messages.texte, messages.date_heure, messages.date_fin, messages.type FROM spip_messages AS messages, spip_auteurs_messages AS lien WHERE ((lien.id_auteur='$connect_id_auteur' AND lien.id_message=messages.id_message) OR messages.type='affich') AND messages.rv='oui' AND ((messages.date_fin >= $avant OR messages.date_heure >= $avant) AND messages.date_heure <= $apres) AND messages.statut='publie' GROUP BY messages.id_message ORDER BY messages.date_heure"); + $result=spip_query("SELECT messages.id_message, messages.titre, messages.texte, messages.date_heure, messages.date_fin, messages.type FROM spip_messages AS messages, spip_auteurs_messages AS lien WHERE ((lien.id_auteur=$connect_id_auteur AND lien.id_message=messages.id_message) OR messages.type='affich') AND messages.rv='oui' AND ((messages.date_fin >= $avant OR messages.date_heure >= $avant) AND messages.date_heure <= $apres) AND messages.statut='publie' GROUP BY messages.id_message ORDER BY messages.date_heure"); while($row=spip_fetch_array($result)){ $date_heure=$row["date_heure"]; $date_fin=$row["date_fin"]; @@ -1453,7 +1453,7 @@ function sql_calendrier_interval_rv($avant, $apres) { else { $cat = 'calendrier-couleur9'; $auteurs = array(); - $result_aut=spip_query("SELECT nom FROM spip_auteurs AS auteurs, spip_auteurs_messages AS lien WHERE (lien.id_message='$id_message' AND (auteurs.id_auteur!='$connect_id_auteur' AND lien.id_auteur=auteurs.id_auteur))"); + $result_aut=spip_query("SELECT nom FROM spip_auteurs AS auteurs, spip_auteurs_messages AS lien WHERE (lien.id_message=$id_message AND (auteurs.id_auteur!=$connect_id_auteur AND lien.id_auteur=auteurs.id_auteur))"); while($row_auteur=spip_fetch_array($result_aut)){ $auteurs[] = $row_auteur['nom']; } @@ -1546,7 +1546,7 @@ function sql_calendrier_taches_rv () { $r = array(); if (!$connect_id_auteur) return $r; - $result = spip_query("SELECT messages.texte AS DESCRIPTION, messages.id_message AS UID, messages.date_heure AS DTSTART, messages.date_fin AS DTEND, messages.titre AS SUMMARY, messages.type AS CATEGORY, messages.rv AS LOCATION FROM spip_messages AS messages, spip_auteurs_messages AS lien WHERE ((lien.id_auteur='$connect_id_auteur' AND lien.id_message=messages.id_message) OR messages.type='affich') AND messages.rv='oui' AND ( (messages.date_heure > DATE_SUB(NOW(), INTERVAL 1 DAY) AND messages.date_heure < DATE_ADD(NOW(), INTERVAL 1 MONTH)) OR (messages.date_heure < NOW() AND messages.date_fin > NOW() )) AND messages.statut='publie' GROUP BY messages.id_message ORDER BY messages.date_heure"); + $result = spip_query("SELECT messages.texte AS DESCRIPTION, messages.id_message AS UID, messages.date_heure AS DTSTART, messages.date_fin AS DTEND, messages.titre AS SUMMARY, messages.type AS CATEGORY, messages.rv AS LOCATION FROM spip_messages AS messages, spip_auteurs_messages AS lien WHERE ((lien.id_auteur=$connect_id_auteur AND lien.id_message=messages.id_message) OR messages.type='affich') AND messages.rv='oui' AND ( (messages.date_heure > DATE_SUB(NOW(), INTERVAL 1 DAY) AND messages.date_heure < DATE_ADD(NOW(), INTERVAL 1 MONTH)) OR (messages.date_heure < NOW() AND messages.date_fin > NOW() )) AND messages.statut='publie' GROUP BY messages.id_message ORDER BY messages.date_heure"); while ($row = spip_fetch_array($result,SPIP_ASSOC)) { $row['URL'] = tache_redirige($row); $r[] = $row; @@ -1566,7 +1566,7 @@ function sql_calendrier_agenda ($annee, $mois) { $annee = annee($date); // rendez-vous personnels dans le mois - $result_messages=spip_query("SELECT messages.titre AS SUMMARY, messages.texte AS DESCRIPTION, messages.id_message AS UID, messages.date_heure FROM spip_messages AS messages, spip_auteurs_messages AS lien WHERE ((lien.id_auteur='$connect_id_auteur' AND lien.id_message=messages.id_message) OR messages.type='affich') AND messages.rv='oui' AND messages.date_heure >='$annee-$mois-1' AND date_heure < DATE_ADD('$annee-$mois-1', INTERVAL 1 MONTH) AND messages.statut='publie'"); + $result_messages=spip_query("SELECT messages.titre AS SUMMARY, messages.texte AS DESCRIPTION, messages.id_message AS UID, messages.date_heure FROM spip_messages AS messages, spip_auteurs_messages AS lien WHERE ((lien.id_auteur=$connect_id_auteur AND lien.id_message=messages.id_message) OR messages.type='affich') AND messages.rv='oui' AND messages.date_heure >='$annee-$mois-1' AND date_heure < DATE_ADD('$annee-$mois-1', INTERVAL 1 MONTH) AND messages.statut='publie'"); while($row=spip_fetch_array($result_messages, SPIP_ASSOC)){ $rv[journum($row['date_heure'])] = $row; } diff --git a/ecrire/inc/auth.php b/ecrire/inc/auth.php index 7f2ea39f4c..e8874bed19 100644 --- a/ecrire/inc/auth.php +++ b/ecrire/inc/auth.php @@ -124,7 +124,7 @@ function inc_auth_dist() { // Trouver les autres infos dans la table auteurs. // le champ 'quand' est utilise par l'agenda - $result = @spip_query("SELECT *, UNIX_TIMESTAMP(en_ligne) AS quand FROM spip_auteurs WHERE $where AND statut!='5poubelle'"); + $result = spip_query("SELECT *, en_ligne AS quand FROM spip_auteurs WHERE $where AND statut!='5poubelle'"); if (!$row = spip_fetch_array($result)) { // il n'est PLUS connu. c'est SQL qui est desyncrho auth_areconnecter($connect_login); @@ -189,9 +189,11 @@ function inc_auth_dist() { // Pour les redacteurs, inc_version a fait l'initialisation minimale // Indiquer la connexion. A la minute pres ca suffit. - $connect_quand = $row['quand']; + if (!is_numeric($connect_quand = $row['quand'])) + $connect_quand = strtotime($connect_quand); + if ((time() - $connect_quand) >= 60) { - @spip_query("UPDATE spip_auteurs SET en_ligne=NOW() WHERE id_auteur='$connect_id_auteur'"); + spip_query("UPDATE spip_auteurs SET en_ligne=NOW() WHERE id_auteur=$connect_id_auteur"); } return ''; // i.e. pas de pb. diff --git a/ecrire/inc/boutons.php b/ecrire/inc/boutons.php index 63cb99bc08..bad5457a88 100644 --- a/ecrire/inc/boutons.php +++ b/ecrire/inc/boutons.php @@ -100,7 +100,7 @@ function definir_barre_boutons() { $sousmenu=array(); - $nombre_articles = spip_num_rows(spip_query("SELECT art.id_article FROM spip_articles AS art, spip_auteurs_articles AS lien WHERE lien.id_auteur = '".$GLOBALS['connect_id_auteur']."' AND art.id_article = lien.id_article LIMIT 1")); + $nombre_articles = spip_num_rows(spip_query("SELECT art.id_article FROM spip_articles AS art, spip_auteurs_articles AS lien WHERE lien.id_auteur =".$GLOBALS['connect_id_auteur']." AND art.id_article = lien.id_article LIMIT 1")); if ($nombre_articles > 0) { $sousmenu['articles_page']= new Bouton('article-24.gif', 'icone_tous_articles'); diff --git a/ecrire/inc/meta.php b/ecrire/inc/meta.php index 478c1884a1..9f1e55102e 100644 --- a/ecrire/inc/meta.php +++ b/ecrire/inc/meta.php @@ -33,11 +33,15 @@ function ecrire_meta($nom, $valeur, $importable = NULL) { if (strlen($nom)){ $GLOBALS['meta'][$nom] = $valeur; if (!_FILE_CONNECT && !@file_exists(_FILE_CONNECT_INS .'.php')) return; + $r = spip_query("SELECT impt FROM spip_meta WHERE nom=" . _q($nom)); + $r = spip_fetch_array($r); // conserver la valeur de impt si existante - if ($importable === NULL) - spip_query("REPLACE spip_meta (nom, valeur) VALUES ("._q($nom).", " . _q($valeur) . ")"); - else - spip_query("REPLACE spip_meta (nom, valeur, impt) VALUES ("._q($nom).", " . _q($valeur) . ","._q($importable).")"); + if ($r) { + $r = ($importable === NULL) ? '' + : ", impt=" . _q($importable); + spip_query("UPDATE spip_meta SET valeur=" . _q($valeur) ."$r WHERE nom=" . _q($nom) ); + } else + spip_query("INSERT INTO spip_meta (nom,valeur,impt) VALUES (" . _q($nom) . "," . _q($valeur) ."," . _q($importable) . ')'); } } -- GitLab