2 ** nxdbmgr - NetXMS database manager
3 ** Copyright (C) 2003-2016 Victor Kirhenshtein
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.
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.
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.
24 * Read table object from tdata_* tables
26 static Table
*ReadTable(UINT64 recordId
, UINT32 tableId
, UINT32 objectId
)
29 _sntprintf(query
, 1024,
30 _T("SELECT r.row_id,w.column_id,n.column_name,c.flags,c.display_name,w.value FROM tdata_records_%d r ")
31 _T("INNER JOIN tdata_rows_%d w ON w.row_id = r.row_id ")
32 _T("INNER JOIN dct_column_names n ON n.column_id=w.column_id ")
33 _T("LEFT OUTER JOIN dc_table_columns c ON c.table_id=%d AND c.column_name=n.column_name ")
34 _T("WHERE r.record_id=") UINT64_FMT
_T(" ")
35 _T("ORDER BY r.row_id"), objectId
, objectId
, tableId
, recordId
);
36 DB_RESULT hResult
= DBSelect(g_hCoreDB
, query
);
40 int count
= DBGetNumRows(hResult
);
46 for(int i
= 0; i
< count
; i
++)
48 TCHAR columnName
[MAX_COLUMN_NAME
];
49 DBGetField(hResult
, i
, 2, columnName
, MAX_COLUMN_NAME
);
50 int columnIndex
= table
->getColumnIndex(columnName
);
51 if (columnIndex
== -1)
53 TCHAR displayName
[256];
54 DBGetField(hResult
, i
, 4, displayName
, 256);
55 UINT16 flags
= (UINT16
)DBGetFieldULong(hResult
, i
, 3);
56 columnIndex
= table
->addColumn(columnName
, TCF_GET_DATA_TYPE(flags
), displayName
, (flags
& TCF_INSTANCE_COLUMN
) ? true : false);
59 UINT64 rowId
= DBGetFieldUInt64(hResult
, i
, 0);
60 if (rowId
!= currRowId
)
66 TCHAR value
[MAX_RESULT_LENGTH
];
67 DBGetField(hResult
, i
, 5, value
, MAX_RESULT_LENGTH
);
68 table
->set(columnIndex
, value
);
71 DBFreeResult(hResult
);
76 * Convert tdata table for given object
78 static bool ConvertTData(UINT32 id
, int *skippedRecords
)
80 TCHAR oldName
[64], newName
[64];
81 _sntprintf(oldName
, 64, _T("tdata_%d"), id
);
82 _sntprintf(newName
, 64, _T("tdata_temp_%d"), id
);
83 if (!RenameDatabaseTable(oldName
, newName
))
87 if (CreateTDataTable(id
))
89 int total
= 0x07FFFFFF;
91 _sntprintf(query
, 256, _T("SELECT count(*) FROM tdata_temp_%d"), id
);
92 DB_RESULT hCountResult
= DBSelect(g_hCoreDB
, query
);
93 if (hCountResult
!= NULL
)
95 total
= DBGetFieldLong(hCountResult
, 0, 0);
98 DBFreeResult(hCountResult
);
101 // Open second connection to database to allow unbuffered query in parallel with inserts
102 DB_HANDLE hdb
= ConnectToDatabase();
105 _sntprintf(query
, 256, _T("SELECT item_id,tdata_timestamp,record_id FROM tdata_temp_%d"), id
);
106 DB_UNBUFFERED_RESULT hResult
= DBSelectUnbuffered(hdb
, query
);
109 _sntprintf(query
, 256, _T("INSERT INTO tdata_%d (item_id,tdata_timestamp,tdata_value) VALUES (?,?,?)"), id
);
110 DB_STATEMENT hStmt
= DBPrepare(g_hCoreDB
, query
);
117 while(DBFetch(hResult
))
119 UINT32 tableId
= DBGetFieldULong(hResult
, 0);
120 UINT32 timestamp
= DBGetFieldULong(hResult
, 1);
121 UINT64 recordId
= DBGetFieldUInt64(hResult
, 2);
122 Table
*value
= ReadTable(recordId
, tableId
, id
);
125 DBBind(hStmt
, 1, DB_SQLTYPE_INTEGER
, tableId
);
126 DBBind(hStmt
, 2, DB_SQLTYPE_INTEGER
, timestamp
);
127 DBBind(hStmt
, 3, DB_SQLTYPE_TEXT
, DB_CTYPE_UTF8_STRING
, value
->createPackedXML(), DB_BIND_DYNAMIC
);
128 if (!SQLExecute(hStmt
))
142 if (converted
% 100 == 0)
144 int pct
= (converted
* 100) / total
;
147 WriteToTerminalEx(_T("\b\b\b\b%3d%%"), pct
);
154 DBFreeStatement(hStmt
);
155 *skippedRecords
= skipped
;
157 DBFreeResult(hResult
);
166 _sntprintf(query
, 256, _T("DROP TABLE tdata_rows_%d"), id
);
168 _sntprintf(query
, 256, _T("DROP TABLE tdata_records_%d"), id
);
170 _sntprintf(query
, 256, _T("DROP TABLE tdata_temp_%d"), id
);
176 _sntprintf(query
, 256, _T("DROP TABLE tdata_%d"), id
);
179 _sntprintf(oldName
, 64, _T("tdata_temp_%d"), id
);
180 _sntprintf(newName
, 64, _T("tdata_%d"), id
);
181 RenameDatabaseTable(oldName
, newName
);
188 * Check data tables for given o bject class
190 static bool ConvertTDataForClass(const TCHAR
*className
)
192 bool success
= false;
194 _sntprintf(query
, 256, _T("SELECT id FROM %s"), className
);
195 DB_RESULT hResult
= SQLSelect(query
);
199 int count
= DBGetNumRows(hResult
);
200 for(int i
= 0; i
< count
; i
++)
202 UINT32 id
= DBGetFieldULong(hResult
, i
, 0);
203 if (IsDataTableExist(_T("tdata_%d"), id
))
205 WriteToTerminalEx(_T("Converting table \x1b[1mtdata_%d\x1b[0m: 0%%"), id
);
207 int skippedRecords
= 0;
208 if (ConvertTData(id
, &skippedRecords
))
210 if (skippedRecords
== 0)
211 WriteToTerminalEx(_T("\b\b\b\b\x1b[32;1mdone\x1b[0m\n"));
213 WriteToTerminalEx(_T("\b\b\b\b\x1b[33;1mdone with %d records skipped\x1b[0m\n"), skippedRecords
);
217 WriteToTerminalEx(_T("\b\b\b\b\x1b[31;1mfailed\x1b[0m\n"));
224 CreateTDataTable(id
);
225 WriteToTerminalEx(_T("Created empty table \x1b[1mtdata_%d\x1b[0m\n"), id
);
228 DBFreeResult(hResult
);
234 * Convert tdata tables into new format
236 bool ConvertTDataTables()
238 CHK_EXEC(ConvertTDataForClass(_T("nodes")));
239 CHK_EXEC(ConvertTDataForClass(_T("clusters")));
240 CHK_EXEC(ConvertTDataForClass(_T("mobile_devices")));
241 CHK_EXEC(ConvertTDataForClass(_T("access_points")));
242 CHK_EXEC(ConvertTDataForClass(_T("chassis")));