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 //
12 #include <anna/config/defines.hpp>
13 #include <anna/core/tracing/Logger.hpp>
14 #include <anna/core/DataBlock.hpp>
16 #include <anna/dbms/Float.hpp>
17 #include <anna/dbms/ShortBlock.hpp>
18 #include <anna/dbms/LongBlock.hpp>
19 #include <anna/dbms/String.hpp>
20 #include <anna/dbms/Date.hpp>
21 #include <anna/dbms/TimeStamp.hpp>
23 #include <anna/dbms.oracle/oracle.hpp>
28 OutputBind::OutputBind(const char* name, dbms::Data& data) :
29 dbms::OutputBind(name, data),
34 OutputBind::~OutputBind() {
37 void OutputBind::prepare(dbms::Statement* dbmsStatement, dbms::Connection* connection, const int pos)
38 throw(dbms::DatabaseException) {
39 if(a_ociDefine != NULL)
42 Database& database(static_cast <Database&>(dbmsStatement->getDatabase()));
43 OCIError* error = database.getErrorHandler();
44 Statement* statement(static_cast <Statement*>(dbmsStatement));
45 dbms::Data& data = anna::dbms::Bind::getData();
46 oci_param ociparam = getOCIParam(database, static_cast <oracle::Connection*>(connection), data);
48 if(data.isNulleable() == false) {
49 anna_dbms_oracle_check(
51 *statement, &a_ociDefine, error, pos, ociparam.buffer, ociparam.maxLength, ociparam.type,
52 0, ociparam.length, 0, OCI_DEFAULT
57 anna_dbms_oracle_check(
59 *statement, &a_ociDefine, error, pos, ociparam.buffer, ociparam.maxLength, ociparam.type,
60 &a_nullIndicator, ociparam.length, 0, OCI_DEFAULT
67 std::string msg("anna::dbms::oracle::OutputBind::prepare | ");
69 msg += " | Sentence: ";
70 msg += statement->getName();
71 msg += " | Position: ";
72 msg += functions::asString(pos);
73 Logger::debug(msg, ANNA_FILE_LOCATION)
77 //-------------------------------------------------------------------------------
78 // Transfiere la informacin obtenida desde Oracle. Todos los comprobados en �te
79 // m�odo son parametros que modificados al ejecuta la sentencia Oracle debido cmo
80 // hemos invocamo al m�odo OCIDefineByPos
82 // Todo esto se podr� haber hecho en la anna::dbms::DataBlock pero exigir�
83 // definir una clase distinta para cada RDBMS. Creo que los Binds particulares de
84 // cada base de datos se ocupen toda la complejidad de convertir los datos.
86 // (1) Truco para fijar el contenido y la longitud actual.
87 //-------------------------------------------------------------------------------
88 void OutputBind::decode() const
89 throw(RuntimeException) {
90 OutputBind* _this = const_cast <OutputBind*>(this);
92 Data& data = _this->getData();
93 data.setNull(a_nullIndicator < 0);
95 switch(data.getType()) {
96 case Data::Type::String:
97 str = (char*) data.getBuffer();
99 if(data.isNull() == true)
102 dbms::String::strip(str);
105 case Data::Type::Integer:
106 throw RuntimeException("anna::dbms::oracle::OutputBind::decode not implemented for Data::Type::Integer", ANNA_FILE_LOCATION);
108 case Data::Type::Float:
111 case Data::Type::ShortBlock:
112 decodeShortBlock(data);
114 case Data::Type::LongBlock:
115 decodeLongBlock(data);
117 case Data::Type::Date:
118 case Data::Type::TimeStamp:
122 } catch(DatabaseException& edb) {
123 throw RuntimeException(edb);
130 void OutputBind::decodeFloat(dbms::Data& data) const
131 throw(RuntimeException) {
132 dbms::Float& _float = static_cast <dbms::Float&>(data);
134 if(data.isNull() == true) {
139 char* _data = (char*) a_ofb->getData();
140 const char decimalPoint = oracle::Database::getDecimalPoint();
142 if(decimalPoint != 0) {
143 char* point = anna_strchr(_data, decimalPoint);
149 sscanf(_data, _float.getFormat(), (float*) _float.getBuffer());
152 void OutputBind::decodeShortBlock(dbms::Data& data) const
153 throw(RuntimeException) {
154 const anna::DataBlock& constdbms(static_cast <dbms::ShortBlock&>(data).getValue());
155 anna::DataBlock& dataBlock(const_cast <anna::DataBlock&>(constdbms));
157 if(data.isNull() == true) {
162 const char* src = a_ofb->getData();
164 char* dest = (char*) dataBlock.getData();
170 for(int i = 1; i < a_length; i += 2, j ++) {
171 hex = asByte(src [i - 1]) << 4;
172 hex |= asByte(src [i]);
177 dataBlock.allocate(j); // (1)
180 //--------------------------------------------------------------------------------------------
181 // (1) Offset = 1 => primer caracter.
182 //--------------------------------------------------------------------------------------------
183 void OutputBind::decodeLongBlock(dbms::Data& data) const
184 throw(RuntimeException) {
185 const anna::DataBlock& constdbms(static_cast <dbms::LongBlock&>(data).getValue());
186 anna::DataBlock& dataBlock(const_cast <anna::DataBlock&>(constdbms));
189 if(data.isNull() == true)
197 ub4 offset = 1; // (1)
200 buffer = (ub1*) a_ofb->getData();
201 maxLength = a_ofb->getSize();
205 ret = OCILobRead(a_blob.context, a_blob.error, a_blob.handle, &length, offset, buffer, maxLength, 0, 0, 0, SQLCS_IMPLICIT);
209 dataBlock += anna::DataBlock((const char*) buffer, length, false);
213 dataBlock += anna::DataBlock((const char*) buffer, length, false);
217 throw dbms::DatabaseException(oracle::ResultCode(ret, a_blob.error), ANNA_FILE_LOCATION);
219 } while(stop == false);
220 } catch(dbms::DatabaseException& edbms) {
221 throw RuntimeException(edbms);
225 void OutputBind::do_write(const dbms::LongBlock& data) const
226 throw(RuntimeException, dbms::DatabaseException) {
227 const anna::DataBlock& dataBlock = data.getValue();
229 if(a_blob.handle == NULL) {
230 string msg("anna::dbms::oracle::OutputBind::do_write | ");
231 msg += data.asString();
232 msg += " | BLOB must be loaded before modification";
233 throw RuntimeException(msg, ANNA_FILE_LOCATION);
236 ub1* buffer = (ub1*) dataBlock.getData();
237 ub4 length = dataBlock.getSize();
238 anna_dbms_oracle_check(
239 OCILobWrite(a_blob.context, a_blob.error, a_blob.handle, &length, (ub4) 1, buffer, length, OCI_ONE_PIECE, 0, 0, 0, SQLCS_IMPLICIT),
244 void OutputBind::decodeDate(dbms::Data& data) const
245 throw(RuntimeException, dbms::DatabaseException) {
246 if(data.isNull() == true)
249 Date& date = static_cast <Date&>(data);
252 anna_dbms_oracle_check(
253 OCIDateTimeGetDate(a_datetime.env, a_datetime.error, a_datetime.handle, &year, &month, &day),
257 date.setMonth(month);
261 sword status = OCIDateTimeGetTime(a_datetime.env, a_datetime.error, a_datetime.handle, &hour, &min, &sec, &fsec);
263 if(status == OCI_SUCCESS) {
268 if(data.getType() == Data::Type::TimeStamp)
269 static_cast <dbms::TimeStamp&>(data).setFractionalSecond(fsec / 1000);
275 if(data.getType() == Data::Type::TimeStamp)
276 static_cast <dbms::TimeStamp&>(data).setFractionalSecond(0);