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

Noreddine MARGOUM

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. ♪

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

- Auteur : Noreddine MARGOUM

- Parution : 24 décembre 2019

- Licence : 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.

Sommaire

- I. Introduction

- II. Présentation de la commande

- Table

- Vue

- Procédure

- Fonction

- Package

- Type

- Synonyme

- Séquence

- Schéma

- Base de données

- III. Mise en œuvre de la commande OCIDescribeAnyText

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

- Sélection des objets à décrire

- Sélection des tables

- Sélection des vues

- Sélection des procédures

- Sélection des fonctions

- Sélection des packages

- Méthodes de description des objets

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

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

- Méthode de description d'un package

- IV. Utilisation de la base de test

- V. Conclusion

- VI. Base exemple

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.

1. `OCI_SELECT_OBJECT

3. C_POINTEUR($1) `pointeur pour le define pour récupérer les valeurs de la colonne

4. C_TEXTE(${2}) `colonne et table de la requête, et éventuellement clause WHERE

5. C_TEXTE($requete_sql) `libellé de la requête SQL

6. C_ENTIER LONG($status) `code retour des commandes OCI

7. C_ENTIER LONG($errhp) `handle-erreur

8. C_ENTIER LONG($stmthp) `handle- requête

9. C_ENTIER LONG($define) `handle-define

11. C_TEXTE(vt_temp) `variable pour récupérer temporairement les données résultat

12. C_ENTIER LONG(null_ind1;null_ind2;null_ind3) `variables indicateurs

14. `construction de la requête SELECT

15. $requete_sql:="SELECT "+$2+" FROM "+$3

16. `éventuellement une clause WHERE

17. Si (Nombre de parametres=4)

18. $requete_sql:=$requete_sql+" "+$4

19. Fin de si

21. `allocation du handle-requête

22. $status:=OCIHandleAlloc(envhp;$stmthp;OCI_HTYPE_STMT)

24. `allocation du handle-erreur

25. $status:=OCIHandleAlloc(envhp;$errhp;OCI_HTYPE_ERROR)

27. `affectation du libellé de la requête SQL au handle-requête

28. $status:=OCIStmtPrepare($stmthp;$errhp;$requete_sql;OCI_DEFAULT)

30. `variables-indicateurs pour la commande OCIDefineByPos().

31. `Les informations retournées par ces variables sont inutiles dans notre exemple.

32. `ces variables servent notamment à savoir s'il y a des valeurs NULL, tronquées.

33. null_ind1:=0

34. null_ind2:=0

35. null_ind3:=0

37. `réalisation du Define avec l'unique colonne de la requête

38. $status:=OCIDefineByPos($stmthp;$define;$errhp;1;->vt_temp;SQLT_STR;->null_ind1;->null_ind2;->null_ind3;OCI_DEFAULT)

40. `exécution de la requête SQL

41. $status:=OCIStmtExecute (svchp;$stmthp;$errhp;1;0;0;0;OCI_DEFAULT )

43. `traitement du résultat : on affecte le résultat au tableau passé en premier paramètre

44. Tant que($status#OCI_NO_DATA )

45. AJOUTER A TABLEAU($1->;vt_temp)

46. $status:=OCIStmtFetch($stmthp;$errhp;1)

47. Fin tant que

49. `libération du handle-requête

50. $status:=OCIHandleFree($stmthp)

51. `libération du handle-erreur

53. $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

1. `SELECT table_name FROM user_tables

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

Sélection des vues

1. `SELECT view_name FROM user_views

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

Sélection des procédures

1. `SELECT DISTINCT name FROM user_source WHERE Type='PROCEDURE'

3. 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

1. `SELECT distinct name FROM user_source WHERE Type='FUNCTION'

3. 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

1. `SELECT object_name FROM user_objects WHERE object_type='PACKAGE'

3. 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

1. `OCI_DESCRIBE_TABLE_OR_VIEW

3. C_TEXTE($1) `nom de la table ou de la vue à décrire

4. C_ENTIER LONG($2) `1 (OCI_PTYPE_TABLE) : description de la table

5. `2 (OCI_PTYPE_VIEW) : description de la vue:

