Fix symlinks
[anna.git] / source / dbms.oracle / Statement.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 <oci.h>
10
11 #include <anna/config/defines.hpp>
12 #include <anna/core/tracing/TraceMethod.hpp>
13
14 #include <anna/dbms.oracle/oracle.hpp>
15
16 using namespace std;
17 using namespace anna;
18
19 dbms::oracle::Statement::~Statement() {
20   if(a_ociStmt)
21     OCIHandleFree(a_ociStmt, OCI_HTYPE_STMT);
22 }
23
24 void dbms::oracle::Statement::prepare(dbms::Connection* dbmsConnection)
25 throw(RuntimeException, dbms::DatabaseException) {
26   LOGMETHOD(TraceMethod tm("anna::dbms::oracle::Statement", "prepare", ANNA_FILE_LOCATION));
27   Connection* connection(static_cast <Connection*>(dbmsConnection));
28   Database& dbms(static_cast <Database&>(connection->getDatabase()));
29   a_ociError = dbms.getErrorHandler();
30
31   if(a_ociStmt != NULL) {
32     anna_dbms_oracle_check(OCIHandleFree(a_ociStmt, OCI_HTYPE_STMT), a_ociError);
33     a_ociStmt = NULL;
34   }
35
36   const char* expression = dbms::oracle::Statement::getExpression().c_str();
37
38   anna_dbms_oracle_check(OCIHandleAlloc(dbms, (void**) &a_ociStmt, OCI_HTYPE_STMT, 0, 0), a_ociError);
39
40   anna_dbms_oracle_check(
41     OCIStmtPrepare(a_ociStmt, a_ociError, (text*) expression, anna_strlen(expression), OCI_NTV_SYNTAX, OCI_DEFAULT),
42     a_ociError
43   );
44
45   int pos = 1;
46
47   for(input_iterator ii = input_begin(), maxii = input_end(); ii != maxii; ii ++)
48     inputBind(ii)->prepare(this, dbmsConnection, pos ++);
49
50   pos = 1;
51
52   for(output_iterator oo = output_begin(), maxoo = output_end(); oo != maxoo; oo ++)
53     outputBind(oo)->prepare(this, dbmsConnection, pos ++);
54 }
55
56 dbms::ResultCode dbms::oracle::Statement::execute(dbms::Connection* dbmsConnection)
57 throw(RuntimeException, dbms::DatabaseException) {
58   Connection* connection(static_cast <Connection*>(dbmsConnection));
59
60   for(input_iterator ii = input_begin(), maxii = input_end(); ii != maxii; ii ++) {
61     inputBind(ii)->code();
62     LOGDEBUG(
63       string msg("anna::dbms::oracle::Statement::InputBind: ");
64       msg += inputBind(ii)->asString();
65       Logger::debug(msg, ANNA_FILE_LOCATION);
66     );
67   }
68
69   const sword status = OCIStmtExecute(*connection, a_ociStmt, a_ociError, 1, 0, NULL, NULL, OCI_DEFAULT);
70
71   a_firstFetch = false;
72
73   ResultCode result(status, a_ociError);
74
75   if(result.successful() == true && result.notFound() == false) {
76     for(output_iterator oo = output_begin(), maxoo = output_end(); oo != maxoo; oo ++) {
77       outputBind(oo)->decode();
78       LOGDEBUG(
79         string msg("anna::dbms::oracle::Statement::OutputBind: ");
80         msg += outputBind(oo)->asString();
81         Logger::debug(msg, ANNA_FILE_LOCATION);
82       );
83     }
84
85     a_firstFetch = true;
86   }
87
88   return result;
89 }
90
91 //-------------------------------------------------------------------------------------------------
92 // (1) Si es una consulta de seleccin, entonces, nada m� ejecutar la sentencia el primer registro
93 //     encontrado ya est�cargado en las variables de salida, para obtener los siguientes hay que invocar
94 //     a fetch. Vamos a hacer este esquema m� gen�ico de forma que siempre habr�que invocar a
95 //     'fetch' para obtener los datos, pero en Oracle, la primera llamada no har�nada.
96 //-------------------------------------------------------------------------------------------------
97 bool dbms::oracle::Statement::fetch()
98 throw(RuntimeException, dbms::DatabaseException) {
99   bool result;
100
101   if(a_firstFetch == true) {    // (1)
102     a_firstFetch = false;
103     result = true;
104   } else {
105     ResultCode resultCode(OCIStmtFetch(a_ociStmt, a_ociError, 1, OCI_FETCH_NEXT, OCI_DEFAULT), a_ociError);
106     result = resultCode.successful();
107
108     if(result == false && resultCode.notFound() == false)
109       Logger::write(Logger::Error, asString(), resultCode.asString(), ANNA_FILE_LOCATION);
110
111     if(result == true) {
112       for(output_iterator oo = output_begin(), maxoo = output_end(); oo != maxoo; oo ++) {
113         outputBind(oo)->decode();
114         LOGDEBUG(Logger::write(Logger::Debug, outputBind(oo)->asString(), ANNA_FILE_LOCATION));
115       }
116     }
117   }
118
119   LOGDEBUG(
120     string msg("anna::dbms::oracle::Statement::fetch | Result: ");
121     msg += functions::asString(result);
122     Logger::debug(msg, ANNA_FILE_LOCATION);
123   );
124   return result;
125 }
126
127
128