1 // ANNA - Anna is Not Nothingness Anymore //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
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 //
9 #include <mysql/mysql.h>
11 #include <anna/config/defines.hpp>
12 #include <anna/core/tracing/TraceMethod.hpp>
14 #include <anna/dbms.mysql/mysql.hpp>
19 dbms::mysql::Statement::~Statement() {
22 anna_dbms_mysql_check(mysql_stmt_close(a_mysqlStmt), a_mysqlStmt);
23 } catch(DatabaseException& edb) {
33 * Según el ejemplo de: http://dev.mysql.com/doc/refman/4.1/en/mysql-stmt-fetch.html
36 void dbms::mysql::Statement::prepare(dbms::Connection* dbmsConnection)
37 throw(RuntimeException, dbms::DatabaseException) {
38 LOGMETHOD(TraceMethod tm("anna::dbms::mysql::Statement", "prepare", ANNA_FILE_LOCATION));
39 Connection* connection(static_cast <Connection*>(dbmsConnection));
40 Database& dbms(static_cast <Database&>(connection->getDatabase()));
42 string msg("anna::dbms::mysql::Statement::prepare | ");
44 Logger::debug(msg, ANNA_FILE_LOCATION);
48 * Libera la información establecida anteriormente. Las sentencias se pueden reusar.
50 if(a_mysqlStmt != NULL) {
51 anna_dbms_mysql_check(mysql_stmt_reset(a_mysqlStmt), a_mysqlStmt);
54 a_params = a_results = NULL;
55 } else if((a_mysqlStmt = mysql_stmt_init(*connection)) == NULL) {
56 string msg(asString());
57 msg += " | Insufficient memory";
58 throw RuntimeException(msg, ANNA_FILE_LOCATION);
61 const char* expression = dbms::Statement::getExpression().c_str();
63 anna_dbms_mysql_check(mysql_stmt_prepare(a_mysqlStmt, expression, anna_strlen(expression)), a_mysqlStmt);
65 const int paramCount = mysql_stmt_param_count(a_mysqlStmt);
67 const int inputSize = dbms::Statement::input_size();
69 const int outputSize = dbms::Statement::output_size();
72 * Verifica que el número de parámetros de entrada de la sentencia coincida con el número de parámetros
73 * indicados por el programador.
75 if(paramCount != inputSize) {
76 string msg(asString());
77 msg += " | Wrong input parameters";
78 throw RuntimeException(msg, ANNA_FILE_LOCATION);
82 * Verifica que el número de parámetros de salida de la sentencia coincida con el número de parámetros
83 * indicados por el programador. Si no tiene parámetros de salida (INSERT) => no debe tener parámetros
84 * indicados por el programador.
86 MYSQL_RES* metaResult = mysql_stmt_result_metadata(a_mysqlStmt);
89 if(metaResult == NULL) {
91 string msg(asString());
92 msg += " | Wrong output parameters";
93 throw RuntimeException(msg, ANNA_FILE_LOCATION);
95 } else if(mysql_num_fields(metaResult) != outputSize) {
96 string msg(asString());
97 msg += " | Wrong output parameters";
98 throw RuntimeException(msg, ANNA_FILE_LOCATION);
100 } catch(RuntimeException&) {
101 mysql_free_result(metaResult);
106 * Define las estructuras requeridas para asociar las columasn MySQL con las áreas de memoria C++
110 if((a_params = create(inputSize, "input")) != NULL) {
113 for(input_iterator ii = input_begin(), maxii = input_end(); ii != maxii; ii ++)
114 inputBind(ii)->prepare(this, dbmsConnection, pos ++);
116 anna_dbms_mysql_check(mysql_stmt_bind_param(a_mysqlStmt, a_params), a_mysqlStmt);
119 if((a_results = create(outputSize, "output")) != NULL) {
122 for(output_iterator oo = output_begin(), maxoo = output_end(); oo != maxoo; oo ++)
123 outputBind(oo)->prepare(this, dbmsConnection, pos ++);
125 anna_dbms_mysql_check(mysql_stmt_bind_result(a_mysqlStmt, a_results), a_mysqlStmt);
129 dbms::ResultCode dbms::mysql::Statement::execute(dbms::Connection* dbmsConnection)
130 throw(RuntimeException, dbms::DatabaseException) {
131 Connection* connection(static_cast <Connection*>(dbmsConnection));
133 for(input_iterator ii = input_begin(), maxii = input_end(); ii != maxii; ii ++) {
134 inputBind(ii)->code();
136 string msg("anna::dbms::mysql::Statement::InputBind: ");
137 msg += inputBind(ii)->asString();
138 Logger::debug(msg, ANNA_FILE_LOCATION);
142 anna_dbms_mysql_check(mysql_stmt_execute(a_mysqlStmt), a_mysqlStmt)
143 ResultCode result(a_mysqlStmt);
148 * Según la información de http://dev.mysql.com/doc/refman/4.1/en/mysql-stmt-fetch.html
150 bool dbms::mysql::Statement::fetch()
151 throw(RuntimeException, dbms::DatabaseException) {
154 switch(mysql_stmt_fetch(a_mysqlStmt)) {
158 for(output_iterator oo = output_begin(), maxoo = output_end(); oo != maxoo; oo ++) {
159 outputBind(oo)->decode();
160 LOGDEBUG(Logger::write(Logger::Debug, outputBind(oo)->asString(), ANNA_FILE_LOCATION));
165 throw DatabaseException(ResultCode(a_mysqlStmt), ANNA_FILE_LOCATION);
172 string msg("anna::dbms::mysql::Statement::fetch | Result: ");
173 msg += functions::asString(result);
174 Logger::debug(msg, ANNA_FILE_LOCATION);
179 st_mysql_bind* dbms::mysql::Statement::create(const int size, const char* whatis)
180 throw(RuntimeException) {
181 st_mysql_bind* result = NULL;
184 if((result = new st_mysql_bind [size]) == NULL) {
185 string msg(asString());
186 msg += anna::functions::asString("Insufficient memory to create %d parameters of %s", size, whatis);
187 throw RuntimeException(msg, ANNA_FILE_LOCATION);