Revert "Remove mysql and oracle resources for anna-ericsson project"
[anna.git] / source / dbms.oracle / Database.cpp
diff --git a/source/dbms.oracle/Database.cpp b/source/dbms.oracle/Database.cpp
new file mode 100644 (file)
index 0000000..a90785e
--- /dev/null
@@ -0,0 +1,139 @@
+// ANNA - Anna is Not Nothingness Anymore                                                         //
+//                                                                                                //
+// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
+//                                                                                                //
+// See project site at http://redmine.teslayout.com/projects/anna-suite                           //
+// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
+
+
+#include <locale.h>
+
+#include <oci.h>
+
+#include <anna/core/tracing/Logger.hpp>
+#include <anna/core/tracing/TraceMethod.hpp>
+
+#include <anna/dbms.oracle/oracle.hpp>
+#include <anna/dbms.oracle/internal/sccs.hpp>
+
+using namespace std;
+using namespace anna;
+using namespace anna::dbms;
+
+char oracle::Database::st_decimalPoint = 0;
+
+oracle::Database::Database(const char* dbmsName) :
+  dbms::Database(getClassName(), dbmsName),
+  a_env(NULL),
+  a_error(NULL) {
+  oracle::sccs::activate();
+}
+
+oracle::Database::Database(const char* componentName, const char* dbmsName) :
+  dbms::Database(componentName, dbmsName),
+  a_env(NULL),
+  a_error(NULL) {
+  oracle::sccs::activate();
+}
+
+void oracle::Database::do_initialize()
+throw(RuntimeException) {
+  LOGMETHOD(TraceMethod tm("anna::dbms::oracle::Database", "do_initialize", ANNA_FILE_LOCATION));
+
+  if(a_env != NULL) {
+    Logger::write(Logger::Warning, asString(), "Already initialized", ANNA_FILE_LOCATION);
+    return;
+  }
+
+  if(OCIInitialize(OCI_DEFAULT, 0, 0, 0, 0) != OCI_SUCCESS) {
+    string msg(asString());
+    msg += " | Cannot initialize Oracle access system";
+    throw RuntimeException(msg, ANNA_FILE_LOCATION);
+  }
+
+  if(OCIEnvInit(&a_env, OCI_DEFAULT, 0, 0) != OCI_SUCCESS) {
+    string msg(asString());
+    msg += " | Cannot create database environment";
+    throw RuntimeException(msg, ANNA_FILE_LOCATION);
+  }
+
+  if(OCIHandleAlloc(a_env, (void**) &a_error, OCI_HTYPE_ERROR, 0, 0) != OCI_SUCCESS) {
+    string msg(asString());
+    msg += " | Cannot create database error handler";
+    throw RuntimeException(msg, ANNA_FILE_LOCATION);
+  }
+
+  WHEN_MULTITHREAD(
+    OCIThreadProcessInit();
+    anna_dbms_oracle_check(OCIThreadInit(a_env, a_error), a_error);
+  );
+  initializeDecimalPoint();
+  dbms::Database::do_initialize();
+}
+
+//----------------------------------------------------------------------------------
+// Libera todos los manejadores asociados a �te entorno.
+//----------------------------------------------------------------------------------
+oracle::Database::~Database() {
+  LOGMETHOD(TraceMethod tm("anna::dbms::oracle::Database", "~Database", ANNA_FILE_LOCATION));
+
+  if(a_error) {
+    OCIHandleFree(a_env, OCI_HTYPE_ERROR);
+    a_env = NULL;
+  }
+
+  if(a_env) {
+    OCIHandleFree(a_env, OCI_HTYPE_ENV);
+    a_env = NULL;
+  }
+}
+
+dbms::Connection* oracle::Database::allocateConnection(const std::string& name, const char* user, const char* password)
+throw(RuntimeException) {
+  return new Connection(*this, name, user, password);
+}
+
+dbms::Statement* oracle::Database::allocateStatement(const char* name, const std::string& expression, const bool isCritical)
+throw(RuntimeException) {
+  return new Statement(*this, name, expression, isCritical);
+}
+
+dbms::InputBind* oracle::Database::allocateInputBind(const char* name, Data& data)
+throw(RuntimeException) {
+  return new InputBind(name, data);
+}
+
+void oracle::Database::deallocate(dbms::InputBind* inputBind)
+throw() {
+  delete(InputBind*) inputBind;
+}
+
+dbms::OutputBind* oracle::Database::allocateOutputBind(const char* name, Data& data)
+throw(RuntimeException) {
+  return new OutputBind(name, data);
+}
+
+void oracle::Database::deallocate(dbms::OutputBind* outputBind)
+throw() {
+  delete(OutputBind*) outputBind;
+}
+
+/**
+ * Ojo no se activa el uso de forma definitiva porque afectaría a todo el programa, cualquier
+ * conversion texto -> float/double que se hiciera se vería afectado por este cambio, que sólo debería
+ * aplicar a temas relaciones con la base de datos.
+ *
+ * Carga el valor del LC_NUMERIC de la correspondiente variable del entorno y luego repone el
+ * usado por defecto en las librerias del core de C.
+ */
+/*static*/
+void oracle::Database::initializeDecimalPoint()
+throw(RuntimeException) {
+  setlocale(LC_NUMERIC, "");
+  struct lconv *locale = localeconv();
+
+  if(*locale->decimal_point != '.')
+    st_decimalPoint = *locale->decimal_point;
+
+  setlocale(LC_NUMERIC, "C");
+}