PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/e107_handlers/db_table_admin_class.php

https://github.com/CasperGemini/e107
PHP | 705 lines | 597 code | 30 blank | 78 comment | 98 complexity | 694aedc6381ff4c99dadd58316afb919 MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. /*
  3. * e107 website system
  4. *
  5. * Copyright (C) 2008-2013 e107 Inc (e107.org)
  6. * Released under the terms and conditions of the
  7. * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
  8. *
  9. * Database utilities
  10. *
  11. */
  12. /*
  13. Database utilities for admin tasks:
  14. Get structure of a table from a database
  15. Get structure of a table from a file
  16. First level parse of table structure
  17. Parse of field definitions part of table structure
  18. Comparison of two structures, including generation of MySQL to make them the same
  19. Some crude printing utilities
  20. Note: there are some uncommented 'echo' statements which are intentional to highlight that something's gone wrong! (not that it should, of course)
  21. */
  22. // DEPRECATED - USE db_verify_class where possible.
  23. class db_table_admin
  24. {
  25. var $file_buffer = ''; // Contents of a file
  26. var $last_file = '';
  27. // Get list of fields and keys for a table - return FALSE if unsuccessful
  28. // Return as for get_table_def
  29. function get_current_table($table_name, $prefix = "")
  30. {
  31. $sql = e107::getDb();
  32. if(!isset($sql))
  33. {
  34. $sql = new db;
  35. }
  36. if (!$prefix)
  37. {
  38. $prefix = MPREFIX;
  39. }
  40. // echo "Get table structure for: {$table_name}, prefix: {$prefix}<br />";
  41. $sql->db_Select_gen('SET SQL_QUOTE_SHOW_CREATE = 1');
  42. $qry = 'SHOW CREATE TABLE `'.$prefix.$table_name."`";
  43. if (!($z = $sql->db_Select_gen($qry)))
  44. {
  45. return FALSE;
  46. }
  47. $row = $sql->db_Fetch(MYSQL_NUM);
  48. $tmp = str_replace("`", "", stripslashes($row[1])).';'; // Add semicolon to work with our parser
  49. $count = preg_match_all("#CREATE\s+?TABLE\s+?`{0,1}({$prefix}{$table_name})`{0,1}\s+?\((.*?)\)\s+?(?:TYPE|ENGINE)\s*\=\s*(.*?);#is", $tmp, $matches, PREG_SET_ORDER);
  50. if ($count === FALSE)
  51. {
  52. return "Error occurred";
  53. }
  54. if (!$count)
  55. {
  56. return "No matches";
  57. }
  58. return $matches;
  59. }
  60. /**
  61. * Routine to do first-level parse of table structure
  62. *---------------------------------------------------
  63. * Given the name of a file, returns an array, with each element being a table creation definition.
  64. * Tracks the last file read - only reads it once
  65. * If the file name is an empty string, uses a previously read/set buffer
  66. *
  67. * @param string $table_name - If specified, returns only that table's info; otherwise returns a list of all tables
  68. * The table name must include a prefix where appropriate (although not required with standard E107 table definition files)
  69. * @return string|array
  70. * - if error, returns a brief text message
  71. * - if successful, returns an array of table definitions, each of which is itself an array:
  72. * [0] - The complete string which creates a table (unless a prefix needs adding to the table name), including terminating ';'
  73. * [1] - The table name. Any backticks are stripped
  74. * [2] - Field definitions, with the surrounding (...) stripped
  75. * [3] - The 'TYPE' field ('TYPE=' is stripped) and any AUTO-INCREMENT definition or other text.
  76. */
  77. function get_table_def($table_name = '', $file_name = "")
  78. {
  79. if ($file_name != '')
  80. { // Read in and buffer a new file (if we've not already got one)
  81. if ($this->last_file != $file_name)
  82. {
  83. if (!is_readable($file_name))
  84. {
  85. return "No file";
  86. }
  87. $temp = file_get_contents($file_name);
  88. // Strip any php header
  89. $temp = preg_replace("#\<\?php.*?\?\>#mis", '', $temp);
  90. // Strip any comments (only /*...*/ supported
  91. $this->file_buffer = preg_replace("#\/\*.*?\*\/#mis", '', $temp);
  92. $this->last_file = $file_name;
  93. }
  94. }
  95. if (!$table_name)
  96. {
  97. $table_name = '\w+?';
  98. }
  99. // Regex should be identical to that in get_current_table (apart from the source text variable name)
  100. $count = preg_match_all("#CREATE\s+?TABLE\s+?`{0,1}({$table_name})`{0,1}\s+?\((.*?)\)\s+?(?:TYPE|ENGINE)\s*\=\s*(.*?);#is", $this->file_buffer, $matches, PREG_SET_ORDER);
  101. if ($count === false)
  102. {
  103. return "Error occurred";
  104. }
  105. if (!$count)
  106. {
  107. return "No matches";
  108. }
  109. return $matches;
  110. }
  111. // Parses the block of lines which make up the field and index definitions
  112. // Returns an array where each entry is the definitions of a field or index
  113. function parse_field_defs($text)
  114. {
  115. $ans = array(
  116. );
  117. $text = str_replace("\r", "\n", $text);
  118. $field_lines = explode("\n", $text);
  119. foreach ($field_lines as $fv)
  120. {
  121. unset($defs);
  122. $fv = trim(str_replace(' ', ' ', $fv));
  123. $fv = str_replace('`', '', $fv);
  124. if (substr($fv, -1) == ',')
  125. {
  126. $fv = trim(substr($fv, 0, -1));
  127. }
  128. // echo "Line: ".$fv."<br />";
  129. if ($fv)
  130. {
  131. $fd = explode(' ', $fv);
  132. switch (strtoupper($fd[0]))
  133. {
  134. case 'PRIMARY':
  135. if (strtoupper($fd[1]) == 'KEY')
  136. $defs['type'] = 'pkey';
  137. $defs['name'] = $fd[2];
  138. break;
  139. case 'UNIQUE':
  140. if (count($fd) < 3)
  141. {
  142. echo "Truncated definition after UNIQUE {$i}: ".$fd[1]."<br />";
  143. }
  144. elseif (strtoupper($fd[1]) == 'KEY')
  145. {
  146. $defs['type'] = 'ukey';
  147. $defs['name'] = $fd[2];
  148. if (isset($fd[3])) $defs['keyfield'] = $fd[3];
  149. else $defs['keyfield'] = '['.$fd[2].']';
  150. }
  151. else
  152. {
  153. echo "Unrecognised word after UNIQUE in definition {$i}: ".$fd[1]."<br />";
  154. }
  155. break;
  156. case 'FULLTEXT':
  157. if (count($fd) < 3)
  158. {
  159. echo "Truncated definition after FULLTEXT {$i}: ".$fd[1]."<br />";
  160. }
  161. elseif (strtoupper($fd[1]) == 'KEY')
  162. {
  163. $defs['type'] = 'ftkey';
  164. $defs['name'] = $fd[2];
  165. if (isset($fd[3])) $defs['keyfield'] = $fd[3];
  166. else $defs['keyfield'] = '['.$fd[2].']';
  167. }
  168. else
  169. {
  170. echo "Unrecognised word after FULLTEXT in definition {$i}: ".$fd[1]."<br />";
  171. }
  172. break;
  173. case 'KEY':
  174. $defs['type'] = 'key';
  175. $defs['name'] = $fd[1];
  176. if (isset($fd[2]))
  177. {
  178. $defs['keyfield'] = $fd[2];
  179. }
  180. else
  181. {
  182. $defs['keyfield'] = '['.$fd[1].']';
  183. }
  184. break;
  185. default: // Must be a DB field name
  186. $defs['type'] = 'field';
  187. $defs['name'] = $fd[0];
  188. $defs['fieldtype'] = $fd[1];
  189. $i = 2; // First unused field
  190. if ((strpos($fd[1], 'int') === 0) || (strpos($fd[1], 'tinyint') === 0) || (strpos($fd[1], 'smallint') === 0) || (strpos($fd[1], 'bigint') === 0))
  191. {
  192. if (isset($fd[2]) && (strtoupper($fd[2]) == 'UNSIGNED'))
  193. {
  194. $defs['vartype'] = $fd[2];
  195. $i++;
  196. }
  197. }
  198. while ($i < count($fd))
  199. {
  200. switch (strtoupper($fd[$i]))
  201. {
  202. case 'NOT':
  203. if (isset($fd[$i + 1]) && strtoupper($fd[$i + 1]) == 'NULL')
  204. {
  205. $i++;
  206. $defs['nulltype'] = 'NOT NULL';
  207. }
  208. else
  209. { // Syntax error
  210. echo "Unrecognised word in definition {$i} after 'NOT': ".$fd[$i + 1]."<br />";
  211. }
  212. break;
  213. case 'DEFAULT':
  214. if (isset($fd[$i + 1]))
  215. {
  216. $i++;
  217. $defs['default'] = $fd[$i];
  218. }
  219. break;
  220. case 'COLLATE':
  221. $i++; // Just skip over - we ignore collation
  222. break;
  223. case 'AUTO_INCREMENT':
  224. $defs['autoinc'] = TRUE;
  225. break;
  226. default:
  227. if(E107_DBG_SQLDETAILS)
  228. {
  229. $mes = e107::getMessage();
  230. $mes->add("db_table_admin_class.php :: parse_field_defs() Line: 230 - Unknown definition {$i}: ".$fd[$i], E_MESSAGE_DEBUG);
  231. }
  232. }
  233. $i++;
  234. }
  235. }
  236. if (count($defs) > 1)
  237. {
  238. $ans[] = $defs;
  239. }
  240. else
  241. {
  242. echo "Partial definition<br />";
  243. }
  244. }
  245. }
  246. if (!count($ans))
  247. {
  248. return FALSE;
  249. }
  250. return $ans;
  251. }
  252. // Utility routine - given our array-based definition, create a string MySQL field definition
  253. function make_def($list)
  254. {
  255. switch ($list['type'])
  256. {
  257. case 'key':
  258. return 'KEY '.$list['name'].' ('.str_replace(array( '(', ')' ), '', $list['keyfield']).')';
  259. case 'ukey':
  260. return 'UNIQUE KEY '.$list['name'].' ('.str_replace(array( '(', ')' ), '', $list['keyfield']).')';
  261. case 'ftkey':
  262. return 'FULLTEXT KEY '.$list['name'].' ('.str_replace(array( '(', ')' ), '', $list['keyfield']).')';
  263. case 'pkey':
  264. return 'PRIMARY KEY ('.$list['name'].')';
  265. case 'field': // Require a field - got a key. so add a field at the end
  266. $def = $list['name'];
  267. if (isset($list['fieldtype']))
  268. {
  269. $def .= ' '.$list['fieldtype'];
  270. }
  271. if (isset($list['vartype']))
  272. {
  273. $def .= ' '.$list['vartype'];
  274. }
  275. if (isset($list['nulltype']))
  276. {
  277. $def .= ' '.$list['nulltype'];
  278. }
  279. if (isset($list['default']))
  280. {
  281. $def .= ' default '.$list['default'];
  282. }
  283. if (varsettrue($list['autoinc']))
  284. {
  285. $def .= ' auto_increment';
  286. }
  287. return $def;
  288. }
  289. return "Cannot generate definition for: ".$list['type'].' '.$list['name'];
  290. }
  291. // Compare two field/index lists as generated by parse_field_defs
  292. // If $stop_on_error is TRUE, returns TRUE if the same, false if different
  293. // Return a text list of differences, plus an array of MySQL queries to fix
  294. // List1 is the reference, List 2 is the actual
  295. // This version looks ahead on a failed match, and moves a field up in the table if already defined - should retain as much as possible
  296. function compare_field_lists($list1, $list2, $stop_on_error = FALSE)
  297. {
  298. $i = 0; // Counts records in list1 (required format)
  299. $j = 0; // Counts records in $created_list (our 'table so far' list)
  300. $error_list = array(
  301. ); // Free text list of differences
  302. $change_list = array(
  303. ); // MySQL statements to implement changes
  304. $created_list = array(
  305. ); // List of field defs that we build up (just names)
  306. while ($i < count($list1))
  307. {
  308. if (count($list2) == 0)
  309. { // Missing field at end
  310. if ($stop_on_error)
  311. {
  312. return FALSE;
  313. }
  314. $error_list[] = 'Missing field at end: '.$list1[$i]['name'];
  315. $change_list[] = 'ADD '.$this->make_def($list1[$i]);
  316. $created_list[$j] = $list1[$i]['name'];
  317. $j++;
  318. }
  319. elseif ($list1[$i]['type'] == $list2[0]['type'])
  320. { // Worth doing a compare - fields are same type
  321. // echo $i.': compare - '.$list1[$i]['name'].', '.$list2[0]['name'].'<br />';
  322. if (strcasecmp($list1[$i]['name'], $list2[0]['name']) != 0)
  323. { // Names differ, so need to add or subtract a field.
  324. // echo $i.': names differ - '.$list1[$i]['name'].', '.$list2[0]['name'].'<br />';
  325. if ($stop_on_error)
  326. {
  327. return FALSE;
  328. }
  329. $found = FALSE;
  330. for ($k = $i + 1; $k < count($list1); $k++)
  331. {
  332. // echo "Compare ".$list1[$k]['name'].' with '.$list2[0]['name'];
  333. if (strcasecmp($list1[$k]['name'], $list2[0]['name']) == 0)
  334. { // Field in list2 found later in list1; do nothing
  335. // echo " - match<br />";
  336. $found = TRUE;
  337. break;
  338. }
  339. // echo " - no match<br />";
  340. }
  341. if (!$found)
  342. { // Field in existing DB no longer required
  343. $error_list[] = 'Obsolete field: '.$list2[0]['name'];
  344. $change_list[] = 'DROP '.($list2[0]['type'] == 'field' ? '' : 'INDEX ').$list2[0]['name'];
  345. array_shift($list2);
  346. continue;
  347. }
  348. $found = FALSE;
  349. for ($k = 0; $k < count($list2); $k++)
  350. {
  351. // echo "Compare ".$list1[$i]['name'].' with '.$list2[$k]['name'];
  352. if (strcasecmp($list1[$i]['name'], $list2[$k]['name']) == 0)
  353. { // Field found; we need to move it up
  354. // echo " - match<br />";
  355. $found = TRUE;
  356. break;
  357. }
  358. // echo " - no match<br />";
  359. }
  360. if ($found)
  361. {
  362. $error_list[] = 'Field out of position: '.$list2[$k]['name'];
  363. $change_list[] = 'MODIFY '.$this->make_def($list1[$i]).(count($created_list) ? ' AFTER '.$created_list[count($created_list) - 1] : ' FIRST');
  364. array_splice($list2, $k, 1); // Finished with this element - delete it, and renumber the keys
  365. $created_list[$j] = $list1[$i]['name'];
  366. $j++;
  367. // The above also amends any parameters as necessary
  368. }
  369. else
  370. { // Need to insert a field
  371. $error_list[] = 'Missing field: '.$list1[$i]['name'].' (found: '.$list2[0]['type'].' '.$list2[0]['name'].')';
  372. switch ($list1[$i]['type'])
  373. {
  374. case 'key':
  375. case 'ukey':
  376. case 'ftkey':
  377. case 'pkey': // Require a key
  378. $change_list[] = 'ADD '.$this->make_def($list1[$i]);
  379. $error_list[] = 'Missing index: '.$list1[$i]['name'];
  380. $created_list[$j] = $list1[$i]['name'];
  381. $j++;
  382. break;
  383. case 'field':
  384. $change_list[] = 'ADD '.$this->make_def($list1[$i]).(count($created_list) ? ' AFTER '.$created_list[count($created_list) - 1] : ' FIRST');
  385. $error_list[] = 'Missing field: '.$list1[$i]['name'].' (found: '.$list2[0]['type'].' '.$list2[0]['name'].')';
  386. $created_list[$j] = $list1[$i]['name'];
  387. $j++;
  388. break;
  389. }
  390. }
  391. }
  392. else
  393. { // Field/index is present as required; may be changes though
  394. // Any difference and we need to update the table
  395. // echo $i.': name match - '.$list1[$i]['name'].'<br />';
  396. foreach ($list1[$i] as $fi=>$v)
  397. {
  398. $t = $list2[0][$fi];
  399. if (stripos($v, 'varchar') !== FALSE)
  400. {
  401. $v = substr($v, 3);
  402. } // Treat char, varchar the same
  403. if (stripos($t, 'varchar') !== FALSE)
  404. {
  405. $t = substr($t, 3);
  406. } // Treat char, varchar the same
  407. if (strcasecmp($t, $v) !== 0)
  408. {
  409. if ($stop_on_error)
  410. {
  411. return FALSE;
  412. }
  413. $error_list[] = 'Incorrect definition: '.$fi.' = '.$v;
  414. $change_list[] = 'MODIFY '.$this->make_def($list1[$i]);
  415. break;
  416. }
  417. }
  418. array_shift($list2);
  419. $created_list[$j] = $list1[$i]['name'];
  420. $j++;
  421. }
  422. }
  423. else
  424. { // Field type has changed. We know fields come before indexes. So something's missing
  425. // echo $i.': types differ - '.$list1[$i]['type'].' '.$list1[$i]['name'].', '.$list2[$k]['type'].' '.$list2[$k]['name'].'<br />';
  426. if ($stop_on_error)
  427. {
  428. return FALSE;
  429. }
  430. switch ($list1[$i]['type'])
  431. {
  432. case 'key':
  433. case 'ukey':
  434. case 'ftkey':
  435. case 'pkey': // Require a key - got a field, or a key of a different type
  436. while ((count($list2) > 0) && ($list2[0]['type'] == 'field'))
  437. {
  438. $error_list[] = 'Extra field: '.$list2[0]['name'];
  439. $change_list[] = 'DROP '.$list2[0]['name'];
  440. array_shift($list2);
  441. }
  442. if ((count($list2) == 0) || ($list1[$i]['type'] != $list2[0]['type']))
  443. { // need to add a key
  444. $change_list[] = 'ADD '.$this->make_def($list1[$i]);
  445. $error_list[] = 'Missing index: '.$list1[$i]['name'];
  446. $created_list[$j] = $list1[$i]['name'];
  447. $j++;
  448. }
  449. break;
  450. case 'field': // Require a field - got a key. so add a field at the end
  451. $error_list[] = 'Missing field: '.$list1[$i]['name'].' (found: '.$list2[0]['type'].' '.$list2[0]['name'].')';
  452. $change_list[] = 'ADD '.$this->make_def($list1[$i]);
  453. break;
  454. default:
  455. $error_list[] = 'Unknown field type: '.$list1[$i]['type'];
  456. $change_list[] = ''; // Null entry to keep them in step
  457. }
  458. } // End - missing or extra field
  459. $i++; // On to next field
  460. }
  461. if (count($list2))
  462. { // Surplus fields in actual table
  463. // Echo count($list2)." fields at end to delete<br />";
  464. foreach ($list2 as $f)
  465. {
  466. switch ($f['type'])
  467. {
  468. case 'key':
  469. case 'ukey':
  470. case 'ftkey':
  471. case 'pkey': // Require a key - got a field
  472. $error_list[] = 'Extra index: '.$list2[0]['name'];
  473. $change_list[] = 'DROP INDEX '.$list2[0]['name'];
  474. break;
  475. case 'field':
  476. $error_list[] = 'Extra field: '.$list2[0]['name'];
  477. $change_list[] = 'DROP '.$list2[0]['name'];
  478. break;
  479. }
  480. }
  481. }
  482. if ($stop_on_error)
  483. return TRUE; // If doing a simple comparison and we get to here, all matches
  484. return array(
  485. $error_list, $change_list
  486. );
  487. }
  488. function make_changes_list($result)
  489. {
  490. if (!is_array($result))
  491. {
  492. return "Not an array<br />";
  493. }
  494. $text = "<table>";
  495. for ($i = 0; $i < count($result[0]); $i++)
  496. {
  497. $text .= "<tr><td>{$result[0][$i]}</td>";
  498. $text .= "<td>{$result[1][$i]}</td>";
  499. $text .= "</tr>\n";
  500. }
  501. $text .= "</table><br /><br />";
  502. return $text;
  503. }
  504. // Return a table of info from the output of get_table_def
  505. function make_table_list($result)
  506. {
  507. if (!is_array($result))
  508. {
  509. return "Not an array<br />";
  510. }
  511. $text = "<table>";
  512. for ($i = 0; $i < count($result); $i++)
  513. {
  514. $text .= "<tr><td>{$result[$i][0]}</td>";
  515. $text .= "<td>{$result[$i][1]}</td>";
  516. $text .= "<td>{$result[$i][2]}</td>";
  517. $text .= "<td>{$result[$i][3]}</td></tr>\n";
  518. }
  519. $text .= "</table><br /><br />";
  520. return $text;
  521. }
  522. // Return a table of info from the output of parse_field_defs()
  523. function make_field_list($fields)
  524. {
  525. $text = "<table>";
  526. foreach ($fields as $f)
  527. {
  528. switch ($f['type'])
  529. {
  530. case 'pkey':
  531. $text .= "<tr><td>PRIMARY KEY</td><td>{$f['name']}</td><td>&nbsp;</td></tr>";
  532. break;
  533. case 'ukey':
  534. $text .= "<tr><td>UNIQUE KEY</td><td>{$f['name']}</td><td>{$f['keyfield']}</td></tr>";
  535. break;
  536. case 'ftkey':
  537. $text .= "<tr><td>FULLTEXT KEY</td><td>{$f['name']}</td><td>{$f['keyfield']}</td></tr>";
  538. break;
  539. case 'key':
  540. $text .= "<tr><td>KEY</td><td>{$f['name']}</td><td>{$f['keyfield']}</td></tr>";
  541. break;
  542. case 'field':
  543. $text .= "<tr><td>FIELD</td><td>{$f['name']}</td><td>{$f['fieldtype']}";
  544. if (isset($f['vartype']))
  545. {
  546. $text .= " ".$f['vartype'];
  547. }
  548. $text .= "</td>";
  549. if (isset($f['nulltype']))
  550. {
  551. $text .= "<td>{$f['nulltype']}</td>";
  552. }
  553. else
  554. {
  555. $text .= "<td>&nbsp;</td>";
  556. }
  557. if (isset($f['default']))
  558. {
  559. $text .= "<td>default {$f['default']}</td>";
  560. }
  561. elseif (isset($f['autoinc']))
  562. {
  563. $text .= "<td>AUTO_INCREMENT</td>";
  564. }
  565. else
  566. {
  567. $text .= "<td>&nbsp;</td>";
  568. }
  569. $text .= "</tr>";
  570. break;
  571. default:
  572. $text .= "<tr><td>!!Unknown!!</td><td>{$f['type']}</td><td>&nbsp;</td></tr>";
  573. }
  574. }
  575. $text .= "</table><br /><br />--Ends--<br />";
  576. return $text;
  577. }
  578. //--------------------------------------------------
  579. // Update a table to required structure
  580. //--------------------------------------------------
  581. // $newStructure is an array element as returned from get_table_def()
  582. // If $mlUpdate is TRUE, applies same query to all tables of same language
  583. // Return TRUE on success.
  584. // Return text string if $justCheck is TRUE and changes needed
  585. // Return text string on most failures
  586. // Return FALSE on certain failures (generally indicative of code/system problems)
  587. function update_table_structure($newStructure, $justCheck = FALSE, $makeNewifNotExist = TRUE, $mlUpdate = FALSE)
  588. {
  589. global $sql;
  590. // Pull out table name
  591. $debugLevel = E107_DBG_SQLDETAILS;
  592. $tableName = $newStructure[1];
  593. if (!$sql->db_Table_exists($tableName))
  594. {
  595. if ($makeNewifNotExist === FALSE)
  596. {
  597. return 'Table doesn\'t exist';
  598. }
  599. if ($sql->db_Select_gen($newStructure[0]))
  600. {
  601. return TRUE;
  602. }
  603. return 'Error creating new table: '.$tableName;
  604. }
  605. $reqFields = $this->parse_field_defs($newStructure[2]); // Required field definitions
  606. if ($debugLevel)
  607. {
  608. echo "Required table structure: <br />".$this->make_field_list($reqFields);
  609. }
  610. if ((($actualDefs = $this->get_current_table($tableName)) === FALSE) || !is_array($actualDefs)) // Get actual table definition (Adds current default prefix)
  611. {
  612. return "Couldn't get table structure: {$tableName}<br />";
  613. }
  614. else
  615. {
  616. // echo $db_parser->make_table_list($actual_defs);
  617. $actualFields = $this->parse_field_defs($actualDefs[0][2]); // Split into field definitions
  618. if ($debugLevel)
  619. {
  620. echo 'Actual table structure: <br />'.$this->make_field_list($actualFields);
  621. }
  622. $diffs = $this->compare_field_lists($reqFields, $actualFields); // Work out any differences
  623. if (count($diffs[0]))
  624. { // Changes needed
  625. if ($justCheck)
  626. {
  627. return 'Field changes rqd; table: '.$tableName.'<br />';
  628. }
  629. // Do the changes here
  630. if ($debugLevel)
  631. {
  632. echo "List of changes found:<br />".$this->make_changes_list($diffs);
  633. }
  634. $qry = 'ALTER TABLE '.MPREFIX.$tableName.' '.implode(', ', $diffs[1]);
  635. if ($debugLevel)
  636. {
  637. echo 'Update Query used: '.$qry.'<br />';
  638. }
  639. if ($mlUpdate)
  640. {
  641. $ret = $sql->db_Query_all($qry); // Returns TRUE = success, FALSE = fail
  642. }
  643. else
  644. {
  645. $ret = $sql->gen($qry);
  646. }
  647. if ($ret === FALSE)
  648. {
  649. return $sql->dbError();
  650. }
  651. }
  652. return TRUE; // Success even if no changes required
  653. }
  654. return FALSE;
  655. }
  656. function createTable($pathToSqlFile = '', $tableName = '', $addPrefix = true, $renameTable = '')
  657. {
  658. $e107 = e107::getInstance();
  659. $tmp = $this->get_table_def($tableName, $pathToSqlFile);
  660. $createText = $tmp[0][0];
  661. $newTableName = ($renameTable ? $renameTable : $tableName);
  662. if ($addPrefix)
  663. {
  664. $newTableName = MPREFIX.$newTableName;
  665. }
  666. if ($newTableName != $tableName)
  667. {
  668. $createText = preg_replace('#create +table +(\w*?) +#i', 'CREATE TABLE '.$newTableName.' ', $createText);
  669. }
  670. return e107::getDb()->gen($createText);
  671. }
  672. }
  673. ?>