IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

4D For OCI et la lecture des métadonnées

Cette note technique a pour but de vous montrer l'utilisation de la commande OCIDescribeAnyText du plug-in 4D For OCI, pour lire des métadonnées. On entend par métadonnée la description des objets Oracle. Pour une table ou une vue, par exemple, on décrira l'ensemble des colonnes (champs), pour lire le nom et le type de chaque colonne. ♪

Article lu   fois.

L'auteur

Site personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction

Cette note technique a pour but de vous montrer l'utilisation de la commande OCIDescribeAnyText du plug-in 4D For OCI, pour lire des métadonnées. On entend par métadonnée la description des objets Oracle. Pour une table ou une vue, par exemple, on décrira l'ensemble des colonnes (champs), pour lire le nom et le type de chaque colonne.

II. Présentation de la commande

Voici l'interface de la commande :

OCIDescribeAnyText (svchp;errhp;NomObjet;LongObjet;NiveauInfo;TypeObjet;dschp) -> Entier long

Paramètre

Type

Description

svchp

Entier long

Handle contexte (service context handle). Doit être alloué avant l’appel de la commande.

errhp

Entier long

Handle erreur (error handle) Doit être alloué avant l’appel de la commande.

NomObjet

Texte

Libellé de l’objet à décrire. Peut être un nom de table, de vue…

LongObjet

Entier long

Représente la longueur de l’objet. Passez la valeur 1.

NiveauInfo

Entier long

Paramètre réservé pour de futures extensions. Passez la constante OCI_DEFAULT.

TypeObjet

Entier long

Type de l’objet à décrire. Peut recevoir les valeurs données dans la description de la commande(*).

dschp

Entier long

Handle descripteur (OCI_HTYPE_DESCRIBE). Doit être alloué avant l’appel de la commande.

Résultat

Entier long

Code retour de la commande égal à OCI_SUCCESS (0) en cas de succès, ou OCI_ERROR (-1) en cas d’erreur.

(*) Voici la liste des valeurs des types d'objets (paramètre TypeObjet) susceptibles d'être décrits. Les constantes correspondantes n'existent pas dans 4D For OCI. Il faudra donc passer les valeurs :

Constante

Valeur

Objet

OCI_PTYPE_UNK

0

Objet inconnu

OCI_PTYPE_TABLE

1

Table

OCI_PTYPE_VIEW

2

Vue

OCI_PTYPE_PROC

3

Procédure

OCI_PTYPE_FUNC

4

Fonction

OCI_PTYPE_PKG

5

Package

OCI_PTYPE_TYPE

6

Type

OCI_PTYPE_SYN

7

Synonyme

OCI_PTYPE_SEQ

8

Séquence

OCI_PTYPE_SCHEMA

17

Schéma

OCI_PTYPE_DATABASE

18

Base de données

La commande OCIDescribeAnyText permet donc de décrire tous ces objets.

Voici une brève présentation de ces objets ainsi que quelques informations, non exhaustives, que la commande peut lire.

Table

La table, dans le même sens que la table 4D, contient les données utilisateur. La table est constituée de colonnes, dans le même sens qu'un champ d'une table 4D.

Liste des informations (non exhaustive) que peut lire la commande :

Information

Type

Description

OCI_ATTR_NUM_COLS

Entier long

Nombre de colonnes (champs) de la table.

OCI_ATTR_LIST_COLUMNS

Entier long

Handle sur la liste des colonnes. Ce handle a lui-même un certain nombre d’informations qui lui sont rattachées (nombre d’éléments de la liste (OCI_ATTR_NUM_PARAM), etc.).

OCI_ATTR_PTYPE

Entier long

Code indiquant s’il s’agit d’une table (= 1) ou d’une vue (= 2).

Pour une colonne donnée (référencée par un handle), on peut lire les informations suivantes :

Information

Type

Description

OCI_ATTR_NAME

Texte

Nom de la colonne (champ).

OCI_ATTR_DATA_TYPE

Entier long

Code indiquant le type de donnée Oracle.

Vue

Une vue est une sorte de fenêtre, d'aperçu, sur une table. Une vue peut ainsi pointer sur plusieurs tables. Il n'y a pas de duplication de données, et la vue est simplement stockée comme un SELECT ayant un nom.

Liste des informations (non exhaustive) que peut lire la commande pour l'objet vue :

