Revert "Remove mysql and oracle resources for anna-ericsson project"
[anna.git] / source / dbms.mysql / Statement.cpp
diff --git a/source/dbms.mysql/Statement.cpp b/source/dbms.mysql/Statement.cpp
new file mode 100644 (file)
index 0000000..df18acc
--- /dev/null
@@ -0,0 +1,192 @@
+// 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 <mysql/mysql.h>
+
+#include <anna/config/defines.hpp>
+#include <anna/core/tracing/TraceMethod.hpp>
+
+#include <anna/dbms.mysql/mysql.hpp>
+
+using namespace std;
+using namespace anna;
+
+dbms::mysql::Statement::~Statement() {
+  if(a_mysqlStmt) {
+    try {
+      anna_dbms_mysql_check(mysql_stmt_close(a_mysqlStmt), a_mysqlStmt);
+    } catch(DatabaseException& edb) {
+      edb.trace();
+    }
+  }
+
+  delete [] a_params;
+  delete [] a_results;
+}
+
+/**
+ * Según el ejemplo de: http://dev.mysql.com/doc/refman/4.1/en/mysql-stmt-fetch.html
+ *
+ */
+void dbms::mysql::Statement::prepare(dbms::Connection* dbmsConnection)
+throw(RuntimeException, dbms::DatabaseException) {
+  LOGMETHOD(TraceMethod tm("anna::dbms::mysql::Statement", "prepare", ANNA_FILE_LOCATION));
+  Connection* connection(static_cast <Connection*>(dbmsConnection));
+  //Database& dbms(static_cast <Database&>(connection->getDatabase()));
+  LOGDEBUG(
+    string msg("anna::dbms::mysql::Statement::prepare | ");
+    msg += asString();
+    Logger::debug(msg, ANNA_FILE_LOCATION);
+  );
+
+  /*
+   * Libera la información establecida anteriormente. Las sentencias se pueden reusar.
+   */
+  if(a_mysqlStmt != NULL) {
+    anna_dbms_mysql_check(mysql_stmt_reset(a_mysqlStmt), a_mysqlStmt);
+    delete [] a_params;
+    delete [] a_results;
+    a_params = a_results = NULL;
+  } else if((a_mysqlStmt = mysql_stmt_init(*connection)) == NULL) {
+    string msg(asString());
+    msg += " | Insufficient memory";
+    throw RuntimeException(msg, ANNA_FILE_LOCATION);
+  }
+
+  const char* expression = dbms::Statement::getExpression().c_str();
+
+  anna_dbms_mysql_check(mysql_stmt_prepare(a_mysqlStmt, expression, anna_strlen(expression)), a_mysqlStmt);
+
+  const int paramCount = mysql_stmt_param_count(a_mysqlStmt);
+
+  const int inputSize = dbms::Statement::input_size();
+
+  const int outputSize = dbms::Statement::output_size();
+
+  /*
+   * Verifica que el número de parámetros de entrada de la sentencia coincida con el número de parámetros
+   * indicados por el programador.
+   */
+  if(paramCount != inputSize) {
+    string msg(asString());
+    msg += " | Wrong input parameters";
+    throw RuntimeException(msg, ANNA_FILE_LOCATION);
+  }
+
+  /*
+   * Verifica que el número de parámetros de salida de la sentencia coincida con el número de parámetros
+   * indicados por el programador. Si no tiene parámetros de salida (INSERT) => no debe tener parámetros
+   * indicados por el programador.
+   */
+  MYSQL_RES* metaResult = mysql_stmt_result_metadata(a_mysqlStmt);
+
+  try {
+    if(metaResult == NULL) {
+      if(outputSize != 0) {
+        string msg(asString());
+        msg += " | Wrong output parameters";
+        throw RuntimeException(msg, ANNA_FILE_LOCATION);
+      }
+    } else if(mysql_num_fields(metaResult) != outputSize) {
+      string msg(asString());
+      msg += " | Wrong output parameters";
+      throw RuntimeException(msg, ANNA_FILE_LOCATION);
+    }
+  } catch(RuntimeException&) {
+    mysql_free_result(metaResult);
+    throw;
+  }
+
+  /*
+   * Define las estructuras requeridas para asociar las columasn MySQL con las áreas de memoria C++
+   */
+  int pos;
+
+  if((a_params = create(inputSize, "input")) != NULL) {
+    pos = 0;
+
+    for(input_iterator ii = input_begin(), maxii = input_end(); ii != maxii; ii ++)
+      inputBind(ii)->prepare(this, dbmsConnection, pos ++);
+
+    anna_dbms_mysql_check(mysql_stmt_bind_param(a_mysqlStmt, a_params), a_mysqlStmt);
+  }
+
+  if((a_results = create(outputSize, "output")) != NULL) {
+    pos = 0;
+
+    for(output_iterator oo = output_begin(), maxoo = output_end(); oo != maxoo; oo ++)
+      outputBind(oo)->prepare(this, dbmsConnection, pos ++);
+
+    anna_dbms_mysql_check(mysql_stmt_bind_result(a_mysqlStmt, a_results), a_mysqlStmt);
+  }
+}
+
+dbms::ResultCode dbms::mysql::Statement::execute(dbms::Connection* dbmsConnection)
+throw(RuntimeException, dbms::DatabaseException) {
+  //Connection* connection(static_cast <Connection*>(dbmsConnection));
+
+  for(input_iterator ii = input_begin(), maxii = input_end(); ii != maxii; ii ++) {
+    inputBind(ii)->code();
+    LOGDEBUG(
+      string msg("anna::dbms::mysql::Statement::InputBind: ");
+      msg += inputBind(ii)->asString();
+      Logger::debug(msg, ANNA_FILE_LOCATION);
+    );
+  }
+
+  anna_dbms_mysql_check(mysql_stmt_execute(a_mysqlStmt), a_mysqlStmt)
+  ResultCode result(a_mysqlStmt);
+  return result;
+}
+
+/*
+ * Según la información de http://dev.mysql.com/doc/refman/4.1/en/mysql-stmt-fetch.html
+ */
+bool dbms::mysql::Statement::fetch()
+throw(RuntimeException, dbms::DatabaseException) {
+  bool result = false;
+
+  switch(mysql_stmt_fetch(a_mysqlStmt)) {
+  case 0:
+    result = true;
+
+    for(output_iterator oo = output_begin(), maxoo = output_end(); oo != maxoo; oo ++) {
+      outputBind(oo)->decode();
+      LOGDEBUG(Logger::write(Logger::Debug, outputBind(oo)->asString(), ANNA_FILE_LOCATION));
+    }
+
+    break;
+  case 1:
+    throw DatabaseException(ResultCode(a_mysqlStmt), ANNA_FILE_LOCATION);
+  default:
+    result = false;
+    break;
+  }
+
+  LOGDEBUG(
+    string msg("anna::dbms::mysql::Statement::fetch | Result: ");
+    msg += functions::asString(result);
+    Logger::debug(msg, ANNA_FILE_LOCATION);
+  );
+  return result;
+}
+
+st_mysql_bind* dbms::mysql::Statement::create(const int size, const char* whatis)
+throw(RuntimeException) {
+  st_mysql_bind* result = NULL;
+
+  if(size > 0) {
+    if((result = new st_mysql_bind [size]) == NULL) {
+      string msg(asString());
+      msg += anna::functions::asString("Insufficient memory to create %d parameters of %s", size, whatis);
+      throw RuntimeException(msg, ANNA_FILE_LOCATION);
+    }
+  }
+
+  return result;
+}