Added database abstractions
[gnucomo.git] / src / lib / database.cpp
1
2 /**************************************************************************
3 **  (c) Copyright 2002, Andromeda Technology & Automation
4 ** This is free software; you can redistribute it and/or modify it under the
5 ** terms of the GNU General Public License, see the file COPYING.
6 ***************************************************************************
7 ** MODULE INFORMATION *
8 ***********************
9 **      FILE NAME      : database.cpp
10 **      SYSTEM NAME    : Gnucomo - Gnu Computer Monitoring
11 **      VERSION NUMBER : $Revision: 1.13 $
12 **
13 **  DESCRIPTION      :  Implementation of the gnucomo database classes
14 **
15 **  EXPORTED OBJECTS : 
16 **  LOCAL    OBJECTS : 
17 **  MODULES  USED    :
18 ***************************************************************************
19 **  ADMINISTRATIVE INFORMATION *
20 ********************************
21 **      ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl
22 **      CREATION DATE   : Sep 10, 2002
23 **      LAST UPDATE     : Aug 17, 2003
24 **      MODIFICATIONS   : 
25 **************************************************************************/
26
27 #include <date.h>
28
29 //#define DEBUG
30
31 #include "database.h"
32
33 extern std::ostream *Log;
34
35 /*=========================================================================
36 **  NAME           : gnucomo_database
37 **  SYNOPSIS       : gnucomo_database(gnucomo_config &c);
38 **  PARAMETERS     : 
39 **  RETURN VALUE   : Database constructor. Establishes a connection with
40 **                   the database server.
41 **
42 **  DESCRIPTION    : 
43 **
44 **  VARS USED      :
45 **  VARS CHANGED   :
46 **  FUNCTIONS USED :
47 **  SEE ALSO       :
48 **  LAST MODIFIED  : Sep 23, 2020
49 **=========================================================================
50 */
51
52 static int gdb_refcount = 0;
53
54 gnucomo_database::gnucomo_database(gnucomo_config *c)
55 {
56    dbconn = 0;
57    dbxact = 0;
58    cfg = c;
59
60    try
61    {
62       dbconn = new pqxx::connection(cfg->Database());
63
64       if (!dbconn->is_open())
65       {
66          std::cerr << "Connection to database failed.\n";
67       }
68       else
69       {
70          // Create the transaction object
71
72          dbxact = new pqxx::work(*dbconn, "GnuCoMo");
73          gdb_refcount++;
74       }
75    }
76    catch (std::exception &e)
77    {
78       *Log << "Cannot setup the database transaction: " << e.what() << "\n";
79    }
80 }
81
82 gnucomo_database::gnucomo_database(const gnucomo_database &gdb)
83 {
84    dbconn = gdb.dbconn;
85    dbxact = gdb.dbxact;
86    gdb_refcount++;
87 }
88
89 void gnucomo_database::operator = (const gnucomo_database &gdb)
90 {
91    dbconn = gdb.dbconn;
92    dbxact = gdb.dbxact;
93    gdb_refcount++;
94 }
95
96    //      A destructor must Commit the transaction and
97    //      destroy the transaction before destroying the
98    //      connection.
99    //      The connection can only be destroyed by the last
100    //      object alive.
101
102 gnucomo_database::~gnucomo_database()
103 {
104    if (--gdb_refcount == 0 && dbconn != 0 && dbxact != 0)
105    {
106       dbxact->commit();
107       delete dbxact;
108       dbxact = 0;
109       delete dbconn;
110       dbconn = 0;
111    }
112 }
113
114 /*=========================================================================
115 **  NAME           : find_host
116 **  SYNOPSIS       : String gnucomo_database::find_host(String hostname);
117 **  PARAMETERS     : 
118 **  RETURN VALUE   : Find a hostname in the 'object' table of the gnucomo database
119 **                   and return its object id.
120 **                   Return an empty string as objectid if the hostname is
121 **                   not found.
122 **
123 **  DESCRIPTION    : 
124 **
125 **  VARS USED      :
126 **  VARS CHANGED   :
127 **  FUNCTIONS USED :
128 **  SEE ALSO       :
129 **  LAST MODIFIED  : Aug 15, 2003
130 **=========================================================================
131 */
132
133 String gnucomo_database::find_host(const String hostname)
134 {
135    String objectid("");
136    String check_host("select objectid from object where ");
137
138    check_host += "objectname = '";
139    check_host += hostname;
140    check_host += "'";
141
142    if (Query(check_host) > 0)
143    {
144       objectid = Field(0, "objectid");
145    }
146
147    return objectid;
148 }
149
150 /*
151  *  Create a new notification with an action_user and return the notification id
152  */
153
154 String gnucomo_database::new_notification(String objectid, String issue, String remark)
155 {
156    String qry;
157    UTC    now = Now();
158
159    String insertion;
160    String notif_id("");
161
162    String issueid("");
163
164    *Log << "Creating notification for " << issue << ": " << remark << "\n";
165
166    qry = "select type_of_issueid, suggested_priority from type_of_issue where name='";
167    qry += issue + "'";
168    if (Query(qry) == 1)
169    {
170       issueid = Field(0, "type_of_issueid");
171       insertion = "insert into notification (objectid, type_of_issueid, timestamp, ";
172       insertion += "   statuscode, priority) values ('";
173       insertion += objectid + "', '";
174       insertion += issueid + "', '" + now.format("%Y-%m-%d %T") + "', 'new', '";
175       insertion += Field(0, "suggested_priority") + "')";
176
177       Query(insertion);
178
179       Query("select currval('notification_notificationid_seq')");
180       notif_id = Field(0, "currval");
181
182       if (notif_id != "")
183       {
184          insertion = "insert into action_user (actionid, username, notificationid,";
185          insertion += "    timestamp, statuscode, remarks) values ('1', 'gnucomo', '";
186          insertion += notif_id + "', '" + now.format("%Y-%m-%d %T") + "', 'new', '";
187          insertion += remark + "')";
188
189          Query(insertion);
190       }
191       else
192       {
193          std::cerr << "Error inserting notification.\n";
194       }
195    }
196    else
197    {
198       std::cerr << "DATABASE ERROR: Type of issue " << issue << " not found.\n";
199    }
200
201    return notif_id;
202 }
203
204 database_entity::database_entity(database_entity *from, int row)
205 {
206    db = from->db;
207    table = from->connected_table;
208
209    int          col;
210    pqxx::result res;
211
212    res = db->Result();
213
214    fresh = false;
215
216    for  (col = 0; col < res.columns(); col++)
217    {
218       fields[res.column_name(col)] = res[row][col].c_str();
219    }
220 }
221
222 int database_entity::find_one(String key)
223 {
224    String query("select * from ");
225
226    query += table;
227    query += " where ";
228    query += key;
229
230    if ( db->Query(query) == 1)
231    {
232       int          col;
233       pqxx::result res;
234
235       res = db->Result();
236
237       fresh = false;
238
239       for  (col = 0; col < res.columns(); col++)
240       {
241          std::cerr << "Field[" << col << "] " << res.column_name(col);
242          std::cerr << "  = " << res[0][col].c_str() << "\n";
243
244          fields[res.column_name(col)] = res[0][col].c_str();
245       }
246
247       return 1;
248    }
249    return 0;
250 }
251
252 int database_entity::find_many(String tab, String where)
253 {
254    connected_table = tab;
255
256    String query("select * from ");
257
258    query += tab;
259    query += " where ";
260    query += where;
261
262    return db->Query(query);
263
264 }
265