1 // +------------------------------------------------------------------+
2 // |             ____ _               _        __  __ _  __           |
3 // |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
4 // |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
5 // |           | |___| | | |  __/ (__|   <    | |  | | . \            |
6 // |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
7 // |                                                                  |
8 // | Copyright Mathias Kettner 2014             mk@mathias-kettner.de |
9 // +------------------------------------------------------------------+
10 //
11 // This file is part of Check_MK.
12 // The official homepage is at http://mathias-kettner.de/check_mk.
13 //
14 // check_mk is free software;  you can redistribute it and/or modify it
15 // under the  terms of the  GNU General Public License  as published by
16 // the Free Software Foundation in version 2.  check_mk is  distributed
17 // in the hope that it will be useful, but WITHOUT ANY WARRANTY;  with-
18 // out even the implied warranty of  MERCHANTABILITY  or  FITNESS FOR A
19 // PARTICULAR PURPOSE. See the  GNU General Public License for more de-
20 // ails.  You should have  received  a copy of the  GNU  General Public
21 // License along with GNU Make; see the file  COPYING.  If  not,  write
22 // to the Free Software Foundation, Inc., 51 Franklin St,  Fifth Floor,
23 // Boston, MA 02110-1301 USA.
24 
25 #include "Table.h"
26 #include <string.h>
27 #include <utility>
28 #include "Column.h"
29 #include "DynamicColumn.h"
30 #include "Query.h"
31 
32 using std::make_pair;
33 using std::string;
34 
addColumn(Column * col)35 void Table::addColumn(Column *col) {
36     // do not insert column if one with that name
37     // already exists. Delete that column in that
38     // case. (For example needed for TableLog->TableHosts,
39     // which both define host_name.
40     if (column(col->name()) != nullptr) {
41         delete col;
42     } else {
43         _columns.insert(make_pair(col->name(), col));
44     }
45 }
46 
addDynamicColumn(DynamicColumn * dyncol)47 void Table::addDynamicColumn(DynamicColumn *dyncol) {
48     _dynamic_columns.insert(make_pair(dyncol->name(), dyncol));
49 }
50 
~Table()51 Table::~Table() {
52     for (auto &column : _columns) {
53         delete column.second;
54     }
55 
56     for (auto &dynamic_column : _dynamic_columns) {
57         delete dynamic_column.second;
58     }
59 }
60 
addAllColumnsToQuery(Query * q)61 void Table::addAllColumnsToQuery(Query *q) {
62     for (auto &column : _columns) {
63         q->addColumn(column.second);
64     }
65 }
66 
column(const char * colname)67 Column *Table::column(const char *colname) {
68     // We allow the name of the table to be
69     // prefixed to the column name. So if we
70     // detect this prefix, we simply remove it.
71     int prefix_len = strlen(prefixname());  // replace 's' with '_'
72 
73     // Multisite seems to query "service_service_description". We can fix this
74     // in newer versions, but need to be compatible. So we need a "while" here,
75     // not just an "if".
76     while ((strncmp(colname, prefixname(), prefix_len - 1) == 0) &&
77            colname[prefix_len - 1] == '_') {
78         colname += prefix_len;
79     }
80 
81     // If the colum name contains a ':' then we have a dynamic
82     // column with column arguments
83     if (strchr(colname, ':') != nullptr) {
84         return dynamicColumn(colname);
85     }
86 
87     // First try exact match
88     auto it = _columns.find(string(colname));
89     if (it != _columns.end()) {
90         return it->second;
91     }
92 
93     // Now we try to readd the removed prefix. That way we tackle the
94     // problem with the column "service_period". Here the prefix service_
95     // is part of the actual name of the column!
96     string with_prefix(prefixname(), prefix_len - 1);
97     with_prefix += "_";
98     with_prefix += colname;
99 
100     it = _columns.find(with_prefix);
101     if (it != _columns.end()) {
102         return it->second;
103     }
104     return nullptr;
105 }
106 
dynamicColumn(const char * colname_with_args)107 Column *Table::dynamicColumn(const char *colname_with_args) {
108     const char *sep_pos = strchr(colname_with_args, ':');
109     string name(colname_with_args, sep_pos - colname_with_args);
110 
111     const char *argstring = sep_pos + 1;
112 
113     auto it = _dynamic_columns.find(name);
114     if (it != _dynamic_columns.end()) {
115         return it->second->createColumn(argstring);
116     }
117     return nullptr;
118 }
119 
hasColumn(Column * col)120 bool Table::hasColumn(Column *col) {
121     // this is not very efficient but seldomly used
122     for (auto &column : _columns) {
123         if (col == column.second) {
124             return true;
125         }
126     }
127     return false;
128 }
129