+++ /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 <oci.h>
-
-#include <time.h>
-
-#include <anna/config/defines.hpp>
-#include <anna/core/functions.hpp>
-#include <anna/core/DataBlock.hpp>
-#include <anna/core/tracing/Logger.hpp>
-
-#include <anna/dbms/Float.hpp>
-#include <anna/dbms/ShortBlock.hpp>
-#include <anna/dbms/Date.hpp>
-#include <anna/dbms/TimeStamp.hpp>
-#include <anna/dbms/Database.hpp>
-
-#include <anna/dbms.oracle/oracle.hpp>
-
-using namespace std;
-using namespace anna;
-
-InputBind::InputBind(const char* name, dbms::Data& data) :
- dbms::InputBind(name, data),
- BaseBind(data),
- a_ociBind(NULL) {
-}
-
-InputBind::~InputBind() {
-}
-
-// Slo se invoca una vez. Establece las variables atrav� de las que nos vamos a poder
-// comunicar con Oracle, para indicar la longitud de una variable, o su estado de nulo o
-// no nulo.
-void InputBind::prepare(dbms::Statement* dbmsStatement, dbms::Connection* connection, const int pos)
-throw(RuntimeException, dbms::DatabaseException) {
- if(a_ociBind != NULL)
- return;
-
- Data& data = anna::dbms::Bind::getData();
-
- if(data.getType() == Data::Type::LongBlock) {
- string msg("anna::dbms::oracle::InputBind::prepare | ");
- msg += data.asString();
- msg += " | This RDBMS doesn't support BLOB type as BindInput (see anna::dbms::OutputBind::write)";
- throw RuntimeException(msg, ANNA_FILE_LOCATION);
- }
-
- Database& database = static_cast <Database&>(dbmsStatement->getDatabase());
- OCIError* error = database.getErrorHandler();
- Statement* statement(static_cast <Statement*>(dbmsStatement));
- oci_param ociparam = getOCIParam(database, static_cast <oracle::Connection*>(connection), data);
-
- if(data.isNulleable() == false) {
- anna_dbms_oracle_check(
- OCIBindByPos(
- *statement, &a_ociBind, error, pos, ociparam.buffer, ociparam.maxLength, ociparam.type,
- 0, ociparam.length, 0, 0, 0, OCI_DEFAULT
- ),
- error
- );
- } else {
- anna_dbms_oracle_check(
- OCIBindByPos(
- *statement, &a_ociBind, error, pos, ociparam.buffer, ociparam.maxLength, ociparam.type,
- &a_nullIndicator, ociparam.length, 0, 0, 0, OCI_DEFAULT
- ),
- error
- );
- }
-
- LOGDEBUG(
- std::string msg("anna::dbms::oracle::InputBind::prepare | ");
- msg += asString();
- msg += " | Sentence: ";
- msg += statement->getName();
- msg += " | Position: ";
- msg += functions::asString(pos);
- Logger::debug(msg, ANNA_FILE_LOCATION)
- );
-}
-
-//-------------------------------------------------------------------------------
-// Establece la informacin mediante la que conectamos con Oracle. Todos los
-// par�etros que modificamos en �te m�odo tienen efecto en la llamada a Oracle
-// debido cmo hemos invocamo al m�odo OCIBindByPos.
-//
-// Todo esto se podr� haber hecho en la anna::dbms::DataBlock pero exigir�
-// definir una clase distinta para cada RDBMS. Creo que los Binds particulares de
-// cada base de datos se ocupen toda la complejidad de convertir los datos.
-//-------------------------------------------------------------------------------
-void InputBind::code() const
-throw(RuntimeException) {
- InputBind* _this = const_cast <InputBind*>(this);
- Data& data = _this->getData();
-
- if((_this->a_nullIndicator = data.isNull() ? -1 : 0) == -1)
- return;
-
- switch(data.getType()) {
- case Data::Type::String:
- throw RuntimeException("anna::dbms::oracle::InputBind::code not implemented for Data::Type::String", ANNA_FILE_LOCATION);
- break;
- case Data::Type::Integer:
- throw RuntimeException("anna::dbms::oracle::InputBind::code not implemented for Data::Type::Integer", ANNA_FILE_LOCATION);
- break;
- case Data::Type::Float:
- codeFloat(data);
- break;
- case Data::Type::ShortBlock:
- codeShortBlock(data);
- break;
- case Data::Type::LongBlock:
- throw RuntimeException("anna::dbms::oracle::InputBind::code not implemented for Data::Type::LongBlock", ANNA_FILE_LOCATION);
- break;
- case Data::Type::Date:
- case Data::Type::TimeStamp:
-
- try {
- codeDate(data);
- } catch(DatabaseException& edb) {
- throw RuntimeException(edb);
- }
-
- break;
- }
-}
-
-/**
- * Transfiere el valor numerico del float, al buffer reservado para
- * ubiucarlo como una cadena. Ã\89ste buffer es el que está "conectado" con
- * Oracle (tm).
- */
-void InputBind::codeFloat(dbms::Data& data) const
-throw() {
- dbms::Float& _float = static_cast <dbms::Float&>(data);
- InputBind* _this = const_cast <InputBind*>(this);
- char* buffer = (char*) _this->a_ofb->getData();
- snprintf(buffer, FloatSize, _float.getFormat(), _float.getValue());
- const char decimalPoint = oracle::Database::getDecimalPoint();
-
- if(decimalPoint != 0) {
- char* point = anna_strchr(buffer, '.');
-
- if(point != NULL)
- *point = decimalPoint;
- }
-}
-
-void InputBind::codeShortBlock(dbms::Data& data) const
-throw() {
- const int length = static_cast <dbms::ShortBlock&>(data).getSize();
- InputBind* _this = const_cast <InputBind*>(this);
-
- if(length == 0) {
- _this->a_ofb->clear();
- _this->a_length = 0;
- return;
- }
-
- const char* src = (const char*) data.getBuffer();
-
- char* dest = const_cast <char*>(a_ofb->getData());
-
- int j = 0;
-
- for(int i = 0; i < length; i ++) {
- dest [j ++] = asCharacter((src [i] & 0xf0) >> 4);
- dest [j ++] = asCharacter(src [i] & 0x0f);
- }
-
- dest [j ++] = 0;
- _this->a_length = j;
-}
-
-void InputBind::codeDate(dbms::Data& data) const
-throw(RuntimeException, dbms::DatabaseException) {
- dbms::Date& date = static_cast <dbms::Date&>(data);
- ub4 fsec(0);
-
- if(data.getType() == Data::Type::TimeStamp)
- fsec = static_cast <dbms::TimeStamp&>(data).getFractionalSecond() * 1000;
-
- anna_dbms_oracle_check(
- OCIDateTimeConstruct(
- a_datetime.env, a_datetime.error, a_datetime.handle,
- date.getYear(), date.getMonth(), date.getDay(), date.getHour(), date.getMinute(), date.getSecond(), fsec, NULL, 0
- ),
- a_datetime.error
- );
- ub4 errorMask(0);
- anna_dbms_oracle_check(
- OCIDateTimeCheck(a_datetime.env, a_datetime.error, a_datetime.handle, &errorMask),
- a_datetime.error
- );
-
- if(errorMask != 0) {
- string msg(data.asString());
- msg += anna::functions::asHexText(" | Invalid date | ErrorCode: ", (int) errorMask);
- throw RuntimeException(msg, ANNA_FILE_LOCATION);
- }
-}