Carnet Wiki

MultiBase Oracle

Nota SPIP-Contrib : une contrib qui remonte initialement a août 2005 (post SPIP 1.9 donc), depuis de nombreuses choses on changé sur le code, en particulier pour le portage multibase, voir par exemple : Portage de SPIP en PostGres

Une contrib donc probablement à remanier et à aboutir, mais la preuve est déjà faite que c’est possible ... contributeurs à vos claviers


Interroger une base Oracle grâce au MultiBase

Après plusieurs heures de recherche, de debug, j’ai enfin réussi à interroger une base Oracle.
voici donc le résultat des mes investigations :

Prérequis

Une connexion à Oracle qui fonctionne,

  1. vérifiez que vous avez bien un client oracle installé sur votre machine
  2. que le fichier TNSNAMES.ORA est bien configuré
  3. que l’extension php est installée
    dans le fichier php.ini supprimer le point virgule devant extension
    ;extension=php_oracle.dll

note : J’ai choisi de me connecter avec les commandes php Oracle ora, et non avec les commandes Oracle 8 oci, pas pour la simplicité du code, mais plutôt parce que je n’ai pas réussi a me connecter à ma base de tests avec les oci.

le fichier de connection et de traitement des boucles

j’ai créé un fichier inc_connect-ora.php3 avec pour début :

if (defined("_ECRIRE_INC_CONNECT_ORA")) return;
define("_ECRIRE_INC_CONNECT_ORA", "1");

global $connexion ;
$tns = monserveur';
$user = "login@$tns";
$pass = 'pass';
$connexion  = ora_logon($user, $pass);
if ($connexion  == FALSE) {
   echo "<h1>Erreur d'ouverture de ora_logon</h1>".ora_errorcode($connexion)." : ".ora_error($connexion) ;
}

et avec les fonctions suivantes :
function spip_ora_select, notez la gestion de $limit différente de mysql.

function spip_ora_select($select, $from, $where, $groupby, $orderby, $limit, $sousrequete, $cpt, $table, $id, $serveur)
{
    global $connexion ;
    // gestion de la variable $limit
    if ($limit <> ""){
       $limit_ora = explode(",", $limit,2);
       $start = $limit_ora['0'];
       $end = $limit_ora['1'];
    }
    
    $q = " FROM " . ereg_replace (" AS ", " ",join(",", $from)) // supprimer le AS de la commande MYSQL
    . ($where ? " WHERE " . join(" AND ", $where) : '')
    . ($groupby ? " GROUP BY $groupby " : '')
    . ($orderby ? " ORDER BY ". join(", ", $orderby) : '');
    if ($limit <> ""){
    $q .= " ) WHERE n BETWEEN $start AND $end"; // pour oracle
    }

    if (!$sousrequete)
      if ($limit <> ""){
        $q = "SELECT * FROM ( SELECT ROWNUM AS n, ". join(", ", $select) . $q;    // gestion de la variable $limit
      }else{
        $q = "SELECT ROWNUM AS n, ". join(", ", $select) . $q;
      }
    else
        $q = " SELECT S_" . join(", S_", $select)
        . " FROM (" . join(", ", $select)
        . ", COUNT(".$sousrequete.") compteur " . $q
        .") AS S_$table WHERE compteur=" . $cpt;

    // Erreur ? C'est du debug de squelette, ou une erreur du serveur
    if ($GLOBALS['var_mode'] == 'debug') {
        boucle_debug_resultat($id, '', $q);
    }
    $q = ereg_replace (strtolower($serveur)."_", "", $q); 
   // remplacer le debut des noms de tables pour coller avec les tables réelles du serveur 
   // permet de ne pas avoir un doublon avec les tables spip

$mycursor = ora_open ($connexion);
if ($mycursor == FALSE){
echo "<h1>Erreur d'ouverture de ora_open</h1>".ora_error($mycursor)."".ora_errorcode($mycursor)."<br />";
}
ora_parse ($mycursor, $q, 0);
if ($mycursor == FALSE){
echo "<h1>Erreur d'ouverture de ora_parse</h1>".ora_error($mycursor)."".ora_errorcode($mycursor)."<br />";
}
ora_exec ($mycursor);
if ($mycursor == FALSE){
echo "<h1>Erreur d'ouverture de ora_exec</h1>".ora_error($mycursor)."".ora_errorcode($mycursor)."<br />";
}

return $mycursor;
}

