f8f14b9025194f3fc81d51908283bf55114848d4
[anna.git] / source / dbms.oracle / Database.cpp
1 // ANNA - Anna is Not Nothingness Anymore                                                         //
2 //                                                                                                //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
4 //                                                                                                //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite                           //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
7
8
9 #include <locale.h>
10
11 #include <oci.h>
12
13 #include <anna/core/tracing/Logger.hpp>
14 #include <anna/core/tracing/TraceMethod.hpp>
15
16 #include <anna/dbms.oracle/oracle.hpp>
17 #include <anna/dbms.oracle/internal/sccs.hpp>
18
19 using namespace std;
20 using namespace anna;
21 using namespace anna::dbms;
22
23 char oracle::Database::st_decimalPoint = 0;
24
25 oracle::Database::Database(const char* dbmsName) :
26   dbms::Database(getClassName(), dbmsName),
27   a_env(NULL),
28   a_error(NULL) {
29   oracle::sccs::activate();
30 }
31
32 oracle::Database::Database(const char* componentName, const char* dbmsName) :
33   dbms::Database(componentName, dbmsName),
34   a_env(NULL),
35   a_error(NULL) {
36   oracle::sccs::activate();
37 }
38
39 void oracle::Database::do_initialize()
40 throw(RuntimeException) {
41   LOGMETHOD(TraceMethod tm("anna::dbms::oracle::Database", "do_initialize", ANNA_FILE_LOCATION));
42   int status;
43
44   if(a_env != NULL) {
45     Logger::write(Logger::Warning, asString(), "Already initialized", ANNA_FILE_LOCATION);
46     return;
47   }
48
49   if(OCIInitialize(OCI_DEFAULT, 0, 0, 0, 0) != OCI_SUCCESS) {
50     string msg(asString());
51     msg += " | Cannot initialize Oracle access system";
52     throw RuntimeException(msg, ANNA_FILE_LOCATION);
53   }
54
55   if(OCIEnvInit(&a_env, OCI_DEFAULT, 0, 0) != OCI_SUCCESS) {
56     string msg(asString());
57     msg += " | Cannot create database environment";
58     throw RuntimeException(msg, ANNA_FILE_LOCATION);
59   }
60
61   if(OCIHandleAlloc(a_env, (void**) &a_error, OCI_HTYPE_ERROR, 0, 0) != OCI_SUCCESS) {
62     string msg(asString());
63     msg += " | Cannot create database error handler";
64     throw RuntimeException(msg, ANNA_FILE_LOCATION);
65   }
66
67   WHEN_MULTITHREAD(
68     OCIThreadProcessInit();
69     anna_dbms_oracle_check(OCIThreadInit(a_env, a_error), a_error);
70   );
71   initializeDecimalPoint();
72   dbms::Database::do_initialize();
73 }
74
75 //----------------------------------------------------------------------------------
76 // Libera todos los manejadores asociados a �te entorno.
77 //----------------------------------------------------------------------------------
78 oracle::Database::~Database() {
79   LOGMETHOD(TraceMethod tm("anna::dbms::oracle::Database", "~Database", ANNA_FILE_LOCATION));
80
81   if(a_error) {
82     OCIHandleFree(a_env, OCI_HTYPE_ERROR);
83     a_env = NULL;
84   }
85
86   if(a_env) {
87     OCIHandleFree(a_env, OCI_HTYPE_ENV);
88     a_env = NULL;
89   }
90 }
91
92 dbms::Connection* oracle::Database::allocateConnection(const std::string& name, const char* user, const char* password)
93 throw(RuntimeException) {
94   return new Connection(*this, name, user, password);
95 }
96
97 dbms::Statement* oracle::Database::allocateStatement(const char* name, const std::string& expression, const bool isCritical)
98 throw(RuntimeException) {
99   return new Statement(*this, name, expression, isCritical);
100 }
101
102 dbms::InputBind* oracle::Database::allocateInputBind(const char* name, Data& data)
103 throw(RuntimeException) {
104   return new InputBind(name, data);
105 }
106
107 void oracle::Database::deallocate(dbms::InputBind* inputBind)
108 throw() {
109   delete(InputBind*) inputBind;
110 }
111
112 dbms::OutputBind* oracle::Database::allocateOutputBind(const char* name, Data& data)
113 throw(RuntimeException) {
114   return new OutputBind(name, data);
115 }
116
117 void oracle::Database::deallocate(dbms::OutputBind* outputBind)
118 throw() {
119   delete(OutputBind*) outputBind;
120 }
121
122 /**
123  * Ojo no se activa el uso de forma definitiva porque afectaría a todo el programa, cualquier
124  * conversion texto -> float/double que se hiciera se vería afectado por este cambio, que sólo debería
125  * aplicar a temas relaciones con la base de datos.
126  *
127  * Carga el valor del LC_NUMERIC de la correspondiente variable del entorno y luego repone el
128  * usado por defecto en las librerias del core de C.
129  */
130 /*static*/
131 void oracle::Database::initializeDecimalPoint()
132 throw(RuntimeException) {
133   setlocale(LC_NUMERIC, "");
134   struct lconv *locale = localeconv();
135
136   if(*locale->decimal_point != '.')
137     st_decimalPoint = *locale->decimal_point;
138
139   setlocale(LC_NUMERIC, "C");
140 }