-
Notifications
You must be signed in to change notification settings - Fork 0
/
vaultpress_db_import.php
319 lines (254 loc) · 7.94 KB
/
vaultpress_db_import.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
<?php
/**
* DB import script for VaultPress database.
* Author - Vikas Sharma
*
* Usage: php vaultpress_db_import.php
*
* Recommended settings in php.ini
* -------------------------------
* display_error = On
* memory_limit = 2G
*
*
* Recommended settings in my.ini
* ------------------------------
* [mysqld]
* max_allowed_packet = 2G
*
*/
class VaultPress_DB_Import {
/**
* Update database settings here:
*/
var $dbname = "database_name";
var $host = "database_hostname";
var $username = "database_username";
var $password = "database_password";
// No. of rows to insert per query (how fast we want the script to run).
var $max_rows_per_insert = 500;
var $db_object = null;
var $sql_files = [];
public static $is_cli = false;
function __construct() {
set_time_limit(0);
ob_implicit_flush();
error_reporting(E_ALL);
self::$is_cli = 'cli' === php_sapi_name();
$this->db_object = $this->connect();
$this->sql_files = $this->get_sql_files();
$this->start_import();
}
function start_import() {
if ( empty( $this->sql_files ) ) {
self::print_message( 'Import error, sql files not found!', 'message' );
exit;
}
foreach( $this->sql_files as $current_sql_file ) {
self::print_message( 'Processing ' . $current_sql_file, 'heading' );
// Get DB structure for the current table
$structure = $this->get_structure( $current_sql_file );
if( empty( $structure ) ) {
self::print_message( 'Empty table structure found in' . $current_sql_file, 'error' );
continue;
}
// Add if NOT EXISTS
if ( strpos( $structure, 'CREATE TABLE `' ) !== FALSE ) {
$structure = str_replace( 'CREATE TABLE `', 'CREATE TABLE IF NOT EXISTS `', $structure );
}
// Create Table structure (if not exists)
if( ! mysqli_query( $this->db_object, $structure ) ) {
self::print_message( 'Error in creating table structure - ' . mysqli_error( $this->db_object ), 'error' );
continue;
}
// Get current table name
$table_name = str_replace( '.sql', '', $current_sql_file );
// Check how much data was inserted in previous attempt
// To Do: will come up with a different logic to make the script resume.
$skip_rows = 0;
$query = mysqli_query( $this->db_object, "SELECT COUNT(*) as total_rows FROM $table_name" );
$res = mysqli_fetch_array( $query );
if ( ! empty( $res['total_rows'] ) ) {
$skip_rows = $res['total_rows'];
}
// INSERT insert statements
$this->insert_data( $current_sql_file, $skip_rows );
}
}
/**
* Connect to the database.
*/
function connect() {
$db_object = mysqli_connect( $this->host, $this->username, $this->password, $this->dbname );
if( empty( $db_object ) ) {
self::print_message( 'Error: Unable to connect to the database! ' . $this->db_object . ', ' . mysqli_error(), 'error' );
exit;
}
return $db_object;
}
/**
* Scan current working directory and return the list of SQL file.
* @return array
*/
function get_sql_files() {
$all_files = scandir( getcwd() );
$sql_files = [];
foreach( $all_files as $filename ) {
if( substr( strtolower( $filename ), -4 ) == ".sql" ) {
$sql_files[] = $filename;
}
}
if ( empty( $sql_files ) ) {
self::print_message( 'Error: no sql file found, nothing to do! <br />current directory :' . dirname( __FILE__ ), 'error' );
exit;
}
return $sql_files;
}
/**
* Read the input file and extract DB structure.
* @param $input_file
* @return string
*/
function get_structure( $input_file ) {
$fp = fopen( $input_file, "r" );
if( ! $fp ) {
self::print_message( "Could not open input file $input_file", 'error' );
}
$line_counter = 0;
$structure = "";
$save_structure = false;
while( ! feof( $fp ) ) {
$line_counter ++;
if( $line_counter > 100 ) {
self::print_message( "Error: something went wrong! table structure can't be 100 lines long :(", 'error' );
exit;
}
$line = fgets( $fp );
// Database Structure
if( strpos( $line, "CREATE TABLE" ) !== FALSE ) {
$save_structure = true;
}
if( $save_structure ) {
$structure .= $line;
}
if( strpos( $line, "ENGINE=InnoDB" ) !== FALSE ) {
break;
}
}
fclose( $fp );
return $structure;
}
/**
* Read the input file and execute all INSERT statements
* @param $input_file
* @param $skip_rows
* @return string
*/
function insert_data( $input_file, $skip_rows ) {
$fp = fopen( $input_file, "r" );
if( ! $fp ) {
self::print_message( "Could not open input file $input_file", 'error' );
exit;
}
$insert_row_counter = 0;
$header_found = false;
$header_string = "";
$value_string = "";
$separator_position = 0;
$total_inserts = 0;
$total_rows_skipped = 0;
while( ! feof( $fp ) ) {
$line = fgets( $fp );
// Merge INSERT statements
if( $header_found && strpos( $line, "INSERT INTO" ) !== FALSE ) {
// Check if we need to skip some lines (because the data was inserted in a previous attempt).
if ( $skip_rows > 0 && $total_rows_skipped < $skip_rows ) {
$total_rows_skipped ++;
continue;
}
$value_string .= substr( $line, $separator_position, -2 ) . ",";
$insert_row_counter ++;
}
// Find Header and separator_position
if( ! $header_found && strpos( $line, "INSERT INTO" ) !== FALSE ) {
$separator_position = strpos( $line, "`) VALUES (" );
$header_string = substr( $line, 0, $separator_position );
$separator_position += 10;
$value_string = substr( $line, $separator_position, -2 ) . ",";
$header_found = true;
}
if( $insert_row_counter == $this->max_rows_per_insert ) {
// Remove coma at the end of the statement.
$sql = substr( $header_string. "`) VALUES " . $value_string, 0, -1 );
// Insert
$results = mysqli_query( $this->db_object, $sql);
if( empty( $results ) ) {
self::print_message( "Error while inserting row: " . mysqli_error( $this->db_object ), 'error' );
self::print_message( "Error at following Line: " . $line, 'error' );
}
if ( self::$is_cli ) {
// print a dot for each insert.
self::print_message('.');
}
$total_inserts += $insert_row_counter;
// Reset variables.
$value_string = "";
$insert_row_counter = 0;
}
}
// Insert Remaining Rows
// Remove coma at the end of the statement.
$sql = substr( $header_string. "`) VALUES " . $value_string, 0, -1 );
if( ! mysqli_query( $this->db_object, $sql ) ) {
self::print_message( "Mysql Error: " . mysqli_error( $this->db_object ), 'error' );
}
$total_inserts += $insert_row_counter;
self::print_message( "Total $total_inserts rows inserted ", 'success' );
fclose( $fp );
}
/**
* Print Message
* @param String $message
* @param String $type
*/
public static function print_message( String $message = '', String $type = '' ) : void {
if ( self::$is_cli ) {
switch( $type ) {
case 'message':
echo $message . PHP_EOL;
break;
case 'heading':
echo PHP_EOL . $message . PHP_EOL;
echo '............................';
break;
case 'success':
echo "\033[32m {$message} \033[0m " . PHP_EOL;
break;
case 'error':
echo "\033[31m {$message} \033[0m " . PHP_EOL;
break;
default:
echo $message;
}
} else {
switch( $type ) {
case 'message':
echo $message . '<br />';
break;
case 'heading':
echo '<h1>' . $message . '</h1>';
break;
case 'success':
echo '<div style="color: #008800">' . $message . '</div>';
break;
case 'error':
echo '<div style="color: #ff0000">' . $message . '</div>';
break;
default:
echo $message;
}
}
}
}
new VaultPress_DB_Import();
// EOF