Friendica Communications Platform (please note that this is a clone of the repository at github, issues are handled there) https://friendi.ca
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1792 lines
90 KiB

  1. <?php
  2. /**
  3. * @file src/Database/DBStructure.php
  4. */
  5. namespace Friendica\Database;
  6. use Friendica\Core\Config;
  7. use Friendica\Core\L10n;
  8. use Friendica\Database\DBM;
  9. use dba;
  10. require_once 'boot.php';
  11. require_once 'include/dba.php';
  12. require_once 'include/enotify.php';
  13. require_once 'include/text.php';
  14. /**
  15. * @brief This class contain functions for the database management
  16. *
  17. * This class contains functions that doesn't need to know if pdo, mysqli or whatever is used.
  18. */
  19. class DBStructure
  20. {
  21. /*
  22. * Converts all tables from MyISAM to InnoDB
  23. */
  24. public static function convertToInnoDB() {
  25. $r = q("SELECT `TABLE_NAME` FROM `information_schema`.`tables` WHERE `engine` = 'MyISAM' AND `table_schema` = '%s'",
  26. dbesc(dba::database_name()));
  27. if (!DBM::is_result($r)) {
  28. echo L10n::t('There are no tables on MyISAM.')."\n";
  29. return;
  30. }
  31. foreach ($r AS $table) {
  32. $sql = sprintf("ALTER TABLE `%s` engine=InnoDB;", dbesc($table['TABLE_NAME']));
  33. echo $sql."\n";
  34. $result = dba::e($sql);
  35. if (!DBM::is_result($result)) {
  36. self::printUpdateError($sql);
  37. }
  38. }
  39. }
  40. /*
  41. * send the email and do what is needed to do on update fails
  42. *
  43. * @param update_id (int) number of failed update
  44. * @param error_message (str) error message
  45. */
  46. public static function updateFail($update_id, $error_message) {
  47. $a = get_app();
  48. //send the administrators an e-mail
  49. $admin_mail_list = "'".implode("','", array_map(dbesc, explode(",", str_replace(" ", "", $a->config['admin_email']))))."'";
  50. $adminlist = q("SELECT uid, language, email FROM user WHERE email IN (%s)",
  51. $admin_mail_list
  52. );
  53. // No valid result?
  54. if (!DBM::is_result($adminlist)) {
  55. logger(sprintf('Cannot notify administrators about update_id=%d, error_message=%s', $update_id, $error_message), LOGGER_NORMAL);
  56. // Don't continue
  57. return;
  58. }
  59. // every admin could had different language
  60. foreach ($adminlist as $admin) {
  61. $lang = (($admin['language'])?$admin['language']:'en');
  62. L10n::pushLang($lang);
  63. $preamble = deindent(L10n::t("
  64. The friendica developers released update %s recently,
  65. but when I tried to install it, something went terribly wrong.
  66. This needs to be fixed soon and I can't do it alone. Please contact a
  67. friendica developer if you can not help me on your own. My database might be invalid."));
  68. $body = L10n::t("The error message is\n[pre]%s[/pre]");
  69. $preamble = sprintf($preamble, $update_id);
  70. $body = sprintf($body, $error_message);
  71. notification([
  72. 'type' => SYSTEM_EMAIL,
  73. 'to_email' => $admin['email'],
  74. 'preamble' => $preamble,
  75. 'body' => $body,
  76. 'language' => $lang]
  77. );
  78. }
  79. //try the logger
  80. logger("CRITICAL: Database structure update failed: ".$error_message);
  81. }
  82. private static function tableStructure($table) {
  83. $structures = q("DESCRIBE `%s`", $table);
  84. $full_columns = q("SHOW FULL COLUMNS FROM `%s`", $table);
  85. $indexes = q("SHOW INDEX FROM `%s`", $table);
  86. $table_status = q("SHOW TABLE STATUS WHERE `name` = '%s'", $table);
  87. if (DBM::is_result($table_status)) {
  88. $table_status = $table_status[0];
  89. } else {
  90. $table_status = [];
  91. }
  92. $fielddata = [];
  93. $indexdata = [];
  94. if (DBM::is_result($indexes)) {
  95. foreach ($indexes AS $index) {
  96. if ($index['Key_name'] != 'PRIMARY' && $index['Non_unique'] == '0' && !isset($indexdata[$index["Key_name"]])) {
  97. $indexdata[$index["Key_name"]] = ['UNIQUE'];
  98. }
  99. $column = $index["Column_name"];
  100. if ($index["Sub_part"] != "") {
  101. $column .= "(".$index["Sub_part"].")";
  102. }
  103. $indexdata[$index["Key_name"]][] = $column;
  104. }
  105. }
  106. if (DBM::is_result($structures)) {
  107. foreach ($structures AS $field) {
  108. // Replace the default size values so that we don't have to define them
  109. $search = ['tinyint(1)', 'tinyint(4)', 'smallint(5) unsigned', 'smallint(6)', 'mediumint(9)', 'bigint(20)', 'int(11)'];
  110. $replace = ['boolean', 'tinyint', 'smallint unsigned', 'smallint', 'mediumint', 'bigint', 'int'];
  111. $field["Type"] = str_replace($search, $replace, $field["Type"]);
  112. $fielddata[$field["Field"]]["type"] = $field["Type"];
  113. if ($field["Null"] == "NO") {
  114. $fielddata[$field["Field"]]["not null"] = true;
  115. }
  116. if (isset($field["Default"])) {
  117. $fielddata[$field["Field"]]["default"] = $field["Default"];
  118. }
  119. if ($field["Extra"] != "") {
  120. $fielddata[$field["Field"]]["extra"] = $field["Extra"];
  121. }
  122. if ($field["Key"] == "PRI") {
  123. $fielddata[$field["Field"]]["primary"] = true;
  124. }
  125. }
  126. }
  127. if (DBM::is_result($full_columns)) {
  128. foreach ($full_columns AS $column) {
  129. $fielddata[$column["Field"]]["Collation"] = $column["Collation"];
  130. $fielddata[$column["Field"]]["comment"] = $column["Comment"];
  131. }
  132. }
  133. return ["fields" => $fielddata, "indexes" => $indexdata, "table_status" => $table_status];
  134. }
  135. public static function printStructure() {
  136. $database = self::definition();
  137. echo "-- ------------------------------------------\n";
  138. echo "-- ".FRIENDICA_PLATFORM." ".FRIENDICA_VERSION." (".FRIENDICA_CODENAME,")\n";
  139. echo "-- DB_UPDATE_VERSION ".DB_UPDATE_VERSION."\n";
  140. echo "-- ------------------------------------------\n\n\n";
  141. foreach ($database AS $name => $structure) {
  142. echo "--\n";
  143. echo "-- TABLE $name\n";
  144. echo "--\n";
  145. self::createTable($name, $structure['fields'], true, false, $structure["indexes"]);
  146. echo "\n";
  147. }
  148. }
  149. /**
  150. * @brief Print out database error messages
  151. *
  152. * @param string $message Message to be added to the error message
  153. *
  154. * @return string Error message
  155. */
  156. private static function printUpdateError($message) {
  157. echo L10n::t("\nError %d occurred during database update:\n%s\n",
  158. dba::errorNo(), dba::errorMessage());
  159. return L10n::t('Errors encountered performing database changes: ').$message.EOL;
  160. }
  161. /**
  162. * Updates DB structure and returns eventual errors messages
  163. *
  164. * @param bool $verbose
  165. * @param bool $action Whether to actually apply the update
  166. * @param array $tables An array of the database tables
  167. * @param array $definition An array of the definition tables
  168. * @return string Empty string if the update is successful, error messages otherwise
  169. */
  170. public static function update($verbose, $action, array $tables = null, array $definition = null) {
  171. if ($action) {
  172. Config::set('system', 'maintenance', 1);
  173. Config::set('system', 'maintenance_reason', L10n::t(': Database update', DBM::date().' '.date('e')));
  174. }
  175. $errors = '';
  176. logger('updating structure', LOGGER_DEBUG);
  177. // Get the current structure
  178. $database = [];
  179. if (is_null($tables)) {
  180. $tables = q("SHOW TABLES");
  181. }
  182. if (DBM::is_result($tables)) {
  183. foreach ($tables AS $table) {
  184. $table = current($table);
  185. logger(sprintf('updating structure for table %s ...', $table), LOGGER_DEBUG);
  186. $database[$table] = self::tableStructure($table);
  187. }
  188. }
  189. // Get the definition
  190. if (is_null($definition)) {
  191. $definition = self::definition();
  192. }
  193. // MySQL >= 5.7.4 doesn't support the IGNORE keyword in ALTER TABLE statements
  194. if ((version_compare(dba::server_info(), '5.7.4') >= 0) &&
  195. !(strpos(dba::server_info(), 'MariaDB') !== false)) {
  196. $ignore = '';
  197. } else {
  198. $ignore = ' IGNORE';
  199. }
  200. // Compare it
  201. foreach ($definition AS $name => $structure) {
  202. $is_new_table = false;
  203. $group_by = "";
  204. $sql3 = "";
  205. $is_unique = false;
  206. $temp_name = $name;
  207. if (!isset($database[$name])) {
  208. $r = self::createTable($name, $structure["fields"], $verbose, $action, $structure['indexes']);
  209. if (!DBM::is_result($r)) {
  210. $errors .= self::printUpdateError($name);
  211. }
  212. $is_new_table = true;
  213. } else {
  214. foreach ($structure["indexes"] AS $indexname => $fieldnames) {
  215. if (isset($database[$name]["indexes"][$indexname])) {
  216. $current_index_definition = implode(",",$database[$name]["indexes"][$indexname]);
  217. } else {
  218. $current_index_definition = "__NOT_SET__";
  219. }
  220. $new_index_definition = implode(",",$fieldnames);
  221. if ($current_index_definition != $new_index_definition) {
  222. if ($fieldnames[0] == "UNIQUE") {
  223. $is_unique = true;
  224. if ($ignore == "") {
  225. $temp_name = "temp-".$name;
  226. }
  227. }
  228. }
  229. }
  230. /*
  231. * Drop the index if it isn't present in the definition
  232. * or the definition differ from current status
  233. * and index name doesn't start with "local_"
  234. */
  235. foreach ($database[$name]["indexes"] as $indexname => $fieldnames) {
  236. $current_index_definition = implode(",",$fieldnames);
  237. if (isset($structure["indexes"][$indexname])) {
  238. $new_index_definition = implode(",",$structure["indexes"][$indexname]);
  239. } else {
  240. $new_index_definition = "__NOT_SET__";
  241. }
  242. if ($current_index_definition != $new_index_definition && substr($indexname, 0, 6) != 'local_') {
  243. $sql2=self::dropIndex($indexname);
  244. if ($sql3 == "") {
  245. $sql3 = "ALTER".$ignore." TABLE `".$temp_name."` ".$sql2;
  246. } else {
  247. $sql3 .= ", ".$sql2;
  248. }
  249. }
  250. }
  251. // Compare the field structure field by field
  252. foreach ($structure["fields"] AS $fieldname => $parameters) {
  253. if (!isset($database[$name]["fields"][$fieldname])) {
  254. $sql2=self::addTableField($fieldname, $parameters);
  255. if ($sql3 == "") {
  256. $sql3 = "ALTER" . $ignore . " TABLE `".$temp_name."` ".$sql2;
  257. } else {
  258. $sql3 .= ", ".$sql2;
  259. }
  260. } else {
  261. // Compare the field definition
  262. $field_definition = $database[$name]["fields"][$fieldname];
  263. // Remove the relation data that is used for the referential integrity
  264. unset($parameters['relation']);
  265. // We change the collation after the indexes had been changed.
  266. // This is done to avoid index length problems.
  267. // So here we always ensure that there is no need to change it.
  268. unset($parameters['Collation']);
  269. unset($field_definition['Collation']);
  270. // Only update the comment when it is defined
  271. if (!isset($parameters['comment'])) {
  272. $parameters['comment'] = "";
  273. }
  274. $current_field_definition = implode(",", $field_definition);
  275. $new_field_definition = implode(",", $parameters);
  276. if ($current_field_definition != $new_field_definition) {
  277. $sql2 = self::modifyTableField($fieldname, $parameters);
  278. if ($sql3 == "") {
  279. $sql3 = "ALTER" . $ignore . " TABLE `".$temp_name."` ".$sql2;
  280. } else {
  281. $sql3 .= ", ".$sql2;
  282. }
  283. }
  284. }
  285. }
  286. }
  287. /*
  288. * Create the index if the index don't exists in database
  289. * or the definition differ from the current status.
  290. * Don't create keys if table is new
  291. */
  292. if (!$is_new_table) {
  293. foreach ($structure["indexes"] AS $indexname => $fieldnames) {
  294. if (isset($database[$name]["indexes"][$indexname])) {
  295. $current_index_definition = implode(",",$database[$name]["indexes"][$indexname]);
  296. } else {
  297. $current_index_definition = "__NOT_SET__";
  298. }
  299. $new_index_definition = implode(",",$fieldnames);
  300. if ($current_index_definition != $new_index_definition) {
  301. $sql2 = self::createIndex($indexname, $fieldnames);
  302. // Fetch the "group by" fields for unique indexes
  303. if ($fieldnames[0] == "UNIQUE") {
  304. $group_by = self::groupBy($indexname, $fieldnames);
  305. }
  306. if ($sql2 != "") {
  307. if ($sql3 == "") {
  308. $sql3 = "ALTER" . $ignore . " TABLE `".$temp_name."` ".$sql2;
  309. } else {
  310. $sql3 .= ", ".$sql2;
  311. }
  312. }
  313. }
  314. }
  315. if (isset($database[$name]["table_status"]["Comment"])) {
  316. if ($database[$name]["table_status"]["Comment"] != $structure['comment']) {
  317. $sql2 = "COMMENT = '".dbesc($structure['comment'])."'";
  318. if ($sql3 == "") {
  319. $sql3 = "ALTER" . $ignore . " TABLE `".$temp_name."` ".$sql2;
  320. } else {
  321. $sql3 .= ", ".$sql2;
  322. }
  323. }
  324. }
  325. if (isset($database[$name]["table_status"]["Collation"])) {
  326. if ($database[$name]["table_status"]["Collation"] != 'utf8mb4_general_ci') {
  327. $sql2 = "DEFAULT COLLATE utf8mb4_general_ci";
  328. if ($sql3 == "") {
  329. $sql3 = "ALTER" . $ignore . " TABLE `".$temp_name."` ".$sql2;
  330. } else {
  331. $sql3 .= ", ".$sql2;
  332. }
  333. }
  334. }
  335. if ($sql3 != "") {
  336. $sql3 .= "; ";
  337. }
  338. // Now have a look at the field collations
  339. // Compare the field structure field by field
  340. foreach ($structure["fields"] AS $fieldname => $parameters) {
  341. // Compare the field definition
  342. $field_definition = $database[$name]["fields"][$fieldname];
  343. // Define the default collation if not given
  344. if (!isset($parameters['Collation']) && !is_null($field_definition['Collation'])) {
  345. $parameters['Collation'] = 'utf8mb4_general_ci';
  346. } else {
  347. $parameters['Collation'] = null;
  348. }
  349. if ($field_definition['Collation'] != $parameters['Collation']) {
  350. $sql2 = self::modifyTableField($fieldname, $parameters);
  351. if (($sql3 == "") || (substr($sql3, -2, 2) == "; ")) {
  352. $sql3 .= "ALTER" . $ignore . " TABLE `".$temp_name."` ".$sql2;
  353. } else {
  354. $sql3 .= ", ".$sql2;
  355. }
  356. }
  357. }
  358. }
  359. if ($sql3 != "") {
  360. if (substr($sql3, -2, 2) != "; ") {
  361. $sql3 .= ";";
  362. }
  363. $field_list = '';
  364. if ($is_unique && $ignore == '') {
  365. foreach ($database[$name]["fields"] AS $fieldname => $parameters) {
  366. $field_list .= 'ANY_VALUE(`' . $fieldname . '`),';
  367. }
  368. $field_list = rtrim($field_list, ',');
  369. }
  370. if ($verbose) {
  371. // Ensure index conversion to unique removes duplicates
  372. if ($is_unique && ($temp_name != $name)) {
  373. if ($ignore != "") {
  374. echo "SET session old_alter_table=1;\n";
  375. } else {
  376. echo "DROP TABLE IF EXISTS `".$temp_name."`;\n";
  377. echo "CREATE TABLE `".$temp_name."` LIKE `".$name."`;\n";
  378. }
  379. }
  380. echo $sql3."\n";
  381. if ($is_unique && ($temp_name != $name)) {
  382. if ($ignore != "") {
  383. echo "SET session old_alter_table=0;\n";
  384. } else {
  385. echo "INSERT INTO `".$temp_name."` SELECT ".dba::any_value_fallback($field_list)." FROM `".$name."`".$group_by.";\n";
  386. echo "DROP TABLE `".$name."`;\n";
  387. echo "RENAME TABLE `".$temp_name."` TO `".$name."`;\n";
  388. }
  389. }
  390. }
  391. if ($action) {
  392. Config::set('system', 'maintenance_reason', L10n::t('%s: updating %s table.', DBM::date().' '.date('e'), $name));
  393. // Ensure index conversion to unique removes duplicates
  394. if ($is_unique && ($temp_name != $name)) {
  395. if ($ignore != "") {
  396. dba::e("SET session old_alter_table=1;");
  397. } else {
  398. $r = dba::e("DROP TABLE IF EXISTS `".$temp_name."`;");
  399. if (!DBM::is_result($r)) {
  400. $errors .= self::printUpdateError($sql3);
  401. return $errors;
  402. }
  403. $r = dba::e("CREATE TABLE `".$temp_name."` LIKE `".$name."`;");
  404. if (!DBM::is_result($r)) {
  405. $errors .= self::printUpdateError($sql3);
  406. return $errors;
  407. }
  408. }
  409. }
  410. $r = dba::e($sql3);
  411. if (!DBM::is_result($r)) {
  412. $errors .= self::printUpdateError($sql3);
  413. }
  414. if ($is_unique && ($temp_name != $name)) {
  415. if ($ignore != "") {
  416. dba::e("SET session old_alter_table=0;");
  417. } else {
  418. $r = dba::e("INSERT INTO `".$temp_name."` SELECT ".$field_list." FROM `".$name."`".$group_by.";");
  419. if (!DBM::is_result($r)) {
  420. $errors .= self::printUpdateError($sql3);
  421. return $errors;
  422. }
  423. $r = dba::e("DROP TABLE `".$name."`;");
  424. if (!DBM::is_result($r)) {
  425. $errors .= self::printUpdateError($sql3);
  426. return $errors;
  427. }
  428. $r = dba::e("RENAME TABLE `".$temp_name."` TO `".$name."`;");
  429. if (!DBM::is_result($r)) {
  430. $errors .= self::printUpdateError($sql3);
  431. return $errors;
  432. }
  433. }
  434. }
  435. }
  436. }
  437. }
  438. if ($action) {
  439. Config::set('system', 'maintenance', 0);
  440. Config::set('system', 'maintenance_reason', '');
  441. }
  442. if ($errors) {
  443. Config::set('system', 'dbupdate', DB_UPDATE_FAILED);
  444. } else {
  445. Config::set('system', 'dbupdate', DB_UPDATE_SUCCESSFUL);
  446. }
  447. return $errors;
  448. }
  449. private static function FieldCommand($parameters, $create = true) {
  450. $fieldstruct = $parameters["type"];
  451. if (!is_null($parameters["Collation"])) {
  452. $fieldstruct .= " COLLATE ".$parameters["Collation"];
  453. }
  454. if ($parameters["not null"]) {
  455. $fieldstruct .= " NOT NULL";
  456. }
  457. if (isset($parameters["default"])) {
  458. if (strpos(strtolower($parameters["type"]),"int")!==false) {
  459. $fieldstruct .= " DEFAULT ".$parameters["default"];
  460. } else {
  461. $fieldstruct .= " DEFAULT '".$parameters["default"]."'";
  462. }
  463. }
  464. if ($parameters["extra"] != "") {
  465. $fieldstruct .= " ".$parameters["extra"];
  466. }
  467. if (!is_null($parameters["comment"])) {
  468. $fieldstruct .= " COMMENT '".dbesc($parameters["comment"])."'";
  469. }
  470. /*if (($parameters["primary"] != "") && $create)
  471. $fieldstruct .= " PRIMARY KEY";*/
  472. return($fieldstruct);
  473. }
  474. private static function createTable($name, $fields, $verbose, $action, $indexes=null) {
  475. $r = true;
  476. $sql_rows = [];
  477. $primary_keys = [];
  478. foreach ($fields AS $fieldname => $field) {
  479. $sql_rows[] = "`".dbesc($fieldname)."` ".self::FieldCommand($field);
  480. if (x($field,'primary') && $field['primary']!='') {
  481. $primary_keys[] = $fieldname;
  482. }
  483. }
  484. if (!is_null($indexes)) {
  485. foreach ($indexes AS $indexname => $fieldnames) {
  486. $sql_index = self::createIndex($indexname, $fieldnames, "");
  487. if (!is_null($sql_index)) {
  488. $sql_rows[] = $sql_index;
  489. }
  490. }
  491. }
  492. $sql = implode(",\n\t", $sql_rows);
  493. $sql = sprintf("CREATE TABLE IF NOT EXISTS `%s` (\n\t", dbesc($name)).$sql."\n) DEFAULT COLLATE utf8mb4_general_ci";
  494. if ($verbose) {
  495. echo $sql.";\n";
  496. }
  497. if ($action) {
  498. $r = dba::e($sql);
  499. }
  500. return $r;
  501. }
  502. private static function addTableField($fieldname, $parameters) {
  503. $sql = sprintf("ADD `%s` %s", dbesc($fieldname), self::FieldCommand($parameters));
  504. return($sql);
  505. }
  506. private static function modifyTableField($fieldname, $parameters) {
  507. $sql = sprintf("MODIFY `%s` %s", dbesc($fieldname), self::FieldCommand($parameters, false));
  508. return($sql);
  509. }
  510. private static function dropIndex($indexname) {
  511. $sql = sprintf("DROP INDEX `%s`", dbesc($indexname));
  512. return($sql);
  513. }
  514. private static function createIndex($indexname, $fieldnames, $method = "ADD") {
  515. $method = strtoupper(trim($method));
  516. if ($method!="" && $method!="ADD") {
  517. throw new \Exception("Invalid parameter 'method' in self::createIndex(): '$method'");
  518. }
  519. if ($fieldnames[0] == "UNIQUE") {
  520. array_shift($fieldnames);
  521. $method .= ' UNIQUE';
  522. }
  523. $names = "";
  524. foreach ($fieldnames AS $fieldname) {
  525. if ($names != "") {
  526. $names .= ",";
  527. }
  528. if (preg_match('|(.+)\((\d+)\)|', $fieldname, $matches)) {
  529. $names .= "`".dbesc($matches[1])."`(".intval($matches[2]).")";
  530. } else {
  531. $names .= "`".dbesc($fieldname)."`";
  532. }
  533. }
  534. if ($indexname == "PRIMARY") {
  535. return sprintf("%s PRIMARY KEY(%s)", $method, $names);
  536. }
  537. $sql = sprintf("%s INDEX `%s` (%s)", $method, dbesc($indexname), $names);
  538. return($sql);
  539. }
  540. private static function groupBy($indexname, $fieldnames) {
  541. if ($fieldnames[0] != "UNIQUE") {
  542. return "";
  543. }
  544. array_shift($fieldnames);
  545. $names = "";
  546. foreach ($fieldnames AS $fieldname) {
  547. if ($names != "") {
  548. $names .= ",";
  549. }
  550. if (preg_match('|(.+)\((\d+)\)|', $fieldname, $matches)) {
  551. $names .= "`".dbesc($matches[1])."`";
  552. } else {
  553. $names .= "`".dbesc($fieldname)."`";
  554. }
  555. }
  556. $sql = sprintf(" GROUP BY %s", $names);
  557. return $sql;
  558. }
  559. public static function definition() {
  560. $database = [];
  561. $database["addon"] = [
  562. "comment" => "registered addons",
  563. "fields" => [
  564. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  565. "name" => ["type" => "varchar(190)", "not null" => "1", "default" => "", "comment" => ""],
  566. "version" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  567. "installed" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  568. "hidden" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  569. "timestamp" => ["type" => "bigint", "not null" => "1", "default" => "0", "comment" => ""],
  570. "plugin_admin" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  571. ],
  572. "indexes" => [
  573. "PRIMARY" => ["id"],
  574. "name" => ["UNIQUE", "name"],
  575. ]
  576. ];
  577. $database["attach"] = [
  578. "comment" => "file attachments",
  579. "fields" => [
  580. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  581. "uid" => ["type" => "mediumint", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
  582. "hash" => ["type" => "varchar(64)", "not null" => "1", "default" => "", "comment" => ""],
  583. "filename" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  584. "filetype" => ["type" => "varchar(64)", "not null" => "1", "default" => "", "comment" => ""],
  585. "filesize" => ["type" => "int", "not null" => "1", "default" => "0", "comment" => ""],
  586. "data" => ["type" => "longblob", "not null" => "1", "comment" => ""],
  587. "created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  588. "edited" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  589. "allow_cid" => ["type" => "mediumtext", "comment" => ""],
  590. "allow_gid" => ["type" => "mediumtext", "comment" => ""],
  591. "deny_cid" => ["type" => "mediumtext", "comment" => ""],
  592. "deny_gid" => ["type" => "mediumtext", "comment" => ""],
  593. ],
  594. "indexes" => [
  595. "PRIMARY" => ["id"],
  596. ]
  597. ];
  598. $database["auth_codes"] = [
  599. "comment" => "OAuth usage",
  600. "fields" => [
  601. "id" => ["type" => "varchar(40)", "not null" => "1", "primary" => "1", "comment" => ""],
  602. "client_id" => ["type" => "varchar(20)", "not null" => "1", "default" => "", "relation" => ["clients" => "client_id"], "comment" => ""],
  603. "redirect_uri" => ["type" => "varchar(200)", "not null" => "1", "default" => "", "comment" => ""],
  604. "expires" => ["type" => "int", "not null" => "1", "default" => "0", "comment" => ""],
  605. "scope" => ["type" => "varchar(250)", "not null" => "1", "default" => "", "comment" => ""],
  606. ],
  607. "indexes" => [
  608. "PRIMARY" => ["id"],
  609. ]
  610. ];
  611. $database["cache"] = [
  612. "comment" => "Used to store different data that doesn't to be stored for a long time",
  613. "fields" => [
  614. "k" => ["type" => "varbinary(255)", "not null" => "1", "primary" => "1", "comment" => ""],
  615. "v" => ["type" => "mediumtext", "comment" => ""],
  616. "expire_mode" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => ""],
  617. "updated" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  618. ],
  619. "indexes" => [
  620. "PRIMARY" => ["k"],
  621. "expire_mode_updated" => ["expire_mode", "updated"],
  622. ]
  623. ];
  624. $database["challenge"] = [
  625. "comment" => "",
  626. "fields" => [
  627. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  628. "challenge" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  629. "dfrn-id" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  630. "expire" => ["type" => "int", "not null" => "1", "default" => "0", "comment" => ""],
  631. "type" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  632. "last_update" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  633. ],
  634. "indexes" => [
  635. "PRIMARY" => ["id"],
  636. ]
  637. ];
  638. $database["clients"] = [
  639. "comment" => "OAuth usage",
  640. "fields" => [
  641. "client_id" => ["type" => "varchar(20)", "not null" => "1", "primary" => "1", "comment" => ""],
  642. "pw" => ["type" => "varchar(20)", "not null" => "1", "default" => "", "comment" => ""],
  643. "redirect_uri" => ["type" => "varchar(200)", "not null" => "1", "default" => "", "comment" => ""],
  644. "name" => ["type" => "text", "comment" => ""],
  645. "icon" => ["type" => "text", "comment" => ""],
  646. "uid" => ["type" => "mediumint", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
  647. ],
  648. "indexes" => [
  649. "PRIMARY" => ["client_id"],
  650. ]
  651. ];
  652. $database["config"] = [
  653. "comment" => "main configuration storage",
  654. "fields" => [
  655. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  656. "cat" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => ""],
  657. "k" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => ""],
  658. "v" => ["type" => "mediumtext", "comment" => ""],
  659. ],
  660. "indexes" => [
  661. "PRIMARY" => ["id"],
  662. "cat_k" => ["UNIQUE", "cat", "k"],
  663. ]
  664. ];
  665. $database["contact"] = [
  666. "comment" => "contact table",
  667. "fields" => [
  668. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  669. "uid" => ["type" => "mediumint", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
  670. "created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  671. "self" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  672. "remote_self" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  673. "rel" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => ""],
  674. "duplex" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  675. "network" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  676. "name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  677. "nick" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  678. "location" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  679. "about" => ["type" => "text", "comment" => ""],
  680. "keywords" => ["type" => "text", "comment" => ""],
  681. "gender" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => ""],
  682. "xmpp" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  683. "attag" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  684. "avatar" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  685. "photo" => ["type" => "text", "comment" => ""],
  686. "thumb" => ["type" => "text", "comment" => ""],
  687. "micro" => ["type" => "text", "comment" => ""],
  688. "site-pubkey" => ["type" => "text", "comment" => ""],
  689. "issued-id" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  690. "dfrn-id" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  691. "url" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  692. "nurl" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  693. "addr" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  694. "alias" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  695. "pubkey" => ["type" => "text", "comment" => ""],
  696. "prvkey" => ["type" => "text", "comment" => ""],
  697. "batch" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  698. "request" => ["type" => "text", "comment" => ""],
  699. "notify" => ["type" => "text", "comment" => ""],
  700. "poll" => ["type" => "text", "comment" => ""],
  701. "confirm" => ["type" => "text", "comment" => ""],
  702. "poco" => ["type" => "text", "comment" => ""],
  703. "aes_allow" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  704. "ret-aes" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  705. "usehub" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  706. "subhub" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  707. "hub-verify" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  708. "last-update" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  709. "success_update" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  710. "failure_update" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  711. "name-date" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  712. "uri-date" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  713. "avatar-date" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  714. "term-date" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  715. "last-item" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  716. "priority" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => ""],
  717. "blocked" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => ""],
  718. "readonly" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  719. "writable" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  720. "forum" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  721. "prv" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  722. "contact-type" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => ""],
  723. "hidden" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  724. "archive" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  725. "pending" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => ""],
  726. "rating" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => ""],
  727. "reason" => ["type" => "text", "comment" => ""],
  728. "closeness" => ["type" => "tinyint", "not null" => "1", "default" => "99", "comment" => ""],
  729. "info" => ["type" => "mediumtext", "comment" => ""],
  730. "profile-id" => ["type" => "int", "not null" => "1", "default" => "0", "comment" => ""],
  731. "bdyear" => ["type" => "varchar(4)", "not null" => "1", "default" => "", "comment" => ""],
  732. "bd" => ["type" => "date", "not null" => "1", "default" => "0001-01-01", "comment" => ""],
  733. "notify_new_posts" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  734. "fetch_further_information" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => ""],
  735. "ffi_keyword_blacklist" => ["type" => "text", "comment" => ""],
  736. ],
  737. "indexes" => [
  738. "PRIMARY" => ["id"],
  739. "uid_name" => ["uid", "name(190)"],
  740. "self_uid" => ["self", "uid"],
  741. "alias_uid" => ["alias(32)", "uid"],
  742. "pending_uid" => ["pending", "uid"],
  743. "blocked_uid" => ["blocked", "uid"],
  744. "uid_rel_network_poll" => ["uid", "rel", "network(4)", "poll(64)", "archive"],
  745. "uid_network_batch" => ["uid", "network(4)", "batch(64)"],
  746. "addr_uid" => ["addr(32)", "uid"],
  747. "nurl_uid" => ["nurl(32)", "uid"],
  748. "nick_uid" => ["nick(32)", "uid"],
  749. "dfrn-id" => ["dfrn-id(64)"],
  750. "issued-id" => ["issued-id(64)"],
  751. ]
  752. ];
  753. $database["conv"] = [
  754. "comment" => "private messages",
  755. "fields" => [
  756. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  757. "guid" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  758. "recips" => ["type" => "text", "comment" => ""],
  759. "uid" => ["type" => "mediumint", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
  760. "creator" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  761. "created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  762. "updated" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  763. "subject" => ["type" => "text", "comment" => ""],
  764. ],
  765. "indexes" => [
  766. "PRIMARY" => ["id"],
  767. "uid" => ["uid"],
  768. ]
  769. ];
  770. $database["conversation"] = [
  771. "comment" => "Raw data and structure information for messages",
  772. "fields" => [
  773. "item-uri" => ["type" => "varbinary(255)", "not null" => "1", "primary" => "1", "comment" => ""],
  774. "reply-to-uri" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => ""],
  775. "conversation-uri" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => ""],
  776. "conversation-href" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => ""],
  777. "protocol" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => ""],
  778. "source" => ["type" => "mediumtext", "comment" => ""],
  779. "received" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  780. ],
  781. "indexes" => [
  782. "PRIMARY" => ["item-uri"],
  783. "conversation-uri" => ["conversation-uri"],
  784. "received" => ["received"],
  785. ]
  786. ];
  787. $database["event"] = [
  788. "comment" => "Events",
  789. "fields" => [
  790. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  791. "guid" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  792. "uid" => ["type" => "mediumint", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
  793. "cid" => ["type" => "int", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => ""],
  794. "uri" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  795. "created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  796. "edited" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  797. "start" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  798. "finish" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  799. "summary" => ["type" => "text", "comment" => ""],
  800. "desc" => ["type" => "text", "comment" => ""],
  801. "location" => ["type" => "text", "comment" => ""],
  802. "type" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  803. "nofinish" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  804. "adjust" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => ""],
  805. "ignore" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  806. "allow_cid" => ["type" => "mediumtext", "comment" => ""],
  807. "allow_gid" => ["type" => "mediumtext", "comment" => ""],
  808. "deny_cid" => ["type" => "mediumtext", "comment" => ""],
  809. "deny_gid" => ["type" => "mediumtext", "comment" => ""],
  810. ],
  811. "indexes" => [
  812. "PRIMARY" => ["id"],
  813. "uid_start" => ["uid", "start"],
  814. ]
  815. ];
  816. $database["fcontact"] = [
  817. "comment" => "Diaspora compatible contacts - used in the Diaspora implementation",
  818. "fields" => [
  819. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  820. "guid" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  821. "url" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  822. "name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  823. "photo" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  824. "request" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  825. "nick" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  826. "addr" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  827. "batch" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  828. "notify" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  829. "poll" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  830. "confirm" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  831. "priority" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => ""],
  832. "network" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => ""],
  833. "alias" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  834. "pubkey" => ["type" => "text", "comment" => ""],
  835. "updated" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  836. ],
  837. "indexes" => [
  838. "PRIMARY" => ["id"],
  839. "addr" => ["addr(32)"],
  840. "url" => ["UNIQUE", "url(190)"],
  841. ]
  842. ];
  843. $database["fsuggest"] = [
  844. "comment" => "friend suggestion stuff",
  845. "fields" => [
  846. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  847. "uid" => ["type" => "mediumint", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
  848. "cid" => ["type" => "int", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => ""],
  849. "name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  850. "url" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  851. "request" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  852. "photo" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  853. "note" => ["type" => "text", "comment" => ""],
  854. "created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  855. ],
  856. "indexes" => [
  857. "PRIMARY" => ["id"],
  858. ]
  859. ];
  860. $database["gcign"] = [
  861. "comment" => "contacts ignored by friend suggestions",
  862. "fields" => [
  863. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  864. "uid" => ["type" => "mediumint", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
  865. "gcid" => ["type" => "int", "not null" => "1", "default" => "0", "relation" => ["gcontact" => "id"], "comment" => ""],
  866. ],
  867. "indexes" => [
  868. "PRIMARY" => ["id"],
  869. "uid" => ["uid"],
  870. "gcid" => ["gcid"],
  871. ]
  872. ];
  873. $database["gcontact"] = [
  874. "comment" => "global contacts",
  875. "fields" => [
  876. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  877. "name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  878. "nick" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  879. "url" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  880. "nurl" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  881. "photo" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  882. "connect" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  883. "created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  884. "updated" => ["type" => "datetime", "default" => NULL_DATE, "comment" => ""],
  885. "last_contact" => ["type" => "datetime", "default" => NULL_DATE, "comment" => ""],
  886. "last_failure" => ["type" => "datetime", "default" => NULL_DATE, "comment" => ""],
  887. "location" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  888. "about" => ["type" => "text", "comment" => ""],
  889. "keywords" => ["type" => "text", "comment" => ""],
  890. "gender" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => ""],
  891. "birthday" => ["type" => "varchar(32)", "not null" => "1", "default" => "0001-01-01", "comment" => ""],
  892. "community" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  893. "contact-type" => ["type" => "tinyint", "not null" => "1", "default" => "-1", "comment" => ""],
  894. "hide" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  895. "nsfw" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  896. "network" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  897. "addr" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  898. "notify" => ["type" => "text", "comment" => ""],
  899. "alias" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  900. "generation" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => ""],
  901. "server_url" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  902. ],
  903. "indexes" => [
  904. "PRIMARY" => ["id"],
  905. "nurl" => ["UNIQUE", "nurl(190)"],
  906. "name" => ["name(64)"],
  907. "nick" => ["nick(32)"],
  908. "addr" => ["addr(64)"],
  909. "hide_network_updated" => ["hide", "network(4)", "updated"],
  910. "updated" => ["updated"],
  911. ]
  912. ];
  913. $database["glink"] = [
  914. "comment" => "'friends of friends' linkages derived from poco",
  915. "fields" => [
  916. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  917. "cid" => ["type" => "int", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => ""],
  918. "uid" => ["type" => "mediumint", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
  919. "gcid" => ["type" => "int", "not null" => "1", "default" => "0", "relation" => ["gcontact" => "id"], "comment" => ""],
  920. "zcid" => ["type" => "int", "not null" => "1", "default" => "0", "relation" => ["gcontact" => "id"], "comment" => ""],
  921. "updated" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  922. ],
  923. "indexes" => [
  924. "PRIMARY" => ["id"],
  925. "cid_uid_gcid_zcid" => ["UNIQUE", "cid","uid","gcid","zcid"],
  926. "gcid" => ["gcid"],
  927. ]
  928. ];
  929. $database["group"] = [
  930. "comment" => "privacy groups, group info",
  931. "fields" => [
  932. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  933. "uid" => ["type" => "mediumint", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
  934. "visible" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  935. "deleted" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  936. "name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  937. ],
  938. "indexes" => [
  939. "PRIMARY" => ["id"],
  940. "uid" => ["uid"],
  941. ]
  942. ];
  943. $database["group_member"] = [
  944. "comment" => "privacy groups, member info",
  945. "fields" => [
  946. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  947. "gid" => ["type" => "int", "not null" => "1", "default" => "0", "relation" => ["group" => "id"], "comment" => ""],
  948. "contact-id" => ["type" => "int", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => ""],
  949. ],
  950. "indexes" => [
  951. "PRIMARY" => ["id"],
  952. "contactid" => ["contact-id"],
  953. "gid_contactid" => ["UNIQUE", "gid", "contact-id"],
  954. ]
  955. ];
  956. $database["gserver"] = [
  957. "comment" => "Global servers",
  958. "fields" => [
  959. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  960. "url" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  961. "nurl" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  962. "version" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  963. "site_name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  964. "info" => ["type" => "text", "comment" => ""],
  965. "register_policy" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => ""],
  966. "registered-users" => ["type" => "int", "not null" => "1", "default" => "0", "comment" => ""],
  967. "poco" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  968. "noscrape" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  969. "network" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => ""],
  970. "platform" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  971. "created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  972. "last_poco_query" => ["type" => "datetime", "default" => NULL_DATE, "comment" => ""],
  973. "last_contact" => ["type" => "datetime", "default" => NULL_DATE, "comment" => ""],
  974. "last_failure" => ["type" => "datetime", "default" => NULL_DATE, "comment" => ""],
  975. ],
  976. "indexes" => [
  977. "PRIMARY" => ["id"],
  978. "nurl" => ["UNIQUE", "nurl(190)"],
  979. ]
  980. ];
  981. $database["hook"] = [
  982. "comment" => "addon hook registry",
  983. "fields" => [
  984. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  985. "hook" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  986. "file" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  987. "function" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  988. "priority" => ["type" => "smallint", "not null" => "1", "default" => "0", "comment" => ""],
  989. ],
  990. "indexes" => [
  991. "PRIMARY" => ["id"],
  992. "hook_file_function" => ["UNIQUE", "hook(50)","file(80)","function(60)"],
  993. ]
  994. ];
  995. $database["intro"] = [
  996. "comment" => "",
  997. "fields" => [
  998. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  999. "uid" => ["type" => "mediumint", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
  1000. "fid" => ["type" => "int", "not null" => "1", "default" => "0", "relation" => ["fcontact" => "id"], "comment" => ""],
  1001. "contact-id" => ["type" => "int", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => ""],
  1002. "knowyou" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1003. "duplex" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1004. "note" => ["type" => "text", "comment" => ""],
  1005. "hash" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1006. "datetime" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  1007. "blocked" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => ""],
  1008. "ignore" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1009. ],
  1010. "indexes" => [
  1011. "PRIMARY" => ["id"],
  1012. ]
  1013. ];
  1014. $database["item"] = [
  1015. "comment" => "All posts",
  1016. "fields" => [
  1017. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "relation" => ["thread" => "iid"]],
  1018. "guid" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1019. "uri" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1020. "uid" => ["type" => "mediumint", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
  1021. "contact-id" => ["type" => "int", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => ""],
  1022. "gcontact-id" => ["type" => "int", "not null" => "1", "default" => "0", "relation" => ["gcontact" => "id"], "comment" => ""],
  1023. "type" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1024. "wall" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1025. "gravity" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => ""],
  1026. "parent" => ["type" => "int", "not null" => "1", "default" => "0", "relation" => ["item" => "id"], "comment" => ""],
  1027. "parent-uri" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1028. "extid" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1029. "thr-parent" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1030. "created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  1031. "edited" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  1032. "commented" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  1033. "received" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  1034. "changed" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  1035. "owner-id" => ["type" => "int", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => ""],
  1036. "owner-name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1037. "owner-link" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1038. "owner-avatar" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1039. "author-id" => ["type" => "int", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => ""],
  1040. "author-name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1041. "author-link" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1042. "author-avatar" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1043. "title" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1044. "body" => ["type" => "mediumtext", "comment" => ""],
  1045. "app" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1046. "verb" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1047. "object-type" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1048. "object" => ["type" => "text", "comment" => ""],
  1049. "target-type" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1050. "target" => ["type" => "text", "comment" => ""],
  1051. "postopts" => ["type" => "text", "comment" => ""],
  1052. "plink" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1053. "resource-id" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1054. "event-id" => ["type" => "int", "not null" => "1", "default" => "0", "relation" => ["event" => "id"], "comment" => ""],
  1055. "tag" => ["type" => "mediumtext", "comment" => ""],
  1056. "attach" => ["type" => "mediumtext", "comment" => ""],
  1057. "inform" => ["type" => "mediumtext", "comment" => ""],
  1058. "file" => ["type" => "mediumtext", "comment" => ""],
  1059. "location" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1060. "coord" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1061. "allow_cid" => ["type" => "mediumtext", "comment" => ""],
  1062. "allow_gid" => ["type" => "mediumtext", "comment" => ""],
  1063. "deny_cid" => ["type" => "mediumtext", "comment" => ""],
  1064. "deny_gid" => ["type" => "mediumtext", "comment" => ""],
  1065. "private" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1066. "pubmail" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1067. "moderated" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1068. "visible" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1069. "spam" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1070. "starred" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1071. "bookmark" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1072. "unseen" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => ""],
  1073. "deleted" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1074. "origin" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1075. "forum_mode" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => ""],
  1076. "mention" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1077. "network" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => ""],
  1078. "rendered-hash" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => ""],
  1079. "rendered-html" => ["type" => "mediumtext", "comment" => ""],
  1080. "global" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1081. ],
  1082. "indexes" => [
  1083. "PRIMARY" => ["id"],
  1084. "guid" => ["guid(191)"],
  1085. "uri" => ["uri(191)"],
  1086. "parent" => ["parent"],
  1087. "parent-uri" => ["parent-uri(191)"],
  1088. "extid" => ["extid(191)"],
  1089. "uid_id" => ["uid","id"],
  1090. "uid_contactid_id" => ["uid","contact-id","id"],
  1091. "uid_created" => ["uid","created"],
  1092. "uid_unseen_contactid" => ["uid","unseen","contact-id"],
  1093. "uid_network_received" => ["uid","network(4)","received"],
  1094. "uid_network_commented" => ["uid","network(4)","commented"],
  1095. "uid_thrparent" => ["uid","thr-parent(190)"],
  1096. "uid_parenturi" => ["uid","parent-uri(190)"],
  1097. "uid_contactid_created" => ["uid","contact-id","created"],
  1098. "authorid_created" => ["author-id","created"],
  1099. "ownerid" => ["owner-id"],
  1100. "uid_uri" => ["uid", "uri(190)"],
  1101. "resource-id" => ["resource-id(191)"],
  1102. "contactid_allowcid_allowpid_denycid_denygid" => ["contact-id","allow_cid(10)","allow_gid(10)","deny_cid(10)","deny_gid(10)"], //
  1103. "uid_type_changed" => ["uid","type(190)","changed"],
  1104. "contactid_verb" => ["contact-id","verb(190)"],
  1105. "deleted_changed" => ["deleted","changed"],
  1106. "uid_wall_changed" => ["uid","wall","changed"],
  1107. "uid_eventid" => ["uid","event-id"],
  1108. "uid_authorlink" => ["uid","author-link(190)"],
  1109. "uid_ownerlink" => ["uid","owner-link(190)"],
  1110. ]
  1111. ];
  1112. $database["locks"] = [
  1113. "comment" => "",
  1114. "fields" => [
  1115. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  1116. "name" => ["type" => "varchar(128)", "not null" => "1", "default" => "", "comment" => ""],
  1117. "locked" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1118. "pid" => ["type" => "int", "not null" => "1", "default" => "0", "comment" => ""],
  1119. ],
  1120. "indexes" => [
  1121. "PRIMARY" => ["id"],
  1122. ]
  1123. ];
  1124. $database["mail"] = [
  1125. "comment" => "private messages",
  1126. "fields" => [
  1127. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  1128. "uid" => ["type" => "mediumint", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
  1129. "guid" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1130. "from-name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1131. "from-photo" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1132. "from-url" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1133. "contact-id" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "relation" => ["contact" => "id"], "comment" => ""],
  1134. "convid" => ["type" => "int", "not null" => "1", "default" => "0", "relation" => ["conv" => "id"], "comment" => ""],
  1135. "title" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1136. "body" => ["type" => "mediumtext", "comment" => ""],
  1137. "seen" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1138. "reply" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1139. "replied" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1140. "unknown" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1141. "uri" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1142. "parent-uri" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1143. "created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  1144. ],
  1145. "indexes" => [
  1146. "PRIMARY" => ["id"],
  1147. "uid_seen" => ["uid", "seen"],
  1148. "convid" => ["convid"],
  1149. "uri" => ["uri(64)"],
  1150. "parent-uri" => ["parent-uri(64)"],
  1151. "contactid" => ["contact-id(32)"],
  1152. ]
  1153. ];
  1154. $database["mailacct"] = [
  1155. "comment" => "Mail account data for fetching mails",
  1156. "fields" => [
  1157. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  1158. "uid" => ["type" => "mediumint", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
  1159. "server" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1160. "port" => ["type" => "smallint unsigned", "not null" => "1", "default" => "0", "comment" => ""],
  1161. "ssltype" => ["type" => "varchar(16)", "not null" => "1", "default" => "", "comment" => ""],
  1162. "mailbox" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1163. "user" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1164. "pass" => ["type" => "text", "comment" => ""],
  1165. "reply_to" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1166. "action" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => ""],
  1167. "movetofolder" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1168. "pubmail" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1169. "last_check" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  1170. ],
  1171. "indexes" => [
  1172. "PRIMARY" => ["id"],
  1173. ]
  1174. ];
  1175. $database["manage"] = [
  1176. "comment" => "table of accounts that can manage each other",
  1177. "fields" => [
  1178. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  1179. "uid" => ["type" => "mediumint", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
  1180. "mid" => ["type" => "mediumint", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
  1181. ],
  1182. "indexes" => [
  1183. "PRIMARY" => ["id"],
  1184. "uid_mid" => ["UNIQUE", "uid","mid"],
  1185. ]
  1186. ];
  1187. $database["notify"] = [
  1188. "comment" => "notifications",
  1189. "fields" => [
  1190. "id" => ["type" => "int", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
  1191. "hash" => ["type" => "varchar(64)", "not null" => "1", "default" => "", "comment" => ""],
  1192. "type" => ["type" => "smallint", "not null" => "1", "default" => "0", "comment" => ""],
  1193. "name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1194. "url" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1195. "photo" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1196. "date" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
  1197. "msg" => ["type" => "mediumtext", "comment" => ""],
  1198. "uid" => ["type" => "mediumint", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
  1199. "link" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
  1200. "iid" => ["type" => "int", "not null" => "1", "default" => "0", "relation" => ["item" => "id"], "comment" => ""],
  1201. "parent" => ["type" => "int", "not null" => "1", "default" => "0", "relation" => ["item" => "id"], "comment" => ""],
  1202. "seen" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
  1203. "verb" => ["type" => "varchar(255)", "not null