6. C_POINTEUR(${3}) `pointeurs sur les tableaux des noms et types de colonnes

7. C_ENTIER LONG($status) `code retour de la fonction OCI

8. C_ENTIER LONG($dschp) `handle descripteur

9. C_ENTIER LONG($collsth) `handle pour la liste des colonnes

10. C_ENTIER LONG($colh) `handle colonne

11. C_ENTIER LONG($paramh) `handle paramètre

12. C_ENTIER LONG($index;$nb_columns) `nombre de colonnes

13. C_TEXTE($name_column) `nom d'une colonne

14. C_ENTIER LONG($dtype_column) `code du type de donnée d'une colonne

15. C_TEXTE($lib_dtype_column) `libellé du type de donnée de la colonne

17. `allocation du handle descripteur

18. $status:=OCIHandleAlloc (envhp;$dschp;OCI_HTYPE_DESCRIBE)

19. `1 : OCI_PTYPE_TABLE (pour une table), 2 : OCI_PTYPE_VIEW (pour une vue)

20. $status:=OCIDescribeAnyText (svchp;errhp;$1;1;OCI_DEFAULT;$2;$dschp)

21. `récupération du `handle paramètre $paramh, attribut du handle descripteur $dschp

22. $status:=OCIAttrGetVal ($dschp;$paramh;OCI_ATTR_PARAM;errhp)

23. `récupération du nombre de colonnes de la table

24. $status:=OCIAttrGetVal ($paramh;$nb_columns;OCI_ATTR_NUM_COLS;errhp)

25. `récupération du handle liste des colonnes $collsth

26. $status:=OCIAttrGetVal ($paramh;$collsth;OCI_ATTR_LIST_COLUMNS;errhp)

28. Si ($nb_columns>0)

29. `boucle sur les colonnes

30. Boucle ($index;1;$nb_columns)

31. `récupération du handle colonne $colh

32. $status:=OCIParamGet ($collsth;errhp;$colh;$index)

33. `nom de la colonne

34. $status:=OCIAttrGetText($colh;$name_column;OCI_ATTR_NAME;errhp)

35. `type de la colonne

36. $status:=OCIAttrGetVal($colh;$dtype_column;OCI_ATTR_DATA_TYPE;errhp)

37. `récupération du libellé du type de donnée de la colonne avec le code du type

38. $lib_dtype_column:=OCI_Lib_External_Type($dtype_column)

39. `inscrire le nom de la colonne

40. AJOUTER A TABLEAU($3->;$name_column)

41. `inscrire le libellé du type de la colonne

42. AJOUTER A TABLEAU($4->;$lib_dtype_column)

43. Fin de boucle

44. 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)

1. `OCI_DESCRIBE_SUBPROGRAM

3. C_TEXTE($1) `nom du sous-programme (procédure ou fonction) à décrire

4. C_ENTIER LONG($2) `Description d'une procédure ou d'une fonction ?

5. `3 : OCI_PTYPE_PROC, 4 : OCI_PTYPE_FUNC

6. C_POINTEUR(${3})  `listes des paramètres de la procédure et leurs types

7. C_ENTIER LONG($status)  `code retour de la fonction OCI

8. C_ENTIER LONG($count;$startloop;$endloop)

9. C_ENTIER LONG($dschp)  `handle descripteur

10. C_ENTIER LONG($paramh)  `handle paramètre

11. C_ENTIER LONG($args_listh)  `handle sur la liste des paramètres du sous-programme

12. C_ENTIER LONG($argh)  `handle sur un paramètre du sous-programme

13. C_ENTIER LONG($args_num)  `nombre de paramètres du sous-programme

14. C_ENTIER LONG($arg_type)  `type du paramètre du sous-programme

15. C_TEXTE($arg_name)  `nom du paramètre du sous-programme

17. $status:=OCIHandleAlloc (envhp;$dschp;OCI_HTYPE_DESCRIBE)

18. $status:=OCIDescribeAnyText (svchp;errhp;$1;1;OCI_DEFAULT;$2;$dschp)

