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 //
13 #include <anna/config/defines.hpp>
14 #include <anna/core/functions.hpp>
15 #include <anna/core/DataBlock.hpp>
16 #include <anna/core/tracing/Logger.hpp>
18 #include <anna/dbms/Float.hpp>
19 #include <anna/dbms/ShortBlock.hpp>
20 #include <anna/dbms/Date.hpp>
21 #include <anna/dbms/TimeStamp.hpp>
22 #include <anna/dbms/Database.hpp>
24 #include <anna/dbms.oracle/oracle.hpp>
29 InputBind::InputBind(const char* name, dbms::Data& data) :
30 dbms::InputBind(name, data),
35 InputBind::~InputBind() {
38 // Slo se invoca una vez. Establece las variables atrav� de las que nos vamos a poder
39 // comunicar con Oracle, para indicar la longitud de una variable, o su estado de nulo o
41 void InputBind::prepare(dbms::Statement* dbmsStatement, dbms::Connection* connection, const int pos)
42 throw(RuntimeException, dbms::DatabaseException) {
46 Data& data = anna::dbms::Bind::getData();
48 if(data.getType() == Data::Type::LongBlock) {
49 string msg("anna::dbms::oracle::InputBind::prepare | ");
50 msg += data.asString();
51 msg += " | This RDBMS doesn't support BLOB type as BindInput (see anna::dbms::OutputBind::write)";
52 throw RuntimeException(msg, ANNA_FILE_LOCATION);
55 Database& database = static_cast <Database&>(dbmsStatement->getDatabase());
56 OCIError* error = database.getErrorHandler();
57 Statement* statement(static_cast <Statement*>(dbmsStatement));
58 oci_param ociparam = getOCIParam(database, static_cast <oracle::Connection*>(connection), data);
60 if(data.isNulleable() == false) {
61 anna_dbms_oracle_check(
63 *statement, &a_ociBind, error, pos, ociparam.buffer, ociparam.maxLength, ociparam.type,
64 0, ociparam.length, 0, 0, 0, OCI_DEFAULT
69 anna_dbms_oracle_check(
71 *statement, &a_ociBind, error, pos, ociparam.buffer, ociparam.maxLength, ociparam.type,
72 &a_nullIndicator, ociparam.length, 0, 0, 0, OCI_DEFAULT
79 std::string msg("anna::dbms::oracle::InputBind::prepare | ");
81 msg += " | Sentence: ";
82 msg += statement->getName();
83 msg += " | Position: ";
84 msg += functions::asString(pos);
85 Logger::debug(msg, ANNA_FILE_LOCATION)
89 //-------------------------------------------------------------------------------
90 // Establece la informacin mediante la que conectamos con Oracle. Todos los
91 // par�etros que modificamos en �te m�odo tienen efecto en la llamada a Oracle
92 // debido cmo hemos invocamo al m�odo OCIBindByPos.
94 // Todo esto se podr� haber hecho en la anna::dbms::DataBlock pero exigir�
95 // definir una clase distinta para cada RDBMS. Creo que los Binds particulares de
96 // cada base de datos se ocupen toda la complejidad de convertir los datos.
97 //-------------------------------------------------------------------------------
98 void InputBind::code() const
99 throw(RuntimeException) {
100 InputBind* _this = const_cast <InputBind*>(this);
101 Data& data = _this->getData();
103 if((_this->a_nullIndicator = data.isNull() ? -1 : 0) == -1)
106 switch(data.getType()) {
107 case Data::Type::Float:
110 case Data::Type::ShortBlock:
111 codeShortBlock(data);
113 case Data::Type::Date:
114 case Data::Type::TimeStamp:
118 } catch(DatabaseException& edb) {
119 throw RuntimeException(edb);
127 * Transfiere el valor numerico del float, al buffer reservado para
128 * ubiucarlo como una cadena. Ã
\89ste buffer es el que está "conectado" con
131 void InputBind::codeFloat(dbms::Data& data) const
133 dbms::Float& _float = static_cast <dbms::Float&>(data);
134 InputBind* _this = const_cast <InputBind*>(this);
135 char* buffer = (char*) _this->a_ofb->getData();
136 snprintf(buffer, FloatSize, _float.getFormat(), _float.getValue());
137 const char decimalPoint = oracle::Database::getDecimalPoint();
139 if(decimalPoint != 0) {
140 char* point = anna_strchr(buffer, '.');
143 *point = decimalPoint;
147 void InputBind::codeShortBlock(dbms::Data& data) const
149 const int length = static_cast <dbms::ShortBlock&>(data).getSize();
150 InputBind* _this = const_cast <InputBind*>(this);
153 _this->a_ofb->clear();
158 const char* src = (const char*) data.getBuffer();
160 char* dest = const_cast <char*>(a_ofb->getData());
164 for(int i = 0; i < length; i ++) {
165 dest [j ++] = asCharacter((src [i] & 0xf0) >> 4);
166 dest [j ++] = asCharacter(src [i] & 0x0f);
173 void InputBind::codeDate(dbms::Data& data) const
174 throw(RuntimeException, dbms::DatabaseException) {
175 dbms::Date& date = static_cast <dbms::Date&>(data);
178 if(data.getType() == Data::Type::TimeStamp)
179 fsec = static_cast <dbms::TimeStamp&>(data).getFractionalSecond() * 1000;
181 anna_dbms_oracle_check(
182 OCIDateTimeConstruct(
183 a_datetime.env, a_datetime.error, a_datetime.handle,
184 date.getYear(), date.getMonth(), date.getDay(), date.getHour(), date.getMinute(), date.getSecond(), fsec, NULL, 0
189 anna_dbms_oracle_check(
190 OCIDateTimeCheck(a_datetime.env, a_datetime.error, a_datetime.handle, &errorMask),
195 string msg(data.asString());
196 msg += anna::functions::asHexText(" | Invalid date | ErrorCode: ", (int) errorMask);
197 throw RuntimeException(msg, ANNA_FILE_LOCATION);