972 lines
42 KiB
C
972 lines
42 KiB
C
/*---------------------------------------------------------------------------------*/
|
||
/* $RCSfile: libdatabase.c,v $ */
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* $Revision: 1.1 $ */
|
||
/* $Name: $ */
|
||
/* $Date: 2006/02/28 23:28:21 $ */
|
||
/* $Author: agibert $ */
|
||
/*---------------------------------------------------------------------------------*/
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* This file is part of LibDataBase */
|
||
/* */
|
||
/* LibDataBase is free software; you can redistribute it and/or modify */
|
||
/* it under the terms of the GNU Lesser General Public Licence as published by */
|
||
/* the Free Software Foundation; either version 2.1 of the License, or */
|
||
/* (at your option) any later version. */
|
||
/* */
|
||
/* LibDataBase is distributed in the hope that it will be useful, */
|
||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
||
/* GNU Lesser General Public License for more details. */
|
||
/* */
|
||
/* You should have received a copy of the GNU Lesser General Public License */
|
||
/* along with LibDataBase; if not, write to the Free Software */
|
||
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||
/*---------------------------------------------------------------------------------*/
|
||
|
||
|
||
|
||
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <stdarg.h>
|
||
#include <string.h>
|
||
extern char *strdup (const char *);
|
||
|
||
#include <bdm.h>
|
||
#include "database.h"
|
||
|
||
BDM_VERSION_EXPORT(libdatabase, "$Revision: 1.1 $", "$Name: $", __FILE__, "$Author: agibert $")
|
||
|
||
/* fonctions locales */
|
||
static DBT_Status DB__Disconnect(DBT_Connection *connection, int reportErrors);
|
||
static void DB__Error(OCIError *errhp, char *buffer, int length, dword *errorCode, sword status);
|
||
static void DB__Error_Connection(DBT_Connection *connection, sword status);
|
||
static void DB__Error_Statement(DBT_Statement *statement, sword status);
|
||
static DBT_Status DB__CheckFetch(DBT_Statement *statement, sword OCIrc, DBT_Result *result);
|
||
|
||
static int initialized = 0;
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Initializes library and OCI environment. */
|
||
/*---------------------------------------------------------------------------------*/
|
||
DBT_Status DB_Library_Open(int flags) {
|
||
/* flags non utilis<69> */
|
||
if (flags) BDM_Trace(1, "libdatabase", "DB_Library_Open", "Le param<61>tre flags (%d) est ignor<6F> car il est obsol<6F>te", flags);
|
||
|
||
if (!initialized) {
|
||
sword OCIrc = OCIInitialize(OCI_OBJECT | OCI_THREADED, NULL, NULL, NULL, NULL);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
BDM_Trace(0, "libdatabase", "DB_Library_Open", "Echec d'initialisation du process OCI");
|
||
return DBS_ERROCI;
|
||
}
|
||
initialized = 1;
|
||
}
|
||
|
||
initialized++;
|
||
return DBS_OK;
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Closes library. */
|
||
/*---------------------------------------------------------------------------------*/
|
||
DBT_Status DB_Library_Close(void) {
|
||
initialized--;
|
||
return DBS_OK;
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Connects to an Oracle database. */
|
||
/*---------------------------------------------------------------------------------*/
|
||
DBT_Status DB_Connect(DBT_Connection *connection, const char *Login, const char *Password, const char *Database) {
|
||
sword OCIrc;
|
||
char *buf, *ptr;
|
||
|
||
memset(connection, 0, sizeof(DBT_Connection));
|
||
|
||
ptr = buf = strdup(Password);
|
||
while (*ptr) *(ptr++) = '*';
|
||
BDM_Trace(3, "libdatabase", "DB_Connect", "Connexion <20> la base %s/%s%s%s...\n", Login, buf, Database ? "@" : "", Database ? Database : "");
|
||
free(buf);
|
||
|
||
if (!initialized) {
|
||
BDM_Trace(0, "libdatabase", "DB_Connect", "La librairie n'a pas <20>t<EFBFBD> initialis<69>e");
|
||
return DBS_ERRAPI;
|
||
}
|
||
|
||
/* Initialisation de l'environnement OCI */
|
||
OCIrc = OCIEnvInit(&connection->envhp, OCI_DEFAULT, 0, NULL);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
BDM_Trace(0, "libdatabase", "DB_Connect", "Echec de l'initialisation du process OCI");
|
||
DB__Disconnect(connection, 0);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
/* Allocation d'un handle de contexte */
|
||
OCIrc = OCIHandleAlloc(connection->envhp, (void **)&connection->svchp, OCI_HTYPE_SVCCTX, 0, NULL);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
BDM_Trace(0, "libdatabase", "DB_Connect", "Echec de l'allocation du handle de contexte");
|
||
DB__Disconnect(connection, 0);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
/* Allocation d'un handle d'erreur */
|
||
OCIrc = OCIHandleAlloc(connection->envhp, (void **)&connection->errhp, OCI_HTYPE_ERROR, 0, NULL);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
BDM_Trace(0, "libdatabase", "DB_Connect", "Echec de l'allocation du handle d'erreur");
|
||
DB__Disconnect(connection, 0);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
/* Allocation d'un handle de serveur */
|
||
OCIrc = OCIHandleAlloc(connection->envhp, (void **)&connection->srvhp, OCI_HTYPE_SERVER, 0, NULL);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
BDM_Trace(0, "libdatabase", "DB_Connect", "Echec de l'allocation du handle de serveur");
|
||
DB__Disconnect(connection, 0);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
/* Allocation d'un handle de session */
|
||
OCIrc = OCIHandleAlloc(connection->envhp, (void **)&connection->authp, OCI_HTYPE_SESSION, 0, NULL);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
BDM_Trace(0, "libdatabase", "DB_Connect", "Echec de l'allocation du handle de session");
|
||
DB__Disconnect(connection, 0);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
/* Allocation d'un handle de transaction */
|
||
OCIrc = OCIHandleAlloc(connection->envhp, (void **)&connection->transp, OCI_HTYPE_TRANS, 0, NULL);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
BDM_Trace(0, "libdatabase", "DB_Connect", "Echec de l'allocation du handle de transaction");
|
||
DB__Disconnect(connection, 0);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
connection->handlesAreValid = 1;
|
||
|
||
/* log in */
|
||
OCIrc = OCIAttrSet(connection->authp, OCI_HTYPE_SESSION, (char *)(int)Login, strlen(Login), OCI_ATTR_USERNAME, connection->errhp);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
DB__Error_Connection(connection, OCIrc);
|
||
BDM_Trace(0, "libdatabase", "DB_Connect", "Echec de d<>finition de l'attribut USERNAME : %s", connection->error);
|
||
DB__Disconnect(connection, 0);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
OCIrc = OCIAttrSet(connection->authp, OCI_HTYPE_SESSION, (char *)(int)Password, strlen(Password), OCI_ATTR_PASSWORD, connection->errhp);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
DB__Error_Connection(connection, OCIrc);
|
||
BDM_Trace(0, "libdatabase", "DB_Connect", "Echec de d<>finition de l'attribut PASSWORD : %s", connection->error);
|
||
DB__Disconnect(connection, 0);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
/* Allocation et initialisation du handle de serveur */
|
||
OCIrc = OCIServerAttach(connection->srvhp, connection->errhp, (text *)(int)Database, (signed)(Database ? strlen(Database) : 0), OCI_DEFAULT);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
DB__Error_Connection(connection, OCIrc);
|
||
BDM_Trace(0, "libdatabase", "DB_Connect", "Echec de l'attachement de la base %s%sau serveur : %s", Database ? Database : "", Database ? " " : "", connection->error);
|
||
DB__Disconnect(connection, 0);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
/* Ajoute le handle du serveur au handle de contexte */
|
||
OCIrc = OCIAttrSet(connection->svchp, OCI_HTYPE_SVCCTX, connection->srvhp, 0, OCI_ATTR_SERVER, connection->errhp);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
DB__Error_Connection(connection, OCIrc);
|
||
BDM_Trace(0, "libdatabase", "DB_Connect", "Echec d'attachement du handle de serveur au handle de service : %s", connection->error);
|
||
DB__Disconnect(connection, 0);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
/* Ouverture d'une session */
|
||
OCIrc = OCISessionBegin(connection->svchp, connection->errhp, connection->authp, OCI_CRED_RDBMS, OCI_DEFAULT);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
DB__Error_Connection(connection, OCIrc);
|
||
BDM_Trace(0, "libdatabase", "DB_Connect", "Echec du d<>marrage de la session : %s", connection->error);
|
||
DB__Disconnect(connection, 0);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
/* R<>f<EFBFBD>rencement de la session ouverte dans le handle de contexte */
|
||
OCIrc = OCIAttrSet(connection->svchp, OCI_HTYPE_SVCCTX, connection->authp, 0, OCI_ATTR_SESSION, connection->errhp);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
DB__Error_Connection(connection, OCIrc);
|
||
BDM_Trace(0, "libdatabase", "DB_Connect", "Echec du r<>f<EFBFBD>rencement de la session dans le handle de contexte : %s", connection->error);
|
||
DB__Disconnect(connection, 0);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
/* R<>f<EFBFBD>rencement de la transaction */
|
||
OCIrc = OCIAttrSet(connection->svchp, OCI_HTYPE_SVCCTX, connection->transp, 0, OCI_ATTR_TRANS, connection->errhp);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
DB__Error_Connection(connection, OCIrc);
|
||
BDM_Trace(0, "libdatabase", "DB_Connect", "Echec du r<>f<EFBFBD>rencement de la transaction");
|
||
DB__Disconnect(connection, 0);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
BDM_Trace(2, "libdatabase", "DB_Connect", "Connect<EFBFBD> <20> Oracle %s%s%s", Login, Database ? "@" : "", Database ? Database : "");
|
||
return DBS_OK;
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Disconnects from an Oracle database. */
|
||
/*---------------------------------------------------------------------------------*/
|
||
DBT_Status DB_Disconnect(DBT_Connection *connection) {
|
||
return DB__Disconnect(connection, 1);
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Starts a new transaction. */
|
||
/* */
|
||
/* User can then execute one or more statements before committing or rolling back. */
|
||
/* If multiple transactions are necessary, each DB_Transaction_Start() must be */
|
||
/* called on a different DBT_Connection, i.e. DB_Connect() should be called as */
|
||
/* many times as there will be transactions. */
|
||
/*---------------------------------------------------------------------------------*/
|
||
DBT_Status DB_Transaction_Start(DBT_Connection *conn) {
|
||
sword OCIrc;
|
||
|
||
OCIrc = OCITransStart(conn->svchp, conn->errhp, 1, OCI_TRANS_NEW);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
DB__Error_Connection(conn, OCIrc);
|
||
BDM_Trace(0, "libdatabase", "DB_Transaction_Start", "Echec du d<>marrage de la transaction : %s", conn->error);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
return DBS_OK;
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Commits a transaction. */
|
||
/*---------------------------------------------------------------------------------*/
|
||
DBT_Status DB_Transaction_Commit(DBT_Connection *conn) {
|
||
sword OCIrc;
|
||
|
||
OCIrc = OCITransCommit(conn->svchp, conn->errhp, OCI_DEFAULT);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
DB__Error_Connection(conn, OCIrc);
|
||
BDM_Trace(0, "libdatabase", "DB_Transaction_Commit", "Echec du commit de la transaction : %s", conn->error);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
return DBS_OK;
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Rolls back a transaction. */
|
||
/*---------------------------------------------------------------------------------*/
|
||
DBT_Status DB_Transaction_Rollback(DBT_Connection *conn) {
|
||
sword OCIrc;
|
||
|
||
OCIrc = OCITransRollback(conn->svchp, conn->errhp, OCI_DEFAULT);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
DB__Error_Connection(conn, OCIrc);
|
||
BDM_Trace(0, "libdatabase", "DB_Transaction_Rollback", "Echec du rollback de la transaction : %s", conn->error);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
return DBS_OK;
|
||
}
|
||
|
||
|
||
/*------------------------------------------------------------------------------*/
|
||
/* Initializes an 'hostvar', variable that will be later associated to an */
|
||
/* input or output value. */
|
||
/*------------------------------------------------------------------------------*/
|
||
/* (I/O) HostVar: Address of an existing DBT_HostVar that will be filled in. */
|
||
/* (I) type : Type of data this hostvar refers to. */
|
||
/* (I) size : Size in bytes of the data type. Ex: DBD_INTEGER: sizeof(int); */
|
||
/* DBD_STRING: size of largest string + 1. */
|
||
/* (I) value : Pointer to input or output value (or array of values). */
|
||
/* (I) indicator: DBT_Indicator or array of DBT_Indicator. */
|
||
/* */
|
||
/* Type can be DBD_{INTEGER,STRING,FLOAT,DOUBLE,DATE}. */
|
||
/* */
|
||
/* Value points to an array of data (int[] for DBD_INTEGER, double[] for */
|
||
/* DBD_DOUBLE etc. Note: for strings, value points to a char[][] and not */
|
||
/* a char*[]) */
|
||
/* For DBD_DATE fields, the array must be allocated via DB_DateArray_Alloc. */
|
||
/* */
|
||
/* The value of indicator, for outgoing data, must be -1 for a null value */
|
||
/* and 0 otherwise. For incoming data, it is -1 if the value is null, 0 */
|
||
/* if the value was retrieved correctly, and >0 if the value is truncated */
|
||
/* (in the latter case, it is the real length of the data value). */
|
||
/*------------------------------------------------------------------------------*/
|
||
DBT_Status DB_HostVar_Setup(DBT_HostVar *HostVar, int type, int size, void *value, DBT_Indicator *indicator) {
|
||
if (type != DBD_STRING && size)
|
||
BDM_Trace(1, "libdatabase", "DB_HostVar_Setup", "Le param<61>tre size n'est utilis<69> que pour le type DBD_STRING");
|
||
switch (type) {
|
||
case DBD_STRING:
|
||
if (size <= 0) {
|
||
BDM_Trace(0, "libdatabase", "DB_HostVar_Setup", "Le param<61>tre size doit <20>tre > 0");
|
||
return DBS_ERRAPI;
|
||
}
|
||
HostVar->size = size;
|
||
HostVar->type = SQLT_STR;
|
||
break;
|
||
case DBD_INTEGER:
|
||
HostVar->size = sizeof(int);
|
||
HostVar->type = SQLT_INT;
|
||
break;
|
||
case DBD_FLOAT:
|
||
HostVar->size = sizeof(float);
|
||
HostVar->type = SQLT_FLT;
|
||
break;
|
||
case DBD_DOUBLE:
|
||
HostVar->size = sizeof(double);
|
||
HostVar->type = SQLT_FLT;
|
||
break;
|
||
case DBD_DATE:
|
||
HostVar->size = sizeof(OCIDate);
|
||
HostVar->type = SQLT_ODT;
|
||
break;
|
||
case DBD_ROWID:
|
||
HostVar->size = 16;/*sizeof(OCIRowid);*/
|
||
HostVar->type = SQLT_RDD;
|
||
break;
|
||
default:
|
||
BDM_Trace(0, "libdatabase", "DB_HostVar_Setup", "Param<EFBFBD>tre type (%d) non reconnu ; les valeurs possibles sont DBD_STRING, DBD_INTEGER, DBD_FLOAT, DBD_DOUBLE, DBD_DATE");
|
||
return DBS_ERRAPI;
|
||
}
|
||
|
||
HostVar->value = value;
|
||
HostVar->indicator = indicator;
|
||
|
||
return DBS_OK;
|
||
}
|
||
|
||
|
||
/*------------------------------------------------------------------------------*/
|
||
/* The following functions are used to manipulate Oracle dates in their */
|
||
/* native format. */
|
||
/* Although less compact, it is often more simple to consider dates in a table */
|
||
/* as strings and to define hostvars in consequence. */
|
||
/* Ex: if col1 is a date, "SELECT col1 from TABLEX WHERE ..." or */
|
||
/* "SELECT TO_CHAR(col1, 'DD/MM/YYYY HH24:MI:SS') from TABLEX WHERE ..." */
|
||
/* will do the job with a hostvar's type of DBD_STRING with size 20. */
|
||
/*------------------------------------------------------------------------------*/
|
||
DBT_Status DB_DateArray_Alloc(DBT_Date_Ptr *array, int size) {
|
||
*array = (OCIDate *)malloc(size * sizeof(OCIDate));
|
||
if (!array) {
|
||
BDM_Trace(0, "libdatabase", "DB_DateArray_Alloc", "Impossible d'allouer de la m<>moire pour un tableau de %d dates", size);
|
||
return DBS_ERRMEM;
|
||
}
|
||
|
||
return DBS_OK;
|
||
}
|
||
|
||
|
||
/*------------------------------------------------------------------------------*/
|
||
/* Free memory allocated by DB_DateArray_Alloc */
|
||
/*------------------------------------------------------------------------------*/
|
||
DBT_Status DB_DateArray_Free(DBT_Date_Ptr array) {
|
||
free(array);
|
||
return DBS_OK;
|
||
}
|
||
|
||
|
||
/*------------------------------------------------------------------------------*/
|
||
/* Convert a string into the native type Date using a given format */
|
||
/*------------------------------------------------------------------------------*/
|
||
DBT_Status DB_String_To_Date(DBT_Date_Ptr array, int idx, char *value, char *format) {
|
||
sword OCIrc;
|
||
|
||
OCIDate *Date = ((OCIDate *)array) + idx;
|
||
|
||
OCIrc = OCIDateFromText(NULL, (text *)value, strlen(value), (text *)format, strlen(format), NULL, 0, Date);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
BDM_Trace(0, "libdatabase", "DB_String_To_Date", "Erreur lors de la conversion de \"%s\" en date avec le format \"%s\"", value, format);
|
||
return DBS_ERRAPI;
|
||
}
|
||
|
||
return DBS_OK;
|
||
}
|
||
|
||
|
||
/*------------------------------------------------------------------------------*/
|
||
/* Convert a date into a string using a given format */
|
||
/*------------------------------------------------------------------------------*/
|
||
DBT_Status DB_Date_To_String(DBT_Date_Ptr array, int idx, char *Value, char *format) {
|
||
sword OCIrc;
|
||
unsigned long Value_Size;
|
||
|
||
OCIDate *Date = ((OCIDate*)array) + idx;
|
||
Value_Size = strlen(format) + 1;
|
||
|
||
OCIrc = OCIDateToText(NULL, Date, (text *)format, strlen(format), NULL, 0, &Value_Size, (text *)Value);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
BDM_Trace(0, "libdatabase", "DB_Date_To_String", "Erreur lors de la conversion d'une date avec le format \"%s\"", format);
|
||
return DBS_ERRAPI;
|
||
}
|
||
|
||
return DBS_OK;
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Initializes a statement. */
|
||
/* */
|
||
/* A statement is initialized only once, but can be prepared as many times as */
|
||
/* wanted (cf. DB_Statement_Prepare()). */
|
||
/*---------------------------------------------------------------------------------*/
|
||
DBT_Status DB_Statement_Init(DBT_Connection *connection, DBT_Statement *statement) {
|
||
sword OCIrc;
|
||
|
||
memset(statement, 0, sizeof(DBT_Statement));
|
||
statement->connection = connection;
|
||
|
||
/* Allocation d'un handle de statement */
|
||
OCIrc = OCIHandleAlloc(connection->envhp, (dvoid **)&statement->handle, OCI_HTYPE_STMT, 0, NULL);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
DB__Error_Connection(connection, OCIrc);
|
||
BDM_Trace(0, "libdatabase", "DB_Statement_Init", "Echec de l'allocation d'un handle de statement : %s", connection->error);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
/* Allocation d'un handle d'erreur */
|
||
OCIrc = OCIHandleAlloc(connection->envhp, (dvoid **)&statement->errhp, OCI_HTYPE_ERROR, 0, NULL);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
DB__Error_Connection(connection, OCIrc);
|
||
BDM_Trace(0, "libdatabase", "DB_Statement_Init", "Echec de l'allocation d'un handle d'erreur : %s", connection->error);
|
||
DB_Statement_Close(statement);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
return DBS_OK;
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Frees all resources used by a previously initialized statement. */
|
||
/*---------------------------------------------------------------------------------*/
|
||
DBT_Status DB_Statement_Close(DBT_Statement *statement) {
|
||
if (statement->errhp)
|
||
OCIHandleFree(statement->errhp, OCI_HTYPE_ERROR);
|
||
if (statement->handle)
|
||
OCIHandleFree(statement->handle, OCI_HTYPE_STMT);
|
||
|
||
return DBS_OK;
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Prepares a statement, i.e. associates SQL request and statement structure. */
|
||
/* A statement is initialized only once, but can be prepared as many times as */
|
||
/* wanted. */
|
||
/*---------------------------------------------------------------------------------*/
|
||
DBT_Status DB_Statement_Prepare(DBT_Statement *statement, const char *query) {
|
||
sword OCIrc;
|
||
ub2 statementType;
|
||
|
||
OCIrc = OCIStmtPrepare(statement->handle, statement->errhp, (text *)(int)query, strlen(query), OCI_NTV_SYNTAX, OCI_DEFAULT);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
DB__Error_Statement(statement, OCIrc);
|
||
BDM_Trace(0, "libdatabase", "DB_Statement_Prepare", "Echec de la pr<70>paration du statement \"%s\" : %s", query, statement->error);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
/* It will be useful to know if the query is a SELECT: */
|
||
OCIrc = OCIAttrGet(statement->handle, OCI_HTYPE_STMT, &statementType, 0, OCI_ATTR_STMT_TYPE, statement->errhp);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
DB__Error_Statement(statement, OCIrc);
|
||
BDM_Trace(0, "libdatabase", "DB_Statement_Prepare", "Erreur lors de la r<>cup<75>ration du type pour le statement \"%s\" : %s", query, statement->error);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
statement->isSelect = (statementType == OCI_STMT_SELECT);
|
||
statement->isPrepared = 1;
|
||
|
||
return DBS_OK;
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Defines output variables associations. */
|
||
/* Should be called to associate hostvar variables to output results (one hostvar */
|
||
/* for one column). Not needed if SQL request doesn't produce any result. */
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* (I) statement: An initialized statement. */
|
||
/* (I) rows : Size of the array of values each HostVar uses (1 if not an array)*/
|
||
/* (I) ... : One or more pointers to initialized HostVar, ending with NULL. */
|
||
/*---------------------------------------------------------------------------------*/
|
||
DBT_Status DB_Statement_DefineVars(DBT_Statement *statement, int rows, ...) {
|
||
va_list args;
|
||
DBT_HostVar *hostVar = NULL;
|
||
int column = 1;
|
||
DBT_Status rc = DBS_OK;
|
||
|
||
va_start(args, rows);
|
||
|
||
/* Associate all hostvars to each columns that will be potentially output */
|
||
while (rc == DBS_OK && (hostVar = va_arg(args, DBT_HostVar *))) {
|
||
rc = DB_Statement_DefineVar(statement, rows, column, hostVar);
|
||
if (rc != DBS_OK) break;
|
||
++column;
|
||
}
|
||
|
||
va_end(args);
|
||
return rc;
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Defines output variable association. */
|
||
/* Called to associate one hostvar variable to one output result. See */
|
||
/* DB_Statement_DefineVars(). */
|
||
/*---------------------------------------------------------------------------------*/
|
||
DBT_Status DB_Statement_DefineVar(DBT_Statement *statement, int rows, int column, DBT_HostVar *hv) {
|
||
OCIDefine *def = NULL;
|
||
sword OCIrc;
|
||
|
||
if (!statement->isPrepared) {
|
||
BDM_Trace(0, "libdatabase", "DB_Statement_DefineVar", "Le statement n'a pas <20>t<EFBFBD> pr<70>par<61>");
|
||
return DBS_ERRAPI;
|
||
}
|
||
|
||
/* Associate hostvar to the current column: */
|
||
OCIrc = OCIDefineByPos(statement->handle, &def, statement->errhp, (unsigned)column, hv->value, hv->size, hv->type, hv->indicator, NULL, NULL, OCI_DEFAULT);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
DB__Error_Statement(statement, OCIrc);
|
||
BDM_Trace(0, "libdatabase", "DB_Statement_DefineVar", "Echec de la d<>finition de la variable n<> %d : %s", column, statement->error);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
statement->varsDefined = 1;
|
||
statement->rowsToFetch = rows;
|
||
|
||
return DBS_OK;
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Binds input variables to placeholders in the SQL request. */
|
||
/* NOTE: The statement must have been prepared using the SQL request */
|
||
/* */
|
||
/* Should be called to associate hostvar variables to input placeholders */
|
||
/* e.g., :1 and :2 in "INSERT INTO TableX (col1, col2) VALUES (:1, :2)". */
|
||
/* Placeholders can be named whatever you want since binding is done by position, */
|
||
/* not by name. */
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* (I) statement: An initialized statement. */
|
||
/* (I) rowsBound: Size of the array of values each HostVar uses (1 if not an array)*/
|
||
/* (I) ... : One or more pointers to initialized HostVar, ending with NULL. */
|
||
/*---------------------------------------------------------------------------------*/
|
||
DBT_Status DB_Statement_BindVars(DBT_Statement *statement, int rowsBound, ...) {
|
||
va_list args;
|
||
DBT_HostVar *hostVar;
|
||
int placeHolderIndex = 1;
|
||
DBT_Status rc = DBS_OK;
|
||
|
||
va_start(args, rowsBound);
|
||
|
||
/* Bind each hostvar to each placeholder, starting form 1: */
|
||
while (rc == DBS_OK && (hostVar = va_arg(args, DBT_HostVar *))) {
|
||
rc = DB_Statement_BindVar(statement, rowsBound, placeHolderIndex, hostVar);
|
||
if (rc != DBS_OK) break;
|
||
++placeHolderIndex;
|
||
}
|
||
|
||
va_end(args);
|
||
return rc;
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Binds one input variable to one placeholders in the SQL request. */
|
||
/* Cf. DB_Statement_BindVars(). */
|
||
/*---------------------------------------------------------------------------------*/
|
||
DBT_Status DB_Statement_BindVar(DBT_Statement *statement, int rowsBound, int placeHolderIndex, DBT_HostVar *hostVar) {
|
||
OCIBind *bind = NULL;
|
||
sword OCIrc;
|
||
|
||
if (!statement->isPrepared) {
|
||
BDM_Trace(0, "libdatabase", "DB_Statement_BindVar", "Le statement n'a pas <20>t<EFBFBD> pr<70>par<61>");
|
||
return DBS_ERRAPI;
|
||
}
|
||
|
||
OCIrc = OCIBindByPos(statement->handle, &bind, statement->errhp, (unsigned)placeHolderIndex, hostVar->value, hostVar->size, hostVar->type, hostVar->indicator,NULL, NULL, 0, NULL, OCI_DEFAULT);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
DB__Error_Statement(statement, OCIrc);
|
||
BDM_Trace(0, "libdatabase", "DB_Statement_BindVar", "Echec du binding de la variable n<> %d : %s", placeHolderIndex, statement->error);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
statement->varsBound = 1;
|
||
statement->rowsBound = rowsBound;
|
||
|
||
return DBS_OK;
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Shorthand to execute a prepared statement using a SELECT query. */
|
||
/*---------------------------------------------------------------------------------*/
|
||
DBT_Status DB_Statement_ExecuteSelect(DBT_Statement *statement, DBT_Result *result) {
|
||
return DB_Statement_Execute(statement, 0, 1, result);
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Executes a prepared statement. */
|
||
/* */
|
||
/* If statement is SELECT: */
|
||
/* _ if DB_Statement_DefineVars() has already been called, as many rows as */
|
||
/* specified by the size of defined hostvars will be directly fetched here. */
|
||
/* Ex: "SELECT col1, col2 FROM table WHERE col3 == 12" */
|
||
/* _ If DB_Statement_DefineVars() has not been called yet, user will need to */
|
||
/* perform one or more DB_Statement_Fetch() to retrieve the results. */
|
||
/* */
|
||
/* If statement is not SELECT: */
|
||
/* _ If no variables were bound, execute statement only once. */
|
||
/* Ex: "INSERT INTO table VALUES (123, 'ABC')" */
|
||
/* _ If some variables are bound, execute statement request 'count' times. */
|
||
/* Ex: "INSERT INTO table VALUES (:1, :2)" */
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* */
|
||
/*---------------------------------------------------------------------------------*/
|
||
DBT_Status DB_Statement_Execute(DBT_Statement *statement, int startingRow, int count, DBT_Result *result) {
|
||
sword OCIrc;
|
||
sword OCIrc2;
|
||
unsigned int iters;
|
||
char err[512];
|
||
int errLen = sizeof(err);
|
||
dword errCode;
|
||
DBT_Status rc;
|
||
|
||
if (!statement->isPrepared) {
|
||
BDM_Trace(0, "libdatabase", "DB_Statement_Execute", "Le statement n'a pas <20>t<EFBFBD> pr<70>par<61>");
|
||
return DBS_ERRAPI;
|
||
}
|
||
|
||
/* Set 'iters', number of times the request will be executed */
|
||
if (statement->isSelect) {
|
||
iters = (statement->varsDefined) ? statement->rowsToFetch : 0;
|
||
if (statement->varsBound) {
|
||
if (startingRow != 0 || count != 1) {
|
||
BDM_Trace(0, "libdatabase", "DB_Statement_Execute", "Un statement SELECT avec des variables en sortie ne peut travailler avec des tableaux en entr<74>e");
|
||
return DBS_ERRAPI;
|
||
}
|
||
}
|
||
} else {
|
||
if (!statement->varsBound) {
|
||
iters = 1;
|
||
} else {
|
||
if (startingRow < 0 || startingRow >= statement->rowsBound) {
|
||
BDM_Trace(0, "libdatabase", "DB_Statement_Execute", "Le param<61>tre startingRow est invalide (0 <20> %d au lieu de %d)", statement->rowsBound, startingRow);
|
||
return DBS_ERRAPI;
|
||
}
|
||
if (count <= 0 || startingRow + count > statement->rowsBound) {
|
||
BDM_Trace(0, "libdatabase", "DB_Statement_Execute", "Le param<61>tre count est invalide (1 <20> %d au lieu de %d)", statement->rowsBound - startingRow, count);
|
||
return DBS_ERRAPI;
|
||
}
|
||
iters = startingRow + count;
|
||
}
|
||
}
|
||
|
||
statement->rowsFetchedSoFar = 0;
|
||
statement->isEOF = 0;
|
||
statement->isExecuted = 0;
|
||
|
||
BDM_Trace(3, "libdatabase", "DB_Statement_Execute", "Ex<EFBFBD>cution du statement, iter = %d, <20> partir de %d", iters, startingRow);
|
||
|
||
OCIrc = OCIStmtExecute(statement->connection->svchp, statement->handle, statement->errhp, iters, (unsigned)startingRow, NULL, NULL, OCI_DEFAULT);
|
||
if (statement->isSelect) {
|
||
result->errorIteration = 0; /* only one iteration for SELECTs */
|
||
rc = DB__CheckFetch(statement, OCIrc, result);
|
||
if (!DB_ERROR(rc)) statement->isExecuted = 1;
|
||
return rc;
|
||
}
|
||
|
||
/* This is not a SELECT statement */
|
||
result->rowsProcessed = -1;
|
||
result->errorIteration = -1;
|
||
/* Get number of rows processed */
|
||
OCIrc2 = OCIAttrGet(statement->handle, OCI_HTYPE_STMT, &result->rowsProcessed, NULL, OCI_ATTR_ROW_COUNT, statement->errhp);
|
||
if (OCIrc2 != OCI_SUCCESS) {
|
||
/* Don't report any errors, since the statement succeeded.
|
||
Leave rowsProcessed to -1 if impossible to get it. */
|
||
DB__Error(statement->errhp, err, errLen, &errCode, OCIrc2);
|
||
BDM_Trace(0, "libdatabase", "DB_Statement_Execute", "Erreur lors de la r<>cup<75>ration du nombre de lignes trait<69>es : %s", err);
|
||
return DBS_ERROCI;
|
||
}
|
||
if (OCIrc == OCI_SUCCESS) return DBS_OK;
|
||
|
||
/* An error happened */
|
||
DB__Error_Statement(statement, OCIrc);
|
||
BDM_Trace(0, "libdatabase", "DB_Statement_Execute", "Erreur lors de l'ex<65>cution du statement : %s", statement->error);
|
||
if (iters == 1) result->errorIteration = 0;
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Fetches next rows. */
|
||
/* Called by user after a DB_Statement_Execute() using a SELECT query. */
|
||
/*---------------------------------------------------------------------------------*/
|
||
DBT_Status DB_Statement_Fetch(DBT_Statement *statement, DBT_Result *result) {
|
||
sword OCIrc;
|
||
|
||
if (!statement->isPrepared) {
|
||
BDM_Trace(0, "libdatabase", "DB_Statement_Fetch", "Le statement n'a pas <20>t<EFBFBD> pr<70>par<61>");
|
||
return DBS_ERRAPI;
|
||
}
|
||
|
||
if (!statement->isSelect) {
|
||
BDM_Trace(0, "libdatabase", "DB_Statement_Fetch", "Le statement n'est pas un SELECT");
|
||
return DBS_ERRAPI;
|
||
}
|
||
|
||
if (!statement->varsDefined) {
|
||
BDM_Trace(0, "libdatabase", "DB_Statement_Fetch", "Aucune variable n'est d<>finie");
|
||
return DBS_ERRAPI;
|
||
}
|
||
|
||
if (!statement->isExecuted) {
|
||
BDM_Trace(0, "libdatabase", "DB_Statement_Fetch", "Le statement n'a pas encore <20>t<EFBFBD> ex<65>cut<75>");
|
||
return DBS_ERRAPI;
|
||
}
|
||
|
||
if (statement->isEOF) /* the end of data was seen during last fetch */
|
||
return DBS_END_OF_DATA;
|
||
|
||
BDM_Trace(3, "libdatabase", "DB_Statement_Fetch", "Fetch...");
|
||
|
||
OCIrc = OCIStmtFetch(statement->handle, statement->errhp, (unsigned)statement->rowsToFetch, OCI_FETCH_NEXT, OCI_DEFAULT);
|
||
return DB__CheckFetch(statement, OCIrc, result);
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Cancels implicit cursor associated to last fetch. */
|
||
/*---------------------------------------------------------------------------------*/
|
||
DBT_Status DB_Statement_Fetch_Terminate(DBT_Statement *statement) {
|
||
sword OCIrc;
|
||
|
||
if (! statement->isPrepared) {
|
||
BDM_Trace(0, "libdatabase", "DB_Statement_Fetch", "Le statement n'a pas <20>t<EFBFBD> pr<70>par<61>");
|
||
return DBS_ERRAPI;
|
||
}
|
||
|
||
if (! statement->isSelect) {
|
||
BDM_Trace(0, "libdatabase", "DB_Statement_Fetch", "Le statement n'est pas un SELECT");
|
||
return DBS_ERRAPI;
|
||
}
|
||
|
||
OCIrc = OCIStmtFetch(statement->handle, statement->errhp, 0, OCI_FETCH_NEXT, OCI_DEFAULT);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
DB__Error_Statement(statement, OCIrc);
|
||
if (statement->errorCode == 1406) {
|
||
statement->errorCode = 0;
|
||
strcpy(statement->error, "");
|
||
BDM_Trace(1, "libdatabase", "DB_Statement_Fetch_Terminate", "Donn<EFBFBD>e tronqu<71>e");
|
||
return DBS_OK;
|
||
}
|
||
BDM_Trace(0, "libdatabase", "DB_Statement_FetchTerminate", "Erreur lors du fetch : %s", statement->error);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
return DBS_OK;
|
||
}
|
||
|
||
static DBT_Status DB__Disconnect(DBT_Connection *connection, int reportErrors) {
|
||
sword OCIrc;
|
||
DBT_Status rc = DBS_OK;
|
||
char *err;
|
||
int errLen;
|
||
char localErr[512];
|
||
dword *errCode;
|
||
dword localErrCode;
|
||
|
||
if (connection->handlesAreValid) {
|
||
if (reportErrors) {
|
||
err = connection->error;
|
||
errLen = sizeof(connection->error);
|
||
errCode = &connection->errorCode;
|
||
} else {
|
||
err = localErr;
|
||
errLen = sizeof(localErr);
|
||
errCode = &localErrCode;
|
||
}
|
||
|
||
/* D<>connexion de la base de donn<6E>es */
|
||
OCIrc = OCISessionEnd(connection->svchp, connection->errhp, connection->authp, 0);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
DB__Error(connection->errhp, err, errLen, errCode, OCIrc);
|
||
BDM_Trace(0, "libdatabase", "DB__Disconnect", "Echec de la fermeture de la session : %s", err);
|
||
rc = DBS_ERROCI;
|
||
}
|
||
|
||
/* D<>tachement du serveur */
|
||
OCIrc = OCIServerDetach(connection->srvhp, connection->errhp, OCI_DEFAULT);
|
||
if (OCIrc != OCI_SUCCESS) {
|
||
DB__Error(connection->errhp, err, errLen, errCode, OCIrc);
|
||
BDM_Trace(0, "libdatabase", "DB__Disconnect", "Echec du d<>tachement du serveur : %s", err);
|
||
rc = DBS_ERROCI;
|
||
}
|
||
|
||
BDM_Trace(2, "libdatabase", "DB__Disconnect", "D<EFBFBD>connect<EFBFBD> d'Oracle");
|
||
}
|
||
|
||
if (connection->srvhp)
|
||
OCIHandleFree(connection->srvhp, OCI_HTYPE_SERVER);
|
||
|
||
if (connection->errhp)
|
||
OCIHandleFree(connection->errhp, OCI_HTYPE_ERROR);
|
||
|
||
if (connection->authp)
|
||
OCIHandleFree(connection->authp, OCI_HTYPE_SESSION);
|
||
|
||
if (connection->transp)
|
||
OCIHandleFree(connection->transp, OCI_HTYPE_TRANS);
|
||
|
||
if (connection->svchp)
|
||
OCIHandleFree(connection->svchp, OCI_HTYPE_SVCCTX);
|
||
|
||
memset(connection, 0, sizeof(DBT_Connection));
|
||
|
||
return rc;
|
||
}
|
||
|
||
|
||
static void DB__Error(OCIError *errhp, char *buffer, int length, dword *errorCode, sword status) {
|
||
unsigned int len = length;
|
||
*errorCode = 0;
|
||
|
||
switch (status) {
|
||
case OCI_SUCCESS:
|
||
buffer[0] = '\0';
|
||
break;
|
||
case OCI_SUCCESS_WITH_INFO:
|
||
snprintf(buffer, len, "ErrorOCI_SUCCESS_WITH_INFO");
|
||
break;
|
||
case OCI_NEED_DATA:
|
||
snprintf(buffer, len, "ErrorOCI_NEED_DATA");
|
||
break;
|
||
case OCI_NO_DATA:
|
||
snprintf(buffer, len, "ErrorOCI_NO_DATA");
|
||
break;
|
||
case OCI_ERROR:
|
||
OCIErrorGet(errhp, 1, NULL, errorCode, (text*)buffer, len, OCI_HTYPE_ERROR);
|
||
break;
|
||
case OCI_INVALID_HANDLE:
|
||
snprintf(buffer, len, "ErrorOCI_INVALID_HANDLE");
|
||
break;
|
||
case OCI_STILL_EXECUTING:
|
||
snprintf(buffer, len, "ErrorOCI_STILL_EXECUTE");
|
||
break;
|
||
case OCI_CONTINUE:
|
||
snprintf(buffer, len, "ErrorOCI_CONTINUE");
|
||
break;
|
||
default:
|
||
snprintf(buffer, len, "Unknown Error");
|
||
break;
|
||
}
|
||
}
|
||
|
||
|
||
static void DB__Error_Connection(DBT_Connection *connection, sword status) {
|
||
DB__Error(connection->errhp, connection->error, sizeof(connection->error), &connection->errorCode, status);
|
||
}
|
||
|
||
|
||
static void DB__Error_Statement(DBT_Statement *statement, sword status) {
|
||
DB__Error(statement->errhp, statement->error, sizeof(statement->error), &statement->errorCode, status);
|
||
}
|
||
|
||
|
||
static DBT_Status DB__CheckFetch(DBT_Statement *statement, sword OCIrc, DBT_Result *result) {
|
||
sword OCIrc2;
|
||
int fetched = 0;
|
||
|
||
result->rowsProcessed = 0; /* will set it later if possible */
|
||
|
||
if (OCIrc == OCI_ERROR) {
|
||
/* see whether the error is "Fetched column value is truncated" */
|
||
/* do not consider it an error -- indicators indicate truncated data */
|
||
DB__Error_Statement(statement, OCIrc);
|
||
if (statement->errorCode == 1406) {
|
||
OCIrc = OCI_SUCCESS;
|
||
BDM_Trace(1, "libdatabase", "DB__CheckFetch", "Donn<EFBFBD>e tronqu<71>e");
|
||
} else {
|
||
BDM_Trace(0, "libdatabase", "DB__CheckFetch", "Erreur <20> l'ex<65>cution du statement : %s", statement->error);
|
||
return DBS_ERROCI;
|
||
}
|
||
} else if (OCIrc != OCI_SUCCESS && OCIrc != OCI_SUCCESS_WITH_INFO && OCIrc != OCI_NO_DATA) {
|
||
DB__Error_Statement(statement, OCIrc);
|
||
BDM_Trace(0, "libdatabase", "DB__CheckFetch", "Erreur <20> l'ex<65>cution du statement : %s", statement->error);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
/* OCI_SUCCESS_WITH_INFO may happen because of EOF reached or some
|
||
* data was truncated. I don't know how to distinguish these. */
|
||
|
||
/* get number of rows fetched -- this is mandatory */
|
||
OCIrc2 = OCIAttrGet(statement->handle, OCI_HTYPE_STMT, &fetched, NULL, OCI_ATTR_ROW_COUNT, statement->errhp);
|
||
if (OCIrc2 != OCI_SUCCESS) {
|
||
DB__Error_Statement(statement, OCIrc2);
|
||
BDM_Trace(0, "libdatabase", "DB__CheckFetch", "Echec de la r<>cup<75>ration du nombre de lignes du fetch : %sErreur <20> l'ex<65>cution du statement : %s", statement->error);
|
||
return DBS_ERROCI;
|
||
}
|
||
|
||
result->rowsProcessed = fetched - statement->rowsFetchedSoFar;
|
||
statement->rowsFetchedSoFar = fetched;
|
||
|
||
if (OCIrc == OCI_NO_DATA) {
|
||
statement->isEOF = 1;
|
||
return result->rowsProcessed ? DBS_OK : DBS_END_OF_DATA;
|
||
}
|
||
|
||
return DBS_OK;
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Fonction pour compatibilit<69> avec les pr<70>c<EFBFBD>dentes versions de libdatabase */
|
||
/*---------------------------------------------------------------------------------*/
|
||
DBT_Status DB_Connection_SQLError_Get(DBT_Connection *connection, dword *errCode, char **errStr) {
|
||
BDM_Trace(1, "libdatabase", "DB_Connection_SQLError_Get", "Cette fonction est obsol<6F>te ; cf BDT_Connection");
|
||
*errCode = connection->errorCode;
|
||
*errStr = connection->error;
|
||
return DBS_OK;
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Fonction pour compatibilit<69> avec les pr<70>c<EFBFBD>dentes versions de libdatabase */
|
||
/*---------------------------------------------------------------------------------*/
|
||
void DB_Debug_Level_Set(int level) {
|
||
BDM_Trace(1, "libdatabase", "DB_Debug_Level_Set", "Cette fonction est obsol<6F>te ; cf BDM_Trace_SetLevel");
|
||
BDM_Trace_SetLevel(level, "libdatabase");
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Fonction pour compatibilit<69> avec les pr<70>c<EFBFBD>dentes versions de libdatabase */
|
||
/*---------------------------------------------------------------------------------*/
|
||
DBT_Status DB_Statement_SQLError_Get(DBT_Statement *st, dword *errCode, char **errStr) {
|
||
BDM_Trace(1, "libdatabase", "DB_Statement_SQLError_Get", "Cette fonction est obsol<6F>te ; cf BDT_Statement");
|
||
*errCode = st->errorCode;
|
||
*errStr = st->error;
|
||
return DBS_OK;
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------------*/
|
||
/* Fonction pour compatibilit<69> avec les pr<70>c<EFBFBD>dentes versions de libdatabase */
|
||
/*---------------------------------------------------------------------------------*/
|
||
const char *DB_Error_Message_Get() {
|
||
BDM_Trace(1, "libdatabase", "DB_Error_Message_Get", "Cette fonction est obsol<6F>te ; cf BDM_Trace_LastError");
|
||
return BDM_Trace_LastError();
|
||
}
|