DatabaseDAOPGSQL.php 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. <?php
  2. /**
  3. * This class is used to test database is well-constructed.
  4. */
  5. class FreshRSS_DatabaseDAOPGSQL extends FreshRSS_DatabaseDAOSQLite {
  6. //PostgreSQL error codes
  7. const UNDEFINED_COLUMN = '42703';
  8. const UNDEFINED_TABLE = '42P01';
  9. public function tablesAreCorrect(): bool {
  10. $db = FreshRSS_Context::$system_conf->db;
  11. $dbowner = $db['user'];
  12. $sql = 'SELECT * FROM pg_catalog.pg_tables where tableowner=?';
  13. $stm = $this->pdo->prepare($sql);
  14. $values = array($dbowner);
  15. $stm->execute($values);
  16. $res = $stm->fetchAll(PDO::FETCH_ASSOC);
  17. $tables = array(
  18. $this->pdo->prefix() . 'category' => false,
  19. $this->pdo->prefix() . 'feed' => false,
  20. $this->pdo->prefix() . 'entry' => false,
  21. $this->pdo->prefix() . 'entrytmp' => false,
  22. $this->pdo->prefix() . 'tag' => false,
  23. $this->pdo->prefix() . 'entrytag' => false,
  24. );
  25. foreach ($res as $value) {
  26. $tables[array_pop($value)] = true;
  27. }
  28. return count(array_keys($tables, true, true)) == count($tables);
  29. }
  30. /** @return array<array<string,string|bool>> */
  31. public function getSchema(string $table): array {
  32. $sql = 'select column_name as field, data_type as type, column_default as default, is_nullable as null from INFORMATION_SCHEMA.COLUMNS where table_name = ?';
  33. $stm = $this->pdo->prepare($sql);
  34. $stm->execute(array($this->pdo->prefix() . $table));
  35. return $this->listDaoToSchema($stm->fetchAll(PDO::FETCH_ASSOC));
  36. }
  37. /**
  38. * @param array<string,string> $dao
  39. * @return array<string,string|bool>
  40. */
  41. public function daoToSchema(array $dao): array {
  42. return array(
  43. 'name' => $dao['field'],
  44. 'type' => strtolower($dao['type']),
  45. 'notnull' => (bool)$dao['null'],
  46. 'default' => $dao['default'],
  47. );
  48. }
  49. public function size(bool $all = false): int {
  50. if ($all) {
  51. $db = FreshRSS_Context::$system_conf->db;
  52. $sql = 'SELECT pg_database_size(:base)';
  53. $stm = $this->pdo->prepare($sql);
  54. $stm->bindParam(':base', $db['base']);
  55. $stm->execute();
  56. } else {
  57. $sql = <<<SQL
  58. SELECT
  59. pg_total_relation_size('`{$this->pdo->prefix()}category`') +
  60. pg_total_relation_size('`{$this->pdo->prefix()}feed`') +
  61. pg_total_relation_size('`{$this->pdo->prefix()}entry`') +
  62. pg_total_relation_size('`{$this->pdo->prefix()}entrytmp`') +
  63. pg_total_relation_size('`{$this->pdo->prefix()}tag`') +
  64. pg_total_relation_size('`{$this->pdo->prefix()}entrytag`')
  65. SQL;
  66. $stm = $this->pdo->query($sql);
  67. }
  68. if ($stm == false) {
  69. return 0;
  70. }
  71. $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0);
  72. return intval($res[0]);
  73. }
  74. public function optimize(): bool {
  75. $ok = true;
  76. $tables = array('category', 'feed', 'entry', 'entrytmp', 'tag', 'entrytag');
  77. foreach ($tables as $table) {
  78. $sql = 'VACUUM `_' . $table . '`';
  79. if ($this->pdo->exec($sql) === false) {
  80. $ok = false;
  81. $info = $this->pdo->errorInfo();
  82. Minz_Log::warning(__METHOD__ . ' error: ' . $sql . ' : ' . json_encode($info));
  83. }
  84. }
  85. return $ok;
  86. }
  87. }