--- /dev/null
+// 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;
+}