added basic checking of node and interface objects
[public/netxms.git] / src / server / tools / nxdbmgr / nxdbmgr.cpp
1 /*
2 ** nxdbmgr - NetXMS database manager
3 ** Copyright (C) 2004 Victor Kirhenshtein
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 ** $module: nxdbmgr.cpp
20 **
21 **/
22
23 #include "nxdbmgr.h"
24
25 #ifdef _WIN32
26 #include <conio.h>
27 #endif
28
29
30 //
31 // Global variables
32 //
33
34 DB_HANDLE g_hCoreDB;
35 BOOL g_bIgnoreErrors = FALSE;
36 int g_iSyntax;
37 TCHAR *g_pszSqlType[3][2] =
38 {
39 { _T("blob"), _T("bigint") }, // MySQL
40 { _T("varchar"), _T("bigint") }, // PostgreSQL
41 { _T("text"), _T("bigint") } // Microsoft SQL
42 };
43
44
45 //
46 // Static data
47 //
48
49 static NX_CFG_TEMPLATE m_cfgTemplate[] =
50 {
51 { "DBDriver", CT_STRING, 0, 0, MAX_PATH, 0, g_szDbDriver },
52 { "DBDrvParams", CT_STRING, 0, 0, MAX_PATH, 0, g_szDbDrvParams },
53 { "DBLogin", CT_STRING, 0, 0, MAX_DB_LOGIN, 0, g_szDbLogin },
54 { "DBName", CT_STRING, 0, 0, MAX_DB_NAME, 0, g_szDbName },
55 { "DBPassword", CT_STRING, 0, 0, MAX_DB_PASSWORD, 0, g_szDbPassword },
56 { "DBServer", CT_STRING, 0, 0, MAX_PATH, 0, g_szDbServer },
57 { "LogFailedSQLQueries", CT_IGNORE, 0, 0, 0, 0, NULL },
58 { "LogFile", CT_IGNORE, 0, 0, 0, 0, NULL },
59 { "", CT_END_OF_LIST, 0, 0, 0, 0, NULL }
60 };
61
62
63 //
64 // Get Yes or No answer from keyboard
65 //
66
67 BOOL GetYesNo(void)
68 {
69 #ifdef _WIN32
70 int ch;
71
72 while(1)
73 {
74 ch = getch();
75 if ((ch == 'y') || (ch == 'Y'))
76 {
77 printf("Y\n");
78 return TRUE;
79 }
80 if ((ch == 'n') || (ch == 'N'))
81 {
82 printf("N\n");
83 return FALSE;
84 }
85 }
86 #else
87 TCHAR szBuffer[16];
88
89 fflush(stdout);
90 _fgetts(szBuffer, 16, stdin);
91 StrStrip(szBuffer);
92 return ((szBuffer[0] == 'y') || (szBuffer[0] == 'Y'));
93 #endif
94 }
95
96
97 //
98 // Execute SQL SELECT query and print error message on screen if query failed
99 //
100
101 DB_RESULT SQLSelect(TCHAR *pszQuery)
102 {
103 DB_RESULT hResult;
104
105 hResult = DBSelect(g_hCoreDB, pszQuery);
106 if (hResult == NULL)
107 {
108 #ifdef _WIN32
109 _tprintf(_T("SQL query failed:\n"));
110 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0E);
111 _tprintf(_T("%s\n"), pszQuery);
112 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x07);
113 #else
114 _tprintf(_T("SQL query failed:\n%s\n"), pszQuery);
115 #endif
116 }
117 return hResult;
118 }
119
120
121 //
122 // Execute SQL query and print error message on screen if query failed
123 //
124
125 BOOL SQLQuery(TCHAR *pszQuery)
126 {
127 BOOL bResult;
128
129 bResult = DBQuery(g_hCoreDB, pszQuery);
130 if (!bResult)
131 {
132 #ifdef _WIN32
133 _tprintf(_T("SQL query failed:\n"));
134 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0E);
135 _tprintf(_T("%s\n"), pszQuery);
136 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x07);
137 #else
138 _tprintf(_T("SQL query failed:\n%s\n"), pszQuery);
139 #endif
140 }
141 return bResult;
142 }
143
144
145 //
146 // Execute SQL batch
147 //
148
149 BOOL SQLBatch(TCHAR *pszBatch)
150 {
151 TCHAR *pszQuery, *ptr;
152
153 pszQuery = pszBatch;
154 while(1)
155 {
156 ptr = _tcschr(pszQuery, _T('\n'));
157 if (ptr != NULL)
158 *ptr = 0;
159 if (!_tcscmp(pszQuery, _T("<END>")))
160 break;
161 if (!DBQuery(g_hCoreDB, pszQuery))
162 {
163 #ifdef _WIN32
164 _tprintf(_T("SQL query failed:\n"));
165 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0E);
166 _tprintf(_T("%s\n"), pszQuery);
167 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x07);
168 #else
169 _tprintf(_T("SQL query failed:\n%s\n"), pszQuery);
170 #endif
171 if (!g_bIgnoreErrors)
172 return FALSE;
173 }
174 ptr++;
175 pszQuery = ptr;
176 }
177 return TRUE;
178 }
179
180
181 //
182 // Startup
183 //
184
185 int main(int argc, char *argv[])
186 {
187 BOOL bStart = TRUE, bForce = FALSE;
188 int ch;
189 TCHAR szSyntaxId[16], szConfigFile[MAX_PATH] = DEFAULT_CONFIG_FILE;
190 DB_RESULT hResult;
191
192 printf("NetXMS Database Manager Version " NETXMS_VERSION_STRING "\n\n");
193
194 // Parse command line
195 opterr = 1;
196 while((ch = getopt(argc, argv, "c:fhvX")) != -1)
197 {
198 switch(ch)
199 {
200 case 'h': // Display help and exit
201 _tprintf(_T("Usage: nxdbmgr [<options>] <command>\n"
202 "Valid commands are:\n"
203 " check : Check database for errors\n"
204 " upgrade : Upgrade database to new version\n"
205 "Valid options are:\n"
206 " -c <config> : Use alternate configuration file. Default is " DEFAULT_CONFIG_FILE "\n"
207 " -f : Force repair - do not ask for confirmation.\n"
208 " -h : Display help and exit.\n"
209 " -v : Display version and exit.\n"
210 " -X : Ignore SQL errors when upgrading (USE WITH CARE!!!)\n"
211 "\n"));
212 bStart = FALSE;
213 break;
214 case 'v': // Print version and exit
215 bStart = FALSE;
216 break;
217 case 'c':
218 _tcsncpy(szConfigFile, optarg, MAX_PATH);
219 break;
220 case 'f':
221 bForce = TRUE;
222 break;
223 case 'X':
224 g_bIgnoreErrors = TRUE;
225 break;
226 case '?':
227 bStart = FALSE;
228 break;
229 default:
230 break;
231 }
232 }
233
234 if (!bStart)
235 return 1;
236
237 // Check parameter correctness
238 if (argc - optind == 0)
239 {
240 _tprintf(_T("Command missing. Type nxdbmgr -h for command line syntax.\n"));
241 return 1;
242 }
243 if (strcmp(argv[optind], "check") && strcmp(argv[optind], "upgrade"))
244 {
245 _tprintf(_T("Invalid command \"%s\". Type nxdbmgr -h for command line syntax.\n"), argv[optind]);
246 return 1;
247 }
248
249 // Read configuration file
250 if (NxLoadConfig(szConfigFile, _T(""), m_cfgTemplate, TRUE) != NXCFG_ERR_OK)
251 {
252 _tprintf(_T("Error loading configuration file\n"));
253 return 2;
254 }
255
256 // Connect to database
257 if (!DBInit(FALSE, FALSE))
258 {
259 _tprintf(_T("Unable to load and initialize database driver \"%s\"\n"), g_szDbDriver);
260 return 3;
261 }
262
263 g_hCoreDB = DBConnect();
264 if (g_hCoreDB == NULL)
265 {
266 _tprintf(_T("Unable to connect to database %s@%s as %s\n"), g_szDbName,
267 g_szDbServer, g_szDbLogin);
268 DBUnloadDriver();
269 return 4;
270 }
271
272 // Get database syntax
273 hResult = DBSelect(g_hCoreDB, _T("SELECT var_value FROM config WHERE var_name='DBSyntax'"));
274 if (hResult != NULL)
275 {
276 if (DBGetNumRows(hResult) > 0)
277 {
278 _tcsncpy(szSyntaxId, DBGetField(hResult, 0, 0), sizeof(szSyntaxId));
279 }
280 else
281 {
282 _tcscpy(szSyntaxId, _T("UNKNOWN"));
283 }
284 DBFreeResult(hResult);
285 }
286 else
287 {
288 _tprintf(_T("Unable to determine database syntax\n"));
289 DBDisconnect(g_hCoreDB);
290 DBUnloadDriver();
291 return 5;
292 }
293
294 if (!_tcscmp(szSyntaxId, _T("MYSQL")))
295 {
296 g_iSyntax = DB_SYNTAX_MYSQL;
297 }
298 else if (!_tcscmp(szSyntaxId, _T("PGSQL")))
299 {
300 g_iSyntax = DB_SYNTAX_PGSQL;
301 }
302 else if (!_tcscmp(szSyntaxId, _T("MSSQL")))
303 {
304 g_iSyntax = DB_SYNTAX_MSSQL;
305 }
306 else
307 {
308 _tprintf(_T("Unknown database syntax %s\n"), szSyntaxId);
309 DBDisconnect(g_hCoreDB);
310 DBUnloadDriver();
311 return 6;
312 }
313
314 // Do requested operation
315 if (!strcmp(argv[optind], "check"))
316 CheckDatabase(bForce);
317 else if (!strcmp(argv[optind], "upgrade"))
318 UpgradeDatabase();
319
320 // Shutdown
321 DBDisconnect(g_hCoreDB);
322 DBUnloadDriver();
323 return 0;
324 }