Updated license
[anna.git] / include / anna / dbms / Database.hpp
1 // ANNA - Anna is Not Nothingness Anymore
2 //
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
4 //
5 // https://bitbucket.org/testillano/anna
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 //
11 //     * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 //     * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 //     * Neither the name of Google Inc. nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 // Authors: eduardo.ramos.testillano@gmail.com
34 //          cisco.tierra@gmail.com
35
36
37 #ifndef anna_dbms_Database_hpp
38 #define anna_dbms_Database_hpp
39
40 #include <vector>
41
42 #include <anna/app/Component.hpp>
43
44 #include <anna/dbms/Connection.hpp>
45
46 namespace anna {
47
48 namespace comm {
49 class INetAddress;
50 class Delivery;
51 }
52
53 namespace dbms {
54
55 class Statement;
56 class InputBind;
57 class OutputBind;
58 class Data;
59 class FailRecoveryHandler;
60 class StatementTranslator;
61
62 /**
63    Clase que modela la interaccion entre la base y nuestra aplicacion.
64 */
65 class Database : public app::Component {
66 public:
67   /**
68      Numero maximo de conexiones que podemos crear.
69   */
70   static const int MaxConnection = 32;
71
72   /**
73      Formas de conexion a la base de datos.
74   */
75   struct Type {
76     enum _v { Local, Remote } value;
77     Type() : value(Local) {;}
78     Type(const _v v) : value(v) {;}
79     Type(const Type& v) : value(v.value) {;}
80     operator int () const throw() { return value; }
81   };
82
83   typedef std::vector <Connection*>::const_iterator const_connection_iterator; /**<Iterador para acceder a las conexiones de esta base de datos */
84   typedef std::vector <Statement*>::const_iterator const_statement_iterator; /**<Iterador para acceder a las conexiones de esta base de datos */
85
86   /**
87      Destructor.
88   */
89   virtual ~Database();
90
91   /**
92      Devuelve el tipo de conexion de esta base de datos.
93      \return El tipo de conexion de esta base de datos.
94   */
95   const Type& getType() const throw() { return a_type; }
96
97   /**
98      Devuelve el nombre de la base de datos indicado en el constructor.
99      \return El nombre de la base de datos indicado en el constructor.
100   */
101   const std::string& getName() const throw() { return a_name; }
102
103   /**
104      Establece el manejador encargado de actuar cuando la recuperacion de la conexion falla.
105      El manejador por defecto no realiza ninguna activad.
106      \param failRecoveryHandler Manejador que seria invocado en caso de que no sea posible recuperar
107      una determina conexion.
108   */
109   void setFailRecoveryHandler(FailRecoveryHandler* failRecoveryHandler) throw() { a_failRecoveryHandler = failRecoveryHandler; }
110
111   /**
112    * Establece el traductor de sentencias SQL usado ajustar las sentencias SQL al
113    * motor de base de datos usados en la aplicaciĆ³n.
114    */
115   void setStatementTranslator(StatementTranslator* statementTranslator) throw() { a_statementTranslator = statementTranslator; }
116
117   /**
118      Crea y registra una nueva conexion con esta base de datos.
119      La clase usada para conectar con esta base de datos dependeria de la implementacion particular, que
120      seria definida por el metodo #allocateConnection.
121
122      \param name Nombre logico de la conexion a crear.
123      @param user Nombre del usuario con el que realizamos la conexion.
124      @param password Codigo de acceso del usuario.
125
126      @return La instancia de la nueva conexion a la base de datos.
127   */
128   Connection* createConnection(const char* name, const char* user, const char* password)
129   throw(RuntimeException, DatabaseException);
130
131   /**
132      Devuelve la conexion asociada al nombre logico recibido como parametro.
133      \param name Nombre logico de la conexion que queremos obtener.
134      \return La conexion asociada al nombre logico recibido como parametro.
135      \warning Si la conexion logica no existe no puede ser usada se lanzara una excepcion.
136   */
137   Connection& findConnection(const char* name) throw(RuntimeException);
138
139   /**
140      Devuelve un iterator al comienzo de la lista de conexiones establecidas con esta base de datos.
141      \return Un iterator al comienzo de la lista de conexiones establecidas con esta base de datos.
142   */
143   const_connection_iterator connection_begin() const throw() { return a_connections.begin(); }
144
145   /**
146      Devuelve un iterator al final de la lista de conexiones establecidas con esta base de datos.
147      \return Un iterator al final de la lista de conexiones establecidas con esta base de datos.
148   */
149   const_connection_iterator connection_end() const throw() { return a_connections.end(); }
150
151   /**
152      Crea y registra una nueva sentencia SQL asociada a esta base de datos.
153      La clase usada para interpretar la sentencia SQL dependera de la implementacion particular definida
154      mediante el metodo #allocateStatement.
155
156      \param name Nombre logico de esta sentencia.
157      \param expression Expresion asociada a la sentencia.
158      \param isCritical Si vale \em true indica que si la ejecucion de esta sentencia falla al desbloquear
159      la conexion con la que ejecutamos esta sentencia se invocara a Connection::rollback, en otro caso
160      aunque falle se invocara a Connection::commit. Solo aplicara en sentencias que no sean de seleccion.
161
162      \return Una nueva instancia de una conexion a base de datos. No puede ser NULL.
163   */
164   Statement* createStatement(const char* name, const char* expression, const bool isCritical = true)
165   throw(RuntimeException);
166
167   /**
168      Crea y registra una nueva sentencia SQL asociada a esta base de datos.
169      La clase usada para interpretar la sentencia SQL dependera de la implementacion particular definida
170      mediante el metodo #allocateStatement.
171
172      \param name Nombre logico de esta sentencia.
173      \param expression Expresion asociada a la sentencia.
174      \param isCritical Si vale \em true indica que si la ejecucion de esta sentencia falla al desbloquear
175      la conexion con la que ejecutamos esta sentencia se invocara a Connection::rollback, en otro caso
176      aunque falle se invocara a Connection::commit. Solo aplicara en sentencias que no sean de seleccion.
177
178      \return Una nueva instancia de una conexion a base de datos. No puede ser NULL.
179   */
180   Statement* createStatement(const char* name, const std::string& expression, const bool isCritical = true)
181   throw(RuntimeException) {
182     return createStatement(name, expression.c_str(), isCritical);
183   }
184
185   /**
186      Devuelve la instancia de la sentencia SQL asociada al nombre recibido como parametro.
187
188      @return La instancia de la sentencia SQL  asociada al nombre recibido.
189      Puede ser NULL si el nombre no fue registrado previamente con #createStatement.
190   */
191   Statement* findStatement(const char* name) throw();
192
193   /**
194      Libera los recursos de la sentencia SQL recibida como parametro.
195      \param statement Instancia de la sentencia SQL a liberar. deberia haber sido obtenida mediante
196      el metodo #createStatement.
197   */
198   void releaseStatement(Statement* statement) throw();
199
200   /**
201      Devuelve un iterator al comienzo de la lista de sentencias SQL creadas en esta base de datos.
202      \return Un iterator al comienzo de la lista de sentencias SQL creadas en esta base de datos.
203   */
204   const_statement_iterator statement_begin() const throw() { return a_statements.begin(); }
205
206   /**
207      Devuelve un iterator al final de la lista de sentencias SQL creadas en esta base de datos.
208      \return Un iterator al final de la lista de sentencias SQL creadas en esta base de datos.
209   */
210   const_statement_iterator statement_end() const throw() { return a_statements.end(); }
211
212   /**
213      Devuelve el objeto sobre el que esta posicionado el iterator recibido como parametro.
214      \param ii Iterator que deberia estar comprendido entre #statement_begin y #statement_end.
215      \return El objeto sobre el que esta posicionado el iterator recibido como parametro.
216   */
217   static Statement* statement(const_statement_iterator& ii) throw() { return *ii; }
218
219   /**
220      Devuelve una cadena con la informacion mas relevante de esta instancia.
221      \return Una cadena con la informacion mas relevante de esta instancia.
222   */
223   virtual std::string asString() const throw();
224
225   /**
226      Devuelve un documento XML con la informacion mas relevante de esta instancia.
227      \param parent Nodo XML del que colgar la informacion referente a esta instancia.
228      \return Un documento XML con la informacion mas relevante de esta instancia.
229   */
230   virtual xml::Node* asXML(xml::Node* parent) const throw();
231
232   /**
233      Devuelve el objeto sobre el que esta posicionado el iterator recibido como parametro.
234      \param ii Iterator que deberia estar comprendido entre #connection_begin y #connection_end.
235      \return El objeto sobre el que esta posicionado el iterator recibido como parametro.
236   */
237   static const Connection* connection(const_connection_iterator& ii) throw() { return *ii; }
238
239 protected:
240   typedef std::vector <Connection*>::iterator connection_iterator; /**<Iterador para acceder a las conexiones de esta base de datos */
241
242   /**
243      Contructor.
244      \param rdbmsmsName Nombre del RDMS que gestiona esta base de datos.
245      \param dbmsName Nombre de la base de datos.
246   */
247   Database(const char* rdbmsmsName, const char* dbmsName);
248
249   /**
250      Recupera el estado de una conexion perdida.
251      \warning Este metodo se invoca automaticamente desde el nucleo de ANNA.dbms y nunca deberia
252      ser invocado por el programador.
253      \param connection Instancia de la conexion en la que hemos detectado el fallo.
254      \param tryCounter numero de intentos de recuperacion de la conexion.
255   */
256   void recover(Connection& connection, const int tryCounter) throw(RuntimeException);
257
258   /**
259      Inicializa las conexiones definidas sobre esta base de datos. Este metodo se invocaria
260      automaticamente desde el nucleo de ANNA.
261      Slo seria necesario invocarlo cuando nuestro programa no tenga asociada ninguna aplicacion
262      que se encarga de inicializar los componentes.
263   */
264   virtual void do_initialize() throw(RuntimeException);
265
266   /**
267      Elimina las conexiones definidas sobre esta base de datos. Este metodo se invocaria automaticamente
268      desde el nucleo de ANNA.
269   */
270   virtual void do_stop() throw();
271
272   /**
273      Devuelve un iterator al comienzo de la lista de conexiones establecidas con esta base de datos.
274      \return Un iterator al comienzo de la lista de conexiones establecidas con esta base de datos.
275   */
276   connection_iterator connection_begin() throw() { return a_connections.begin(); }
277
278   /**
279      Devuelve un iterator al final de la lista de conexiones establecidas con esta base de datos.
280      \return Un iterator al final de la lista de conexiones establecidas con esta base de datos.
281   */
282   connection_iterator connection_end() throw() { return a_connections.end(); }
283
284   /**
285      Devuelve el objeto sobre el que esta posicionado el iterator recibido como parametro.
286      \param ii Iterator que deberia estar comprendido entre #connection_begin y #connection_end.
287      \return El objeto sobre el que esta posicionado el iterator recibido como parametro.
288   */
289   static Connection* connection(connection_iterator& ii) throw() { return *ii; }
290
291 private:
292   const std::string a_name;
293   std::vector <Connection*> a_connections;
294   std::vector <Statement*> a_statements;
295   const Type a_type;
296   FailRecoveryHandler* a_failRecoveryHandler;
297   StatementTranslator* a_statementTranslator;
298
299   Database(const Database&);
300
301   void do_cloneChild() throw(RuntimeException);
302
303   virtual Connection* allocateConnection(const std::string& name, const char* user, const char* password)
304   throw(RuntimeException) = 0;
305
306   virtual Statement* allocateStatement(const char* name, const std::string& expression, const bool isCritical)
307   throw(RuntimeException) = 0;
308
309   virtual InputBind* allocateInputBind(const char* name, Data& data)
310   throw(RuntimeException) = 0;
311   virtual void deallocate(InputBind* inputBind) throw() = 0;
312
313   virtual OutputBind* allocateOutputBind(const char* name, Data& data)
314   throw(RuntimeException) = 0;
315   virtual void deallocate(OutputBind* outputBind) throw() = 0;
316
317   friend class Statement;
318   friend ResultCode Connection::execute(Statement*) throw(RuntimeException, DatabaseException);
319 };
320
321 }
322 }
323
324 #endif