DbExtra-sqlite.php 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. <?php
  2. /**
  3. * Simple Machines Forum (SMF)
  4. *
  5. * @package SMF
  6. * @author Simple Machines http://www.simplemachines.org
  7. * @copyright 2011 Simple Machines
  8. * @license http://www.simplemachines.org/about/smf/license.php BSD
  9. *
  10. * @version 2.0
  11. */
  12. if (!defined('SMF'))
  13. die('Hacking attempt...');
  14. /* This file contains rarely used extended database functionality.
  15. void db_extra_init()
  16. - add this file's functions to the $smcFunc array.
  17. resource smf_db_backup_table($table, $backup_table)
  18. - backup $table to $backup_table.
  19. - returns the request handle to the table creation query
  20. string function smf_db_get_version()
  21. - get the version number.
  22. string db_insert_sql(string table_name)
  23. - gets all the necessary INSERTs for the table named table_name.
  24. - goes in 250 row segments.
  25. - returns the query to insert the data back in.
  26. - returns an empty string if the table was empty.
  27. array smf_db_list_tables($db = false, $filter = false)
  28. - lists all tables in the database
  29. - could be filtered according to $filter
  30. - returns an array of table names. (strings)
  31. float smf_db_optimize_table($table)
  32. - optimize a table
  33. - $table - the table to be optimized
  34. - returns how much it was gained
  35. string db_table_sql(string table_name)
  36. - dumps the CREATE for the specified table. (by table_name.)
  37. - returns the CREATE statement.
  38. */
  39. // Add the file functions to the $smcFunc array.
  40. function db_extra_init()
  41. {
  42. global $smcFunc;
  43. if (!isset($smcFunc['db_backup_table']) || $smcFunc['db_backup_table'] != 'smf_db_backup_table')
  44. $smcFunc += array(
  45. 'db_backup_table' => 'smf_db_backup_table',
  46. 'db_optimize_table' => 'smf_db_optimize_table',
  47. 'db_insert_sql' => 'smf_db_insert_sql',
  48. 'db_table_sql' => 'smf_db_table_sql',
  49. 'db_list_tables' => 'smf_db_list_tables',
  50. 'db_get_backup' => 'smf_db_get_backup',
  51. 'db_get_version' => 'smf_db_get_version',
  52. );
  53. }
  54. // Backup $table to $backup_table.
  55. function smf_db_backup_table($table, $backup_table)
  56. {
  57. global $smcFunc, $db_prefix;
  58. $table = str_replace('{db_prefix}', $db_prefix, $table);
  59. $result = $smcFunc['db_query']('', '
  60. SELECT sql
  61. FROM sqlite_master
  62. WHERE type = {string:txttable}
  63. AND name = {string:table}',
  64. array(
  65. 'table' => $table,
  66. 'txttable' => 'table'
  67. )
  68. );
  69. list ($create) = $smcFunc['db_fetch_row']($result);
  70. $smcFunc['db_free_result']($result);
  71. $create = preg_split('/[\n\r]/', $create);
  72. $auto_inc = '';
  73. // Remove the first line and check to see if the second one contain useless info.
  74. unset($create[0]);
  75. if (trim($create[1]) == '(')
  76. unset($create[1]);
  77. if (trim($create[count($create)]) == ')')
  78. unset($create[count($create)]);
  79. foreach ($create as $k => $l)
  80. {
  81. // Get the name of the auto_increment column.
  82. if (strpos($l, 'primary') || strpos($l, 'PRIMARY'))
  83. $auto_inc = trim($l);
  84. // Skip everything but keys...
  85. if ((strpos($l, 'KEY') !== false && strpos($l, 'PRIMARY KEY') === false) || strpos($l, $table) !== false || strpos(trim($l), 'PRIMARY KEY') === 0)
  86. unset($create[$k]);
  87. }
  88. if (!empty($create))
  89. $create = '(
  90. ' . implode('
  91. ', $create) . ')';
  92. else
  93. $create = '';
  94. // Is there an extra junk at the end?
  95. if (substr($create, -2, 1) == ',')
  96. $create = substr($create, 0, -2) . ')';
  97. if (substr($create, -2) == '))')
  98. $create = substr($create, 0, -1);
  99. $smcFunc['db_query']('', '
  100. DROP TABLE {raw:backup_table}',
  101. array(
  102. 'backup_table' => $backup_table,
  103. 'db_error_skip' => true,
  104. )
  105. );
  106. $request = $smcFunc['db_quote']('
  107. CREATE TABLE {raw:backup_table} {raw:create}',
  108. array(
  109. 'backup_table' => $backup_table,
  110. 'create' => $create,
  111. ));
  112. $smcFunc['db_query']('', '
  113. CREATE TABLE {raw:backup_table} {raw:create}',
  114. array(
  115. 'backup_table' => $backup_table,
  116. 'create' => $create,
  117. ));
  118. $request = $smcFunc['db_query']('', '
  119. INSERT INTO {raw:backup_table}
  120. SELECT *
  121. FROM {raw:table}',
  122. array(
  123. 'backup_table' => $backup_table,
  124. 'table' => $table,
  125. ));
  126. return $request;
  127. }
  128. // Optimize a table - return data freed!
  129. function smf_db_optimize_table($table)
  130. {
  131. global $smcFunc, $db_prefix;
  132. $table = str_replace('{db_prefix}', $db_prefix, $table);
  133. $request = $smcFunc['db_query']('', '
  134. VACUUM {raw:table}',
  135. array(
  136. 'table' => $table,
  137. )
  138. );
  139. if (!$request)
  140. return -1;
  141. $row = $smcFunc['db_fetch_assoc']($request);
  142. $smcFunc['db_free_result']($request);
  143. // The function returns nothing.
  144. return 0;
  145. }
  146. // List all the tables in the database.
  147. function smf_db_list_tables($db = false, $filter = false)
  148. {
  149. global $smcFunc;
  150. $filter = $filter == false ? '' : ' AND name LIKE \'' . str_replace("\_", "_", $filter) . '\'';
  151. $request = $smcFunc['db_query']('', '
  152. SELECT name
  153. FROM sqlite_master
  154. WHERE type = {string:type}
  155. {raw:filter}
  156. ORDER BY name',
  157. array(
  158. 'type' => 'table',
  159. 'filter' => $filter,
  160. )
  161. );
  162. $tables = array();
  163. while ($row = $smcFunc['db_fetch_row']($request))
  164. $tables[] = $row[0];
  165. $smcFunc['db_free_result']($request);
  166. return $tables;
  167. }
  168. // Get the content (INSERTs) for a table.
  169. function smf_db_insert_sql($tableName)
  170. {
  171. global $smcFunc, $db_prefix;
  172. $tableName = str_replace('{db_prefix}', $db_prefix, $tableName);
  173. // This will be handy...
  174. $crlf = "\r\n";
  175. // Get everything from the table.
  176. $result = $smcFunc['db_query']('', '
  177. SELECT *
  178. FROM {raw:table}',
  179. array(
  180. 'table' => $tableName,
  181. )
  182. );
  183. // The number of rows, just for record keeping and breaking INSERTs up.
  184. $num_rows = $smcFunc['db_num_rows']($result);
  185. if ($num_rows == 0)
  186. return '';
  187. $fields = array_keys($smcFunc['db_fetch_assoc']($result));
  188. // SQLite fetches an array so we need to filter out the numberic index for the columns.
  189. foreach ($fields as $key => $name)
  190. if (is_numeric($name))
  191. unset($fields[$key]);
  192. $smcFunc['db_data_seek']($result, 0);
  193. // Start it off with the basic INSERT INTO.
  194. $data = 'BEGIN TRANSACTION;' . $crlf;
  195. // Loop through each row.
  196. while ($row = $smcFunc['db_fetch_row']($result))
  197. {
  198. // Get the fields in this row...
  199. $field_list = array();
  200. for ($j = 0; $j < $smcFunc['db_num_fields']($result); $j++)
  201. {
  202. // Try to figure out the type of each field. (NULL, number, or 'string'.)
  203. if (!isset($row[$j]))
  204. $field_list[] = 'NULL';
  205. elseif (is_numeric($row[$j]) && (int) $row[$j] == $row[$j])
  206. $field_list[] = $row[$j];
  207. else
  208. $field_list[] = '\'' . $smcFunc['db_escape_string']($row[$j]) . '\'';
  209. }
  210. $data .= 'INSERT INTO ' . $tableName . ' (' . implode(', ', $fields) . ') VALUES (' . implode(', ', $field_list) . ');' . $crlf;
  211. }
  212. $smcFunc['db_free_result']($result);
  213. // Return an empty string if there were no rows.
  214. return $num_rows == 0 ? '' : $data . 'COMMIT;' . $crlf;
  215. }
  216. // Get the schema (CREATE) for a table.
  217. function smf_db_table_sql($tableName)
  218. {
  219. global $smcFunc, $db_prefix;
  220. $tableName = str_replace('{db_prefix}', $db_prefix, $tableName);
  221. // This will be needed...
  222. $crlf = "\r\n";
  223. // Start the create table...
  224. $schema_create = '';
  225. $index_create = '';
  226. // Let's get the create statement directly from SQLite.
  227. $result = $smcFunc['db_query']('', '
  228. SELECT sql
  229. FROM sqlite_master
  230. WHERE type = {string:type}
  231. AND name = {string:table_name}',
  232. array(
  233. 'type' => 'table',
  234. 'table_name' => $tableName,
  235. )
  236. );
  237. list ($schema_create) = $smcFunc['db_fetch_row']($result);
  238. $smcFunc['db_free_result']($result);
  239. // Now the indexes.
  240. $result = $smcFunc['db_query']('', '
  241. SELECT sql
  242. FROM sqlite_master
  243. WHERE type = {string:type}
  244. AND tbl_name = {string:table_name}',
  245. array(
  246. 'type' => 'index',
  247. 'table_name' => $tableName,
  248. )
  249. );
  250. $indexes = array();
  251. while ($row = $smcFunc['db_fetch_assoc']($result))
  252. if (trim($row['sql']) != '')
  253. $indexes[] = $row['sql'];
  254. $smcFunc['db_free_result']($result);
  255. $index_create .= implode(';' . $crlf, $indexes);
  256. $schema_create = empty($indexes) ? rtrim($schema_create) : $schema_create . ';' . $crlf . $crlf;
  257. return $schema_create . $index_create;
  258. }
  259. // Get the version number.
  260. function smf_db_get_version()
  261. {
  262. return sqlite_libversion();
  263. }
  264. // Simple return the database - and die!
  265. function smf_db_get_backup()
  266. {
  267. global $db_name;
  268. $db_file = substr($db_name, -3) === '.db' ? $db_name : $db_name . '.db';
  269. // Add more info if zipped...
  270. $ext = '';
  271. if (isset($_REQUEST['compress']) && function_exists('gzencode'))
  272. $ext = '.gz';
  273. // Do the remaining headers.
  274. header('Content-Disposition: attachment; filename="' . $db_file . $ext . '"');
  275. header('Cache-Control: private');
  276. header('Connection: close');
  277. // Literally dump the contents. Try reading the file first.
  278. if (@readfile($db_file) == null)
  279. echo file_get_contents($db_file);
  280. obExit(false);
  281. }
  282. ?>