Mercurial > hg > vamp-website
comparison forum/Sources/DbPackages-sqlite.php @ 76:e3e11437ecea website
Add forum code
author | Chris Cannam |
---|---|
date | Sun, 07 Jul 2013 11:25:48 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
75:72f59aa7e503 | 76:e3e11437ecea |
---|---|
1 <?php | |
2 | |
3 /** | |
4 * Simple Machines Forum (SMF) | |
5 * | |
6 * @package SMF | |
7 * @author Simple Machines http://www.simplemachines.org | |
8 * @copyright 2011 Simple Machines | |
9 * @license http://www.simplemachines.org/about/smf/license.php BSD | |
10 * | |
11 * @version 2.0 | |
12 */ | |
13 | |
14 if (!defined('SMF')) | |
15 die('Hacking attempt...'); | |
16 | |
17 /* This file contains database functionality specifically designed for packages to utilize. | |
18 | |
19 bool smf_db_create_table(string table_name, array columns, array indexes = array(), | |
20 array parameters = array(), string if_exists = 'ignore') | |
21 - Can be used to create a table without worrying about schema compatabilities. | |
22 - If the table exists will, by default, do nothing. | |
23 - Builds table with columns as passed to it - at least one column must be sent. | |
24 The columns array should have one sub-array for each column - these sub arrays contain: | |
25 + 'name' = Column name | |
26 + 'type' = Type of column - values from (smallint,mediumint,int,text,varchar,char,tinytext,mediumtext,largetext) | |
27 + 'size' => Size of column (If applicable) - for example 255 for a large varchar, 10 for an int etc. If not | |
28 set SMF will pick a size. | |
29 + 'default' = Default value - do not set if no default required. | |
30 + 'null' => Can it be null (true or false) - if not set default will be false. | |
31 + 'auto' => Set to true to make it an auto incrementing column. Set to a numerical value to set | |
32 from what it should begin counting. | |
33 - Adds indexes as specified within indexes parameter. Each index should be a member of $indexes. Values are: | |
34 + 'name' => Index name (If left empty SMF will generate). | |
35 + 'type' => Type of index. Choose from 'primary', 'unique' or 'index'. If not set will default to 'index'. | |
36 + 'columns' => Array containing columns that form part of key - in the order the index is to be created. | |
37 - parameters: (None yet) | |
38 - if_exists values: | |
39 + 'ignore' will do nothing if the table exists. (And will return true) | |
40 + 'overwrite' will drop any existing table of the same name. | |
41 + 'error' will return false if the table already exists. | |
42 | |
43 */ | |
44 | |
45 // Add the file functions to the $smcFunc array. | |
46 function db_packages_init() | |
47 { | |
48 global $smcFunc, $reservedTables, $db_package_log, $db_prefix; | |
49 | |
50 if (!isset($smcFunc['db_create_table']) || $smcFunc['db_create_table'] != 'smf_db_create_table') | |
51 { | |
52 $smcFunc += array( | |
53 'db_add_column' => 'smf_db_add_column', | |
54 'db_add_index' => 'smf_db_add_index', | |
55 'db_alter_table' => 'smf_db_alter_table', | |
56 'db_calculate_type' => 'smf_db_calculate_type', | |
57 'db_change_column' => 'smf_db_change_column', | |
58 'db_create_table' => 'smf_db_create_table', | |
59 'db_drop_table' => 'smf_db_drop_table', | |
60 'db_table_structure' => 'smf_db_table_structure', | |
61 'db_list_columns' => 'smf_db_list_columns', | |
62 'db_list_indexes' => 'smf_db_list_indexes', | |
63 'db_remove_column' => 'smf_db_remove_column', | |
64 'db_remove_index' => 'smf_db_remove_index', | |
65 ); | |
66 $db_package_log = array(); | |
67 } | |
68 | |
69 // We setup an array of SMF tables we can't do auto-remove on - in case a mod writer cocks it up! | |
70 $reservedTables = array('admin_info_files', 'approval_queue', 'attachments', 'ban_groups', 'ban_items', | |
71 'board_permissions', 'boards', 'calendar', 'calendar_holidays', 'categories', 'collapsed_categories', | |
72 'custom_fields', 'group_moderators', 'log_actions', 'log_activity', 'log_banned', 'log_boards', | |
73 'log_digest', 'log_errors', 'log_floodcontrol', 'log_group_requests', 'log_karma', 'log_mark_read', | |
74 'log_notify', 'log_online', 'log_packages', 'log_polls', 'log_reported', 'log_reported_comments', | |
75 'log_scheduled_tasks', 'log_search_messages', 'log_search_results', 'log_search_subjects', | |
76 'log_search_topics', 'log_topics', 'mail_queue', 'membergroups', 'members', 'message_icons', | |
77 'messages', 'moderators', 'package_servers', 'permission_profiles', 'permissions', 'personal_messages', | |
78 'pm_recipients', 'poll_choices', 'polls', 'scheduled_tasks', 'sessions', 'settings', 'smileys', | |
79 'themes', 'topics'); | |
80 foreach ($reservedTables as $k => $table_name) | |
81 $reservedTables[$k] = strtolower($db_prefix . $table_name); | |
82 | |
83 // We in turn may need the extra stuff. | |
84 db_extend('extra'); | |
85 } | |
86 | |
87 // Create a table. | |
88 function smf_db_create_table($table_name, $columns, $indexes = array(), $parameters = array(), $if_exists = 'ignore', $error = 'fatal') | |
89 { | |
90 global $reservedTables, $smcFunc, $db_package_log, $db_prefix; | |
91 | |
92 // With or without the database name, the full name looks like this. | |
93 $real_prefix = preg_match('~^(`?)(.+?)\\1\\.(.*?)$~', $db_prefix, $match) === 1 ? $match[3] : $db_prefix; | |
94 $full_table_name = str_replace('{db_prefix}', $real_prefix, $table_name); | |
95 $table_name = str_replace('{db_prefix}', $db_prefix, $table_name); | |
96 | |
97 // First - no way do we touch SMF tables. | |
98 // Commented out for now. We need to alter SMF tables in order to use this in the upgrade. | |
99 /* | |
100 if (in_array(strtolower($table_name), $reservedTables)) | |
101 return false; | |
102 */ | |
103 | |
104 // Log that we'll want to remove this on uninstall. | |
105 $db_package_log[] = array('remove_table', $table_name); | |
106 | |
107 // Does this table exist or not? | |
108 $tables = $smcFunc['db_list_tables'](); | |
109 if (in_array($full_table_name, $tables)) | |
110 { | |
111 // This is a sad day... drop the table? If not, return false (error) by default. | |
112 if ($if_exists == 'overwrite') | |
113 $smcFunc['db_drop_table']($table_name); | |
114 else | |
115 return $if_exists == 'ignore'; | |
116 } | |
117 | |
118 // Righty - let's do the damn thing! | |
119 $table_query = 'CREATE TABLE ' . $table_name . "\n" . '('; | |
120 $done_primary = false; | |
121 foreach ($columns as $column) | |
122 { | |
123 // Auto increment is special | |
124 if (!empty($column['auto'])) | |
125 { | |
126 $table_query .= "\n" . $column['name'] . ' integer PRIMARY KEY,'; | |
127 $done_primary = true; | |
128 continue; | |
129 } | |
130 elseif (isset($column['default']) && $column['default'] !== null) | |
131 $default = 'default \'' . $smcFunc['db_escape_string']($column['default']) . '\''; | |
132 else | |
133 $default = ''; | |
134 | |
135 // Sort out the size... and stuff... | |
136 $column['size'] = isset($column['size']) && is_numeric($column['size']) ? $column['size'] : null; | |
137 list ($type, $size) = $smcFunc['db_calculate_type']($column['type'], $column['size']); | |
138 if ($size !== null) | |
139 $type = $type . '(' . $size . ')'; | |
140 | |
141 // Now just put it together! | |
142 $table_query .= "\n\t" . $column['name'] . ' ' . $type . ' ' . (!empty($column['null']) ? '' : 'NOT NULL') . ' ' . $default . ','; | |
143 } | |
144 | |
145 // Loop through the indexes next... | |
146 $index_queries = array(); | |
147 foreach ($indexes as $index) | |
148 { | |
149 $columns = implode(',', $index['columns']); | |
150 | |
151 // Is it the primary? | |
152 if (isset($index['type']) && $index['type'] == 'primary') | |
153 { | |
154 // If we've done the primary via auto_inc, don't do it again! | |
155 if (!$done_primary) | |
156 $table_query .= "\n\t" . 'PRIMARY KEY (' . implode(',', $index['columns']) . '),'; | |
157 } | |
158 else | |
159 { | |
160 if (empty($index['name'])) | |
161 $index['name'] = implode('_', $index['columns']); | |
162 $index_queries[] = 'CREATE ' . (isset($index['type']) && $index['type'] == 'unique' ? 'UNIQUE' : '') . ' INDEX ' . $table_name . '_' . $index['name'] . ' ON ' . $table_name . ' (' . $columns . ')'; | |
163 } | |
164 } | |
165 | |
166 // No trailing commas! | |
167 if (substr($table_query, -1) == ',') | |
168 $table_query = substr($table_query, 0, -1); | |
169 | |
170 $table_query .= ')'; | |
171 | |
172 if (empty($parameters['skip_transaction'])) | |
173 $smcFunc['db_transaction']('begin'); | |
174 | |
175 // Do the table and indexes... | |
176 $smcFunc['db_query']('', $table_query, | |
177 array( | |
178 'security_override' => true, | |
179 ) | |
180 ); | |
181 foreach ($index_queries as $query) | |
182 $smcFunc['db_query']('', $query, | |
183 array( | |
184 'security_override' => true, | |
185 ) | |
186 ); | |
187 | |
188 if (empty($parameters['skip_transaction'])) | |
189 $smcFunc['db_transaction']('commit'); | |
190 } | |
191 | |
192 // Drop a table. | |
193 function smf_db_drop_table($table_name, $parameters = array(), $error = 'fatal') | |
194 { | |
195 global $reservedTables, $smcFunc, $db_prefix; | |
196 | |
197 // Strip out the table name, we might not need it in some cases | |
198 $real_prefix = preg_match('~^(`?)(.+?)\\1\\.(.*?)$~', $db_prefix, $match) === 1 ? $match[3] : $db_prefix; | |
199 $full_table_name = str_replace('{db_prefix}', $real_prefix, $table_name); | |
200 $table_name = str_replace('{db_prefix}', $db_prefix, $table_name); | |
201 | |
202 // God no - dropping one of these = bad. | |
203 if (in_array(strtolower($table_name), $reservedTables)) | |
204 return false; | |
205 | |
206 // Does it exist? | |
207 if (in_array($full_table_name, $smcFunc['db_list_tables']())) | |
208 { | |
209 $query = 'DROP TABLE ' . $table_name; | |
210 $smcFunc['db_query']('', $query, | |
211 array( | |
212 'security_override' => true, | |
213 ) | |
214 ); | |
215 | |
216 return true; | |
217 } | |
218 | |
219 // Otherwise do 'nout. | |
220 return false; | |
221 } | |
222 | |
223 // Add a column. | |
224 function smf_db_add_column($table_name, $column_info, $parameters = array(), $if_exists = 'update', $error = 'fatal') | |
225 { | |
226 global $smcFunc, $db_package_log, $txt, $db_prefix; | |
227 | |
228 $table_name = str_replace('{db_prefix}', $db_prefix, $table_name); | |
229 | |
230 // Log that we will want to uninstall this! | |
231 $db_package_log[] = array('remove_column', $table_name, $column_info['name']); | |
232 | |
233 // Does it exist - if so don't add it again! | |
234 $columns = $smcFunc['db_list_columns']($table_name, false); | |
235 foreach ($columns as $column) | |
236 if ($column == $column_info['name']) | |
237 { | |
238 // If we're going to overwrite then use change column. | |
239 if ($if_exists == 'update') | |
240 return $smcFunc['db_change_column']($table_name, $column_info['name'], $column_info); | |
241 else | |
242 return false; | |
243 } | |
244 | |
245 // Alter the table to add the column. | |
246 if ($smcFunc['db_alter_table']($table_name, array('add' => array($column_info))) === false) | |
247 return false; | |
248 | |
249 return true; | |
250 } | |
251 | |
252 // We can't reliably do this on SQLite - damn! | |
253 function smf_db_remove_column($table_name, $column_name, $parameters = array(), $error = 'fatal') | |
254 { | |
255 global $smcFunc, $db_prefix; | |
256 | |
257 $table_name = str_replace('{db_prefix}', $db_prefix, $table_name); | |
258 | |
259 if ($smcFunc['db_alter_table']($table_name, array('remove' => array(array('name' => $column_name))))) | |
260 return true; | |
261 else | |
262 return false; | |
263 } | |
264 | |
265 // Change a column. | |
266 function smf_db_change_column($table_name, $old_column, $column_info, $parameters = array(), $error = 'fatal') | |
267 { | |
268 global $smcFunc, $db_prefix; | |
269 | |
270 $table_name = str_replace('{db_prefix}', $db_prefix, $table_name); | |
271 | |
272 if ($smcFunc['db_alter_table']($table_name, array('change' => array(array('name' => $old_column) + $column_info)))) | |
273 return true; | |
274 else | |
275 return false; | |
276 } | |
277 | |
278 // Add an index. | |
279 function smf_db_add_index($table_name, $index_info, $parameters = array(), $if_exists = 'update', $error = 'fatal') | |
280 { | |
281 global $smcFunc, $db_package_log, $db_prefix; | |
282 | |
283 $table_name = str_replace('{db_prefix}', $db_prefix, $table_name); | |
284 | |
285 // No columns = no index. | |
286 if (empty($index_info['columns'])) | |
287 return false; | |
288 $columns = implode(',', $index_info['columns']); | |
289 | |
290 // No name - make it up! | |
291 if (empty($index_info['name'])) | |
292 { | |
293 // No need for primary. | |
294 if (isset($index_info['type']) && $index_info['type'] == 'primary') | |
295 $index_info['name'] = ''; | |
296 else | |
297 $index_info['name'] = implode('_', $index_info['columns']); | |
298 } | |
299 else | |
300 $index_info['name'] = $index_info['name']; | |
301 | |
302 // Log that we are going to want to remove this! | |
303 $db_package_log[] = array('remove_index', $table_name, $index_info['name']); | |
304 | |
305 // Let's get all our indexes. | |
306 $indexes = $smcFunc['db_list_indexes']($table_name, true); | |
307 // Do we already have it? | |
308 foreach ($indexes as $index) | |
309 { | |
310 if ($index['name'] == $index_info['name'] || ($index['type'] == 'primary' && isset($index_info['type']) && $index_info['type'] == 'primary')) | |
311 { | |
312 // If we want to overwrite simply remove the current one then continue. | |
313 if ($if_exists != 'update' || $index['type'] == 'primary') | |
314 return false; | |
315 else | |
316 $smcFunc['db_remove_index']($table_name, $index_info['name']); | |
317 } | |
318 } | |
319 | |
320 // If we're here we know we don't have the index - so just add it. | |
321 if (!empty($index_info['type']) && $index_info['type'] == 'primary') | |
322 { | |
323 //!!! Doesn't work with PRIMARY KEY yet. | |
324 } | |
325 else | |
326 { | |
327 $smcFunc['db_query']('', ' | |
328 CREATE ' . (isset($index_info['type']) && $index_info['type'] == 'unique' ? 'UNIQUE' : '') . ' INDEX ' . $index_info['name'] . ' ON ' . $table_name . ' (' . $columns . ')', | |
329 array( | |
330 'security_override' => true, | |
331 ) | |
332 ); | |
333 } | |
334 } | |
335 | |
336 // Remove an index. | |
337 function smf_db_remove_index($table_name, $index_name, $parameters = array(), $error = 'fatal') | |
338 { | |
339 global $smcFunc, $db_prefix; | |
340 | |
341 $table_name = str_replace('{db_prefix}', $db_prefix, $table_name); | |
342 | |
343 // Better exist! | |
344 $indexes = $smcFunc['db_list_indexes']($table_name, true); | |
345 | |
346 foreach ($indexes as $index) | |
347 { | |
348 //!!! Doesn't do primary key at the moment! | |
349 if ($index['type'] != 'primary' && $index['name'] == $index_name) | |
350 { | |
351 // Drop the bugger... | |
352 $smcFunc['db_query']('', ' | |
353 DROP INDEX ' . $index_name, | |
354 array( | |
355 'security_override' => true, | |
356 ) | |
357 ); | |
358 | |
359 return true; | |
360 } | |
361 } | |
362 | |
363 // Not to be found ;( | |
364 return false; | |
365 } | |
366 | |
367 // Get the schema formatted name for a type. | |
368 function smf_db_calculate_type($type_name, $type_size = null, $reverse = false) | |
369 { | |
370 // Generic => Specific. | |
371 if (!$reverse) | |
372 { | |
373 $types = array( | |
374 'mediumint' => 'int', | |
375 'tinyint' => 'smallint', | |
376 'mediumtext' => 'text', | |
377 'largetext' => 'text', | |
378 ); | |
379 } | |
380 else | |
381 { | |
382 $types = array( | |
383 'integer' => 'int', | |
384 ); | |
385 } | |
386 | |
387 // Got it? Change it! | |
388 if (isset($types[$type_name])) | |
389 { | |
390 if ($type_name == 'tinytext') | |
391 $type_size = 255; | |
392 $type_name = $types[$type_name]; | |
393 } | |
394 // Numbers don't have a size. | |
395 if (strpos($type_name, 'int') !== false) | |
396 $type_size = null; | |
397 | |
398 return array($type_name, $type_size); | |
399 } | |
400 | |
401 // Get table structure. | |
402 function smf_db_table_structure($table_name, $parameters = array()) | |
403 { | |
404 global $smcFunc, $db_prefix; | |
405 | |
406 $table_name = str_replace('{db_prefix}', $db_prefix, $table_name); | |
407 | |
408 return array( | |
409 'name' => $table_name, | |
410 'columns' => $smcFunc['db_list_columns']($table_name, true), | |
411 'indexes' => $smcFunc['db_list_indexes']($table_name, true), | |
412 ); | |
413 } | |
414 | |
415 // Harder than it should be on sqlite! | |
416 function smf_db_list_columns($table_name, $detail = false, $parameters = array()) | |
417 { | |
418 global $smcFunc, $db_prefix; | |
419 | |
420 $table_name = str_replace('{db_prefix}', $db_prefix, $table_name); | |
421 | |
422 $result = $smcFunc['db_query']('', ' | |
423 PRAGMA table_info(' . $table_name . ')', | |
424 array( | |
425 'security_override' => true, | |
426 ) | |
427 ); | |
428 $columns = array(); | |
429 | |
430 $primaries = array(); | |
431 while ($row = $smcFunc['db_fetch_assoc']($result)) | |
432 { | |
433 if (!$detail) | |
434 { | |
435 $columns[] = $row['name']; | |
436 } | |
437 else | |
438 { | |
439 // Auto increment is hard to tell really... if there's only one primary it probably is. | |
440 if ($row['pk']) | |
441 $primaries[] = $row['name']; | |
442 | |
443 // Can we split out the size? | |
444 if (preg_match('~(.+?)\s*\((\d+)\)~i', $row['type'], $matches)) | |
445 { | |
446 $type = $matches[1]; | |
447 $size = $matches[2]; | |
448 } | |
449 else | |
450 { | |
451 $type = $row['type']; | |
452 $size = null; | |
453 } | |
454 | |
455 $columns[$row['name']] = array( | |
456 'name' => $row['name'], | |
457 'null' => $row['notnull'] ? false : true, | |
458 'default' => $row['dflt_value'], | |
459 'type' => $type, | |
460 'size' => $size, | |
461 'auto' => false, | |
462 ); | |
463 } | |
464 } | |
465 $smcFunc['db_free_result']($result); | |
466 | |
467 // Put in our guess at auto_inc. | |
468 if (count($primaries) == 1) | |
469 $columns[$primaries[0]]['auto'] = true; | |
470 | |
471 return $columns; | |
472 } | |
473 | |
474 // What about some index information? | |
475 function smf_db_list_indexes($table_name, $detail = false, $parameters = array()) | |
476 { | |
477 global $smcFunc, $db_prefix; | |
478 | |
479 $table_name = str_replace('{db_prefix}', $db_prefix, $table_name); | |
480 | |
481 $result = $smcFunc['db_query']('', ' | |
482 PRAGMA index_list(' . $table_name . ')', | |
483 array( | |
484 'security_override' => true, | |
485 ) | |
486 ); | |
487 $indexes = array(); | |
488 while ($row = $smcFunc['db_fetch_assoc']($result)) | |
489 { | |
490 if (!$detail) | |
491 $indexes[] = $row['name']; | |
492 else | |
493 { | |
494 $result2 = $smcFunc['db_query']('', ' | |
495 PRAGMA index_info(' . $row['name'] . ')', | |
496 array( | |
497 'security_override' => true, | |
498 ) | |
499 ); | |
500 while ($row2 = $smcFunc['db_fetch_assoc']($result2)) | |
501 { | |
502 // What is the type? | |
503 if ($row['unique']) | |
504 $type = 'unique'; | |
505 else | |
506 $type = 'index'; | |
507 | |
508 // This is the first column we've seen? | |
509 if (empty($indexes[$row['name']])) | |
510 { | |
511 $indexes[$row['name']] = array( | |
512 'name' => $row['name'], | |
513 'type' => $type, | |
514 'columns' => array(), | |
515 ); | |
516 } | |
517 | |
518 // Add the column... | |
519 $indexes[$row['name']]['columns'][] = $row2['name']; | |
520 } | |
521 $smcFunc['db_free_result']($result2); | |
522 } | |
523 } | |
524 $smcFunc['db_free_result']($result); | |
525 | |
526 return $indexes; | |
527 } | |
528 | |
529 function smf_db_alter_table($table_name, $columns) | |
530 { | |
531 global $smcFunc, $db_prefix, $db_name, $boarddir; | |
532 | |
533 $db_file = substr($db_name, -3) === '.db' ? $db_name : $db_name . '.db'; | |
534 | |
535 $table_name = str_replace('{db_prefix}', $db_prefix, $table_name); | |
536 | |
537 // Let's get the current columns for the table. | |
538 $current_columns = $smcFunc['db_list_columns']($table_name, true); | |
539 | |
540 // Let's get a list of columns for the temp table. | |
541 $temp_table_columns = array(); | |
542 | |
543 // Let's see if we have columns to remove or columns that are being added that already exist. | |
544 foreach ($current_columns as $key => $column) | |
545 { | |
546 $exists = false; | |
547 if (isset($columns['remove'])) | |
548 foreach ($columns['remove'] as $drop) | |
549 if ($drop['name'] == $column['name']) | |
550 { | |
551 $exists = true; | |
552 break; | |
553 } | |
554 | |
555 if (isset($columns['add'])) | |
556 foreach ($columns['add'] as $key2 => $add) | |
557 if ($add['name'] == $column['name']) | |
558 { | |
559 unset($columns['add'][$key2]); | |
560 break; | |
561 } | |
562 | |
563 // Doesn't exist then we 'remove'. | |
564 if (!$exists) | |
565 $temp_table_columns[] = $column['name']; | |
566 } | |
567 | |
568 // If they are equal then that means that the column that we are adding exists or it doesn't exist and we are not looking to change any one of them. | |
569 if (count($temp_table_columns) == count($current_columns) && empty($columns['change']) && empty($columns['add'])) | |
570 return true; | |
571 | |
572 // Drop the temp table. | |
573 $smcFunc['db_query']('', ' | |
574 DROP TABLE {raw:temp_table_name}', | |
575 array( | |
576 'temp_table_name' => $table_name . '_tmp', | |
577 'db_error_skip' => true, | |
578 ) | |
579 ); | |
580 | |
581 // Let's make a backup of the current database. | |
582 // We only want the first backup of a table modification. So if there is a backup file and older than an hour just delete and back up again | |
583 $db_backup_file = $boarddir . '/Packages/backups/backup_' . $table_name . '_' . basename($db_file) . md5($table_name . $db_file); | |
584 if (file_exists($db_backup_file) && time() - filemtime($db_backup_file) > 3600) | |
585 { | |
586 @unlink($db_backup_file); | |
587 @copy($db_file, $db_backup_file); | |
588 } | |
589 elseif (!file_exists($db_backup_file)) | |
590 @copy($db_file, $db_backup_file); | |
591 | |
592 // If we don't have temp tables then everything crapped out. Just exit. | |
593 if (empty($temp_table_columns)) | |
594 return false; | |
595 | |
596 // Start | |
597 $smcFunc['db_transaction']('begin'); | |
598 | |
599 // Let's create the temporary table. | |
600 $createTempTable = $smcFunc['db_query']('', ' | |
601 CREATE TEMPORARY TABLE {raw:temp_table_name} | |
602 ( | |
603 {raw:columns} | |
604 );', | |
605 array( | |
606 'temp_table_name' => $table_name . '_tmp', | |
607 'columns' => implode(', ', $temp_table_columns), | |
608 'db_error_skip' => true, | |
609 ) | |
610 ) !== false; | |
611 | |
612 if (!$createTempTable) | |
613 return false; | |
614 | |
615 // Insert into temp table. | |
616 $smcFunc['db_query']('', ' | |
617 INSERT INTO {raw:temp_table_name} | |
618 ({raw:columns}) | |
619 SELECT {raw:columns} | |
620 FROM {raw:table_name}', | |
621 array( | |
622 'table_name' => $table_name, | |
623 'columns' => implode(', ', $temp_table_columns), | |
624 'temp_table_name' => $table_name . '_tmp', | |
625 ) | |
626 ); | |
627 | |
628 // Drop the current table. | |
629 $dropTable = $smcFunc['db_query']('', ' | |
630 DROP TABLE {raw:table_name}', | |
631 array( | |
632 'table_name' => $table_name, | |
633 'db_error_skip' => true, | |
634 ) | |
635 ) !== false; | |
636 | |
637 // If you can't drop the main table then there is no where to go from here. Just return. | |
638 if (!$dropTable) | |
639 return false; | |
640 | |
641 // We need to keep track of the structure for the current columns and the new columns. | |
642 $new_columns = array(); | |
643 $column_names = array(); | |
644 | |
645 // Let's get the ones that we already have first. | |
646 foreach ($current_columns as $name => $column) | |
647 { | |
648 if (in_array($name, $temp_table_columns)) | |
649 { | |
650 $new_columns[$name] = array( | |
651 'name' => $name, | |
652 'type' => $column['type'], | |
653 'size' => isset($column['size']) ? (int) $column['size'] : null, | |
654 'null' => !empty($column['null']), | |
655 'auto' => isset($column['auto']) ? $column['auto'] : false, | |
656 'default' => isset($column['default']) ? $column['default'] : '', | |
657 ); | |
658 | |
659 // Lets keep track of the name for the column. | |
660 $column_names[$name] = $name; | |
661 } | |
662 } | |
663 | |
664 // Now the new. | |
665 if (!empty($columns['add'])) | |
666 foreach ($columns['add'] as $add) | |
667 { | |
668 $new_columns[$add['name']] = array( | |
669 'name' => $add['name'], | |
670 'type' => $add['type'], | |
671 'size' => isset($add['size']) ? (int) $add['size'] : null, | |
672 'null' => !empty($add['null']), | |
673 'auto' => isset($add['auto']) ? $add['auto'] : false, | |
674 'default' => isset($add['default']) ? $add['default'] : '', | |
675 ); | |
676 | |
677 // Let's keep track of the name for the column. | |
678 $column_names[$add['name']] = strstr('int', $add['type']) ? ' 0 AS ' . $add['name'] : ' {string:empty_string} AS ' . $add['name']; | |
679 } | |
680 | |
681 // Now to change a column. Not drop but change it. | |
682 if (isset($columns['change'])) | |
683 foreach ($columns['change'] as $change) | |
684 if (isset($new_columns[$change['name']])) | |
685 $new_columns[$change['name']] = array( | |
686 'name' => $change['name'], | |
687 'type' => $change['type'], | |
688 'size' => isset($change['size']) ? (int) $change['size'] : null, | |
689 'null' => !empty($change['null']), | |
690 'auto' => isset($change['auto']) ? $change['auto'] : false, | |
691 'default' => isset($change['default']) ? $change['default'] : '', | |
692 ); | |
693 | |
694 // Now let's create the table. | |
695 $createTable = $smcFunc['db_create_table']($table_name, $new_columns, array(), array('skip_transaction' => true)); | |
696 | |
697 // Did it create correctly? | |
698 if ($createTable === false) | |
699 return false; | |
700 | |
701 // Back to it's original table. | |
702 $insertData = $smcFunc['db_query']('', ' | |
703 INSERT INTO {raw:table_name} | |
704 ({raw:columns}) | |
705 SELECT ' . implode(', ', $column_names) . ' | |
706 FROM {raw:temp_table_name}', | |
707 array( | |
708 'table_name' => $table_name, | |
709 'columns' => implode(', ', array_keys($new_columns)), | |
710 'columns_select' => implode(', ', $column_names), | |
711 'temp_table_name' => $table_name . '_tmp', | |
712 'empty_string' => '', | |
713 ) | |
714 ); | |
715 | |
716 // Did everything insert correctly? | |
717 if (!$insertData) | |
718 return false; | |
719 | |
720 // Drop the temp table. | |
721 $smcFunc['db_query']('', ' | |
722 DROP TABLE {raw:temp_table_name}', | |
723 array( | |
724 'temp_table_name' => $table_name . '_tmp', | |
725 'db_error_skip' => true, | |
726 ) | |
727 ); | |
728 | |
729 // Commit or else there is no point in doing the previous steps. | |
730 $smcFunc['db_transaction']('commit'); | |
731 | |
732 // We got here so we're good. The temp table should be deleted, if not it will be gone later on >:D. | |
733 return true; | |
734 } | |
735 | |
736 ?> |