Revert "Remove mysql and oracle resources for anna-ericsson project"
[anna.git] / include / anna / dbms / Statement.hpp
diff --git a/include/anna/dbms/Statement.hpp b/include/anna/dbms/Statement.hpp
new file mode 100644 (file)
index 0000000..df20293
--- /dev/null
@@ -0,0 +1,291 @@
+// 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 //
+
+
+#ifndef anna_dbms_Statement_hpp
+#define anna_dbms_Statement_hpp
+
+#include <vector>
+
+#include <anna/core/RuntimeException.hpp>
+#include <anna/core/mt/Mutex.hpp>
+#include <anna/core/util/Average.hpp>
+#include <anna/core/util/Microsecond.hpp>
+
+#include <anna/dbms/DatabaseException.hpp>
+#include <anna/dbms/ResultCode.hpp>
+
+namespace anna {
+
+namespace xml {
+class Node;
+}
+
+namespace dbms {
+
+class Database;
+class Connection;
+class InputBind;
+class OutputBind;
+class Data;
+
+/**
+   Clase que facilita la ejecucion de sentencias SQL.
+
+   Para obtener la instancia de un comando para una determinada base de datos habra que instanciar
+   dicha base de datos e invocar al metodo Database::createStatement. Independientemente del tipo de comando
+   particular que la base de datos retorne, debemos asignarlo a un puntero de tipo anna::dbms::Statement.
+*/
+class Statement : public Mutex {
+public:
+  typedef std::vector <InputBind*>::iterator input_iterator;
+  typedef std::vector <OutputBind*>::iterator output_iterator;
+
+  /**
+     Destructor.
+  */
+  virtual ~Statement();
+
+  /**
+     Devuelve el nombre logico de esta sentencia.
+     \return El nombre logico de esta sentencia.
+  */
+  const std::string& getName() const throw() { return a_name; }
+
+  /**
+     Devuelve la expresion SQL recibida en el constructor.
+     \return La expresion SQL recibida en el constructor.
+  */
+  const std::string& getExpression() const throw() { return a_expression; }
+
+  /**
+     Devuelve el indicador de criticidad, si vale \em true indica que si la ejecucion de esta sentencia
+     falla al desbloquear la conexion con la que ejecutamos esta sentencia se invocara a
+     Connection::rollback, en otro caso  aunque falle se invocara a Connection::commit.
+     Solo aplicara en sentencias que no sean de seleccion.
+     \return El indicador de criticidad de esta sentencia.
+  */
+  bool isCritical() const throw() { return a_isCritical; }
+
+  /**
+     Devuelve la instancia de la base de datos asociada a esta sentencia.
+     \return La instancia de la base de datos asociada a la sentencia.
+  */
+  Database& getDatabase() const throw() { return a_database; }
+
+  /**
+     Establece el parametro de entrada de la sentencia SQL.Cada una de las variables de entrada indicadas
+     en esta sentencia SQL deberia tener un parametro de entrada asociado. La correspondencia entre esta
+     variable y la sentencia SQL vendra dada por el orden de aparacion en la sentencia SQL y por el orden
+     de definicion del parametro.
+
+     Por ejemplo la sentencia:
+
+     \code
+     update tabla1 set xx = :unavariable where yy = :otravariable;
+     \endcode
+
+     Cada una de las variables \em unavariable y \em otravariable debera tener asociado una variable de entrada.
+     Primero debemos indicaremos la correspondiente a \em unavariable y luego la correspondiente a \em otravariable.
+
+     \param name Nombre logico de esta variable. No tiene porque tener ninguna correspondencia con el nombre
+     de la columna.
+     \param data Variable que deseamos asociar como variable de entrada. La correspondencia entre esta
+     y la sentencia SQL vendra dada por el orden de declaracion.
+  */
+  void bindInput(const char* name, Data& data) throw();
+
+  /**
+     Establece el parametro de salida de la sentencia SQL.Cada una de las variables de salida indicadas
+     en esta sentencia SQL deberia tener un parametro de salida asociado. La correspondencia entre esta
+     variable y la sentencia SQL vendra dada por el orden de aparacion en la sentencia SQL y por el orden
+     de definicion del parametro.
+
+     Por ejemplo la sentencia:
+
+     \code
+     select xx, yy from tabla1 where zz = :unavariable;
+     \endcode
+
+     Cada una de las variables \em xx e \em yy debera tener asociado una variable de salida.
+      Ademas la variable \em unavaraible debera tener asociada una variable de entrada.
+
+     \param name Nombre logico de esta variable. No tiene porque tener ninguna correspondencia con el nombre
+     de la columna.
+     \param data Variable que deseamos asociar como variable de salida. La correspondencia entre esta
+     y la sentencia SQL vendra dada por el orden de declaracion.
+
+     \return La instancia del dbms::OutputBind asociado al dato. nos permite
+     grabar el contenido de los tipos de datos BLOB.
+
+     \warning Solo las sentencias SQL del tipo \em select usan las variables de salida.
+  */
+  const dbms::OutputBind* bindOutput(const char* name, Data& data) throw();
+
+  /**
+     Establece el valor del indicador que activa/desactiva la necesidad de invocar al
+     \em commit y/o \em rollback despues de ejecutar esta sentencia.
+  */
+  void setRequiresCommit(const bool requiresCommit) throw() { a_requiresCommit = requiresCommit; }
+
+  /**
+     Devuelve \em true si la sentencia requiere la invocacion a \em commit o \em rollback
+     tras su ejecucion. Puede devolver \em true por tratarse de una sentencia que no tiene variables
+     de salida (insert, update o delete) o bien porque se haya activado el indicador correspondiente
+     mediante la llamada #setRequiresCommit
+  */
+  bool requiresCommit() const throw() { return (a_requiresCommit == true) || (a_outputBinds.empty() == true); }
+
+  /**
+     Devuelve el iterador que apunta a la primera variable de entrada.
+     \return el iterador que apunta a la primera variable de entrada.
+  */
+  input_iterator input_begin() throw() { return a_inputBinds.begin(); }
+
+  /**
+     Devuelve el iterador que apunta a la primera variable de entrada.
+     \return el iterador que apunta a la primera variable de entrada.
+  */
+  input_iterator input_end() throw() { return a_inputBinds.end(); }
+
+  /**
+     Devuelve el numero de variables de entrada asociado a esta sentencia SQL.
+     \return el numero de variables de entrada asociado a esta sentencia SQL.
+  */
+  int input_size() const throw() { return a_inputBinds.size(); }
+
+  /**
+     Devuelve el iterador que apunta a la primera variable de salida.
+     \return el iterador que apunta a la primera variable de salida.
+  */
+  output_iterator output_begin() throw() { return a_outputBinds.begin(); }
+
+  /**
+     Devuelve el iterador que apunta a la primera variable de salida.
+     \return el iterador que apunta a la primera variable de salida.
+  */
+  output_iterator output_end() throw() { return a_outputBinds.end(); }
+
+  /**
+     Devuelve el numero de variables de entrada asociado a esta sentencia SQL.
+     \return el numero de variables de entrada asociado a esta sentencia SQL.
+  */
+  int output_size() const throw() { return a_outputBinds.size(); }
+
+  /**
+     Devuelve un documento XML con la informacion referente a esta instancia.
+     \param parent Nodo XML del que debe colgar la informacion.
+     @return un documento XML con la informacion referente a esta instancia.
+  */
+  virtual xml::Node* asXML(xml::Node* parent) const throw();
+
+  /**
+     Devuelve una cadena con la informacion referente a esta instancia.
+     @return Una cadena con la informacion referente a esta instancia.
+  */
+  virtual std::string asString() const throw();
+
+  /**
+     Transfiere la informacion de una fila de la sentencia SQL de seleccion a las
+     variables de salida asociadas a la sentencia.
+
+     \return \em true si el registro ha sido transferido a las variables de salida o \em false si habiamos llegado
+     al ultimo registro de la seleccion.
+  */
+  virtual bool fetch() throw(RuntimeException, DatabaseException) = 0;
+
+  /**
+     Devuelve la variable de entrada apuntada por el iterador recibido como parametro.
+     \return la variable de entrada apuntada por el iterador recibido como parametro.
+  */
+  static Data& input(input_iterator& ii) throw();
+
+  /**
+     Devuelve la variable de salida apuntada por el iterador recibido como parametro.
+     \return la variable de salida apuntada por el iterador recibido como parametro.
+  */
+  static Data& output(output_iterator& ii) throw();
+
+protected:
+  /**
+     Contructor.
+
+     \param database Base de datos sobre la que se define la sentencia.
+     \param name Nombre logico de la sentencia.
+     \param expression Sentencia SQL asociada a esta clase.
+     \param isCritical Si vale \em true indica que si la ejecucion de esta sentencia falla al desbloquear
+     la conexion con la que ejecutamos esta sentencia se invocara a Connection::rollback, en otro caso
+     aunque falle se invocara a Connection::commit. Solo aplicara en sentencias que no sean de seleccion.
+  */
+  Statement(Database& database, const char* name, const char* expression, const bool isCritical) :
+    a_database(database),
+    a_name(name),
+    a_expression(expression),
+    a_prepared(false),
+    a_isCritical(isCritical),
+    a_measureTiming("Timing", "us"),
+    a_requiresCommit(false) {
+  }
+
+  /**
+     Contructor.
+
+     \param database Base de datos sobre la que se define la sentencia.
+     \param name Nombre logico de la sentencia.
+     \param expression Sentencia SQL asociada a esta clase.
+     \param isCritical Si vale \em true indica que si la ejecucion de esta sentencia falla al desbloquear
+     la conexion con la que ejecutamos esta sentencia se invocara a Connection::rollback, en otro caso
+     aunque falle se invocara a Connection::commit. Solo aplicara en cuenta en sentencias que no
+     sean de seleccion.
+  */
+  Statement(Database& database, const char* name, const std::string& expression, const bool isCritical) :
+    a_database(database),
+    a_name(name),
+    a_expression(expression),
+    a_prepared(false),
+    a_isCritical(isCritical),
+    a_measureTiming("Timing", "us"),
+    a_requiresCommit(false) {
+  }
+
+  /**
+     Devuelve la referencia de entrada apuntada por el iterador recibido como parametro.
+     \return la referencia de entrada apuntada por el iterador recibido como parametro.
+  */
+  static InputBind* inputBind(input_iterator& ii) throw() { return *ii; }
+
+  /**
+     Devuelve la referencia de salida apuntada por el iterador recibido como parametro.
+     \return la referencia de salida apuntada por el iterador recibido como parametro.
+  */
+  static OutputBind* outputBind(output_iterator& ii) throw() { return *ii; }
+
+private:
+  Database& a_database;
+  const std::string a_name;
+  std::string a_expression;
+  std::vector <InputBind*> a_inputBinds;  /**< Lista de variables de entrada */
+  std::vector <OutputBind*> a_outputBinds; /**< Lista de variables de salida */
+  bool a_prepared;
+  const bool a_isCritical;
+  Average <Microsecond> a_measureTiming;
+  bool a_requiresCommit;
+
+  Statement(const Statement&);
+  void measureTiming(const Microsecond & init, const Microsecond & end) throw() { a_measureTiming += (end - init); }
+
+  virtual void prepare(Connection* connection) throw(RuntimeException, DatabaseException) = 0;
+  virtual ResultCode execute(Connection* connection) throw(RuntimeException, DatabaseException) = 0;
+
+  friend class Connection;
+  friend class Database;
+};
+
+}
+}
+
+#endif