PageRenderTime 46ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/dbstruct/SpotStruct_abs.php

https://github.com/elstenaar86/spotweb
PHP | 729 lines | 465 code | 115 blank | 149 comment | 78 complexity | fd885c2bf7e34243d499cfa0955af48b MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, MPL-2.0-no-copyleft-exception, 0BSD, Apache-2.0
  1. <?php
  2. abstract class SpotStruct_abs {
  3. protected $_spotdb;
  4. protected $_dbcon;
  5. public function __construct(SpotDb $spotdb) {
  6. $this->_spotdb = $spotdb;
  7. $this->_dbcon = $spotdb->getDbHandle();
  8. } # __construct
  9. /*
  10. * Optimize / analyze (database specific) a number of hightraffic
  11. * tables.
  12. * This function does not modify any schema or data
  13. */
  14. abstract function analyze();
  15. /*
  16. * Converts a 'spotweb' internal datatype to a
  17. * database specific datatype
  18. */
  19. abstract function swDtToNative($colType);
  20. /*
  21. * Converts a database native datatype to a spotweb native
  22. * datatype
  23. */
  24. abstract function nativeDtToSw($colInfo);
  25. /*
  26. * Adds an index, but first checks if the index doesn't
  27. * exist already.
  28. *
  29. * $idxType can be either 'UNIQUE', '' or 'FULLTEXT'
  30. */
  31. abstract function addIndex($idxname, $idxType, $tablename, $colList);
  32. /* drops an index if it exists */
  33. abstract function dropIndex($idxname, $tablename);
  34. /* adds a column if the column doesn't exist yet */
  35. abstract function addColumn($colName, $tablename, $colType, $colDefault, $notNull, $collation);
  36. /* alters a column - does not check if the column doesn't adhere to the given definition */
  37. abstract function modifyColumn($colName, $tablename, $colType, $colDefault, $notNull, $collation, $what);
  38. /* drops a column (dbms allowing) */
  39. abstract function dropColumn($colName, $tablename);
  40. /* checks if an index exists */
  41. abstract function indexExists($idxname, $tablename);
  42. /* checks if a column exists */
  43. abstract function columnExists($tablename, $colname);
  44. /* checks if a table exists */
  45. abstract function tableExists($tablename);
  46. /* checks if a fts text index exists */
  47. abstract function ftsExists($ftsname, $tablename, $colList);
  48. /* creates a full text index */
  49. abstract function createFts($ftsname, $tablename, $colList);
  50. /* drops a fulltext index */
  51. abstract function dropFts($ftsname, $tablename, $colList);
  52. /* returns FTS info */
  53. abstract function getFtsInfo($ftsname, $tablename, $colList);
  54. /* creates an empty table with onl an ID field. Collation should be either UTF8 or ASCII */
  55. abstract function createTable($tablename, $collation);
  56. /* creates a foreign key constraint */
  57. abstract function addForeignKey($tablename, $colname, $reftable, $refcolumn, $action);
  58. /* drops a foreign key constraint */
  59. abstract function dropForeignKey($tablename, $colname, $reftable, $refcolumn, $action);
  60. /* alters a storage engine (only mysql knows something about store engines, but well :P ) */
  61. abstract function alterStorageEngine($tablename, $engine);
  62. /* drop a table */
  63. abstract function dropTable($tablename);
  64. /* rename a table */
  65. abstract function renameTable($tablename, $newTableName);
  66. /* Returns in a fixed format, index information */
  67. abstract function getIndexInfo($idxname, $tablename);
  68. /* Returns in a fixed format, column information */
  69. abstract function getColumnInfo($tablename, $colname);
  70. /* Checks if a index structure is the same as the requested one. Recreats if not */
  71. function validateIndex($idxname, $type, $tablename, $colList) {
  72. echo "\tValidating index " . $idxname . PHP_EOL;
  73. if (!$this->compareIndex($idxname, $type, $tablename, $colList)) {
  74. # Drop the index
  75. if ($this->indexExists($idxname, $tablename)) {
  76. echo "\t\tDropping index " . $idxname . PHP_EOL;
  77. $this->dropIndex($idxname, $tablename);
  78. } # if
  79. echo "\t\tAdding index " . $idxname . PHP_EOL;
  80. # and recreate the index
  81. $this->addIndex($idxname, $type, $tablename, $colList);
  82. } # if
  83. } # validateIndex
  84. /* Checks if a fulltext structure matches the required one. Recreates if not */
  85. function validateFts($ftsname, $tablename, $colList) {
  86. echo "\tValidating FTS " . $ftsname . PHP_EOL;
  87. if (!$this->compareFts($ftsname, $tablename, $colList)) {
  88. # Drop de FTS
  89. if ($this->ftsExists($ftsname, $tablename, $colList)) {
  90. echo "\t\tDropping FTS " . $ftsname . PHP_EOL;
  91. $this->dropFts($ftsname, $tablename, $colList);
  92. } # if
  93. echo "\t\tAdding FTS " . $ftsname . PHP_EOL;
  94. # and recreate the index
  95. $this->createFts($ftsname, $tablename, $colList);
  96. } # if
  97. } # validateFts
  98. /* Checks if a column definition is the same as the requested one. Recreats if not */
  99. function validateColumn($colName, $tablename, $colType, $colDefault, $notNull, $collation) {
  100. echo "\tValidating " . $tablename . "(" . $colName . ")" . PHP_EOL;
  101. $compResult = $this->compareColumn($colName, $tablename, $colType, $colDefault, $notNull, $collation);
  102. if ($compResult !== true) {
  103. if ($this->columnExists($tablename, $colName)) {
  104. echo "\t\tModifying column " . $colName . " (" . $compResult . ") on " . $tablename . PHP_EOL;
  105. $this->modifyColumn($colName, $tablename, $colType, $colDefault, $notNull, $collation, $compResult);
  106. } else {
  107. echo "\t\tAdding column " . $colName . "(" . $colType . ") to " . $tablename . PHP_EOL;
  108. $this->addColumn($colName, $tablename, $colType, $colDefault, $notNull, $collation);
  109. } # else
  110. } # if
  111. } # validateColumn
  112. /* Compares a columns' definition */
  113. function compareColumn($colName, $tablename, $colType, $colDefault, $notNull, $collation) {
  114. # Retrieve the column information
  115. $q = $this->getColumnInfo($tablename, $colName);
  116. # if column is not found at all, it's easy
  117. if (empty($q)) {
  118. return false;
  119. } # if
  120. # Check data type
  121. if (strtolower($q['COLUMN_TYPE']) != strtolower($this->swDtToNative($colType))) {
  122. #var_dump($q);
  123. #var_dump($colType);
  124. #var_dump($this->swDtToNative($colType));
  125. #die();
  126. return 'type';
  127. } # if
  128. # check default value
  129. if (strtolower($q['COLUMN_DEFAULT']) != strtolower($colDefault)) {
  130. return 'default';
  131. } # if
  132. # check the NOT NULL setting
  133. if (strtolower($q['NOTNULL']) != $notNull) {
  134. return 'not null';
  135. } # if
  136. # Chcek character set setting
  137. if ((strtolower($q['COLLATION_NAME']) != $collation) && ($q['COLLATION_NAME'] != null)) {
  138. # var_dump($q);
  139. # var_dump($collation);
  140. # die();
  141. return 'charset';
  142. } # if
  143. return true;
  144. } # compareColumn
  145. /* Compares an index with the requested structure */
  146. function compareIndex($idxname, $type, $tablename, $colList) {
  147. # Retrieve index information
  148. $q = $this->getIndexInfo($idxname, $tablename);
  149. # If the amount of columns in the index don't match...
  150. if (count($q) != count($colList)) {
  151. return false;
  152. } # if
  153. /*
  154. * We iterate throuhg each column and compare the index order,
  155. * and properties of each index.
  156. */
  157. for($i = 0; $i < count($colList); $i++) {
  158. $same = true;
  159. if ($colList[$i] != $q[$i]['column_name']) {
  160. $same = false;
  161. } # if
  162. if ($same) {
  163. switch(strtolower($type)) {
  164. case 'fulltext' : $same = (strtolower($q[$i]['index_type']) == 'fulltext'); break;
  165. case 'unique' : $same = ($q[$i]['non_unique'] == 0); break;
  166. case '' : $same = (strtolower($q[$i]['index_type']) != 'fulltext') && ($q[$i]['non_unique'] == 1);
  167. } # switch
  168. } # if
  169. if (!$same) {
  170. #var_dump($q[$i]);
  171. #var_dump($type);
  172. #var_dump($colList);
  173. #die();
  174. return false;
  175. } # if
  176. } # for
  177. return true;
  178. } # compareIndex
  179. /* Compares an FTS index with the desired definition */
  180. function compareFts($ftsname, $tablename, $colList) {
  181. # Retrieves FTS information
  182. $q = $this->getFtsInfo($ftsname, $tablename, $colList);
  183. # If the amount of columns in the index don't match...
  184. if (count($q) != count($colList)) {
  185. return false;
  186. } # if
  187. /*
  188. * We iterate throuhg each column and compare the index order,
  189. * and properties of each index.
  190. */
  191. for($i = 0; $i < count($colList); $i++) {
  192. if ($colList[$i + 1] != $q[$i]['column_name']) {
  193. return false;
  194. } # if
  195. } # for
  196. return true;
  197. } # compareFts
  198. function updateSchema() {
  199. # Drop any older (not used anymore) FTS indexes on the spots full table
  200. $this->dropIndex("idx_spotsfull_fts_1", "spotsfull");
  201. $this->dropIndex("idx_spotsfull_fts_2", "spotsfull");
  202. $this->dropIndex("idx_spotsfull_fts_3", "spotsfull");
  203. $this->dropIndex("idx_spotsfull_2", "spotsfull"); # Index on userid
  204. $this->dropIndex("idx_nntp_2", "nntp");
  205. $this->dropIndex("idx_nntp_3", "nntp");
  206. $this->dropIndex("idx_spotteridblacklist_3", "spotteridblacklist");
  207. # Drop any non-valid FK relations
  208. $this->dropForeignKey('spotsfull', 'messageid', 'spots', 'messageid', 'ON DELETE CASCADE ON UPDATE CASCADE');
  209. $this->dropForeignKey('spotstatelist', 'messageid', 'spots', 'messageid', 'ON DELETE CASCADE ON UPDATE CASCADE');
  210. $this->dropForeignKey('commentsposted', 'inreplyto', 'spots', 'messageid', 'ON DELETE CASCADE ON UPDATE CASCADE');
  211. $this->dropForeignKey('commentsposted', 'messageid', 'spots', 'messageid', 'ON DELETE CASCADE ON UPDATE CASCADE');
  212. $this->dropForeignKey('commentsxover', 'messageid', 'spots', 'messageid', 'ON DELETE CASCADE ON UPDATE CASCADE');
  213. $this->dropForeignKey('commentsfull', 'messageid', 'spots', 'messageid', 'ON DELETE CASCADE ON UPDATE CASCADE');
  214. $this->dropForeignKey('reportsposted', 'inreplyto', 'spots', 'messageid', 'ON DELETE CASCADE ON UPDATE CASCADE');
  215. $this->dropForeignKey('reportsposted', 'messageid', 'spots', 'messageid', 'ON DELETE CASCADE ON UPDATE CASCADE');
  216. $this->dropForeignKey('sessions', 'userid', 'users', 'id', 'ON DELETE CASCADE ON UPDATE CASCADE');
  217. ##############################################################################################
  218. # Cleaning up data ###########################################################################
  219. ##############################################################################################
  220. if (($this instanceof SpotStruct_mysql) && (false)) {
  221. echo "Cleaning up old data..." . PHP_EOL;
  222. if ($this->tableExists('usersettings') && $this->tableExists('users')) {
  223. $this->_dbcon->rawExec("DELETE usersettings FROM usersettings LEFT JOIN users ON usersettings.userid=users.id WHERE users.id IS NULL");
  224. } # if
  225. if ($this->tableExists('sessions') && $this->tableExists('users')) {
  226. $this->_dbcon->rawExec("DELETE sessions FROM sessions LEFT JOIN users ON sessions.userid=users.id WHERE users.id IS NULL");
  227. } # if
  228. if ($this->tableExists('spotstatelist') && $this->tableExists('users')) {
  229. $this->_dbcon->rawExec("DELETE spotstatelist FROM spotstatelist LEFT JOIN users ON spotstatelist.ouruserid=users.id WHERE users.id IS NULL");
  230. } # if
  231. if ($this->tableExists('usergroups') && $this->tableExists('users')) {
  232. $this->_dbcon->rawExec("DELETE usergroups FROM usergroups LEFT JOIN users ON usergroups.userid=users.id WHERE users.id IS NULL");
  233. } # if
  234. if ($this->tableExists('usergroups') && $this->tableExists('securitygroups')) {
  235. $this->_dbcon->rawExec("DELETE usergroups FROM usergroups LEFT JOIN securitygroups ON usergroups.groupid=securitygroups.id WHERE securitygroups.id IS NULL");
  236. } # if
  237. if ($this->tableExists('grouppermissions') && $this->tableExists('securitygroups')) {
  238. $this->_dbcon->rawExec("DELETE grouppermissions FROM grouppermissions LEFT JOIN securitygroups ON grouppermissions.groupid=securitygroups.id WHERE securitygroups.id IS NULL");
  239. } # if
  240. if ($this->tableExists('commentsposted') && $this->tableExists('users')) {
  241. $this->_dbcon->rawExec("DELETE commentsposted FROM commentsposted LEFT JOIN users ON commentsposted.ouruserid=users.id WHERE users.id IS NULL");
  242. } # if
  243. if ($this->tableExists('commentsposted') && $this->tableExists('spots')) {
  244. $this->_dbcon->rawExec("DELETE commentsposted FROM commentsposted LEFT JOIN spots ON commentsposted.inreplyto=spots.messageid WHERE spots.messageid IS NULL");
  245. } # if
  246. if ($this->tableExists('commentsfull') && $this->tableExists('commentsxover')) {
  247. $this->_dbcon->rawExec("DELETE commentsfull FROM commentsfull LEFT JOIN commentsxover ON commentsfull.messageid=commentsxover.messageid WHERE commentsxover.messageid IS NULL");
  248. } # if
  249. if ($this->tableExists('spotsfull') && $this->tableExists('spots')) {
  250. $this->_dbcon->rawExec("DELETE spotsfull FROM spotsfull LEFT JOIN spots ON spotsfull.messageid=spots.messageid WHERE spots.messageid IS NULL");
  251. } # if
  252. if ($this->tableExists('spotstatelist') && $this->tableExists('spots')) {
  253. $this->_dbcon->rawExec("DELETE spotstatelist FROM spotstatelist LEFT JOIN spots ON spotstatelist.messageid=spots.messageid WHERE spots.messageid IS NULL");
  254. } # if
  255. if ($this->tableExists('reportsposted') && $this->tableExists('users')) {
  256. $this->_dbcon->rawExec("DELETE reportsposted FROM reportsposted LEFT JOIN users ON reportsposted.ouruserid=users.id WHERE users.id IS NULL");
  257. } # if
  258. if ($this->tableExists('reportsposted') && $this->tableExists('spots')) {
  259. $this->_dbcon->rawExec("DELETE reportsposted FROM reportsposted LEFT JOIN spots ON reportsposted.inreplyto=spots.messageid WHERE spots.messageid IS NULL");
  260. } # if
  261. } # if
  262. # ---- spots table ---- #
  263. $this->createTable('spots', "utf8");
  264. $this->validateColumn('messageid', 'spots', 'VARCHAR(128)', "''", true, 'ascii');
  265. $this->validateColumn('poster', 'spots', 'VARCHAR(128)', NULL, false, 'utf8');
  266. $this->validateColumn('title', 'spots', 'VARCHAR(128)', NULL, false, 'utf8');
  267. $this->validateColumn('tag', 'spots', 'VARCHAR(128)', NULL, false, 'utf8');
  268. $this->validateColumn('category', 'spots', 'INTEGER', NULL, false, '');
  269. $this->validateColumn('subcata', 'spots', 'VARCHAR(64)', NULL, false, 'ascii');
  270. $this->validateColumn('subcatb', 'spots', 'VARCHAR(64)', NULL, false, 'ascii');
  271. $this->validateColumn('subcatc', 'spots', 'VARCHAR(64)', NULL, false, 'ascii');
  272. $this->validateColumn('subcatd', 'spots', 'VARCHAR(64)', NULL, false, 'ascii');
  273. $this->validateColumn('subcatz', 'spots', 'VARCHAR(64)', NULL, false, 'ascii');
  274. $this->validateColumn('stamp', 'spots', 'UNSIGNED INTEGER', NULL, false, '');
  275. $this->validateColumn('reversestamp', 'spots', 'INTEGER', "0", false, '');
  276. $this->validateColumn('filesize', 'spots', 'UNSIGNED BIGINTEGER', "0", true, '');
  277. $this->validateColumn('moderated', 'spots', 'BOOLEAN', NULL, false, '');
  278. $this->validateColumn('commentcount', 'spots', 'INTEGER', "0", false, '');
  279. $this->validateColumn('spotrating', 'spots', 'INTEGER', "0", false, '');
  280. $this->validateColumn('reportcount', 'spots', 'INTEGER', "0", false, '');
  281. $this->validateColumn('spotterid', 'spots', 'VARCHAR(32)', NULL, false, 'ascii_bin');
  282. $this->alterStorageEngine("spots", "MyISAM");
  283. # ---- spotsfull table ---- #
  284. $this->createTable('spotsfull', "utf8");
  285. $this->validateColumn('messageid', 'spotsfull', 'VARCHAR(128)', "''", true, 'ascii');
  286. $this->validateColumn('verified', 'spotsfull', 'BOOLEAN', NULL, false, '');
  287. $this->validateColumn('usersignature', 'spotsfull', 'VARCHAR(255)', NULL, false, 'ascii');
  288. $this->validateColumn('userkey', 'spotsfull', 'VARCHAR(512)', NULL, false, 'ascii');
  289. $this->validateColumn('xmlsignature', 'spotsfull', 'VARCHAR(255)', NULL, false, 'ascii');
  290. $this->validateColumn('fullxml', 'spotsfull', 'TEXT', NULL, false, 'utf8');
  291. $this->alterStorageEngine("spotsfull", "InnoDB");
  292. # ---- nntp table ---- #
  293. $this->createTable('nntp', "utf8");
  294. $this->validateColumn('server', 'nntp', 'VARCHAR(128)', "''", true, 'ascii');
  295. $this->validateColumn('maxarticleid', 'nntp', 'INTEGER', NULL, false, '');
  296. $this->validateColumn('nowrunning', 'nntp', 'INTEGER', "0", false, '');
  297. $this->validateColumn('lastrun', 'nntp', 'INTEGER', "0", false, '');
  298. $this->validateColumn('serverdatelastrun', 'nntp', 'VARCHAR(14)', "00000000000000", false, 'ascii');
  299. $this->alterStorageEngine("nntp", "InnoDB");
  300. # ---- commentsxover table ---- #
  301. $this->createTable('commentsxover', "ascii");
  302. $this->validateColumn('messageid', 'commentsxover', 'VARCHAR(128)', "''", true, 'ascii');
  303. $this->validateColumn('nntpref', 'commentsxover', 'VARCHAR(128)', "''", true, 'ascii');
  304. $this->validateColumn('spotrating', 'commentsxover', 'INTEGER', "0", false, '');
  305. $this->validateColumn('moderated', 'commentsxover', 'BOOLEAN', NULL, false, '');
  306. $this->validateColumn('stamp', 'commentsxover', 'UNSIGNED INTEGER', NULL, false, '');
  307. $this->alterStorageEngine("commentsxover", "InnoDB");
  308. # ---- reportsxover table ---- #
  309. $this->createTable('reportsxover', "ascii");
  310. $this->validateColumn('messageid', 'reportsxover', 'VARCHAR(128)', "''", true, 'ascii');
  311. $this->validateColumn('fromhdr', 'reportsxover', 'VARCHAR(128)', "''", true, 'utf8');
  312. $this->validateColumn('keyword', 'reportsxover', 'VARCHAR(128)', "''", true, 'ascii');
  313. $this->validateColumn('nntpref', 'reportsxover', 'VARCHAR(128)', "''", true, 'ascii');
  314. $this->alterStorageEngine("reportsxover", "InnoDB");
  315. # ---- spotstatelist table ---- #
  316. $this->createTable('spotstatelist', "ascii");
  317. $this->validateColumn('messageid', 'spotstatelist', 'VARCHAR(128)', "''", true, 'ascii');
  318. $this->validateColumn('ouruserid', 'spotstatelist', 'INTEGER', "0", false, '');
  319. $this->validateColumn('download', 'spotstatelist', 'INTEGER', NULL, false, '');
  320. $this->validateColumn('watch', 'spotstatelist', 'INTEGER', NULL, false, '');
  321. $this->validateColumn('seen', 'spotstatelist', 'INTEGER', NULL, false, '');
  322. $this->alterStorageEngine("spotstatelist", "InnoDB");
  323. # ---- commentsfull table ---- #
  324. $this->createTable('commentsfull', "ascii");
  325. $this->validateColumn('messageid', 'commentsfull', 'VARCHAR(128)', "''", true, 'ascii');
  326. $this->validateColumn('fromhdr', 'commentsfull', 'VARCHAR(128)', NULL, false, 'utf8');
  327. $this->validateColumn('stamp', 'commentsfull', 'INTEGER', NULL, false, '');
  328. $this->validateColumn('usersignature', 'commentsfull', 'VARCHAR(255)', NULL, false, 'ascii');
  329. $this->validateColumn('userkey', 'commentsfull', 'VARCHAR(512)', NULL, false, 'ascii');
  330. $this->validateColumn('spotterid', 'commentsfull', 'VARCHAR(32)', NULL, false, 'ascii_bin');
  331. $this->validateColumn('hashcash', 'commentsfull', 'VARCHAR(255)', NULL, false, 'ascii');
  332. $this->validateColumn('body', 'commentsfull', 'TEXT', NULL, false, 'utf8');
  333. $this->validateColumn('verified', 'commentsfull', 'BOOLEAN', NULL, false, '');
  334. $this->validateColumn('avatar', 'commentsfull', 'TEXT', NULL, false, 'ascii');
  335. $this->alterStorageEngine("commentsfull", "InnoDB");
  336. # ---- settings table ---- #
  337. $this->createTable('settings', "ascii");
  338. $this->validateColumn('name', 'settings', 'VARCHAR(128)', "''", true, 'ascii');
  339. $this->validateColumn('value', 'settings', 'TEXT', NULL, false, 'utf8');
  340. $this->validateColumn('serialized', 'settings', 'boolean', NULL, false, '');
  341. $this->alterStorageEngine("settings", "InnoDB");
  342. # ---- commentsposted table ---- #
  343. $this->createTable('commentsposted', "ascii");
  344. $this->validateColumn('ouruserid', 'commentsposted', 'INTEGER', "0", true, '');
  345. $this->validateColumn('messageid', 'commentsposted', 'VARCHAR(128)', "''", true, 'ascii');
  346. $this->validateColumn('inreplyto', 'commentsposted', 'VARCHAR(128)', "''", true, 'ascii');
  347. $this->validateColumn('randompart', 'commentsposted', 'VARCHAR(32)', "''", true, 'ascii');
  348. $this->validateColumn('rating', 'commentsposted', 'INTEGER', 0, true, '');
  349. $this->validateColumn('body', 'commentsposted', 'TEXT', NULL, false, 'utf8');
  350. $this->validateColumn('stamp', 'commentsposted', 'INTEGER', "0", true, '');
  351. $this->alterStorageEngine("commentsposted", "InnoDB");
  352. # ---- spotsposted table ---- #
  353. $this->createTable('spotsposted', "utf8");
  354. $this->validateColumn('messageid', 'spotsposted', 'VARCHAR(128)', "''", true, 'ascii');
  355. $this->validateColumn('ouruserid', 'spotsposted', 'INTEGER', "0", true, '');
  356. $this->validateColumn('stamp', 'spotsposted', 'UNSIGNED INTEGER', NULL, false, '');
  357. $this->validateColumn('title', 'spotsposted', 'VARCHAR(128)', NULL, false, 'utf8');
  358. $this->validateColumn('tag', 'spotsposted', 'VARCHAR(128)', NULL, false, 'utf8');
  359. $this->validateColumn('category', 'spotsposted', 'INTEGER', NULL, false, '');
  360. $this->validateColumn('subcats', 'spotsposted', 'VARCHAR(255)', NULL, false, 'ascii');
  361. $this->validateColumn('filesize', 'spotsposted', 'UNSIGNED BIGINTEGER', "0", true, '');
  362. $this->validateColumn('fullxml', 'spotsposted', 'TEXT', NULL, false, 'utf8');
  363. $this->alterStorageEngine("spotsposted", "InnoDB");
  364. # ---- reportsposted table ---- #
  365. $this->createTable('reportsposted', "ascii");
  366. $this->validateColumn('ouruserid', 'reportsposted', 'INTEGER', "0", true, '');
  367. $this->validateColumn('messageid', 'reportsposted', 'VARCHAR(128)', "''", true, 'ascii');
  368. $this->validateColumn('inreplyto', 'reportsposted', 'VARCHAR(128)', "''", true, 'ascii');
  369. $this->validateColumn('randompart', 'reportsposted', 'VARCHAR(32)', "''", true, 'ascii');
  370. $this->validateColumn('body', 'reportsposted', 'TEXT', NULL, false, 'utf8');
  371. $this->validateColumn('stamp', 'reportsposted', 'INTEGER', "0", true, '');
  372. $this->alterStorageEngine("reportsposted", "InnoDB");
  373. # ---- usersettings table ---- #
  374. $this->createTable('usersettings', "utf8");
  375. $this->validateColumn('userid', 'usersettings', 'INTEGER', '0', true, '');
  376. $this->validateColumn('privatekey', 'usersettings', "TEXT", NULL, false, 'ascii');
  377. $this->validateColumn('publickey', 'usersettings', "TEXT", NULL, false, 'ascii');
  378. $this->validateColumn('avatar', 'usersettings', "TEXT", NULL, false, 'ascii');
  379. $this->validateColumn('otherprefs', 'usersettings', "TEXT", NULL, false, 'utf8');
  380. $this->alterStorageEngine("usersettings", "InnoDB");
  381. # ---- users table ---- #
  382. $this->createTable('users', "utf8");
  383. $this->validateColumn('username', 'users', "VARCHAR(128)", "''", true, 'utf8');
  384. $this->validateColumn('firstname', 'users', "VARCHAR(128)", "''", true, 'utf8');
  385. $this->validateColumn('passhash', 'users', "VARCHAR(40)", "''", true, 'ascii');
  386. $this->validateColumn('lastname', 'users', "VARCHAR(128)", "''", true, 'utf8');
  387. $this->validateColumn('mail', 'users', "VARCHAR(128)", "''", true, 'utf8');
  388. $this->validateColumn('apikey', 'users', "VARCHAR(32)", "''", true, 'ascii');
  389. $this->validateColumn('lastlogin', 'users', "INTEGER", "0", true, '');
  390. $this->validateColumn('lastvisit', 'users', "INTEGER", "0", true, '');
  391. $this->validateColumn('lastread', 'users', "INTEGER", "0", true, '');
  392. $this->validateColumn('lastapiusage', 'users', "INTEGER", "0", true, '');
  393. $this->validateColumn('deleted', 'users', "BOOLEAN", $this->_dbcon->bool2dt(false), true, '');
  394. $this->alterStorageEngine("users", "InnoDB");
  395. # ---- sessions ---- #
  396. $this->createTable('sessions', "ascii");
  397. $this->validateColumn('sessionid', 'sessions', 'VARCHAR(128)', NULL, false, 'ascii');
  398. $this->validateColumn('userid', 'sessions', 'INTEGER', NULL, false, '');
  399. $this->validateColumn('hitcount', 'sessions', 'INTEGER', NULL, false, '');
  400. $this->validateColumn('lasthit', 'sessions', 'INTEGER', NULL, false, '');
  401. $this->validateColumn('ipaddr', 'sessions', "VARCHAR(45)", "''", true, 'ascii');
  402. $this->validateColumn('devicetype', 'sessions', "VARCHAR(8)", "''", true, 'ascii');
  403. $this->alterStorageEngine("sessions", "MyISAM");
  404. # ---- securitygroups ----
  405. $this->createTable('securitygroups', "ascii");
  406. $this->validateColumn('name', 'securitygroups', 'VARCHAR(128)', NULL, false, 'ascii');
  407. $this->alterStorageEngine("securitygroups", "InnoDB");
  408. # ---- grouppermissions ----
  409. $this->createTable('grouppermissions', "ascii");
  410. $this->validateColumn('groupid', 'grouppermissions', 'INTEGER', "0", true, '');
  411. $this->validateColumn('permissionid', 'grouppermissions', 'INTEGER', "0", true, '');
  412. $this->validateColumn('objectid', 'grouppermissions', "VARCHAR(128)", "''", true, 'ascii');
  413. $this->validateColumn('deny', 'grouppermissions', "BOOLEAN", $this->_dbcon->bool2dt(false), true, '');
  414. $this->alterStorageEngine("grouppermissions", "InnoDB");
  415. # ---- usergroups ----
  416. $this->createTable('usergroups', "ascii");
  417. $this->validateColumn('userid', 'usergroups', 'INTEGER', "0", true, '');
  418. $this->validateColumn('groupid', 'usergroups', 'INTEGER', "0", true, '');
  419. $this->validateColumn('prio', 'usergroups', 'INTEGER', '1', true, '');
  420. $this->alterStorageEngine("usergroups", "InnoDB");
  421. # ---- notifications ----
  422. $this->createTable('notifications', "ascii");
  423. $this->validateColumn('userid', 'notifications', 'INTEGER', "0", true, '');
  424. $this->validateColumn('stamp', 'notifications', 'INTEGER', "0", true, '');
  425. $this->validateColumn('objectid', 'notifications', 'VARCHAR(128)', "''", true, 'ascii');
  426. $this->validateColumn('type', 'notifications', 'VARCHAR(128)', "''", true, 'ascii');
  427. $this->validateColumn('title', 'notifications', 'VARCHAR(128)', "''", true, 'utf8');
  428. $this->validateColumn('body', 'notifications', 'TEXT', NULL, false, 'utf8');
  429. $this->validateColumn('sent', 'notifications', 'BOOLEAN', $this->_dbcon->bool2dt(false), true, '');
  430. $this->alterStorageEngine("notifications", "InnoDB");
  431. # ---- filters ----
  432. $this->createTable('filters', "utf8");
  433. $this->validateColumn('userid', 'filters', 'INTEGER', "0", true, '');
  434. $this->validateColumn('filtertype', 'filters', 'VARCHAR(128)', "''", true, 'ascii');
  435. $this->validateColumn('title', 'filters', 'VARCHAR(128)', "''", true, 'utf8');
  436. $this->validateColumn('icon', 'filters', 'VARCHAR(128)', "''", true, 'utf8');
  437. $this->validateColumn('torder', 'filters', 'INTEGER', "0", true, '');
  438. $this->validateColumn('tparent', 'filters', 'INTEGER', "0", true, '');
  439. $this->validateColumn('tree', 'filters', 'TEXT', NULL, false, 'ascii');
  440. $this->validateColumn('valuelist', 'filters', 'TEXT', NULL, false, 'utf8');
  441. $this->validateColumn('sorton', 'filters', 'VARCHAR(128)', NULL, false, 'ascii');
  442. $this->validateColumn('sortorder', 'filters', 'VARCHAR(128)', NULL, false, 'ascii');
  443. $this->validateColumn('enablenotify', 'filters', 'BOOLEAN', $this->_dbcon->bool2dt(false), true, '');
  444. $this->alterStorageEngine("filters", "InnoDB");
  445. # ---- filtercounts ----
  446. $this->createTable('filtercounts', "utf8");
  447. $this->validateColumn('userid', 'filtercounts', 'INTEGER', "0", true, '');
  448. $this->validateColumn('filterhash', 'filtercounts', 'VARCHAR(40)', "''", true, 'ascii');
  449. $this->validateColumn('currentspotcount', 'filtercounts', 'INTEGER', "0", true, '');
  450. $this->validateColumn('lastvisitspotcount', 'filtercounts', 'INTEGER', "0", true, '');
  451. $this->validateColumn('lastupdate', 'filtercounts', 'INTEGER', "0", true, '');
  452. $this->alterStorageEngine("filtercounts", "InnoDB");
  453. # ---- spotteridblacklist table ---- #
  454. $this->createTable('spotteridblacklist', "utf8");
  455. $this->validateColumn('spotterid', 'spotteridblacklist', 'VARCHAR(32)', NULL, false, 'ascii_bin');
  456. $this->validateColumn('ouruserid', 'spotteridblacklist', 'INTEGER', "0", true, '');
  457. $this->validateColumn('idtype', 'spotteridblacklist', 'INTEGER', "0", true, '');
  458. $this->validateColumn('origin', 'spotteridblacklist', 'VARCHAR(255)', NULL, false, 'ascii');
  459. $this->validateColumn('doubled', 'spotteridblacklist', 'BOOLEAN', $this->_dbcon->bool2dt(false), true, '');
  460. $this->alterStorageEngine("spotteridblacklist", "InnoDB");
  461. # Update old blacklisttable
  462. if ($this->_spotdb->getSchemaVer() < 0.56) {
  463. $this->_dbcon->rawExec("UPDATE spotteridblacklist SET idtype = 1");
  464. }
  465. # Drop old cache -- converting is too error prone
  466. if (($this->_spotdb->getSchemaVer() < 0.50) && ($this->tableExists('cache'))) {
  467. $this->dropTable('cache');
  468. } # if
  469. if (($this->_spotdb->getSchemaVer() < 0.51) && ($this->tableExists('cache')) && (!$this->tableExists('cachetmp')) && ($this instanceof SpotStruct_mysql)) {
  470. $this->renameTable('cache', 'cachetmp');
  471. } # if
  472. # ---- cache table ---- #
  473. $this->createTable('cache', "ascii");
  474. $this->validateColumn('resourceid', 'cache', 'VARCHAR(128)', "''", true, 'ascii');
  475. $this->validateColumn('cachetype', 'cache', 'INTEGER', "0", true, '');
  476. $this->validateColumn('stamp', 'cache', 'INTEGER', "0", true, '');
  477. $this->validateColumn('metadata', 'cache', 'TEXT', NULL, false, 'ascii');
  478. $this->validateColumn('serialized', 'cache', 'BOOLEAN', NULL, false, '');
  479. $this->validateColumn('content', 'cache', 'MEDIUMBLOB', NULL, false, '');
  480. $this->alterStorageEngine("cache", "InnoDB");
  481. # ---- permaudit table ---- #
  482. $this->createTable('permaudit', "ascii");
  483. $this->validateColumn('stamp', 'permaudit', 'INTEGER', "0", true, '');
  484. $this->validateColumn('userid', 'permaudit', 'INTEGER', "0", true, '');
  485. $this->validateColumn('permissionid', 'permaudit', 'INTEGER', "0", true, '');
  486. $this->validateColumn('objectid', 'permaudit', "VARCHAR(128)", "''", true, 'ascii');
  487. $this->validateColumn('result', 'permaudit', "BOOLEAN", $this->_dbcon->bool2dt(true), true, '');
  488. $this->validateColumn('ipaddr', 'permaudit', "VARCHAR(45)", "''", true, 'ascii');
  489. $this->alterStorageEngine("permaudit", "InnoDB");
  490. ##############################################################################################
  491. ### Remove old sessions ######################################################################
  492. ##############################################################################################
  493. # Remove sessions with only one hit, older than one day
  494. #
  495. $this->_dbcon->rawExec("DELETE FROM sessions WHERE lasthit < " . (time() - (60*60*60 * 24)) . " AND hitcount = 1");
  496. #
  497. # and remove sessions older than 180 days
  498. #
  499. $this->_dbcon->rawExec("DELETE FROM sessions WHERE lasthit < " . (time() - (60*60*60 * 24) * 180));
  500. ##############################################################################################
  501. ### deprecation of old Spotweb versions ######################################################
  502. ##############################################################################################
  503. if ($this->_spotdb->getSchemaVer() > 0.00 && ($this->_spotdb->getSchemaVer() < 0.51)) {
  504. if ($this->_spotdb->getSchemaVer() < 0.30) {
  505. throw new SpotwebCannotBeUpgradedTooOldException("da6ba29071c49ae88823cccfefc39375b37e9bee");
  506. } # if
  507. if (($this->_spotdb->getSchemaVer() < 0.34) && ($this->tableExists('spottexts'))) {
  508. throw new SpotwebCannotBeUpgradedTooOldException("48bc94a63f94959f9fe6b2372b312e35a4d09997");
  509. } # if
  510. if ($this->_spotdb->getSchemaVer() < 0.48) {
  511. throw new SpotwebCannotBeUpgradedTooOldException("4c874ec24a28d5ee81218271dc584a858f6916af");
  512. } # if
  513. if (($this->_spotdb->getSchemaVer() < 0.51) && ($this->tableExists('cachetmp'))) {
  514. throw new SpotwebCannotBeUpgradedTooOldException("4c874ec24a28d5ee81218271dc584a858f6916af");
  515. } # if
  516. } # if
  517. # Create several indexes
  518. # ---- Indexes on spots -----
  519. $this->validateIndex("idx_spots_1", "UNIQUE", "spots", array("messageid"));
  520. $this->validateIndex("idx_spots_2", "", "spots", array("stamp"));
  521. $this->validateIndex("idx_spots_3", "", "spots", array("reversestamp"));
  522. $this->validateIndex("idx_spots_4", "", "spots", array("category", "subcata", "subcatb", "subcatc", "subcatd", "subcatz"));
  523. $this->validateIndex("idx_spots_5", "", "spots", array("spotterid"));
  524. $this->validateFts("idx_fts_spots", "spots",
  525. array(1 => "poster",
  526. 2 => 'title',
  527. 3 => 'tag'));
  528. # ---- Indexes on nntp ----
  529. $this->validateIndex("idx_nntp_1", "UNIQUE", "nntp", array("server"));
  530. # ---- Indexes on spotsfull ----
  531. $this->validateIndex("idx_spotsfull_1", "UNIQUE", "spotsfull", array("messageid"));
  532. # ---- Indexes on commentsfull ----
  533. $this->validateIndex("idx_commentsfull_1", "UNIQUE", "commentsfull", array("messageid"));
  534. # ---- Indexes on commentsxover ----
  535. $this->validateIndex("idx_commentsxover_1", "UNIQUE", "commentsxover", array("messageid"));
  536. $this->validateIndex("idx_commentsxover_2", "", "commentsxover", array("nntpref"));
  537. # ---- Indexes on reportsxover ----
  538. $this->validateIndex("idx_reportsxover_1", "UNIQUE", "reportsxover", array("messageid"));
  539. $this->validateIndex("idx_reportsxover_2", "", "reportsxover", array("nntpref"));
  540. # ---- Indexes on reportsposted ----
  541. $this->validateIndex("idx_reportsposted_1", "UNIQUE", "reportsposted", array("messageid"));
  542. $this->validateIndex("idx_reportsposted_2", "UNIQUE", "reportsposted", array("inreplyto", "ouruserid"));
  543. $this->validateIndex("idx_reportspostedrel_1", "", "reportsposted", array("ouruserid"));
  544. # ---- Indexes on commentsposted ----
  545. $this->validateIndex("idx_commentsposted_1", "UNIQUE", "commentsposted", array("messageid"));
  546. $this->validateIndex("idx_commentspostedrel_1", "", "commentsposted", array("ouruserid"));
  547. # ---- Indexes on spotsposted ----
  548. $this->validateIndex("idx_spotsposted_1", "UNIQUE", "spotsposted", array("messageid"));
  549. $this->validateIndex("idx_spotspostedrel_1", "", "spotsposted", array("ouruserid"));
  550. # ---- Indexes on settings ----
  551. $this->validateIndex("idx_settings_1", "UNIQUE", "settings", array("name"));
  552. # ---- Indexes on usersettings ----
  553. $this->validateIndex("idx_usersettings_1", "UNIQUE", "usersettings", array("userid"));
  554. # ---- Indexes on users ----
  555. $this->validateIndex("idx_users_1", "UNIQUE", "users", array("username"));
  556. $this->validateIndex("idx_users_2", "UNIQUE", "users", array("mail"));
  557. $this->validateIndex("idx_users_3", "", "users", array("deleted"));
  558. $this->validateIndex("idx_users_4", "UNIQUE", "users", array("apikey"));
  559. # ---- Indexes on sessions
  560. $this->validateIndex("idx_sessions_1", "UNIQUE", "sessions", array("sessionid"));
  561. $this->validateIndex("idx_sessions_2", "", "sessions", array("lasthit"));
  562. $this->validateIndex("idx_sessions_3", "", "sessions", array("sessionid", "userid"));
  563. $this->validateIndex("idx_sessionsrel_1", "", "sessions", array("userid"));
  564. # ---- Indexes on spotstatelist ----
  565. $this->validateIndex("idx_spotstatelist_1", "UNIQUE", "spotstatelist", array("messageid", "ouruserid"));
  566. $this->validateIndex("idx_spotstatelistrel_1", "", "spotstatelist", array("ouruserid"));
  567. # ---- Indexes on securitygroups ----
  568. $this->validateIndex("idx_securitygroups_1", "UNIQUE", "securitygroups", array("name"));
  569. # ---- Indexes on grouppermissions ----
  570. $this->validateIndex("idx_grouppermissions_1", "UNIQUE", "grouppermissions", array("groupid", "permissionid", "objectid"));
  571. # ---- Indexes on usergroups ----
  572. $this->validateIndex("idx_usergroups_1", "UNIQUE", "usergroups", array("userid", "groupid"));
  573. $this->validateIndex("idx_usergroupsrel_1", "", "usergroups", array("groupid"));
  574. # ---- Indexes on notifications ----
  575. $this->validateIndex("idx_notifications_1", "", "notifications", array("userid"));
  576. $this->validateIndex("idx_notifications_2", "", "notifications", array("sent"));
  577. # ---- Indexes on filters ----
  578. $this->validateIndex("idx_filters_1", "", "filters", array("userid", "filtertype", 'tparent', 'torder'));
  579. # ---- Indexes on filtercounts ----
  580. $this->validateIndex("idx_filtercounts_1", "UNIQUE", "filtercounts", array("userid", "filterhash"));
  581. # ---- Indexes on spotteridblacklist ----
  582. $this->validateIndex("idx_spotteridblacklist_1", "UNIQUE", "spotteridblacklist", array("spotterid", "ouruserid", "idtype"));
  583. $this->validateIndex("idx_spotteridblacklist_2", "", "spotteridblacklist", array("ouruserid"));
  584. # ---- Indexes on cache ----
  585. $this->validateIndex("idx_cache_1", "UNIQUE", "cache", array("resourceid", "cachetype"));
  586. $this->validateIndex("idx_cache_2", "", "cache", array("cachetype", "stamp"));
  587. # Create foreign keys where possible
  588. $this->addForeignKey('usersettings', 'userid', 'users', 'id', 'ON DELETE CASCADE ON UPDATE CASCADE');
  589. $this->addForeignKey('spotstatelist', 'ouruserid', 'users', 'id', 'ON DELETE CASCADE ON UPDATE CASCADE');
  590. $this->addForeignKey('usergroups', 'userid', 'users', 'id', 'ON DELETE CASCADE ON UPDATE CASCADE');
  591. $this->addForeignKey('usergroups', 'groupid', 'securitygroups', 'id', 'ON DELETE CASCADE ON UPDATE CASCADE');
  592. $this->addForeignKey('grouppermissions', 'groupid', 'securitygroups', 'id', 'ON DELETE CASCADE ON UPDATE CASCADE');
  593. $this->addForeignKey('commentsfull', 'messageid', 'commentsxover', 'messageid', 'ON DELETE CASCADE ON UPDATE CASCADE');
  594. $this->addForeignKey('notifications', 'userid', 'users', 'id', 'ON DELETE CASCADE ON UPDATE CASCADE');
  595. $this->addForeignKey('commentsposted', 'ouruserid', 'users', 'id', 'ON DELETE CASCADE ON UPDATE CASCADE');
  596. $this->addForeignKey('reportsposted', 'ouruserid', 'users', 'id', 'ON DELETE CASCADE ON UPDATE CASCADE');
  597. $this->addForeignKey('filters', 'userid', 'users', 'id', 'ON DELETE CASCADE ON UPDATE CASCADE');
  598. $this->addForeignKey('spotsposted', 'ouruserid', 'users', 'id', 'ON DELETE CASCADE ON UPDATE CASCADE');
  599. ##############################################################################################
  600. # Drop old columns ###########################################################################
  601. ##############################################################################################
  602. $this->dropColumn('filesize', 'spotsfull');
  603. $this->dropColumn('userid', 'spotsfull');
  604. $this->dropColumn('userid', 'spotteridblacklist');
  605. $this->dropColumn('userid', 'commentsfull');
  606. ##############################################################################################
  607. # Drop old tables ######## ###################################################################
  608. ##############################################################################################
  609. $this->dropTable('webcache');
  610. $this->dropTable('cachetmp');
  611. # update the database with this specific schemaversion
  612. $this->_spotdb->updateSetting('schemaversion', SPOTDB_SCHEMA_VERSION);
  613. } # updateSchema
  614. } # class