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

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Interfaces de programmation Oracle Discussion :

Lire un champ de type timestamp avec OCI


Sujet :

Interfaces de programmation Oracle

  1. #1
    Candidat au Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2014
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2014
    Messages : 3
    Points : 2
    Points
    2
    Par défaut Lire un champ de type timestamp avec OCI
    Bonjour,

    Je suis confronté à un problème qui me tient depuis trois jours déjà.
    Je maintiens une librairie C qui permet via des méthodes génériques d'adresser différentes base de données (MSSql, PostGreSQL et donc Oracle) Pour chacune de ses bases de données il y a des méthodes dérivées qui appellent le client livré avec la base.

    Oracle donc.
    Jusqu'à présent nous ne manipulions que des champs date et j'ai été chargé d'étendre à la gestion des timestamp surtout pour millisecondes.

    Pour chaque colonne on prépare les buffers de réception et on appelle la librairie OCI
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    error = OCIDefineByPos(
        self->ociStmt,
        &(column->ociDefine),
        self->ociError,
        i+1,
        data,     
        size,
        defineType,
        &(column->ociIndicator),
        &(column->ociReturnedLength),
        &(column->ociReturnedCode),
        OCI_DEFAULT
    );
    avec au préalable pour un champs SQLT_DAT
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    case SQLT_DAT:
    size = 64;
    defineType = SQLT_ODT;
    break;
    Pour un champs Timestamp j'ai donc ajouté un case

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    case SQLT_TIMESTAMP:
    size = 64;
    defineType = SQLT_TIMESTAMP;
    break;
    Pour un champ de type Timestamp la librairie crashe dans la dll OraOCIEI10.dll sans possibilité de débugguer.

    On est passé par OCI.dll et c'est l'appel à la fonction OCIStmtFetch2 qui nous a ammené là.

    Ci dessous l'appel au fetch
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    static BOOLEAN
    _cdboci8_fetch(GLObject *_self, const char ***fields, BOOLEAN *reset)
    {
        GLDbOci8 *self = (GLDbOci8 *) _self;
        BOOLEAN result = _cdboci8_setBlockingMode(self);
        if (!result) {
            *fields = NULL;
            *reset = TRUE;
        } else {
            int error = OCIStmtFetch2(
                self->ociStmt, 
                self->ociError,
                (ub4) 1,
                OCI_FETCH_NEXT,
                0, /* Ignored with OCI_FETCH_NEXT*/
                OCI_DEFAULT
    );
    J'ai augmenté la taille du buffer de récéption de 64 à 128 mais sans plus de résultat.

    Si dans le OCIDefineByPos je déclare mon champs comme une date, et bien que dans la base ce soit un champ Timestamp ça ne plante pas et je récupère une date sans les millisecondes.
    Pour l'instant c'est le meilleur résultat que j'aie obtenu.

    A ce propos je m'interroge sur la manière de parser le résultat quand je l'obtiendrai puisque la structure OCIDateTime ne semble pas comporter les millisecondes.
    Sera-t-il nécessaire de passer obligatoirement par la fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    OCIDateTimeToText (
        self->ociEnv, 
        self->ociError
        (const OCIDateTime*) &column->buffer
        (const OraText*) "YYYY-MM-DD HH24:MI:SS,FF3",
        (ub1)25, (ub1)3,
        (OraText *)0,
        0, 
        &dtSize, 
        (OraText*) &dt
    );
    Si quelqu'un pouvait me mettre sur une piste je lui en serai reconnaissant comme on dit jusqu'à la 7eme génération. J'espère que j'ai été assez clair dans mes explications.
    Je vous remercie pour votre aide.

    Claude

  2. #2
    Rédacteur
    Avatar de Vincent Rogier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    2 373
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 2 373
    Points : 5 307
    Points
    5 307
    Par défaut
    Salut,

    En fait, le buffer que tu dois passer a la fonction de define doit correspondre à un OCIDateTime **.
    Donc la taille doit être la taille d'un pointeur et le buffer un pointeur sur un OCIDateTime * alloué par OCIDescriptorAlloc().

    Tu trouveras un snipet la (recherche le paragraphe "Datetime Example") :

    https://docs.oracle.com/cd/B28359_01...5/oci12oty.htm

    Sinon tu peux aussi regarder le code source de OCILIB !

    Regards,

    Vincent
    Vincent Rogier.

    Rubrique ORACLE : Accueil - Forum - Tutoriels - FAQ - Livres - Blog

    Vous voulez contribuer à la rubrique Oracle ? Contactez la rubrique !

    OCILIB (C Driver for Oracle)

    Librairie C Open Source multi-plateformes pour accéder et manipuler des bases de données Oracle

  3. #3
    Candidat au Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2014
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2014
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Merci Vincent de ta réponse. Je vais me pencher là dessus dès que possible.
    Je te ferai part de mes résultats
    Bien à toi
    Claude

  4. #4
    Candidat au Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2014
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2014
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Vincent
    Merci beaucoup mon problème est résolu.
    Comme je suis en asynchrone, j'ai dû m'adapter mais maintenant ça fonctionne.
    Avant le OCIDefineByPos mon case donne ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    case SQLT_TIMESTAMP:
    			/* Allocate the descriptor (storage) for the datatype */
    			status = OCIDescriptorAlloc(self->ociEnv,
    										(void  **)&timestamp, 
    										OCI_DTYPE_TIMESTAMP,
    										0, (void  **)0);	
     
    			/* Flag for OCIDefine*/
    			isTimestamp = TRUE;
    			defineType = SQLT_TIMESTAMP;
    			size = sizeof(timestamp);
    			break;
    ....
     
                            ptData = data;
    			column->buffer = data;
     
    			if (isTimestamp){
    				/* If field is type Timestamp*/
    				/* Allocated address by OCI put in column->buffer*/
    				(OCIDateTime*) column->buffer = timestamp;
    				/* Param for OCIDefine is a pointer of pointer */
    				ptData = &column->buffer;
    			} 
    			/* Binding pour la valeur */
    			error = OCIDefineByPos(self->ociStmt,
    								   &(column->ociDefine),
    								   self->ociError,
    								   i+1,
    								   ptData,     
    								   size,
    								   defineType,
    								   &(column->ociIndicator),
    								   &(column->ociReturnedLength),
    								   &(column->ociReturnedCode),
    								   OCI_DEFAULT);
    et apres le fetch :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    } else if (column->type == SQLT_TIMESTAMP){
    					/* Pointeur */
    					char* pos = NULL;
     
    					OCIDate *ociDate = ociDate = (OCIDate *) column->buffer;
    					int hour   = ociDate->OCIDateTime.OCITimeHH;
    					int minute = ociDate->OCIDateTime.OCITimeMI;
    					int second = ociDate->OCIDateTime.OCITimeSS;
    					int year   = ociDate->OCIDateYYYY;
    					int month  = ociDate->OCIDateMM;
    					int day    = ociDate->OCIDateDD;
    					int millis = 0;
    					char* ptMillis = column->buffer;
    					ptMillis +=8;
    					millis =  (*((int*)ptMillis)) /1000000 ;
     
    					OCIDescriptorFree( &column->buffer, OCI_DTYPE_TIMESTAMP );
    					self->results[i] = column->buffer;
    					pos = column->buffer;

    En revanche je n'ai pas réussi à obtenir un résultat de OCIDateTimeToText()
    J'ai -1 en retour.
    Je me suis débrouillé à la main.

    Encore merci de ton aide.
    Claude

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Lire un champ oracle type long avec une requête ODBC
    Par guidav dans le forum Général VBA
    Réponses: 1
    Dernier message: 02/07/2011, 17h27
  2. mapping champs de type int avec longueur
    Par elbissat dans le forum Hibernate
    Réponses: 3
    Dernier message: 27/11/2007, 10h45
  3. Insert into dans un champ de type "timestamp"
    Par sylvette dans le forum Langage SQL
    Réponses: 2
    Dernier message: 30/10/2007, 17h35
  4. peut-on creer 2 champs de type timeStamp?
    Par kifouillou dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 26/02/2007, 17h01
  5. Réponses: 2
    Dernier message: 24/10/2006, 09h52

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo