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