]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/store/postgresql/postgresql_store_tariffs.cpp
Lots of stylistic fixes.
[stg.git] / projects / stargazer / plugins / store / postgresql / postgresql_store_tariffs.cpp
1 /*
2  *    This program is free software; you can redistribute it and/or modify
3  *    it under the terms of the GNU General Public License as published by
4  *    the Free Software Foundation; either version 2 of the License, or
5  *    (at your option) any later version.
6  *
7  *    This program is distributed in the hope that it will be useful,
8  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *    GNU General Public License for more details.
11  *
12  *    You should have received a copy of the GNU General Public License
13  *    along with this program; if not, write to the Free Software
14  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  */
16
17 /*
18  *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
19  */
20
21 /*
22  *  Tariffs manipulation methods
23  *
24  *  $Revision: 1.2 $
25  *  $Date: 2009/06/09 12:32:40 $
26  *
27  */
28
29 #include <string>
30 #include <vector>
31 #include <sstream>
32 #include <cmath>
33
34 #include <libpq-fe.h>
35
36 #include "postgresql_store.h"
37 #include "stg/locker.h"
38
39 //-----------------------------------------------------------------------------
40 int POSTGRESQL_STORE::GetTariffsList(std::vector<std::string> * tariffsList) const
41 {
42 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
43
44 if (PQstatus(connection) != CONNECTION_OK)
45     {
46     printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
47     if (Reset())
48         {
49         strError = "Connection lost";
50         printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): '%s'\n", strError.c_str());
51         return -1;
52         }
53     }
54
55 PGresult * result;
56
57 if (StartTransaction())
58     {
59     printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to start transaction'\n");
60     return -1;
61     }
62
63 result = PQexec(connection, "SELECT name FROM tb_tariffs");
64
65 if (PQresultStatus(result) != PGRES_TUPLES_OK)
66     {
67     strError = PQresultErrorMessage(result);
68     PQclear(result);
69     printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): '%s'\n", strError.c_str());
70     if (RollbackTransaction())
71         {
72         printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to rollback transaction'\n");
73         }
74     return -1;
75     }
76
77 int tuples = PQntuples(result);
78
79 for (int i = 0; i < tuples; ++i)
80     {
81     tariffsList->push_back(PQgetvalue(result, i, 0));
82     }
83
84 PQclear(result);
85
86 if (CommitTransaction())
87     {
88     printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to commit transaction'\n");
89     return -1;
90     }
91
92 return 0;
93 }
94
95 //-----------------------------------------------------------------------------
96 int POSTGRESQL_STORE::AddTariff(const std::string & name) const
97 {
98 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
99
100 if (PQstatus(connection) != CONNECTION_OK)
101     {
102     printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
103     if (Reset())
104         {
105         strError = "Connection lost";
106         printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): '%s'\n", strError.c_str());
107         return -1;
108         }
109     }
110
111 PGresult * result;
112
113 if (StartTransaction())
114     {
115     printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to start transaction'\n");
116     return -1;
117     }
118
119 std::string ename = name;
120
121 if (EscapeString(ename))
122     {
123     printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to escape name'\n");
124     if (RollbackTransaction())
125         {
126         printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
127         }
128     return -1;
129     }
130
131 std::ostringstream query;
132 query << "SELECT sp_add_tariff('" << ename << "', " << DIR_NUM << ")";
133
134 result = PQexec(connection, query.str().c_str());
135
136 if (PQresultStatus(result) != PGRES_TUPLES_OK)
137     {
138     strError = PQresultErrorMessage(result);
139     PQclear(result);
140     printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): '%s'\n", strError.c_str());
141     if (RollbackTransaction())
142         {
143         printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
144         }
145     return -1;
146     }
147
148 PQclear(result);
149
150 if (CommitTransaction())
151     {
152     printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to commit transaction'\n");
153     return -1;
154     }
155
156 return 0;
157 }
158 //-----------------------------------------------------------------------------
159 int POSTGRESQL_STORE::DelTariff(const std::string & name) const
160 {
161 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
162
163 if (PQstatus(connection) != CONNECTION_OK)
164     {
165     printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
166     if (Reset())
167         {
168         strError = "Connection lost";
169         printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): '%s'\n", strError.c_str());
170         return -1;
171         }
172     }
173
174 PGresult * result;
175
176 if (StartTransaction())
177     {
178     printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to start transaction'\n");
179     return -1;
180     }
181
182 std::string ename = name;
183
184 if (EscapeString(ename))
185     {
186     printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to escape name'\n");
187     if (RollbackTransaction())
188         {
189         printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
190         }
191     return -1;
192     }
193
194 std::ostringstream query;
195 query << "DELETE FROM tb_tariffs WHERE name = '" << ename << "'";
196
197 result = PQexec(connection, query.str().c_str());
198
199 if (PQresultStatus(result) != PGRES_COMMAND_OK)
200     {
201     strError = PQresultErrorMessage(result);
202     PQclear(result);
203     printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): '%s'\n", strError.c_str());
204     if (RollbackTransaction())
205         {
206         printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to rollback transaction'\n");
207         }
208     return -1;
209     }
210
211 PQclear(result);
212
213 if (CommitTransaction())
214     {
215     printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to commit transaction'\n");
216     return -1;
217     }
218
219 return 0;
220 }
221 //-----------------------------------------------------------------------------
222 int POSTGRESQL_STORE::SaveTariff(const TARIFF_DATA & td,
223                                  const std::string & tariffName) const
224 {
225 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
226
227 if (PQstatus(connection) != CONNECTION_OK)
228     {
229     printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
230     if (Reset())
231         {
232         strError = "Connection lost";
233         printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
234         return -1;
235         }
236     }
237
238 PGresult * result;
239
240 if (StartTransaction())
241     {
242     printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to start transaction'\n");
243     return -1;
244     }
245
246 std::string ename = tariffName;
247
248 if (EscapeString(ename))
249     {
250     printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to escape name'\n");
251     if (RollbackTransaction())
252         {
253         printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
254         }
255     return -1;
256     }
257
258     {
259     std::ostringstream query;
260     query << "SELECT pk_tariff FROM tb_tariffs WHERE name = '" << ename << "'";
261
262     result = PQexec(connection, query.str().c_str());
263     }
264
265 if (PQresultStatus(result) != PGRES_TUPLES_OK)
266     {
267     strError = PQresultErrorMessage(result);
268     PQclear(result);
269     printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
270     if (RollbackTransaction())
271         {
272         printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
273         }
274     return -1;
275     }
276
277 int tuples = PQntuples(result);
278
279 if (tuples != 1)
280     {
281     strError = "Failed to fetch tariff ID";
282     printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
283     PQclear(result);
284     if (RollbackTransaction())
285         {
286         printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
287         }
288     return -1;
289     }
290
291     {
292     std::stringstream tuple;
293     tuple << PQgetvalue(result, 0, 0);
294
295     PQclear(result);
296
297     int32_t id;
298     tuple >> id;
299     }
300
301     {
302     std::ostringstream query;
303     query << "UPDATE tb_tariffs SET \
304                   fee = " << td.tariffConf.fee << ", \
305                   free = " << td.tariffConf.free << ", \
306                   passive_cost = " << td.tariffConf.passiveCost << ", \
307                   traff_type = " << td.tariffConf.traffType;
308
309     if (version > 6)
310         query << ", period = '" << TARIFF::PeriodToString(td.tariffConf.period) << "'";
311
312     query << " WHERE pk_tariff = " << id;
313
314     result = PQexec(connection, query.str().c_str());
315     }
316
317 if (PQresultStatus(result) != PGRES_COMMAND_OK)
318     {
319     strError = PQresultErrorMessage(result);
320     PQclear(result);
321     printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
322     if (RollbackTransaction())
323         {
324         printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
325         }
326     return -1;
327     }
328
329 PQclear(result);
330
331 for(int i = 0; i < DIR_NUM; i++)
332     {
333     double pda = td.dirPrice[i].priceDayA * 1024 * 1024;
334     double pdb = td.dirPrice[i].priceDayB * 1024 * 1024;
335     double pna = 0;
336     double pnb = 0;
337
338     if (td.dirPrice[i].singlePrice)
339         {
340         pna = pda;
341         pnb = pdb;
342         }
343     else
344         {
345         pna = td.dirPrice[i].priceNightA * 1024 * 1024;
346         pnb = td.dirPrice[i].priceNightB * 1024 * 1024;
347         }
348
349     int threshold = 0;
350     if (td.dirPrice[i].noDiscount)
351         {
352         threshold = 0xffFFffFF;
353         }
354     else
355         {
356         threshold = td.dirPrice[i].threshold;
357         }
358
359         {
360         std::ostringstream query;
361         query << "UPDATE tb_tariffs_params SET \
362                       price_day_a = " << pda << ", \
363                       price_day_b = " << pdb << ", \
364                       price_night_a = " << pna << ", \
365                       price_night_b = " << pnb << ", \
366                       threshold = " << threshold << ", \
367                       time_day_begins = CAST('" << td.dirPrice[i].hDay
368                                                 << ":"
369                                                 << td.dirPrice[i].mDay << "' AS TIME), \
370                       time_day_ends = CAST('" << td.dirPrice[i].hNight
371                                               << ":"
372                                               << td.dirPrice[i].mNight << "' AS TIME) \
373                  WHERE fk_tariff = " << id << " AND dir_num = " << i;
374
375         result = PQexec(connection, query.str().c_str());
376         }
377
378     if (PQresultStatus(result) != PGRES_COMMAND_OK)
379         {
380         strError = PQresultErrorMessage(result);
381         PQclear(result);
382         printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
383         if (RollbackTransaction())
384             {
385             printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
386             }
387         return -1;
388         }
389
390     PQclear(result);
391     }
392
393 if (CommitTransaction())
394     {
395     printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to commit transaction'\n");
396     return -1;
397     }
398
399 return 0;
400 }
401 //-----------------------------------------------------------------------------
402 int POSTGRESQL_STORE::RestoreTariff(TARIFF_DATA * td,
403                                   const std::string & tariffName) const
404 {
405 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
406
407 if (PQstatus(connection) != CONNECTION_OK)
408     {
409     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
410     if (Reset())
411         {
412         strError = "Connection lost";
413         printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
414         return -1;
415         }
416     }
417
418 PGresult * result;
419
420 if (StartTransaction())
421     {
422     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to start transaction'\n");
423     return -1;
424     }
425
426 std::string ename = tariffName;
427
428 if (EscapeString(ename))
429     {
430     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to escape name'\n");
431     if (RollbackTransaction())
432         {
433         printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
434         }
435     return -1;
436     }
437
438 td->tariffConf.name = tariffName;
439
440 std::ostringstream query;
441 query << "SELECT pk_tariff, \
442                  fee, \
443                  free, \
444                  passive_cost, \
445                  traff_type";
446
447 if (version > 6)
448     query << ", period";
449
450 query << " FROM tb_tariffs WHERE name = '" << ename << "'";
451
452 result = PQexec(connection, query.str().c_str());
453
454 if (PQresultStatus(result) != PGRES_TUPLES_OK)
455     {
456     strError = PQresultErrorMessage(result);
457     PQclear(result);
458     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
459     if (RollbackTransaction())
460         {
461         printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
462         }
463     return -1;
464     }
465
466 int tuples = PQntuples(result);
467
468 if (tuples != 1)
469     {
470     strError = "Failed to fetch tariff data";
471     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
472     PQclear(result);
473     if (RollbackTransaction())
474         {
475         printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
476         }
477     return -1;
478     }
479
480 int id;
481
482     {
483     std::stringstream tuple;
484     tuple << PQgetvalue(result, 0, 0) << " ";
485     tuple << PQgetvalue(result, 0, 1) << " ";
486     tuple << PQgetvalue(result, 0, 2) << " ";
487     tuple << PQgetvalue(result, 0, 3) << " ";
488     tuple << PQgetvalue(result, 0, 4) << " ";
489
490     tuple >> id;
491     tuple >> td->tariffConf.fee;
492     tuple >> td->tariffConf.free;
493     tuple >> td->tariffConf.passiveCost;
494     tuple >> td->tariffConf.traffType;
495     }
496
497 if (version > 6)
498     td->tariffConf.period = TARIFF::StringToPeriod(PQgetvalue(result, 0, 5));
499
500 PQclear(result);
501
502 query.str("");
503 query << "SELECT dir_num, \
504                  price_day_a, \
505                  price_day_b, \
506                  price_night_a, \
507                  price_night_b, \
508                  threshold, \
509                  EXTRACT(hour FROM time_day_begins), \
510                  EXTRACT(minute FROM time_day_begins), \
511                  EXTRACT(hour FROM time_day_ends), \
512                  EXTRACT(minute FROM time_day_ends) \
513           FROM tb_tariffs_params \
514           WHERE fk_tariff = " << id;
515
516 result = PQexec(connection, query.str().c_str());
517
518 if (PQresultStatus(result) != PGRES_TUPLES_OK)
519     {
520     strError = PQresultErrorMessage(result);
521     PQclear(result);
522     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
523     if (RollbackTransaction())
524         {
525         printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
526         }
527     return -1;
528     }
529
530 tuples = PQntuples(result);
531
532 if (tuples != DIR_NUM)
533     {
534     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Tariff params count and DIR_NUM does not feet (wanted %d, actually %d)'\n", DIR_NUM, tuples);
535     }
536
537 for (int i = 0; i < std::min(tuples, DIR_NUM); ++i)
538     {
539     int dir;
540
541         {
542         std::stringstream tuple;
543         tuple << PQgetvalue(result, i, 0) << " ";
544         tuple << PQgetvalue(result, i, 1) << " ";
545         tuple << PQgetvalue(result, i, 2) << " ";
546         tuple << PQgetvalue(result, i, 3) << " ";
547         tuple << PQgetvalue(result, i, 4) << " ";
548         tuple << PQgetvalue(result, i, 5) << " ";
549         tuple << PQgetvalue(result, i, 6) << " ";
550         tuple << PQgetvalue(result, i, 7) << " ";
551         tuple << PQgetvalue(result, i, 8) << " ";
552         tuple << PQgetvalue(result, i, 9) << " ";
553
554         tuple >> dir;
555         tuple >> td->dirPrice[dir].priceDayA;
556         td->dirPrice[dir].priceDayA /= 1024 * 1024;
557         tuple >> td->dirPrice[dir].priceDayB;
558         td->dirPrice[dir].priceDayB /= 1024 * 1024;
559         tuple >> td->dirPrice[dir].priceNightA;
560         td->dirPrice[dir].priceNightA /= 1024 * 1024;
561         tuple >> td->dirPrice[dir].priceNightB;
562         td->dirPrice[dir].priceNightB /= 1024 * 1024;
563         tuple >> td->dirPrice[dir].threshold;
564         tuple >> td->dirPrice[dir].hDay;
565         tuple >> td->dirPrice[dir].mDay;
566         tuple >> td->dirPrice[dir].hNight;
567         tuple >> td->dirPrice[dir].mNight;
568         }
569
570     if (std::fabs(td->dirPrice[dir].priceDayA - td->dirPrice[dir].priceNightA) > 1.0e-3 &&
571         std::fabs(td->dirPrice[dir].priceDayB - td->dirPrice[dir].priceNightB) > 1.0e-3)
572         {
573         td->dirPrice[dir].singlePrice = true;
574         }
575     else
576         {
577         td->dirPrice[dir].singlePrice = false;
578         }
579     if (td->dirPrice[dir].threshold == (int)0xffFFffFF)
580         {
581         td->dirPrice[dir].noDiscount = true;
582         }
583     else
584         {
585
586         td->dirPrice[dir].noDiscount = false;
587         }
588
589     }
590
591 PQclear(result);
592
593 if (CommitTransaction())
594     {
595     printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to commit transaction'\n");
596     return -1;
597     }
598
599 return 0;
600 }
601 //-----------------------------------------------------------------------------
602