19. `$2=3 :OCI_PTYPE_PROC, $2=4 : OCI_PTYPE_FUNC

20. $status:=OCIAttrGetVal ($dschp;$paramh;OCI_ATTR_PARAM;errhp)

21. $status:=OCIAttrGetVal ($paramh;$args_listh;OCI_ATTR_LIST_ARGUMENTS;errhp)

22. $status:=OCIAttrGetVal ($args_listh;$args_num;OCI_ATTR_NUM_PARAMS;errhp)

23. Au cas ou

24. : ($2=4) `Fonction

25. $startloop:=0

26. $endloop:=$args_num-1

27. : ($2=3) `Procédure

28. $startloop:=1

29. $endloop:=$args_num

30. Sinon

31. $endloop:=0

32. $endloop:=0

33. Fin de cas

34. Boucle ($count;$startloop;$endloop)

35. $status:=OCIParamGet ($args_listh;errhp;$argh;$count)

36. `récupération du nom du paramètre

37. $status:=OCIAttrGetText ($argh;$arg_name;OCI_ATTR_NAME;errhp)

38. ` récupération du type du paramètre

39. status:=OCIAttrGetVal ($argh;$arg_type;OCI_ATTR_DATA_TYPE;errhp)

40. AJOUTER A TABLEAU($3->;$arg_name)

41. AJOUTER A TABLEAU($4->;OCI_Lib_External_Type($arg_type))

42. 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

1. `OCI_DESCRIBE_PACKAGE

3. C_TEXTE($1) `nom du package à décrire

4. C_POINTEUR($2) `liste des handles (références) pour chacun des sous-programmes. Utile

5. `pour retrouver la liste des paramètres de chaque sous-programme

6. C_POINTEUR($3) `liste des types des sous-programmes (procédures & fonctions) à

7. `récupérer. 'P' pour Procédure et 'F' pour Fonction

8. C_POINTEUR($4) `liste de sous-programmes (procédures & fonctions) à récupérer

9. C_ENTIER LONG($status) `code retour de la fonction OCI

10. C_ENTIER LONG($count;$endloop)

11. C_ENTIER LONG($dschp) `handle descripteur

12. C_ENTIER LONG($paramh)  `handle paramètre

13. C_ENTIER LONG($progs_listh) `handle sur la liste des sous-programmes

14. C_ENTIER LONG($progh) `handle sur un sous-programme

15. C_ENTIER LONG($progs_num) `nombre de sous-programmes

16. C_TEXTE($prog_name) `nom du sous-programme

17. C_ENTIER LONG($prog_type) `type du sous-programme, type = 3 alors procédure,

18. `type = 4 alors fonction

20. $status:=OCIHandleAlloc(envhp;$dschp;OCI_HTYPE_DESCRIBE)

21. `5: OCI_PTYPE_PKG

22. $status:=OCIDescribeAnyText(svchp;errhp;$1;1;OCI_DEFAULT;5;$dschp)

23. $status:=OCIAttrGetVal($dschp;$paramh;OCI_ATTR_PARAM;errhp)

24. $status:=OCIAttrGetVal($paramh;$progs_listh;OCI_ATTR_LIST_SUBPROGRAMS; errhp)

25. `récupération du handle sur la liste des sous-programmes

26. $status:=OCIAttrGetVal($progs_listh;$progs_num;OCI_ATTR_NUM_PARAMS;errhp) `récupération du nombre de sous-programmes

27. $endloop:=$progs_num-1

28. Boucle ($count;0;$endloop)

29. `récupération du handle sur un sous-programme

30. $status:=OCIParamGet($progs_listh;errhp;$progh;$count)

31. `récupération du nom du sous-programme

32. $status:=OCIAttrGetText($progh;$prog_name;OCI_ATTR_NAME;errhp)

33. `récupération du type du sous-programme

34. $status:=OCIAttrGetVal($progh;$prog_type;OCI_ATTR_PTYPE;errhp)

35. AJOUTER A TABLEAU($2->;$progh) `stocker le handle sur le sous-programme

36. Au cas ou

37. :($prog_type=3) `le sous-programme est une Procédure. Mettre 'P'

38. AJOUTER A TABLEAU($3->;"P")

39. :($prog_type=4) `le sous-programme est une Fonction. Mettre 'F'

40. AJOUTER A TABLEAU($3->;"F")

41. Fin de cas

42. AJOUTER A TABLEAU($4->;$prog_name) `stocker le nom du sous-programme

43. 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 :

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