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 //
9 #ifndef anna_dbms_Statement_hpp
10 #define anna_dbms_Statement_hpp
14 #include <anna/core/RuntimeException.hpp>
15 #include <anna/core/mt/Mutex.hpp>
16 #include <anna/core/util/Average.hpp>
17 #include <anna/core/util/Microsecond.hpp>
19 #include <anna/dbms/DatabaseException.hpp>
20 #include <anna/dbms/ResultCode.hpp>
37 Clase que facilita la ejecucion de sentencias SQL.
39 Para obtener la instancia de un comando para una determinada base de datos habra que instanciar
40 dicha base de datos e invocar al metodo Database::createStatement. Independientemente del tipo de comando
41 particular que la base de datos retorne, debemos asignarlo a un puntero de tipo anna::dbms::Statement.
43 class Statement : public Mutex {
45 typedef std::vector <InputBind*>::iterator input_iterator;
46 typedef std::vector <OutputBind*>::iterator output_iterator;
54 Devuelve el nombre logico de esta sentencia.
55 \return El nombre logico de esta sentencia.
57 const std::string& getName() const { return a_name; }
60 Devuelve la expresion SQL recibida en el constructor.
61 \return La expresion SQL recibida en el constructor.
63 const std::string& getExpression() const { return a_expression; }
66 Devuelve el indicador de criticidad, si vale \em true indica que si la ejecucion de esta sentencia
67 falla al desbloquear la conexion con la que ejecutamos esta sentencia se invocara a
68 Connection::rollback, en otro caso aunque falle se invocara a Connection::commit.
69 Solo aplicara en sentencias que no sean de seleccion.
70 \return El indicador de criticidad de esta sentencia.
72 bool isCritical() const { return a_isCritical; }
75 Devuelve la instancia de la base de datos asociada a esta sentencia.
76 \return La instancia de la base de datos asociada a la sentencia.
78 Database& getDatabase() const { return a_database; }
81 Establece el parametro de entrada de la sentencia SQL.Cada una de las variables de entrada indicadas
82 en esta sentencia SQL deberia tener un parametro de entrada asociado. La correspondencia entre esta
83 variable y la sentencia SQL vendra dada por el orden de aparacion en la sentencia SQL y por el orden
84 de definicion del parametro.
86 Por ejemplo la sentencia:
89 update tabla1 set xx = :unavariable where yy = :otravariable;
92 Cada una de las variables \em unavariable y \em otravariable debera tener asociado una variable de entrada.
93 Primero debemos indicaremos la correspondiente a \em unavariable y luego la correspondiente a \em otravariable.
95 \param name Nombre logico de esta variable. No tiene porque tener ninguna correspondencia con el nombre
97 \param data Variable que deseamos asociar como variable de entrada. La correspondencia entre esta
98 y la sentencia SQL vendra dada por el orden de declaracion.
100 void bindInput(const char* name, Data& data) ;
103 Establece el parametro de salida de la sentencia SQL.Cada una de las variables de salida indicadas
104 en esta sentencia SQL deberia tener un parametro de salida asociado. La correspondencia entre esta
105 variable y la sentencia SQL vendra dada por el orden de aparacion en la sentencia SQL y por el orden
106 de definicion del parametro.
108 Por ejemplo la sentencia:
111 select xx, yy from tabla1 where zz = :unavariable;
114 Cada una de las variables \em xx e \em yy debera tener asociado una variable de salida.
115 Ademas la variable \em unavaraible debera tener asociada una variable de entrada.
117 \param name Nombre logico de esta variable. No tiene porque tener ninguna correspondencia con el nombre
119 \param data Variable que deseamos asociar como variable de salida. La correspondencia entre esta
120 y la sentencia SQL vendra dada por el orden de declaracion.
122 \return La instancia del dbms::OutputBind asociado al dato. nos permite
123 grabar el contenido de los tipos de datos BLOB.
125 \warning Solo las sentencias SQL del tipo \em select usan las variables de salida.
127 const dbms::OutputBind* bindOutput(const char* name, Data& data) ;
130 Establece el valor del indicador que activa/desactiva la necesidad de invocar al
131 \em commit y/o \em rollback despues de ejecutar esta sentencia.
133 void setRequiresCommit(const bool requiresCommit) { a_requiresCommit = requiresCommit; }
136 Devuelve \em true si la sentencia requiere la invocacion a \em commit o \em rollback
137 tras su ejecucion. Puede devolver \em true por tratarse de una sentencia que no tiene variables
138 de salida (insert, update o delete) o bien porque se haya activado el indicador correspondiente
139 mediante la llamada #setRequiresCommit
141 bool requiresCommit() const { return (a_requiresCommit == true) || (a_outputBinds.empty() == true); }
144 Devuelve el iterador que apunta a la primera variable de entrada.
145 \return el iterador que apunta a la primera variable de entrada.
147 input_iterator input_begin() { return a_inputBinds.begin(); }
150 Devuelve el iterador que apunta a la primera variable de entrada.
151 \return el iterador que apunta a la primera variable de entrada.
153 input_iterator input_end() { return a_inputBinds.end(); }
156 Devuelve el numero de variables de entrada asociado a esta sentencia SQL.
157 \return el numero de variables de entrada asociado a esta sentencia SQL.
159 int input_size() const { return a_inputBinds.size(); }
162 Devuelve el iterador que apunta a la primera variable de salida.
163 \return el iterador que apunta a la primera variable de salida.
165 output_iterator output_begin() { return a_outputBinds.begin(); }
168 Devuelve el iterador que apunta a la primera variable de salida.
169 \return el iterador que apunta a la primera variable de salida.
171 output_iterator output_end() { return a_outputBinds.end(); }
174 Devuelve el numero de variables de entrada asociado a esta sentencia SQL.
175 \return el numero de variables de entrada asociado a esta sentencia SQL.
177 int output_size() const { return a_outputBinds.size(); }
180 Devuelve un documento XML con la informacion referente a esta instancia.
181 \param parent Nodo XML del que debe colgar la informacion.
182 @return un documento XML con la informacion referente a esta instancia.
184 virtual xml::Node* asXML(xml::Node* parent) const ;
187 Devuelve una cadena con la informacion referente a esta instancia.
188 @return Una cadena con la informacion referente a esta instancia.
190 virtual std::string asString() const ;
193 Transfiere la informacion de una fila de la sentencia SQL de seleccion a las
194 variables de salida asociadas a la sentencia.
196 \return \em true si el registro ha sido transferido a las variables de salida o \em false si habiamos llegado
197 al ultimo registro de la seleccion.
199 virtual bool fetch() noexcept(false) = 0;
202 Devuelve la variable de entrada apuntada por el iterador recibido como parametro.
203 \return la variable de entrada apuntada por el iterador recibido como parametro.
205 static Data& input(input_iterator& ii) ;
208 Devuelve la variable de salida apuntada por el iterador recibido como parametro.
209 \return la variable de salida apuntada por el iterador recibido como parametro.
211 static Data& output(output_iterator& ii) ;
217 \param database Base de datos sobre la que se define la sentencia.
218 \param name Nombre logico de la sentencia.
219 \param expression Sentencia SQL asociada a esta clase.
220 \param isCritical Si vale \em true indica que si la ejecucion de esta sentencia falla al desbloquear
221 la conexion con la que ejecutamos esta sentencia se invocara a Connection::rollback, en otro caso
222 aunque falle se invocara a Connection::commit. Solo aplicara en sentencias que no sean de seleccion.
224 Statement(Database& database, const char* name, const char* expression, const bool isCritical) :
225 a_database(database),
227 a_expression(expression),
229 a_isCritical(isCritical),
230 a_measureTiming("Timing", "us"),
231 a_requiresCommit(false) {
237 \param database Base de datos sobre la que se define la sentencia.
238 \param name Nombre logico de la sentencia.
239 \param expression Sentencia SQL asociada a esta clase.
240 \param isCritical Si vale \em true indica que si la ejecucion de esta sentencia falla al desbloquear
241 la conexion con la que ejecutamos esta sentencia se invocara a Connection::rollback, en otro caso
242 aunque falle se invocara a Connection::commit. Solo aplicara en cuenta en sentencias que no
245 Statement(Database& database, const char* name, const std::string& expression, const bool isCritical) :
246 a_database(database),
248 a_expression(expression),
250 a_isCritical(isCritical),
251 a_measureTiming("Timing", "us"),
252 a_requiresCommit(false) {
256 Devuelve la referencia de entrada apuntada por el iterador recibido como parametro.
257 \return la referencia de entrada apuntada por el iterador recibido como parametro.
259 static InputBind* inputBind(input_iterator& ii) { return *ii; }
262 Devuelve la referencia de salida apuntada por el iterador recibido como parametro.
263 \return la referencia de salida apuntada por el iterador recibido como parametro.
265 static OutputBind* outputBind(output_iterator& ii) { return *ii; }
268 Database& a_database;
269 const std::string a_name;
270 std::string a_expression;
271 std::vector <InputBind*> a_inputBinds; /**< Lista de variables de entrada */
272 std::vector <OutputBind*> a_outputBinds; /**< Lista de variables de salida */
274 const bool a_isCritical;
275 Average <Microsecond> a_measureTiming;
276 bool a_requiresCommit;
278 Statement(const Statement&);
279 void measureTiming(const Microsecond & init, const Microsecond & end) { a_measureTiming += (end - init); }
281 virtual void prepare(Connection* connection) noexcept(false) = 0;
282 virtual ResultCode execute(Connection* connection) noexcept(false) = 0;
284 friend class Connection;
285 friend class Database;