function spip_ora_fetch , ne pas oublier de remettre le résultat en minusucules !!!

function spip_ora_fetch($ora_cur)
{
  $res = array();
  ora_fetch_into($ora_cur, $res, ORA_FETCHINTO_ASSOC);
  $res = array_change_key_case($res, CASE_LOWER); // pour retourner le nom des tables en minuscules
  return $res;
}

function spip_ora_count

function spip_ora_count($res) {
    if ($res)
        return ora_numrows($res);
}

function spip_ora_free

function spip_ora_free($res) {
    global $connexion;
    if ($res)
       if ( ora_close($res) == FALSE) {
          echo "<h1>Erreur de fermeture de ora_close</h1>".ora_errorcode($connexion)." : ".ora_error($connexion) ;
       }
       return $res;
}

Définition des tables

dans le fichier monsquelette_fonctions.php3

$articles = array(
  "article" => "VARCHAR2(40) NOT NULL",
  "categorie" => "VARCHAR2(2)",
  "famille" => "VARCHAR2(3)",
  "sou_famille" => "VARCHAR2(5)"
);

$articles_key = array(
  "PRIMARY KEY"  => "article"
);

$table_ora['ora_articles'] =
    array('field' => &$articles, 'key' => &$articles_key);

$ephemeres_options = array(
   "soc" => "VARCHAR2(3)",
   "ephemere" => "VARCHAR2(40) NOT NULL",
   "opton" => "VARCHAR2(18)",
   "valeur_n" => "NUMBER",
);
 
$ephemeres_options_key = array(
   "PRIMARY KEY"  => "ephemere"
);
 
$table_ora['ora_ephemeres_options'] =
     array('field' => &$ephemeres_options, 'key' => &$ephemeres_options_key);

$GLOBALS['tables_des_serveurs_sql']['ORA']=&$table_ora;

note importante : il faut s’arranger pour que les tables définies dans le tableau $GLOBALS['tables_des_serveurs_sql'] n’aient pas le même noms que les tables de SPIP, pour cela j’ai préfixé toutes les tables de « ora_ » qui correspond au code de connexion du serveur ($table_ora['ora_articles'] =.

la boucle dans le squelette

<BOUCLE_ART(ORA:ORA_ARTICLES){categorie = "MP"}{famille="PRO"}{par article}{0,10}>
#ARTICLE #CATEGORIE #FAMILLE #SOU_FAMILLE<br />
</BOUCLE_ART>

Allez, je complique les choses et vais réaliser un lien entre les table ARTICLES et EPHEMERE_OPTIONS
articles.article = ephemeres_options.ephemere

<BOUCLE_ART2(ORA:ORA_ARTICLES){categorie = "MP"}{famille="PRO"}{par article}{0,10}>
#ARTICLE<br />
<ol>
<BOUCLE_EPH(ORA:ORA_EPHEMERES_OPTIONS){ephemere=#ARTICLE}{par opton}>
<li>#OPTON : #VALEUR_N</li>
</BOUCLE_EPH>
Pas d'option
<//B_EPH>
</ol>
</BOUCLE_ART2>

TODO :

  1. Fermer proprement la connexion à la base oracle
  2. tester, tester, et encore tester... merci pour votre aide...

Remerciements
merci beaucoup à :

  • mortimer
  • Déesse A.
  • Philippe Martin
    pour leur aide...

    N’hésitez pas a participer : ajouter vos commentaires, corrections, etc...

@+ Coyote

Coyote - Mise à jour :17 janvier 2008 à 09h32min