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:
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:
1 2 3 4
| case SQLT_DAT:
size = 64;
defineType = SQLT_ODT;
break; |
Pour un champs Timestamp j'ai donc ajouté un case
Code:
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:
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:
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