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: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379: 380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427: 428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438: 439: 440: 441: 442: 443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 453: 454: 455: 456: 457: 458: 459: 460: 461: 462: 463: 464: 465: 466: 467: 468: 469: 470: 471: 472: 473: 474: 475: 476: 477: 478: 479: 480: 481: 482: 483: 484: 485: 486: 487: 488: 489: 490: 491: 492: 493: 494: 495: 496: 497: 498: 499: 500: 501: 502: 503: 504: 505: 506: 507: 508: 509: 510: 511: 512: 513: 514: 515: 516: 517: 518: 519: 520: 521: 522: 523: 524: 525: 526: 527: 528: 529: 530: 531: 532: 533: 534: 535: 536: 537: 538: 539: 540: 541: 542: 543: 544: 545: 546: 547: 548: 549: 550: 551: 552: 553: 554: 555: 556: 557: 558: 559: 560: 561: 562: 563: 564: 565: 566: 567: 568: 569: 570: 571: 572: 573: 574: 575: 576: 577: 578: 579: 580: 581: 582: 583: 584: 585: 586: 587: 588: 589: 590: 591: 592: 593: 594: 595: 596: 597: 598: 599: 600: 601: 602: 603: 604: 605: 606: 607: 608: 609: 610: 611: 612: 613: 614: 615: 616: 617: 618: 619: 620: 621: 622: 623: 624: 625: 626: 627: 628: 629: 630: 631: 632: 633: 634: 635: 636: 637: 638: 639: 640: 641: 642: 643: 644: 645: 646: 647: 648: 649: 650: 651: 652: 653: 654: 655: 656: 657: 658: 659: 660: 661: 662: 663: 664: 665: 666: 667: 668: 669: 670: 671: 672: 673: 674: 675: 676: 677: 678: 679: 680: 681: 682: 683: 684: 685: 686: 687: 688: 689: 690: 691: 692: 693: 694: 695: 696: 697: 698: 699: 700: 701: 702: 703: 704: 705: 706: 707: 708: 709: 710: 711: 712: 713: 714: 715: 716: 717: 718: 719: 720: 721: 722: 723: 724: 725: 726: 727: 728: 729: 730: 731: 732: 733: 734: 735: 736: 737: 738: 739: 740: 741: 742: 743: 744: 745: 746: 747: 748: 749: 750: 751: 752: 753: 754: 755: 756: 757: 758: 759: 760: 761: 762: 763: 764: 765: 766: 767: 768: 769: 770: 771: 772: 773: 774: 775: 776: 777: 778: 779: 780: 781: 782: 783: 784: 785: 786: 787: 788: 789: 790: 791: 792: 793: 794: 795: 796: 797: 798: 799: 800: 801: 802: 803: 804: 805: 806: 807: 808:
<?php
if (!defined('SMF'))
die('No direct access...');
function db_packages_init()
{
global $smcFunc, $reservedTables, $db_package_log, $db_prefix;
if (!isset($smcFunc['db_create_table']) || $smcFunc['db_create_table'] != 'smf_db_create_table')
{
$smcFunc += array(
'db_add_column' => 'smf_db_add_column',
'db_add_index' => 'smf_db_add_index',
'db_calculate_type' => 'smf_db_calculate_type',
'db_change_column' => 'smf_db_change_column',
'db_create_table' => 'smf_db_create_table',
'db_drop_table' => 'smf_db_drop_table',
'db_table_structure' => 'smf_db_table_structure',
'db_list_columns' => 'smf_db_list_columns',
'db_list_indexes' => 'smf_db_list_indexes',
'db_remove_column' => 'smf_db_remove_column',
'db_remove_index' => 'smf_db_remove_index',
);
$db_package_log = array();
}
$reservedTables = array(
'admin_info_files', 'approval_queue', 'attachments',
'background_tasks', 'ban_groups', 'ban_items', 'board_permissions',
'board_permissions_view', 'boards', 'calendar', 'calendar_holidays',
'categories', 'custom_fields', 'group_moderators', 'log_actions',
'log_activity', 'log_banned', 'log_boards', 'log_comments',
'log_digest', 'log_errors', 'log_floodcontrol', 'log_group_requests',
'log_mark_read', 'log_member_notices', 'log_notify', 'log_online',
'log_packages', 'log_polls', 'log_reported', 'log_reported_comments',
'log_scheduled_tasks', 'log_search_messages', 'log_search_results',
'log_search_subjects', 'log_search_topics', 'log_spider_hits',
'log_spider_stats', 'log_subscribed', 'log_topics', 'mail_queue',
'member_logins', 'membergroups', 'members', 'mentions',
'message_icons', 'messages', 'moderator_groups', 'moderators',
'package_servers', 'permission_profiles', 'permissions',
'personal_messages', 'pm_labeled_messages', 'pm_labels',
'pm_recipients', 'pm_rules', 'poll_choices', 'polls', 'qanda',
'scheduled_tasks', 'sessions', 'settings', 'smiley_files', 'smileys',
'spiders', 'subscriptions', 'themes', 'topics', 'user_alerts',
'user_alerts_prefs', 'user_drafts', 'user_likes',
);
foreach ($reservedTables as $k => $table_name)
$reservedTables[$k] = strtolower($db_prefix . $table_name);
db_extend('extra');
}
function smf_db_create_table($table_name, $columns, $indexes = array(), $parameters = array(), $if_exists = 'ignore', $error = 'fatal')
{
global $reservedTables, $smcFunc, $db_package_log, $db_prefix, $db_character_set, $db_name;
static $engines = array();
$old_table_exists = false;
$real_prefix = preg_match('~^(`?)(.+?)\\1\\.(.*?)$~', $db_prefix, $match) === 1 ? $match[3] : $db_prefix;
$full_table_name = str_replace('{db_prefix}', $real_prefix, $table_name);
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
if (in_array(strtolower($table_name), $reservedTables))
return false;
$db_package_log[] = array('remove_table', $table_name);
$tables = $smcFunc['db_list_tables']();
if (in_array($full_table_name, $tables))
{
if ($if_exists == 'overwrite')
$smcFunc['db_drop_table']($table_name);
elseif ($if_exists == 'update')
{
$smcFunc['db_transaction']('begin');
$db_trans = true;
$smcFunc['db_drop_table']($table_name . '_old');
$smcFunc['db_query']('', '
RENAME TABLE ' . $table_name . ' TO ' . $table_name . '_old',
array(
'security_override' => true,
)
);
$old_table_exists = true;
}
else
return $if_exists == 'ignore';
}
$table_query = 'CREATE TABLE ' . $table_name . "\n" . '(';
foreach ($columns as $column)
$table_query .= "\n\t" . smf_db_create_query_column($column) . ',';
foreach ($indexes as $index)
{
$columns = implode(',', $index['columns']);
if (isset($index['type']) && $index['type'] == 'primary')
$table_query .= "\n\t" . 'PRIMARY KEY (' . implode(',', $index['columns']) . '),';
else
{
if (empty($index['name']))
$index['name'] = implode('_', $index['columns']);
$table_query .= "\n\t" . (isset($index['type']) && $index['type'] == 'unique' ? 'UNIQUE' : 'KEY') . ' ' . $index['name'] . ' (' . $columns . '),';
}
}
if (substr($table_query, -1) == ',')
$table_query = substr($table_query, 0, -1);
if (empty($engines))
{
$get_engines = $smcFunc['db_query']('', 'SHOW ENGINES', array());
while ($row = $smcFunc['db_fetch_assoc']($get_engines))
{
if ($row['Support'] == 'YES' || $row['Support'] == 'DEFAULT')
$engines[] = $row['Engine'];
}
$smcFunc['db_free_result']($get_engines);
}
if (!isset($parameters['engine']) || !in_array($parameters['engine'], $engines))
{
$parameters['engine'] = in_array('InnoDB', $engines) ? 'InnoDB' : 'MyISAM';
}
$table_query .= ') ENGINE=' . $parameters['engine'];
if (!empty($db_character_set) && $db_character_set == 'utf8')
$table_query .= ' DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci';
$smcFunc['db_query']('', $table_query,
array(
'security_override' => true,
)
);
if ($old_table_exists)
{
$same_col = array();
$request = $smcFunc['db_query']('', '
SELECT count(*), column_name
FROM information_schema.columns
WHERE table_name in ({string:table1},{string:table2}) AND table_schema = {string:schema}
GROUP BY column_name
HAVING count(*) > 1',
array(
'table1' => $table_name,
'table2' => $table_name . '_old',
'schema' => $db_name,
)
);
while ($row = $smcFunc['db_fetch_assoc']($request))
{
$same_col[] = $row['column_name'];
}
$smcFunc['db_query']('', '
INSERT INTO ' . $table_name . '('
. implode($same_col, ',') .
')
SELECT ' . implode($same_col, ',') . '
FROM ' . $table_name . '_old',
array()
);
$smcFunc['db_drop_table']($table_name . '_old');
}
return true;
}
function smf_db_drop_table($table_name, $parameters = array(), $error = 'fatal')
{
global $reservedTables, $smcFunc, $db_prefix;
$real_prefix = preg_match('~^(`?)(.+?)\\1\\.(.*?)$~', $db_prefix, $match) === 1 ? $match[3] : $db_prefix;
$full_table_name = str_replace('{db_prefix}', $real_prefix, $table_name);
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
if (in_array(strtolower($table_name), $reservedTables))
return false;
if (in_array($full_table_name, $smcFunc['db_list_tables']()))
{
$query = 'DROP TABLE ' . $table_name;
$smcFunc['db_query']('',
$query,
array(
'security_override' => true,
)
);
return true;
}
return false;
}
function smf_db_add_column($table_name, $column_info, $parameters = array(), $if_exists = 'update', $error = 'fatal')
{
global $smcFunc, $db_package_log, $db_prefix;
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
$db_package_log[] = array('remove_column', $table_name, $column_info['name']);
$columns = $smcFunc['db_list_columns']($table_name, false);
foreach ($columns as $column)
if ($column == $column_info['name'])
{
if ($if_exists == 'update')
return $smcFunc['db_change_column']($table_name, $column_info['name'], $column_info);
else
return false;
}
$column_info['size'] = isset($column_info['size']) && is_numeric($column_info['size']) ? $column_info['size'] : null;
$query = '
ALTER TABLE ' . $table_name . '
ADD ' . smf_db_create_query_column($column_info) . (empty($column_info['auto']) ? '' : ' primary key'
);
$smcFunc['db_query']('', $query,
array(
'security_override' => true,
)
);
return true;
}
function smf_db_remove_column($table_name, $column_name, $parameters = array(), $error = 'fatal')
{
global $smcFunc, $db_prefix;
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
$columns = $smcFunc['db_list_columns']($table_name, true);
foreach ($columns as $column)
if ($column['name'] == $column_name)
{
$smcFunc['db_query']('', '
ALTER TABLE ' . $table_name . '
DROP COLUMN ' . $column_name,
array(
'security_override' => true,
)
);
return true;
}
return false;
}
function smf_db_change_column($table_name, $old_column, $column_info)
{
global $smcFunc, $db_prefix;
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
$columns = $smcFunc['db_list_columns']($table_name, true);
$old_info = null;
foreach ($columns as $column)
if ($column['name'] == $old_column)
$old_info = $column;
if ($old_info == null)
return false;
if (!isset($column_info['name']))
$column_info['name'] = $old_column;
if (!isset($column_info['default']))
$column_info['default'] = $old_info['default'];
if (!isset($column_info['null']))
$column_info['null'] = $old_info['null'];
if (!isset($column_info['auto']))
$column_info['auto'] = $old_info['auto'];
if (!isset($column_info['type']))
$column_info['type'] = $old_info['type'];
if (!isset($column_info['size']) || !is_numeric($column_info['size']))
$column_info['size'] = $old_info['size'];
if (!isset($column_info['unsigned']) || !in_array($column_info['type'], array('int', 'tinyint', 'smallint', 'mediumint', 'bigint')))
$column_info['unsigned'] = '';
list ($type, $size) = $smcFunc['db_calculate_type']($column_info['type'], $column_info['size']);
$unsigned = in_array($type, array('int', 'tinyint', 'smallint', 'mediumint', 'bigint')) && !empty($column_info['unsigned']) ? 'unsigned ' : '';
if ($size !== null)
$type = $type . '(' . $size . ')';
$smcFunc['db_query']('', '
ALTER TABLE ' . $table_name . '
CHANGE COLUMN `' . $old_column . '` `' . $column_info['name'] . '` ' . $type . ' ' . (!empty($unsigned) ? $unsigned : '') . (empty($column_info['null']) ? 'NOT NULL' : '') . ' ' .
(!isset($column_info['default']) ? '' : 'default \'' . $smcFunc['db_escape_string']($column_info['default']) . '\'') . ' ' .
(empty($column_info['auto']) ? '' : 'auto_increment') . ' ',
array(
'security_override' => true,
)
);
}
function smf_db_add_index($table_name, $index_info, $parameters = array(), $if_exists = 'update', $error = 'fatal')
{
global $smcFunc, $db_package_log, $db_prefix;
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
if (empty($index_info['columns']))
return false;
$columns = implode(',', $index_info['columns']);
if (empty($index_info['name']))
{
if (isset($index_info['type']) && $index_info['type'] == 'primary')
$index_info['name'] = '';
else
$index_info['name'] = implode('_', $index_info['columns']);
}
$db_package_log[] = array('remove_index', $table_name, $index_info['name']);
$indexes = $smcFunc['db_list_indexes']($table_name, true);
foreach ($indexes as $index)
{
if ($index['name'] == $index_info['name'] || ($index['type'] == 'primary' && isset($index_info['type']) && $index_info['type'] == 'primary'))
{
if ($if_exists != 'update' || $index['type'] == 'primary')
return false;
else
$smcFunc['db_remove_index']($table_name, $index_info['name']);
}
}
if (!empty($index_info['type']) && $index_info['type'] == 'primary')
{
$smcFunc['db_query']('', '
ALTER TABLE ' . $table_name . '
ADD PRIMARY KEY (' . $columns . ')',
array(
'security_override' => true,
)
);
}
else
{
$smcFunc['db_query']('', '
ALTER TABLE ' . $table_name . '
ADD ' . (isset($index_info['type']) && $index_info['type'] == 'unique' ? 'UNIQUE' : 'INDEX') . ' ' . $index_info['name'] . ' (' . $columns . ')',
array(
'security_override' => true,
)
);
}
}
function smf_db_remove_index($table_name, $index_name, $parameters = array(), $error = 'fatal')
{
global $smcFunc, $db_prefix;
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
$indexes = $smcFunc['db_list_indexes']($table_name, true);
foreach ($indexes as $index)
{
if ($index['type'] == 'primary' && $index_name == 'primary')
{
$smcFunc['db_query']('', '
ALTER TABLE ' . $table_name . '
DROP PRIMARY KEY',
array(
'security_override' => true,
)
);
return true;
}
if ($index['name'] == $index_name)
{
$smcFunc['db_query']('', '
ALTER TABLE ' . $table_name . '
DROP INDEX ' . $index_name,
array(
'security_override' => true,
)
);
return true;
}
}
return false;
}
function smf_db_calculate_type($type_name, $type_size = null, $reverse = false)
{
$type_name = strtolower($type_name);
if (!$reverse)
{
$types = array(
'inet' => 'varbinary',
);
}
else
{
$types = array(
'varbinary' => 'inet',
);
}
if (isset($types[$type_name]))
{
if ($type_name == 'inet' && !$reverse)
{
$type_size = 16;
$type_name = 'varbinary';
}
elseif ($type_name == 'varbinary' && $reverse && $type_size == 16)
{
$type_name = 'inet';
$type_size = null;
}
elseif ($type_name == 'varbinary')
$type_name = 'varbinary';
else
$type_name = $types[$type_name];
}
elseif ($type_name == 'boolean')
$type_size = null;
return array($type_name, $type_size);
}
function smf_db_table_structure($table_name)
{
global $smcFunc, $db_prefix;
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
$table_status = $smcFunc['db_query']('', '
SHOW TABLE STATUS
LIKE {string:table}',
array(
'table' => strtr($table_name, array('_' => '\\_', '%' => '\\%'))
)
);
$row = $smcFunc['db_fetch_assoc']($table_status);
$smcFunc['db_free_result']($table_status);
return array(
'name' => $table_name,
'columns' => $smcFunc['db_list_columns']($table_name, true),
'indexes' => $smcFunc['db_list_indexes']($table_name, true),
'engine' => $row['Engine'],
);
}
function smf_db_list_columns($table_name, $detail = false, $parameters = array())
{
global $smcFunc, $db_prefix, $db_name;
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
$result = $smcFunc['db_query']('', '
SELECT column_name "Field", COLUMN_TYPE "Type", is_nullable "Null", COLUMN_KEY "Key" , column_default "Default", extra "Extra"
FROM information_schema.columns
WHERE table_name = {string:table_name}
AND table_schema = {string:db_name}
ORDER BY ordinal_position',
array(
'table_name' => $table_name,
'db_name' => $db_name,
)
);
$columns = array();
while ($row = $smcFunc['db_fetch_assoc']($result))
{
if (!$detail)
{
$columns[] = $row['Field'];
}
else
{
$auto = strpos($row['Extra'], 'auto_increment') !== false ? true : false;
if (preg_match('~(.+?)\s*\((\d+)\)(?:(?:\s*)?(unsigned))?~i', $row['Type'], $matches) === 1)
{
$type = $matches[1];
$size = $matches[2];
if (!empty($matches[3]) && $matches[3] == 'unsigned')
$unsigned = true;
}
else
{
$type = $row['Type'];
$size = null;
}
$columns[$row['Field']] = array(
'name' => $row['Field'],
'null' => $row['Null'] != 'YES' ? false : true,
'default' => isset($row['Default']) ? $row['Default'] : null,
'type' => $type,
'size' => $size,
'auto' => $auto,
);
if (isset($unsigned))
{
$columns[$row['Field']]['unsigned'] = $unsigned;
unset($unsigned);
}
}
}
$smcFunc['db_free_result']($result);
return $columns;
}
function smf_db_list_indexes($table_name, $detail = false, $parameters = array())
{
global $smcFunc, $db_prefix;
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
$result = $smcFunc['db_query']('', '
SHOW KEYS
FROM {raw:table_name}',
array(
'table_name' => substr($table_name, 0, 1) == '`' ? $table_name : '`' . $table_name . '`',
)
);
$indexes = array();
while ($row = $smcFunc['db_fetch_assoc']($result))
{
if (!$detail)
$indexes[] = $row['Key_name'];
else
{
if ($row['Key_name'] == 'PRIMARY')
$type = 'primary';
elseif (empty($row['Non_unique']))
$type = 'unique';
elseif (isset($row['Index_type']) && $row['Index_type'] == 'FULLTEXT')
$type = 'fulltext';
else
$type = 'index';
if (empty($indexes[$row['Key_name']]))
{
$indexes[$row['Key_name']] = array(
'name' => $row['Key_name'],
'type' => $type,
'columns' => array(),
);
}
if (!empty($row['Sub_part']))
$indexes[$row['Key_name']]['columns'][] = $row['Column_name'] . '(' . $row['Sub_part'] . ')';
else
$indexes[$row['Key_name']]['columns'][] = $row['Column_name'];
}
}
$smcFunc['db_free_result']($result);
return $indexes;
}
function smf_db_create_query_column($column)
{
global $smcFunc;
if (!empty($column['auto']))
{
$default = 'auto_increment';
}
elseif (isset($column['default']) && $column['default'] !== null)
$default = 'default \'' . $smcFunc['db_escape_string']($column['default']) . '\'';
else
$default = '';
$column['size'] = isset($column['size']) && is_numeric($column['size']) ? $column['size'] : null;
list ($type, $size) = $smcFunc['db_calculate_type']($column['type'], $column['size']);
$unsigned = in_array($type, array('int', 'tinyint', 'smallint', 'mediumint', 'bigint')) && !empty($column['unsigned']) ? 'unsigned ' : '';
if ($size !== null)
$type = $type . '(' . $size . ')';
return '`' . $column['name'] . '` ' . $type . ' ' . (!empty($unsigned) ? $unsigned : '') . (!empty($column['null']) ? '' : 'NOT NULL') . ' ' . $default;
}
?>