2 ** nxdbmgr - NetXMS database manager
3 ** Copyright (C) 2004-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.
28 extern const TCHAR
*g_tables
[];
33 static TCHAR s_dbDriver
[MAX_PATH
] = _T("");
34 static TCHAR s_dbDrvParams
[MAX_PATH
] = _T("");
35 static TCHAR s_dbServer
[MAX_PATH
] = _T("127.0.0.1");
36 static TCHAR s_dbLogin
[MAX_DB_LOGIN
] = _T("netxms");
37 static TCHAR s_dbPassword
[MAX_PASSWORD
] = _T("");
38 static TCHAR s_dbName
[MAX_DB_NAME
] = _T("netxms_db");
39 static TCHAR s_dbSchema
[MAX_DB_NAME
] = _T("");
40 static NX_CFG_TEMPLATE m_cfgTemplate
[] =
42 { _T("DBDriver"), CT_STRING
, 0, 0, MAX_PATH
, 0, s_dbDriver
},
43 { _T("DBDrvParams"), CT_STRING
, 0, 0, MAX_PATH
, 0, s_dbDrvParams
},
44 { _T("DBLogin"), CT_STRING
, 0, 0, MAX_DB_LOGIN
, 0, s_dbLogin
},
45 { _T("DBName"), CT_STRING
, 0, 0, MAX_DB_NAME
, 0, s_dbName
},
46 { _T("DBPassword"), CT_STRING
, 0, 0, MAX_PASSWORD
, 0, s_dbPassword
},
47 { _T("DBEncryptedPassword"), CT_STRING
, 0, 0, MAX_PASSWORD
, 0, s_dbPassword
},
48 { _T("DBSchema"), CT_STRING
, 0, 0, MAX_PATH
, 0, s_dbSchema
},
49 { _T("DBServer"), CT_STRING
, 0, 0, MAX_PATH
, 0, s_dbServer
},
50 { _T(""), CT_END_OF_LIST
, 0, 0, 0, 0, NULL
}
56 static DB_DRIVER s_driver
= NULL
;
57 static DB_HANDLE s_hdbSource
= NULL
;
58 static int s_sourceSyntax
= DB_SYNTAX_UNKNOWN
;
61 * Connect to source database
63 static bool ConnectToSource()
65 s_driver
= DBLoadDriver(s_dbDriver
, s_dbDrvParams
, false, NULL
, NULL
);
68 _tprintf(_T("Unable to load and initialize database driver \"%s\"\n"), s_dbDriver
);
71 WriteToTerminalEx(_T("Database driver \x1b[1m%s\x1b[0m loaded\n"), s_dbDriver
);
73 TCHAR errorText
[DBDRV_MAX_ERROR_TEXT
];
74 s_hdbSource
= DBConnect(s_driver
, s_dbServer
, s_dbName
, s_dbLogin
, s_dbPassword
, s_dbSchema
, errorText
);
75 if (s_hdbSource
== NULL
)
77 _tprintf(_T("Unable to connect to database %s@%s as %s: %s\n"), s_dbName
, s_dbServer
, s_dbLogin
, errorText
);
80 WriteToTerminalEx(_T("Connected to source database\n"));
82 // Get database syntax
83 s_sourceSyntax
= DBGetSyntax(s_hdbSource
);
84 if (s_sourceSyntax
== DB_SYNTAX_UNKNOWN
)
86 _tprintf(_T("Unable to determine source database syntax\n"));
90 // Check source schema version
91 int version
= DBGetSchemaVersion(s_hdbSource
);
92 if (version
< DB_FORMAT_VERSION
)
94 _tprintf(_T("Source database has format version %d, this tool is compiled for version %d.\nUse \"upgrade\" command to upgrade source database first.\n"),
95 version
, DB_FORMAT_VERSION
);
98 if (version
> DB_FORMAT_VERSION
)
100 _tprintf(_T("Source database has format version %d, this tool is compiled for version %d.\n")
101 _T("You need to upgrade your server before using this database.\n"),
102 version
, DB_FORMAT_VERSION
);
110 * Migrate single database table
112 static bool MigrateTable(const TCHAR
*table
)
114 WriteToTerminalEx(_T("Migrating table \x1b[1m%s\x1b[0m\n"), table
);
116 if (!DBBegin(g_hCoreDB
))
118 _tprintf(_T("ERROR: unable to start transaction in target database\n"));
122 bool success
= false;
123 TCHAR buffer
[256], errorText
[DBDRV_MAX_ERROR_TEXT
];
124 _sntprintf(buffer
, 256, _T("SELECT * FROM %s"), table
);
125 DB_UNBUFFERED_RESULT hResult
= DBSelectUnbufferedEx(s_hdbSource
, buffer
, errorText
);
128 _tprintf(_T("ERROR: unable to read data from source table (%s)\n"), errorText
);
129 DBRollback(g_hCoreDB
);
133 // build INSERT query
134 String query
= _T("INSERT INTO ");
137 int columnCount
= DBGetColumnCount(hResult
);
138 for(int i
= 0; i
< columnCount
; i
++)
140 DBGetColumnName(hResult
, i
, buffer
, 256);
145 query
+= _T(") VALUES (?");
146 for(int i
= 1; i
< columnCount
; i
++)
150 DB_STATEMENT hStmt
= DBPrepareEx(g_hCoreDB
, query
, errorText
);
154 int rows
= 0, totalRows
= 0;
155 while(DBFetch(hResult
))
157 for(int i
= 0; i
< columnCount
; i
++)
159 DBBind(hStmt
, i
+ 1, DB_SQLTYPE_VARCHAR
, DBGetField(hResult
, i
, NULL
, 0), DB_BIND_DYNAMIC
);
161 if (!SQLExecute(hStmt
))
163 _tprintf(_T("Failed input record:\n"));
164 for(int i
= 0; i
< columnCount
; i
++)
166 DBGetColumnName(hResult
, i
, buffer
, 256);
167 TCHAR
*value
= DBGetField(hResult
, i
, NULL
, 0);
168 _tprintf(_T(" %s = \"%s\"\n"), buffer
, CHECK_NULL(value
));
176 if (rows
>= g_migrationTxnSize
)
184 if ((totalRows
& 0xFF) == 0)
186 _tprintf(_T("%8d\r"), totalRows
);
194 DBRollback(g_hCoreDB
);
195 DBFreeStatement(hStmt
);
199 _tprintf(_T("ERROR: cannot prepare INSERT statement (%s)\n"), errorText
);
200 DBRollback(g_hCoreDB
);
202 DBFreeResult(hResult
);
207 * Migrate data tables
209 static bool MigrateDataTables()
214 DB_RESULT hResult
= SQLSelect(_T("SELECT id FROM nodes"));
218 // Create and import idata_xx and tdata_xx tables for each node in "nodes" table
219 count
= DBGetNumRows(hResult
);
220 for(i
= 0; i
< count
; i
++)
222 DWORD id
= DBGetFieldULong(hResult
, i
, 0);
223 if (!g_dataOnlyMigration
)
225 if (!CreateIDataTable(id
))
226 break; // Failed to create idata_xx table
229 if (!g_skipDataMigration
)
231 _sntprintf(buffer
, 1024, _T("idata_%d"), id
);
232 if (!MigrateTable(buffer
))
236 if (!g_dataOnlyMigration
)
238 if (!CreateTDataTable(id
))
239 break; // Failed to create tdata tables
242 if (!g_skipDataMigration
)
244 _sntprintf(buffer
, 1024, _T("tdata_%d"), id
);
245 if (!MigrateTable(buffer
))
250 DBFreeResult(hResult
);
257 void MigrateDatabase(const TCHAR
*sourceConfig
)
259 bool success
= false;
261 // Load source config
262 Config
*config
= new Config();
263 if (!config
->loadIniConfig(sourceConfig
, _T("server")) || !config
->parseTemplate(_T("server"), m_cfgTemplate
))
265 _tprintf(_T("Error loading source configuration from %s\n"), sourceConfig
);
270 DecryptPassword(s_dbLogin
, s_dbPassword
, s_dbPassword
, MAX_PASSWORD
);
272 if (!ConnectToSource())
275 if (!g_dataOnlyMigration
)
277 if (!ClearDatabase(true))
281 for(int i
= 0; g_tables
[i
] != NULL
; i
++)
283 if (!MigrateTable(g_tables
[i
]))
288 if (!g_skipDataSchemaMigration
)
290 if (!MigrateDataTables())
297 if (s_hdbSource
!= NULL
)
298 DBDisconnect(s_hdbSource
);
299 if (s_driver
!= NULL
)
300 DBUnloadDriver(s_driver
);
302 _tprintf(success
? _T("Database migration complete.\n") : _T("Database migration failed.\n"));