Note : Voir la Liste des informations pour l'objet Table (paragraphe précédent).

Procédure

Une procédure est un programme stocké, écrit en PL/SQL.

Liste des informations (non exhaustive) que peut lire la commande pour l'objet procédure :

Information

Type

Description

OCI_ATTR_LIST_ARGUMENTS

Entier long

Handle sur la liste des arguments de la procédure. Ce handle a lui-même un certain nombre d’informations qui lui sont rattachées (nombre d’éléments de la liste (OCI_ATTR_NUM_PARAMS), etc.).

Pour chaque paramètre de la procédure, on peut lire le même type d'informations que pour la colonne d'une table, à savoir le nom et le type du paramètre (voir l'objet 'Table').

Fonction

Une fonction est un programme stocké, écrit en PL/SQL, et qui retourne une valeur.

Liste des informations (non exhaustive) que peut lire la commande pour l'objet fonction :

Note : Voir la Liste des informations pour l'objet Procédure (paragraphe précédent).

Package

Un package est un ensemble qui encapsule des procédures et des fonctions, ainsi que certaines données. Le package est constitué de deux parties, une partie spécification qui est la partie déclarative des objets du package et une partie corps qui contient l'implémentation de ces objets.

Liste des informations (non exhaustive) que peut lire la commande pour l'objet package :

Information

Type

Description

OCI_ATTR_LIST_SUBPROGRAMS

Entier long

Handle sur la liste des sous-programmes (procédures et fonctions). Ce handle a lui-même un certain nombre d’informations qui lui sont rattachées (nombre d’éléments de la liste (OCI_ATTR_NUM_PARAMS), etc.).

OCI_ATTR_PTYPE

Entier long

Code indiquant s’il s’agit d’un package (= 5).

Pour un sous-programme donné (référencé par un handle), on peut lire les informations suivantes :

Information

Type

Description

OCI_ATTR_NAME

Texte

Nom du sous-programme.

OCI_ATTR_PTYPE

Entier long

Code indiquant s’il s’agit d’une procédure (= 3) ou d’une fonction (= 4).

Pour les informations sur les paramètres du sous-programme, consulter les explications données pour les objets 'Procédure' ou 'Fonction'.

Type

En plus des types prédéfinis (VARCHAR, NUMBER…), l'utilisateur peut définir ses propres types constitués à partir de ces types de base ou de types existants plus complexes, comme les collections de type Tableau (VARRAY) ou Table (NESTED TABLE).

Liste des informations (non exhaustive) que peut lire la commande pour l'objet type :

Information

Type

Description

OCI_ATTR_VERSION

Texte

Chaîne contenant la version du type, telle que définie par le créateur du type.

OCI_ATTR_NUM_TYPE_ATTRS

Entier long

Nombre d’attributs que contient le type.

OCI_ATTR_PTYPE

Entier long

Code indiquant s’il s’agit d’un type (= 6).

Point important : Pour décrire l'objet Type, il est impératif d'initialiser l'environnement OCI en mode objet.

L'appel suivant doit donc être effectué : $status:=OCIEnvCreate (envhp;OCI_OBJECT)

Synonyme

Dans le même sens qu'a ce mot dans une langue donnée, il définit un nom alternatif donné à un objet (table, vue…)

Liste des informations (non exhaustive) que peut lire la commande pour l'objet synonyme :

Information

Type

Description

OCI_ATTR_SCHEMA_NAME

Texte

Chaîne contenant le nom du schéma du nom original dont dérive le synonyme.

OCI_ATTR_NAME

Texte

Chaîne contenant le nom original dont dérive le synonyme.

OCI_ATTR_PTYPE

Entier long

Code indiquant s’il s’agit d’un synonyme (= 7).

Séquence

Une séquence est une suite de nombres entiers. Cette suite est régie par certains paramètres (valeur de départ, valeur d'incrémentation…). La séquence sert à la génération de clés uniques pour la colonne d'une table, ou simplement de compteur.

Liste des informations (non exhaustive) que peut lire la commande pour l'objet séquence :

Information

Type

Description

OCI_ATTR_MIN

Entier long

Valeur minimum du compteur.

OCI_ATTR_MAX

Entier long

Valeur maximum du compteur.

OCI_ATTR_INCR

Entier long

Valeur d’incrémentation du compteur.

OCI_ATTR_PTYPE

Entier long

Code indiquant s’il s’agit d’une séquence (= 8).

Schéma

C'est l'ensemble des données liées à un utilisateur, par exemple « Scott ».

Liste des informations (exhaustive) que peut lire la commande pour l'objet schéma :

Information

Type

Description

OCI_ATTR_LIST_OBJECTS

Entier long

Handle sur la liste des objets appartenant au schéma.

OCI_ATTR_PTYPE

Entier long

Code indiquant s’il s’agit d’un schéma (= 17).

Remarque  : on peut voir ici qu'à partir d'un objet schéma, on peut atteindre l'ensemble des objets de ce schéma.

Base de données

C'est l'ensemble de tous les schémas.

Liste des informations (non exhaustive) que peut lire la commande pour l'objet base de données :

Information

Type

Description

OCI_ATTR_VERSION

Texte

Version de la base de données.

OCI_ATTR_LIST_SCHEMAS

Entier long

Handle sur la liste des schémas de la base de données.

OCI_ATTR_PTYPE

Entier long

Code indiquant s’il s’agit d’une base de données (= 18).

Remarque 1  : on peut voir ici qu'à partir d'un objet base de données, on peut atteindre l'ensemble des schémas et ainsi l'ensemble de tous les objets de tous les schémas (voir la remarque donnée pour l'objet schéma).

Remarque 2  : d'après la remarque 1, cette structure arborescente (base de données -> schémas -> objets) permet d'écrire un programme général de lecture des métadonnées de tous les objets d'une base de données Oracle.

III. Mise en œuvre de la commande OCIDescribeAnyText

Après avoir présenté la commande et les objets qu'elle peut décrire, nous allons vous montrer, au travers de quelques descriptions d'objets, l'utilisation de cette commande dans 4D For OCI. Nous allons détailler le code à utiliser pour décrire une table, une vue, dont le code pour ces deux objets est similaire, ainsi que pour les packages, les procédures et les fonctions. Pour le reste des objets, leur description n'est pas donnée dans cette note, dans la mesure où nous pensons qu'elle peut se faire en s'appuyant sur le modèle proposé ici.

Méthode de sélection des objets à décrire

La méthode générique ci-après nous permet de sélectionner les objets que nous allons décrire.

La méthode effectue un simple appel à la requête SQL SELECT sur la table adéquate contenant la liste des objets.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
`OCI_SELECT_OBJECT

C_POINTEUR($1) `pointeur pour le define pour récupérer les valeurs de la colonne
C_TEXTE(${2}) `colonne et table de la requête, et éventuellement clause WHERE
C_TEXTE($requete_sql) `libellé de la requête SQL
C_ENTIER LONG($status) `code retour des commandes OCI
C_ENTIER LONG($errhp) `handle-erreur
C_ENTIER LONG($stmthp) `handle- requête
C_ENTIER LONG($define) `handle-define

C_TEXTE(vt_temp) `variable pour récupérer temporairement les données résultat
C_ENTIER LONG(null_ind1;null_ind2;null_ind3) `variables indicateurs

`construction de la requête SELECT
$requete_sql:="SELECT "+$2+" FROM "+$3
`éventuellement une clause WHERE
Si (Nombre de parametres=4)
   $requete_sql:=$requete_sql+" "+$4
Fin de si

`allocation du handle-requête
$status:=OCIHandleAlloc(envhp;$stmthp;OCI_HTYPE_STMT)

`allocation du handle-erreur
$status:=OCIHandleAlloc(envhp;$errhp;OCI_HTYPE_ERROR)

`affectation du libellé de la requête SQL au handle-requête
$status:=OCIStmtPrepare($stmthp;$errhp;$requete_sql;OCI_DEFAULT)

`variables-indicateurs pour la commande OCIDefineByPos().
`Les informations retournées par ces variables sont inutiles dans notre exemple.
`ces variables servent notamment à savoir s'il y a des valeurs NULL, tronquées.
null_ind1:=0
null_ind2:=0
null_ind3:=0

`réalisation du Define avec l'unique colonne de la requête
$status:=OCIDefineByPos($stmthp;$define;$errhp;1;->vt_temp;SQLT_STR;->null_ind1;->null_ind2;->null_ind3;OCI_DEFAULT)

`exécution de la requête SQL
$status:=OCIStmtExecute (svchp;$stmthp;$errhp;1;0;0;0;OCI_DEFAULT )

`traitement du résultat : on affecte le résultat au tableau passé en premier paramètre
Tant que($status#OCI_NO_DATA )
   AJOUTER A TABLEAU($1->;vt_temp)
   $status:=OCIStmtFetch($stmthp;$errhp;1)
Fin tant que

`libération du handle-requête
$status:=OCIHandleFree($stmthp)
`libération du handle-erreur

$status:=OCIHandleFree($errhp)

Sélection des objets à décrire

Pour sélectionner les objets que nous allons décrire, nous allons donc appliquer la méthode OCI_SELECT_OBJECT présentée dans le point précédent. La liste des objets est remontée dans le tableau passé en premier paramètre. On fournit à la méthode les noms de la colonne et de la table contenant la liste de ces objets.

Sélection des tables

 
Sélectionnez
1.
2.
3.
`SELECT table_name FROM user_tables

OCI_SELECT_OBJECT (->tt_Tables;"table_name";"user_tables")

Sélection des vues

 
Sélectionnez
1.
2.
3.
`SELECT view_name FROM user_views

OCI_SELECT_OBJECT (->tt_Views;"view_name";"user_views")

Sélection des procédures

 
Sélectionnez
1.
2.
3.
`SELECT DISTINCT name FROM user_source WHERE Type='PROCEDURE'

OCI_SELECT_OBJECT (->tt_Procedures;"distinct name";"user_source";"WHERE Type='PROCEDURE'")

Remarquez l'utilisation de la clause WHERE pour ne remonter que les objets de type procédure, et éviter notamment la remontée des noms de fonctions. Nous avons aussi utilisé l'option DISTINCT du SELECT pour ne remonter que des noms uniques.

Sélection des fonctions

 
Sélectionnez
1.
2.
3.
`SELECT distinct name FROM user_source WHERE Type='FUNCTION'

OCI_SELECT_OBJECT (->tt_Functions;"distinct name";"user_source";"WHERE Type='FUNCTION'")

Remarquez l'utilisation de la clause WHERE pour ne remonter que les objets de type fonction, et éviter notamment la remontée des noms de procédures. Nous avons aussi utilisé l'option DISTINCT du SELECT pour ne remonter que des noms uniques.

Sélection des packages

 
Sélectionnez
1.
2.
3.
`SELECT object_name FROM user_objects WHERE object_type='PACKAGE'

OCI_SELECT_OBJECT (->tt_Packages;"object_name";"user_objects";"WHERE object_type='PACKAGE'")

Méthodes de description des objets

Méthode de description d'une table ou d'une vue

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
`OCI_DESCRIBE_TABLE_OR_VIEW

C_TEXTE($1) `nom de la table ou de la vue à décrire
C_ENTIER LONG($2) `1 (OCI_PTYPE_TABLE) : description de la table
`2 (OCI_PTYPE_VIEW) : description de la vue:
C_POINTEUR(${3}) `pointeurs sur les tableaux des noms et types de colonnes
C_ENTIER LONG($status) `code retour de la fonction OCI
C_ENTIER LONG($dschp) `handle descripteur
C_ENTIER LONG($collsth) `handle pour la liste des colonnes
C_ENTIER LONG($colh) `handle colonne
C_ENTIER LONG($paramh) `handle paramètre
C_ENTIER LONG($index;$nb_columns) `nombre de colonnes
C_TEXTE($name_column) `nom d'une colonne
C_ENTIER LONG($dtype_column) `code du type de donnée d'une colonne
C_TEXTE($lib_dtype_column) `libellé du type de donnée de la colonne

`allocation du handle descripteur
$status:=OCIHandleAlloc (envhp;$dschp;OCI_HTYPE_DESCRIBE)
`1 : OCI_PTYPE_TABLE (pour une table), 2 : OCI_PTYPE_VIEW (pour une vue)
$status:=OCIDescribeAnyText (svchp;errhp;$1;1;OCI_DEFAULT;$2;$dschp)
`récupération du `handle paramètre $paramh, attribut du handle descripteur $dschp
$status:=OCIAttrGetVal ($dschp;$paramh;OCI_ATTR_PARAM;errhp)
`récupération du nombre de colonnes de la table
$status:=OCIAttrGetVal ($paramh;$nb_columns;OCI_ATTR_NUM_COLS;errhp)
`récupération du handle liste des colonnes $collsth
$status:=OCIAttrGetVal ($paramh;$collsth;OCI_ATTR_LIST_COLUMNS;errhp)

Si ($nb_columns>0)
   `boucle sur les colonnes
   Boucle ($index;1;$nb_columns)
      `récupération du handle colonne $colh
      $status:=OCIParamGet ($collsth;errhp;$colh;$index)
      `nom de la colonne
      $status:=OCIAttrGetText($colh;$name_column;OCI_ATTR_NAME;errhp)
      `type de la colonne
      $status:=OCIAttrGetVal($colh;$dtype_column;OCI_ATTR_DATA_TYPE;errhp)  
      `récupération du libellé du type de donnée de la colonne avec le code du type
      $lib_dtype_column:=OCI_Lib_External_Type($dtype_column)  
      `inscrire le nom de la colonne
      AJOUTER A TABLEAU($3->;$name_column)
      `inscrire le libellé du type de la colonne
      AJOUTER A TABLEAU($4->;$lib_dtype_column)  
   Fin de boucle
Fin de si

Commentaires sur la méthode

La méthode commence par allouer un handle-descripteur en utilisant la commande OCIHandleAlloc à laquelle on spécifie le type de handle souhaité (OCI_HTYPE_DESCRIBE). On associe ensuite le libellé de l'objet à décrire (texte) ainsi que son type (entier) à ce handle-descripteur.


Ensuite, on récupère le handle-paramètre (commande OCIAttrGetVal) qui pointe sur la description de l'objet, description qui se présente de manière arborescente.

Il est à noter que toute la description de l'objet est transférée sur le client à l'appel de la commande OCIDescribeAnyText. Les appels ultérieurs des autres commandes pour récupérer les informations sur la description de l'objet ne consomment donc pas de ressources réseau.

À partir du handle-paramètre, on peut lire le nombre de colonnes de la table (ou de la vue), mais aussi récupérer le handle-liste qui contient les informations sur la liste des colonnes.

À partir de ce handle-liste, on récupérera un handle-colonne, via la commande OCIParamGet, qui pointera donc sur une colonne particulière. On pourra alors lire toutes les informations sur une colonne, comme son libellé ou son type.


Le type d'une colonne est retourné sous forme de code entier, que nous traduisons en texte avec la méthode projet OCI_Lib_External_Type. Cette méthode projet effectue une conversion du code entier reçu en texte représentant le type de données Oracle correspondant. Voici le tableau (non exhaustif) correspondant à cette transformation :

Code entier reçu

Constante OCI correspondante

Libellé Oracle du type

1

SQLT_CHR

VARCHAR2

2

SQLT_NUM

NUMBER

3

SQLT_INT

8 or16 or 32 bits signed INTEGER

4

SQLT_FLT

FLOAT

5

SQLT_STR

Null-terminated STRING

6

SQLT_VNU

VARNUM

8

SQLT_LNG

LONG

9

SQLT_VCS

VARCHAR

11

SQLT_RID

ROWID

12

SQLT_DAT

DATE

15

SQLT_VBI

VARRAW

23

SQLT_BIN

RAW

24

SQLT_LBI

LONG RAW

68

SQLT_UIN

UNSIGNED INT

94

SQLT_LVC

LONG VARCHAR

Méthode de description d'un sous-programme (procédure ou fonction)

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
`OCI_DESCRIBE_SUBPROGRAM

C_TEXTE($1) `nom du sous-programme (procédure ou fonction) à décrire
C_ENTIER LONG($2) `Description d'une procédure ou d'une fonction ?
`3 : OCI_PTYPE_PROC, 4 : OCI_PTYPE_FUNC
C_POINTEUR(${3})  `listes des paramètres de la procédure et leurs types
C_ENTIER LONG($status)  `code retour de la fonction OCI
C_ENTIER LONG($count;$startloop;$endloop)
C_ENTIER LONG($dschp)  `handle descripteur
C_ENTIER LONG($paramh)  `handle paramètre
C_ENTIER LONG($args_listh)  `handle sur la liste des paramètres du sous-programme
C_ENTIER LONG($argh)  `handle sur un paramètre du sous-programme
C_ENTIER LONG($args_num)  `nombre de paramètres du sous-programme
C_ENTIER LONG($arg_type)  `type du paramètre du sous-programme
C_TEXTE($arg_name)  `nom du paramètre du sous-programme

$status:=OCIHandleAlloc (envhp;$dschp;OCI_HTYPE_DESCRIBE)
$status:=OCIDescribeAnyText (svchp;errhp;$1;1;OCI_DEFAULT;$2;$dschp)
`$2=3 :OCI_PTYPE_PROC, $2=4 : OCI_PTYPE_FUNC
$status:=OCIAttrGetVal ($dschp;$paramh;OCI_ATTR_PARAM;errhp)
$status:=OCIAttrGetVal ($paramh;$args_listh;OCI_ATTR_LIST_ARGUMENTS;errhp)
$status:=OCIAttrGetVal ($args_listh;$args_num;OCI_ATTR_NUM_PARAMS;errhp)
Au cas ou
   : ($2=4) `Fonction
      $startloop:=0
      $endloop:=$args_num-1
   : ($2=3) `Procédure
      $startloop:=1
      $endloop:=$args_num
   Sinon
      $endloop:=0
      $endloop:=0
Fin de cas
Boucle ($count;$startloop;$endloop)
   $status:=OCIParamGet ($args_listh;errhp;$argh;$count)
   `récupération du nom du paramètre
   $status:=OCIAttrGetText ($argh;$arg_name;OCI_ATTR_NAME;errhp)
   ` récupération du type du paramètre
   status:=OCIAttrGetVal ($argh;$arg_type;OCI_ATTR_DATA_TYPE;errhp)
   AJOUTER A TABLEAU($3->;$arg_name)
   AJOUTER A TABLEAU($4->;OCI_Lib_External_Type($arg_type))
Fin de boucle

Commentaires sur la méthode

De la même manière que pour la méthode de description d'un objet table ou vue, il faut allouer le handle-descripteur auquel on associe l'objet à décrire. On récupère le handle-paramètre (commande OCIAttrGetVal). À partir du handle-paramètre, on récupère le handle sur la liste des arguments de la fonction ou de la procédure (commande OCIAttrGetVal).

Du handle sur la liste des arguments, on lit le nombre des arguments (paramètres) du sous-programme (commande OCIAttrGetVal).

La position des paramètres d'une fonction commence à zéro, qui est le paramètre retourné par la fonction. La position des paramètres pour une procédure commence à 1. Ceci explique l'utilisation de la boucle paramétrée sur la liste des arguments, boucle qui peut commencer à 0 ou à 1 selon le type de sous-programme (fonction ou procédure). Ensuite, avec le handle d'un paramètre donné sur le sous-programme, on lit le nom du paramètre (OCIAttrGetText) ainsi que son type (OCIAttrGetVal). Le type de l'argument est un entier que nous traduisons en utilisant la méthode OCI_Lib_External_Type, méthode détaillée dans la description d'un objet de type table ou vue.

Méthode de description d'un package

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
`OCI_DESCRIBE_PACKAGE

C_TEXTE($1) `nom du package à décrire
C_POINTEUR($2) `liste des handles (références) pour chacun des sous-programmes. Utile
`pour retrouver la liste des paramètres de chaque sous-programme
C_POINTEUR($3) `liste des types des sous-programmes (procédures & fonctions) à
`récupérer. 'P' pour Procédure et 'F' pour Fonction
C_POINTEUR($4) `liste de sous-programmes (procédures & fonctions) à récupérer
C_ENTIER LONG($status) `code retour de la fonction OCI
C_ENTIER LONG($count;$endloop)
C_ENTIER LONG($dschp) `handle descripteur
C_ENTIER LONG($paramh)  `handle paramètre
C_ENTIER LONG($progs_listh) `handle sur la liste des sous-programmes
C_ENTIER LONG($progh) `handle sur un sous-programme
C_ENTIER LONG($progs_num) `nombre de sous-programmes
C_TEXTE($prog_name) `nom du sous-programme
C_ENTIER LONG($prog_type) `type du sous-programme, type = 3 alors procédure,
`type = 4 alors fonction

$status:=OCIHandleAlloc(envhp;$dschp;OCI_HTYPE_DESCRIBE)
`5: OCI_PTYPE_PKG
$status:=OCIDescribeAnyText(svchp;errhp;$1;1;OCI_DEFAULT;5;$dschp)
$status:=OCIAttrGetVal($dschp;$paramh;OCI_ATTR_PARAM;errhp)
$status:=OCIAttrGetVal($paramh;$progs_listh;OCI_ATTR_LIST_SUBPROGRAMS; errhp)
`récupération du handle sur la liste des sous-programmes
$status:=OCIAttrGetVal($progs_listh;$progs_num;OCI_ATTR_NUM_PARAMS;errhp) `récupération du nombre de sous-programmes
$endloop:=$progs_num-1
Boucle ($count;0;$endloop)
   `récupération du handle sur un sous-programme
   $status:=OCIParamGet($progs_listh;errhp;$progh;$count)
   `récupération du nom du sous-programme
   $status:=OCIAttrGetText($progh;$prog_name;OCI_ATTR_NAME;errhp)
   `récupération du type du sous-programme
   $status:=OCIAttrGetVal($progh;$prog_type;OCI_ATTR_PTYPE;errhp)
   AJOUTER A TABLEAU($2->;$progh) `stocker le handle sur le sous-programme
   Au cas ou
      :($prog_type=3) `le sous-programme est une Procédure. Mettre 'P'
         AJOUTER A TABLEAU($3->;"P")
      :($prog_type=4) `le sous-programme est une Fonction. Mettre 'F'
         AJOUTER A TABLEAU($3->;"F")
   Fin de cas
   AJOUTER A TABLEAU($4->;$prog_name) `stocker le nom du sous-programme
Fin de boucle

Commentaires sur la méthode

La méthode commence par allouer le handle-descripteur, auquel on associe le nom du package à décrire.

Du handle-descripteur, on récupère le handle-paramètre $paramh (commande OCIAttrGetVal).

Du handle paramètre $paramh, on récupère le handle sur la liste des sous-programmes $progs_lish (commande OCIAttrGetVal).

Du handle $progs_listh, on lit le nombre de sous-programmes ($progs_num) sur lequel on effectue une boucle (commande OCIAttrGetVal).

Dans la boucle sur les sous-programmes, on récupère le handle sur un sous-programme donné (commande OCIParamGet), en fournissant le handle sur la liste des sous-programmes et la position du sous-programme dans la liste. Il est important de noter que la position d'un sous-programme dans la liste des sous-programmes, commence à zéro, comme pour la liste des arguments d'une fonction.

À partir du handle sur un sous-programme donné, on lit le nom et le type (fonction ou procédure) du sous-programme. Ces informations, ainsi que le handle sur le sous-programme sont stockés dans des tableaux pour être utilisés en dehors de cette méthode, afin de récupérer la liste des arguments de chaque sous-programme, ainsi que des informations qui s'y rattachent (nom et type de l'argument).

IV. Utilisation de la base de test

La base de test, construite en 4D 2004, contient l'implémentation des différentes méthodes présentées ici. Elle est très simple à utiliser.

En mode structure, vous devez adapter la méthode OCI_CONNEXION.

Dans cette méthode, modifier les paramètres de connexion (nom d'utilisateur, mot de passe et chaîne de connexion) en utilisant les vôtres.

Ensuite en mode Menus Créés, il vous suffit de lancer le menu /Fichier/Démo… et suivre le dialogue. Le dialogue est un onglet qui décrit sur chacune des pages un objet qui a été présenté ici.

Voici un extrait de cette base pour l'objet package par exemple :

Pictures 0542x0380

Sur chaque page, on peut utiliser les boutons de connexion et de déconnexion à la base de données Oracle.

Pour obtenir la liste des objets pour un objet donné, il suffit de cliquer sur le bouton portant le nom de l'objet. Par exemple, sur l'illustration on a la liste des packages.

En cliquant sur un objet de la liste, on obtient les informations abordées pour cet objet dans cet article. Sur l'illustration, on obtient la liste des sous-programmes ainsi que leur type, et pour chaque sous-programme, la liste de ses paramètres et leurs types.

V. Conclusion

Cette note vous a montré l'utilisation de la commande 4D For OCI OCIDescribeAnyText, pour lire les informations descriptives des objets d'une base de données Oracle (Table, vue…), descriptions appelées aussi métadonnées. En partant de là, il vous est donc possible d'écrire une application cliente OCI générale qui décrirait l'ensemble de tous les objets d'une base Oracle, ce qui offre une visibilité plus grande sur la base de données.

VI. Base exemple

Téléchargez la base exemple :

base exemple

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

Ce document est issu de https://www.developpez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.