Minor bugfixes
[public/netxms.git] / src / server / core / dcst.cpp
CommitLineData
34f32920 1/*
4cd1e46b 2** NetXMS - Network Management System
297a88eb 3** Copyright (C) 2003-2016 Victor Kirhenshtein
4cd1e46b
AK
4**
5** This program is free software; you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation; either version 2 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program; if not, write to the Free Software
17** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18**
19** File: dcst.cpp
20**
21**/
22
23#include "nxcore.h"
24
25/**
26 * Modify DCI summary table. Will create new table if id is 0.
27 *
28 * @return RCC ready to be sent to client
29 */
b368969c 30UINT32 ModifySummaryTable(NXCPMessage *msg, LONG *newId)
4cd1e46b 31{
b368969c 32 LONG id = msg->getFieldAsUInt32(VID_SUMMARY_TABLE_ID);
4cd1e46b
AK
33 if (id == 0)
34 {
35 id = CreateUniqueId(IDG_DCI_SUMMARY_TABLE);
36 }
37 *newId = id;
38
39 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
34f32920 40
2096c8f0 41 bool isNew = !IsDatabaseRecordExist(hdb, _T("dci_summary_tables"), _T("id"), (UINT32)id);
4cd1e46b 42 DB_STATEMENT hStmt;
2096c8f0 43 if (isNew)
4cd1e46b 44 {
62485dab 45 hStmt = DBPrepare(hdb, _T("INSERT INTO dci_summary_tables (menu_path,title,node_filter,flags,columns,table_dci_name,id,guid) VALUES (?,?,?,?,?,?,?,?)"));
4cd1e46b
AK
46 }
47 else
48 {
62485dab 49 hStmt = DBPrepare(hdb, _T("UPDATE dci_summary_tables SET menu_path=?,title=?,node_filter=?,flags=?,columns=?,table_dci_name=? WHERE id=?"));
4cd1e46b
AK
50 }
51
52 UINT32 rcc;
53 if (hStmt != NULL)
54 {
b368969c
VK
55 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, msg->getFieldAsString(VID_MENU_PATH), DB_BIND_DYNAMIC);
56 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, msg->getFieldAsString(VID_TITLE), DB_BIND_DYNAMIC);
57 DBBind(hStmt, 3, DB_SQLTYPE_TEXT, msg->getFieldAsString(VID_FILTER), DB_BIND_DYNAMIC);
58 DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, msg->getFieldAsUInt32(VID_FLAGS));
59 DBBind(hStmt, 5, DB_SQLTYPE_TEXT, msg->getFieldAsString(VID_COLUMNS), DB_BIND_DYNAMIC);
62485dab
EJ
60 DBBind(hStmt, 6, DB_SQLTYPE_VARCHAR, msg->getFieldAsString(VID_DCI_NAME), DB_BIND_DYNAMIC);
61 DBBind(hStmt, 7, DB_SQLTYPE_INTEGER, id);
4cd1e46b 62
2096c8f0
VK
63 if (isNew)
64 {
62485dab 65 DBBind(hStmt, 8, DB_SQLTYPE_VARCHAR, uuid::generate());
2096c8f0
VK
66 }
67
4cd1e46b
AK
68 rcc = DBExecute(hStmt) ? RCC_SUCCESS : RCC_DB_FAILURE;
69 if (rcc == RCC_SUCCESS)
70 NotifyClientSessions(NX_NOTIFY_DCISUMTBL_CHANGED, (UINT32)id);
71
72 DBFreeStatement(hStmt);
73 }
74 else
75 {
76 rcc = RCC_DB_FAILURE;
77 }
78
79 DBConnectionPoolReleaseConnection(hdb);
80 return rcc;
81}
82
83/**
84 * Delete DCI summary table
85 */
86UINT32 DeleteSummaryTable(LONG tableId)
87{
88 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
89 UINT32 rcc = RCC_DB_FAILURE;
90 DB_STATEMENT hStmt = DBPrepare(hdb, _T("DELETE FROM dci_summary_tables WHERE id=?"));
91 if (hStmt != NULL)
92 {
93 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, tableId);
94 if (DBExecute(hStmt))
95 {
96 rcc = RCC_SUCCESS;
97 NotifyClientSessions(NX_NOTIFY_DCISUMTBL_DELETED, (UINT32)tableId);
98 }
99 DBFreeStatement(hStmt);
100 }
101 DBConnectionPoolReleaseConnection(hdb);
102 return rcc;
103}
104
5389f7b0
VK
105/**
106 * Create column definition from NXCP message
107 */
b368969c 108SummaryTableColumn::SummaryTableColumn(NXCPMessage *msg, UINT32 baseId)
5389f7b0 109{
b368969c
VK
110 msg->getFieldAsString(baseId, m_name, MAX_DB_STRING);
111 msg->getFieldAsString(baseId + 1, m_dciName, MAX_PARAM_NAME);
112 m_flags = msg->getFieldAsUInt32(baseId + 2);
0a290117
VK
113 if (msg->isFieldExist(baseId + 3))
114 msg->getFieldAsString(baseId + 3, m_separator, 16);
115 else
116 _tcscpy(m_separator, _T(";"));
5389f7b0
VK
117}
118
2096c8f0
VK
119/**
120 * Create export record for column
121 */
122void SummaryTableColumn::createExportRecord(String &xml, int id)
123{
124 xml.append(_T("\t\t\t\t<column id=\""));
125 xml.append(id);
126 xml.append(_T("\">\n\t\t\t\t\t<name>"));
127 xml.appendPreallocated(EscapeStringForXML(m_name, -1));
128 xml.append(_T("</name>\n\t\t\t\t\t<dci>"));
129 xml.appendPreallocated(EscapeStringForXML(m_dciName, -1));
130 xml.append(_T("</dci>\n\t\t\t\t\t<flags>"));
131 xml.append(m_flags);
0a290117
VK
132 xml.append(_T("</flags>\n\t\t\t\t\t<separator>\n"));
133 xml.append(m_separator);
134 xml.append(_T("</separator>\n\t\t\t\t</column>\n"));
2096c8f0
VK
135}
136
4cd1e46b
AK
137/**
138 * Create column definition from configuration string
139 */
140SummaryTableColumn::SummaryTableColumn(TCHAR *configStr)
141{
142 TCHAR *ptr = _tcsstr(configStr, _T("^#^"));
143 if (ptr != NULL)
144 {
145 *ptr = 0;
146 ptr += 3;
147 TCHAR *opt = _tcsstr(ptr, _T("^#^"));
148 if (opt != NULL)
149 {
150 *opt = 0;
151 opt += 3;
0a290117
VK
152 TCHAR *sep = _tcsstr(opt, _T("^#^"));
153 if (sep != NULL)
154 {
155 *sep = 0;
156 sep += 3;
157 nx_strncpy(m_separator, sep, 16);
158 }
159 else
160 {
161 _tcscpy(m_separator, _T(";"));
162 }
4cd1e46b
AK
163 m_flags = _tcstoul(opt, NULL, 10);
164 }
165 else
166 {
167 m_flags = 0;
168 }
169 nx_strncpy(m_dciName, ptr, MAX_PARAM_NAME);
170 }
171 else
172 {
173 nx_strncpy(m_dciName, configStr, MAX_PARAM_NAME);
174 m_flags = 0;
175 }
176 nx_strncpy(m_name, configStr, MAX_DB_STRING);
177}
178
4cd1e46b 179/**
5389f7b0
VK
180 * Create ad-hoc summary table definition from NXCP message
181 */
b368969c 182SummaryTable::SummaryTable(NXCPMessage *msg)
5389f7b0 183{
2096c8f0 184 m_id = 0;
de4af576 185 m_guid = uuid::generate();
5389f7b0 186 m_title[0] = 0;
c7a9d87c 187 m_menuPath[0] = 0;
b368969c 188 m_flags = msg->getFieldAsUInt32(VID_FLAGS);
c7a9d87c 189 m_filterSource = NULL;
5389f7b0 190 m_filter = NULL;
2852ef09
VK
191 m_aggregationFunction = (AggregationFunction)msg->getFieldAsInt16(VID_FUNCTION);
192 m_periodStart = msg->getFieldAsTime(VID_TIME_FROM);
193 m_periodEnd = msg->getFieldAsTime(VID_TIME_TO);
5389f7b0
VK
194
195 int count = msg->getFieldAsInt32(VID_NUM_COLUMNS);
196 m_columns = new ObjectArray<SummaryTableColumn>(count, 16, true);
34f32920 197
5389f7b0
VK
198 UINT32 id = VID_COLUMN_INFO_BASE;
199 for(int i = 0; i < count; i++)
200 {
201 m_columns->add(new SummaryTableColumn(msg, id));
202 id += 10;
203 }
62485dab 204 msg->getFieldAsString(VID_DCI_NAME, m_tableDciName, MAX_PARAM_NAME);
5389f7b0
VK
205}
206
207/**
208 * Create summary table definition from DB data
4cd1e46b 209 */
2096c8f0 210SummaryTable::SummaryTable(INT32 id, DB_RESULT hResult)
4cd1e46b 211{
2096c8f0
VK
212 m_id = id;
213
4cd1e46b
AK
214 DBGetField(hResult, 0, 0, m_title, MAX_DB_STRING);
215 m_flags = DBGetFieldULong(hResult, 0, 1);
de4af576 216 m_guid = DBGetFieldGUID(hResult, 0, 2);
2096c8f0 217 DBGetField(hResult, 0, 3, m_menuPath, MAX_DB_STRING);
4cd1e46b 218
2852ef09
VK
219 m_aggregationFunction = DCI_AGG_LAST;
220 m_periodStart = 0;
221 m_periodEnd = 0;
222
4cd1e46b 223 // Filter script
2096c8f0
VK
224 m_filterSource = DBGetField(hResult, 0, 4, NULL, 0);
225 if (m_filterSource != NULL)
4cd1e46b 226 {
2096c8f0
VK
227 StrStrip(m_filterSource);
228 if (*m_filterSource != 0)
4cd1e46b
AK
229 {
230 TCHAR errorText[1024];
2096c8f0 231 m_filter = NXSLCompileAndCreateVM(m_filterSource, errorText, 1024, new NXSL_ServerEnv);
4cd1e46b
AK
232 if (m_filter == NULL)
233 {
0a290117 234 nxlog_debug(4, _T("Error compiling filter script for DCI summary table: %s"), errorText);
4cd1e46b
AK
235 }
236 }
237 else
238 {
239 m_filter = NULL;
240 }
4cd1e46b
AK
241 }
242 else
243 {
244 m_filter = NULL;
245 }
246
247 // Columns
248 m_columns = new ObjectArray<SummaryTableColumn>(16, 16, true);
2096c8f0 249 TCHAR *config = DBGetField(hResult, 0, 5, NULL, 0);
4cd1e46b
AK
250 if ((config != NULL) && (*config != 0))
251 {
252 TCHAR *curr = config;
253 while(curr != NULL)
254 {
255 TCHAR *next = _tcsstr(curr, _T("^~^"));
256 if (next != NULL)
257 {
258 *next = 0;
259 next += 3;
260 }
261 m_columns->add(new SummaryTableColumn(curr));
262 curr = next;
263 }
264 free(config);
265 }
62485dab 266 DBGetField(hResult, 0, 6, m_tableDciName, MAX_PARAM_NAME);
4cd1e46b
AK
267}
268
269/**
270 * Load summary table object from database
271 */
2096c8f0 272SummaryTable *SummaryTable::loadFromDB(INT32 id, UINT32 *rcc)
4cd1e46b 273{
0a290117 274 nxlog_debug(4, _T("Loading configuration for DCI summary table %d"), id);
4cd1e46b
AK
275 SummaryTable *table = NULL;
276 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
62485dab 277 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT title,flags,guid,menu_path,node_filter,columns,table_dci_name FROM dci_summary_tables WHERE id=?"));
4cd1e46b
AK
278 if (hStmt != NULL)
279 {
280 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, id);
281 DB_RESULT hResult = DBSelectPrepared(hStmt);
282 if (hResult != NULL)
283 {
284 if (DBGetNumRows(hResult) > 0)
285 {
2096c8f0 286 table = new SummaryTable(id, hResult);
4cd1e46b
AK
287 *rcc = RCC_SUCCESS;
288 }
289 else
290 {
291 *rcc = RCC_INVALID_SUMMARY_TABLE_ID;
292 }
293 DBFreeResult(hResult);
294 }
295 else
296 {
297 *rcc = RCC_DB_FAILURE;
298 }
299 DBFreeStatement(hStmt);
300 }
301 else
302 {
303 *rcc = RCC_DB_FAILURE;
304 }
305 DBConnectionPoolReleaseConnection(hdb);
0a290117 306 nxlog_debug(4, _T("SummaryTable::loadFromDB(%d): object=%p, rcc=%d"), id, table, (int)*rcc);
4cd1e46b
AK
307 return table;
308}
309
2096c8f0
VK
310/**
311 * Destructor
312 */
313SummaryTable::~SummaryTable()
314{
315 delete m_columns;
316 delete m_filter;
0a290117 317 free(m_filterSource);
2096c8f0
VK
318}
319
4cd1e46b
AK
320/**
321 * Pass node through filter
322 */
323bool SummaryTable::filter(DataCollectionTarget *object)
324{
325 if (m_filter == NULL)
326 return true; // no filtering
327
328 bool result = true;
297a88eb 329 m_filter->setGlobalVariable(_T("$object"), object->createNXSLObject());
c42b4551 330 if (object->getObjectClass() == OBJECT_NODE)
0a290117 331 m_filter->setGlobalVariable(_T("$node"), object->createNXSLObject());
6b29839d 332 if (m_filter->run())
4cd1e46b
AK
333 {
334 NXSL_Value *value = m_filter->getResult();
335 if (value != NULL)
336 {
337 result = value->getValueAsInt32() ? true : false;
338 }
1e03ee19
VK
339 }
340 else
341 {
0a290117 342 nxlog_debug(4, _T("Error executing filter script for DCI summary table: %s"), m_filter->getErrorText());
4cd1e46b
AK
343 }
344 return result;
345}
346
347/**
348 * Create empty result table
349 */
62485dab 350Table *SummaryTable::createEmptyResultTable(const Table *source)
4cd1e46b
AK
351{
352 Table *result = new Table();
353 result->setTitle(m_title);
3f4c195f 354 result->setExtendedFormat(true);
4cd1e46b 355 result->addColumn(_T("Node"), DCI_DT_STRING);
914580f5
VK
356 if (m_flags & SUMMARY_TABLE_MULTI_INSTANCE)
357 result->addColumn(_T("Instance"), DCI_DT_STRING);
62485dab
EJ
358
359 if (m_flags & SUMMARY_TABLE_TABLE_VALUE)
4cd1e46b 360 {
62485dab
EJ
361 for(int i = 0; i < source->getNumColumns(); i++)
362 {
363 result->addColumn(source->getColumnName(i), source->getColumnDataType(i));
364 }
365 }
366 else
367 {
368 for(int i = 0; i < m_columns->size(); i++)
369 {
370 result->addColumn(m_columns->get(i)->m_name, DCI_DT_STRING);
371 }
4cd1e46b
AK
372 }
373 return result;
374}
375
2096c8f0
VK
376/**
377 * Create export record
378 */
379void SummaryTable::createExportRecord(String &xml)
380{
381 TCHAR buffer[64];
382
383 xml.append(_T("\t\t<table id=\""));
384 xml.append(m_id);
385 xml.append(_T("\">\n\t\t\t<guid>"));
de4af576 386 xml.append(m_guid.toString(buffer));
2096c8f0
VK
387 xml.append(_T("</guid>\n\t\t\t<title>"));
388 xml.appendPreallocated(EscapeStringForXML(m_title, -1));
389 xml.append(_T("</title>\n\t\t\t<flags>"));
390 xml.append(m_flags);
391 xml.append(_T("</flags>\n\t\t\t<path>"));
392 xml.appendPreallocated(EscapeStringForXML(m_menuPath, -1));
393 xml.append(_T("</path>\n\t\t\t<filter>"));
394 xml.appendPreallocated(EscapeStringForXML(m_filterSource, -1));
395 xml.append(_T("</filter>\n\t\t\t<columns>\n"));
396 for(int i = 0; i < m_columns->size(); i++)
397 {
398 m_columns->get(i)->createExportRecord(xml, i + 1);
399 }
400 xml.append(_T("\t\t\t</columns>\n\t\t</table>\n"));
401}
402
4cd1e46b
AK
403/**
404 * Query summary table
405 */
5389f7b0 406Table *QuerySummaryTable(LONG tableId, SummaryTable *adHocDefinition, UINT32 baseObjectId, UINT32 userId, UINT32 *rcc)
4cd1e46b
AK
407{
408 NetObj *object = FindObjectById(baseObjectId);
409 if (object == NULL)
410 {
411 *rcc = RCC_INVALID_OBJECT_ID;
412 return NULL;
413 }
414 if (!object->checkAccessRights(userId, OBJECT_ACCESS_READ))
415 {
416 *rcc = RCC_ACCESS_DENIED;
417 return NULL;
418 }
c42b4551
VK
419 if ((object->getObjectClass() != OBJECT_CONTAINER) && (object->getObjectClass() != OBJECT_CLUSTER) &&
420 (object->getObjectClass() != OBJECT_SERVICEROOT) && (object->getObjectClass() != OBJECT_SUBNET) &&
421 (object->getObjectClass() != OBJECT_ZONE) && (object->getObjectClass() != OBJECT_NETWORK))
4cd1e46b
AK
422 {
423 *rcc = RCC_INCOMPATIBLE_OPERATION;
424 return NULL;
425 }
426
5389f7b0 427 SummaryTable *tableDefinition = (adHocDefinition != NULL) ? adHocDefinition : SummaryTable::loadFromDB(tableId, rcc);
4cd1e46b
AK
428 if (tableDefinition == NULL)
429 return NULL;
430
431 ObjectArray<NetObj> *childObjects = object->getFullChildList(true, true);
f3f1bb5b
EJ
432 Table *tableData = NULL, *lastValue = NULL;
433
62485dab
EJ
434 if (tableDefinition->getFlags() & SUMMARY_TABLE_TABLE_VALUE)
435 {
f3f1bb5b
EJ
436 for(int i = 0; i < childObjects->size(); i++)
437 {
438 if (((childObjects->get(i)->getObjectClass() == OBJECT_NODE) || (childObjects->get(i)->getObjectClass() == OBJECT_MOBILEDEVICE) ||
439 (childObjects->get(i)->getObjectClass() == OBJECT_SENSOR)) && childObjects->get(i)->checkAccessRights(userId, OBJECT_ACCESS_READ))
440 {
441 DCObject *o = ((DataCollectionTarget *)childObjects->get(i))->getDCObjectByName(tableDefinition->getTableDciName());
442 if (o != NULL && (o->getType() == DCO_TYPE_TABLE))
443 {
444 lastValue = ((DCTable *)o)->getLastValue();
445 if (lastValue != NULL)
446 {
447 tableData = tableDefinition->createEmptyResultTable(((DCTable *)o)->getLastValue());
448 break;
449 }
450 }
451 }
452 }
62485dab
EJ
453 }
454 else
455 tableData = tableDefinition->createEmptyResultTable();
4cd1e46b
AK
456
457 for(int i = 0; i < childObjects->size(); i++)
458 {
459 NetObj *obj = childObjects->get(i);
ce9e00cc
VK
460 if (((obj->getObjectClass() != OBJECT_NODE) && (obj->getObjectClass() != OBJECT_MOBILEDEVICE) &&
461 (obj->getObjectClass() != OBJECT_SENSOR)) || !obj->checkAccessRights(userId, OBJECT_ACCESS_READ))
4cd1e46b
AK
462 {
463 obj->decRefCount();
464 continue;
465 }
466
467 if (tableDefinition->filter((DataCollectionTarget *)obj))
468 {
62485dab
EJ
469 if (tableDefinition->getFlags() & SUMMARY_TABLE_TABLE_VALUE)
470 ((DataCollectionTarget *)obj)->getDciValuesSummaryTableValue(tableDefinition, tableData);
471 else
472 ((DataCollectionTarget *)obj)->getDciValuesSummarySingleValue(tableDefinition, tableData);
4cd1e46b
AK
473 }
474 obj->decRefCount();
475 }
476
477 delete childObjects;
478 delete tableDefinition;
479
480 return tableData;
481}
2096c8f0
VK
482
483/**
484 * Create export record for summary table
485 */
486bool CreateSummaryTableExportRecord(INT32 id, String &xml)
487{
488 UINT32 rcc;
489 SummaryTable *t = SummaryTable::loadFromDB(id, &rcc);
490 if (t == NULL)
491 return false;
492 t->createExportRecord(xml);
493 delete t;
494 return true;
495}
c7a9d87c
VK
496
497/**
498 * Build column list
499 */
500static TCHAR *BuildColumnList(ConfigEntry *root)
501{
502 if (root == NULL)
503 return _tcsdup(_T(""));
504
505 String s;
506 ObjectArray<ConfigEntry> *columns = root->getOrderedSubEntries(_T("column#*"));
507 for(int i = 0; i < columns->size(); i++)
508 {
509 if (i > 0)
510 s.append(_T("^~^"));
511
512 ConfigEntry *c = columns->get(i);
513 s.append(c->getSubEntryValue(_T("name")));
514 s.append(_T("^#^"));
515 s.append(c->getSubEntryValue(_T("dci")));
516 s.append(_T("^#^"));
517 s.append(c->getSubEntryValueAsUInt(_T("flags")));
0a290117
VK
518 s.append(_T("^#^"));
519 s.append(c->getSubEntryValue(_T("separator")));
c7a9d87c
VK
520 }
521 delete columns;
522 return _tcsdup((const TCHAR *)s);
523}
524
525/**
526 * Import failure exit
527 */
528static bool ImportFailure(DB_HANDLE hdb, DB_STATEMENT hStmt)
529{
530 if (hStmt != NULL)
531 DBFreeStatement(hStmt);
532 DBRollback(hdb);
533 DBConnectionPoolReleaseConnection(hdb);
534 DbgPrintf(4, _T("ImportObjectTool: database failure"));
535 return false;
536}
537
538/**
539 * Import summary table
540 */
541bool ImportSummaryTable(ConfigEntry *config)
542{
543 const TCHAR *guid = config->getSubEntryValue(_T("guid"));
544 if (guid == NULL)
545 {
546 DbgPrintf(4, _T("ImportSummaryTable: missing GUID"));
547 return false;
548 }
549
550 uuid_t temp;
999945fa 551 if (_uuid_parse(guid, temp) == -1)
c7a9d87c
VK
552 {
553 DbgPrintf(4, _T("ImportSummaryTable: GUID (%s) is invalid"), guid);
554 return false;
555 }
556
557 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
558
559 // Step 1: find existing tool ID by GUID
560 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT id FROM dci_summary_tables WHERE guid=?"));
561 if (hStmt == NULL)
562 {
563 return ImportFailure(hdb, NULL);
564 }
565
566 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, guid, DB_BIND_STATIC);
567 DB_RESULT hResult = DBSelectPrepared(hStmt);
568 if (hResult == NULL)
569 {
570 return ImportFailure(hdb, hStmt);
571 }
572
573 UINT32 id;
574 if (DBGetNumRows(hResult) > 0)
575 {
576 id = DBGetFieldULong(hResult, 0, 0);
577 }
578 else
579 {
580 id = 0;
581 }
582 DBFreeResult(hResult);
583 DBFreeStatement(hStmt);
584
585 // Step 2: create or update summary table configuration record
586 if (id == 0)
587 {
588 id = CreateUniqueId(IDG_DCI_SUMMARY_TABLE);
589 hStmt = DBPrepare(hdb, _T("INSERT INTO dci_summary_tables (menu_path,title,node_filter,flags,columns,guid,id) VALUES (?,?,?,?,?,?,?)"));
590 }
591 else
592 {
593 hStmt = DBPrepare(hdb, _T("UPDATE dci_summary_tables SET menu_path=?,title=?,node_filter=?,flags=?,columns=?,guid=? WHERE id=?"));
594 }
595 if (hStmt == NULL)
596 {
597 return ImportFailure(hdb, NULL);
598 }
599
600 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, config->getSubEntryValue(_T("path")), DB_BIND_STATIC);
601 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, config->getSubEntryValue(_T("title")), DB_BIND_STATIC);
602 DBBind(hStmt, 3, DB_SQLTYPE_TEXT, config->getSubEntryValue(_T("filter")), DB_BIND_STATIC);
603 DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, config->getSubEntryValueAsUInt(_T("flags")));
604 DBBind(hStmt, 5, DB_SQLTYPE_TEXT, BuildColumnList(config->findEntry(_T("columns"))), DB_BIND_DYNAMIC);
605 DBBind(hStmt, 6, DB_SQLTYPE_VARCHAR, guid, DB_BIND_STATIC);
606 DBBind(hStmt, 7, DB_SQLTYPE_INTEGER, id);
607
608 if (!DBExecute(hStmt))
609 {
610 return ImportFailure(hdb, hStmt);
611 }
612
613 NotifyClientSessions(NX_NOTIFY_DCISUMTBL_CHANGED, (UINT32)id);
614
615 DBFreeStatement(hStmt);
616 DBConnectionPoolReleaseConnection(hdb);
617 return true;
618}