Add PostgreSQL backend
Co-authored-by: Kim Lidström <dxtr@users.noreply.github.com>
This commit is contained in:
parent
cc3eca1dc5
commit
35a3d018f1
12 changed files with 457 additions and 46 deletions
|
@ -45,8 +45,8 @@ class Tools {
|
|||
|
||||
# Asserting PDO::SQLite or PDO::MySQL
|
||||
$aPDODrivers = \PDO::getAvailableDrivers();
|
||||
if (!in_array('sqlite', $aPDODrivers, true) && !in_array('mysql', $aPDODrivers, true)) {
|
||||
exit('<strong>Baikal Fatal Error</strong>: Both <strong>PDO::sqlite</strong> and <strong>PDO::mysql</strong> are unavailable. One of them at least is required by Baikal.');
|
||||
if (!in_array('sqlite', $aPDODrivers, true) && !in_array('mysql', $aPDODrivers, true) && !in_array('pgsql', $aPDODrivers, true)) {
|
||||
exit('<strong>Baikal Fatal Error</strong>: None of <strong>PDO::sqlite</strong>, <strong>PDO::mysql</strong> or <strong>PDO::pgsql</strong> are available. One of them at least is required by Baikal.');
|
||||
}
|
||||
|
||||
# Assert that the temp folder is writable
|
||||
|
|
|
@ -244,7 +244,7 @@ class Calendar extends \Flake\Core\Model\Db {
|
|||
|
||||
function hasInstances() {
|
||||
$rSql = $GLOBALS["DB"]->exec_SELECTquery(
|
||||
"count(*)",
|
||||
"count(*) as count",
|
||||
"calendarinstances",
|
||||
"calendarid='" . $this->aData["calendarid"] . "'"
|
||||
);
|
||||
|
@ -254,7 +254,7 @@ class Calendar extends \Flake\Core\Model\Db {
|
|||
} else {
|
||||
reset($aRs);
|
||||
|
||||
return $aRs["count(*)"] > 1;
|
||||
return $aRs["count"] > 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ class Calendar extends \Flake\Core\Model\Db {
|
|||
|
||||
function hasInstances() {
|
||||
$rSql = $GLOBALS["DB"]->exec_SELECTquery(
|
||||
"count(*)",
|
||||
"count(*) as count",
|
||||
"calendarinstances",
|
||||
"calendarid='" . $this->aData["id"] . "'"
|
||||
);
|
||||
|
@ -48,7 +48,7 @@ class Calendar extends \Flake\Core\Model\Db {
|
|||
} else {
|
||||
reset($aRs);
|
||||
|
||||
return $aRs["count(*)"] > 1;
|
||||
return $aRs["count"] > 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,12 +31,16 @@ class Database extends \Baikal\Model\Config {
|
|||
# Default values
|
||||
protected $aData = [
|
||||
"sqlite_file" => PROJECT_PATH_SPECIFIC . "db/db.sqlite",
|
||||
"mysql" => false,
|
||||
"backend" => "",
|
||||
"mysql_host" => "",
|
||||
"mysql_dbname" => "",
|
||||
"mysql_username" => "",
|
||||
"mysql_password" => "",
|
||||
"encryption_key" => "",
|
||||
"pgsql_host" => "",
|
||||
"pgsql_dbname" => "",
|
||||
"pgsql_username" => "",
|
||||
"pgsql_password" => "",
|
||||
];
|
||||
|
||||
function __construct() {
|
||||
|
@ -46,6 +50,14 @@ class Database extends \Baikal\Model\Config {
|
|||
function formMorphologyForThisModelInstance() {
|
||||
$oMorpho = new \Formal\Form\Morphology();
|
||||
|
||||
$oMorpho->add(new \Formal\Element\Listbox([
|
||||
"prop" => "backend",
|
||||
"label" => "Database Backend",
|
||||
"validation" => "required",
|
||||
"options" => ['sqlite', 'mysql', 'pgsql'],
|
||||
"refreshonchange" => true,
|
||||
]));
|
||||
|
||||
$oMorpho->add(new \Formal\Element\Text([
|
||||
"prop" => "sqlite_file",
|
||||
"label" => "SQLite file path",
|
||||
|
@ -54,13 +66,6 @@ class Database extends \Baikal\Model\Config {
|
|||
"help" => "The absolute server path to the SQLite file",
|
||||
]));
|
||||
|
||||
$oMorpho->add(new \Formal\Element\Checkbox([
|
||||
"prop" => "mysql",
|
||||
"label" => "Use MySQL",
|
||||
"help" => "If checked, Baïkal will use MySQL instead of SQLite.",
|
||||
"refreshonchange" => true,
|
||||
]));
|
||||
|
||||
$oMorpho->add(new \Formal\Element\Text([
|
||||
"prop" => "mysql_host",
|
||||
"label" => "MySQL host",
|
||||
|
@ -82,6 +87,27 @@ class Database extends \Baikal\Model\Config {
|
|||
"label" => "MySQL password",
|
||||
]));
|
||||
|
||||
$oMorpho->add(new \Formal\Element\Text([
|
||||
"prop" => "pgsql_host",
|
||||
"label" => "PostgreSQL host",
|
||||
"help" => "Host ip or name, including <strong>':portnumber'</strong> if port is not the default one (?)",
|
||||
]));
|
||||
|
||||
$oMorpho->add(new \Formal\Element\Text([
|
||||
"prop" => "pgsql_dbname",
|
||||
"label" => "PostgreSQL database name",
|
||||
]));
|
||||
|
||||
$oMorpho->add(new \Formal\Element\Text([
|
||||
"prop" => "pgsql_username",
|
||||
"label" => "PostgreSQL username",
|
||||
]));
|
||||
|
||||
$oMorpho->add(new \Formal\Element\Password([
|
||||
"prop" => "pgsql_password",
|
||||
"label" => "PostgreSQL password",
|
||||
]));
|
||||
|
||||
return $oMorpho;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,18 +38,22 @@ class Database extends \Flake\Core\Controller {
|
|||
if (file_exists(PROJECT_PATH_SPECIFIC . "config.system.php")) {
|
||||
require_once PROJECT_PATH_SPECIFIC . "config.system.php";
|
||||
$this->oModel->set('sqlite_file', PROJECT_SQLITE_FILE);
|
||||
$this->oModel->set('mysql', PROJECT_DB_MYSQL);
|
||||
$this->oModel->set('backend', PROJECT_DB_BACKEND);
|
||||
$this->oModel->set('mysql_host', PROJECT_DB_MYSQL_HOST);
|
||||
$this->oModel->set('mysql_dbname', PROJECT_DB_MYSQL_DBNAME);
|
||||
$this->oModel->set('mysql_username', PROJECT_DB_MYSQL_USERNAME);
|
||||
$this->oModel->set('mysql_password', PROJECT_DB_MYSQL_PASSWORD);
|
||||
$this->oModel->set('pgsql_host', PROJECT_DB_PGSQL_HOST);
|
||||
$this->oModel->set('pgsql_dbname', PROJECT_DB_PGSQL_DBNAME);
|
||||
$this->oModel->set('pgsql_username', PROJECT_DB_PGSQL_USERNAME);
|
||||
$this->oModel->set('pgsql_password', PROJECT_DB_PGSQL_PASSWORD);
|
||||
$this->oModel->set('encryption_key', BAIKAL_ENCRYPTION_KEY);
|
||||
}
|
||||
|
||||
$this->oForm = $this->oModel->formForThisModelInstance([
|
||||
"close" => false,
|
||||
"hook.validation" => [$this, "validateConnection"],
|
||||
"hook.morphology" => [$this, "hideMySQLFieldWhenNeeded"],
|
||||
"hook.validation" => [$this, "validateSQLConnection"],
|
||||
"hook.morphology" => [$this, "hideSQLFieldWhenNeeded"],
|
||||
]);
|
||||
|
||||
if ($this->oForm->submitted()) {
|
||||
|
@ -99,11 +103,11 @@ class Database extends \Flake\Core\Controller {
|
|||
return $oView->render();
|
||||
}
|
||||
|
||||
function validateConnection($oForm, $oMorpho) {
|
||||
function validateMySQLConnection($oForm, $oMorpho) {
|
||||
if ($oForm->refreshed()) {
|
||||
return true;
|
||||
}
|
||||
$bMySQLEnabled = $oMorpho->element("mysql")->value();
|
||||
$bMySQLEnabled = $oMorpho->element("backend")->value() == 'mysql';
|
||||
|
||||
if ($bMySQLEnabled) {
|
||||
$sHost = $oMorpho->element("mysql_host")->value();
|
||||
|
@ -129,7 +133,7 @@ class Database extends \Flake\Core\Controller {
|
|||
$sMessage .= "<br /><p>Nothing has been saved. <strong>Please, add these tables to the database before pursuing Baïkal initialization.</strong></p>";
|
||||
|
||||
$oForm->declareError(
|
||||
$oMorpho->element("mysql"),
|
||||
$oMorpho->element("backend"),
|
||||
$sMessage
|
||||
);
|
||||
} else {
|
||||
|
@ -142,7 +146,7 @@ class Database extends \Flake\Core\Controller {
|
|||
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
$oForm->declareError($oMorpho->element("mysql"),
|
||||
$oForm->declareError($oMorpho->element("backend"),
|
||||
"Baïkal was not able to establish a connexion to the MySQL database as configured.<br />MySQL says: " . $e->getMessage());
|
||||
$oForm->declareError($oMorpho->element("mysql_host"));
|
||||
$oForm->declareError($oMorpho->element("mysql_dbname"));
|
||||
|
@ -211,10 +215,10 @@ class Database extends \Flake\Core\Controller {
|
|||
|
||||
function hideMySQLFieldWhenNeeded(\Formal\Form $oForm, \Formal\Form\Morphology $oMorpho) {
|
||||
if ($oForm->submitted()) {
|
||||
$bMySQL = (intval($oForm->postValue("mysql")) === 1);
|
||||
$bMySQL = ($oForm->postValue("backend") == 'mysql');
|
||||
} else {
|
||||
// oMorpho won't have the values from the model set on it yet
|
||||
$bMySQL = $this->oModel->get("mysql");
|
||||
$bMySQL = $this->oModel->get("backend") == 'mysql';
|
||||
}
|
||||
|
||||
if ($bMySQL === true) {
|
||||
|
@ -226,4 +230,103 @@ class Database extends \Flake\Core\Controller {
|
|||
$oMorpho->remove("mysql_password");
|
||||
}
|
||||
}
|
||||
|
||||
function validatePgSQLConnection($oForm, $oMorpho) {
|
||||
$bPgSqlEnabled = $oMorpho->element("backend")->value() == 'pgsql';
|
||||
|
||||
if ($bPgSqlEnabled) {
|
||||
$sHost = $oMorpho->element("pgsql_host")->value();
|
||||
$sDbname = $oMorpho->element("pgsql_dbname")->value();
|
||||
$sUsername = $oMorpho->element("pgsql_username")->value();
|
||||
$sPassword = $oMorpho->element("pgsql_password")->value();
|
||||
|
||||
try {
|
||||
$oDb = new \Flake\Core\Database\Pgsql(
|
||||
$sHost,
|
||||
$sDbname,
|
||||
$sUsername,
|
||||
$sPassword
|
||||
);
|
||||
|
||||
if (($aMissingTables = \Baikal\Core\Tools::isDBStructurallyComplete($oDb)) !== true) {
|
||||
# Checking if all tables are missing
|
||||
$aRequiredTables = \Baikal\Core\Tools::getRequiredTablesList();
|
||||
if (count($aRequiredTables) !== count($aMissingTables)) {
|
||||
$sMessage = "<br /><p><strong>Database is not structurally complete.</strong></p>";
|
||||
$sMessage .= "<p>Missing tables are: <strong>" . implode("</strong>, <strong>", $aMissingTables) . "</strong></p>";
|
||||
$sMessage .= "<p>You will find the SQL definition of Baïkal tables in this file: <strong>Core/Resources/Db/PgSQL/db.sql</strong></p>";
|
||||
$sMessage .= "<br /><p>Nothing has been saved. <strong>Please, add these tables to the database before pursuing Baïkal initialization.</strong></p>";
|
||||
|
||||
$oForm->declareError(
|
||||
$oMorpho->element("backend"),
|
||||
$sMessage
|
||||
);
|
||||
} else {
|
||||
# All tables are missing
|
||||
# We add these tables ourselves to the database, to initialize Baïkal
|
||||
$sSqlDefinition = file_get_contents(PROJECT_PATH_CORERESOURCES . "Db/PgSQL/db.sql");
|
||||
$oDb->getPDO()->exec($sSqlDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
$oForm->declareError(
|
||||
$oMorpho->element("backend"),
|
||||
"Baïkal was not able to establish a connexion to the PostgreSQL database as configured.<br />PostgreSQL says: " . $e->getMessage()
|
||||
);
|
||||
|
||||
$oForm->declareError(
|
||||
$oMorpho->element("pgsql_host")
|
||||
);
|
||||
|
||||
$oForm->declareError(
|
||||
$oMorpho->element("pgsql_dbname")
|
||||
);
|
||||
|
||||
$oForm->declareError(
|
||||
$oMorpho->element("pgsql_username")
|
||||
);
|
||||
|
||||
$oForm->declareError(
|
||||
$oMorpho->element("pgsql_password")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function validateSQLConnection($oForm, $oMorpho) {
|
||||
if ($oMorpho->element("backend")->value() == 'mysql') {
|
||||
$this->validateMySQLConnection($oForm, $oMorpho);
|
||||
} elseif ($oMorpho->element("backend")->value() == 'pgsql') {
|
||||
$this->validatePgSQLConnection($oForm, $oMorpho);
|
||||
}
|
||||
}
|
||||
|
||||
public function hideSqlFieldWhenNeeded(\Formal\Form $oForm, \Formal\Form\Morphology $oMorpho) {
|
||||
if ($oMorpho->element("backend")->value() == 'mysql') {
|
||||
$this->hideMySQLFieldWhenNeeded($oForm, $oMorpho);
|
||||
} elseif ($oMorpho->element("backend")->value() == 'pgsql') {
|
||||
$this->hidePgSQLFieldWhenNeeded($oForm, $oMorpho);
|
||||
}
|
||||
}
|
||||
|
||||
public function hidePgSQLFieldWhenNeeded(\Formal\Form $oForm, \Formal\Form\Morphology $oMorpho) {
|
||||
if ($oForm->submitted()) {
|
||||
$bPgSQL = ($oForm->postValue("backend")) == 'pgsql';
|
||||
} else {
|
||||
// oMorpho won't have the values from the model set on it yet
|
||||
$bPgSQL = $this->oModel->get("backend") == 'pgsql';
|
||||
}
|
||||
|
||||
if ($bPgSQL === true) {
|
||||
$oMorpho->remove("sqlite_file");
|
||||
$this->hideMySQLFieldWhenNeeded($oForm, $oMorpho);
|
||||
} else {
|
||||
$oMorpho->remove("pgsql_host");
|
||||
$oMorpho->remove("pgsql_dbname");
|
||||
$oMorpho->remove("pgsql_username");
|
||||
$oMorpho->remove("pgsql_password");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,8 +82,12 @@ class Initialize extends \Flake\Core\Controller {
|
|||
|
||||
# Default: PDO::SQLite or PDO::MySQL ?
|
||||
$aPDODrivers = \PDO::getAvailableDrivers();
|
||||
if (!in_array('sqlite', $aPDODrivers)) { # PDO::MySQL is already asserted in \Baikal\Core\Tools::assertEnvironmentIsOk()
|
||||
$oDatabaseConfig->set("mysql", true);
|
||||
if (in_array('sqlite', $aPDODrivers)) { # PDO::MySQL is already asserted in \Baikal\Core\Tools::assertEnvironmentIsOk()
|
||||
$oDatabaseConfig->set("backend", 'sqlite');
|
||||
} elseif (in_array('mysql', $aPDODrivers)) {
|
||||
$oDatabaseConfig->set("backend", 'mysql');
|
||||
} else {
|
||||
$oDatabaseConfig->set("backend", 'pgsql');
|
||||
}
|
||||
|
||||
$oDatabaseConfig->persist();
|
||||
|
|
|
@ -505,6 +505,14 @@ SQL
|
|||
$this->aSuccess[] = 'Updated default values in calendarinstances table';
|
||||
}
|
||||
|
||||
if (version_compare($sVersionFrom, '0.10.0', '<')) {
|
||||
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "baikal.yaml");
|
||||
|
||||
$oConfig = new \Baikal\Model\Config\Database();
|
||||
$oConfig->set("backend", intval($config['database']['mysql']) === 1 ? 'mysql' : 'sqlite');
|
||||
$oConfig->persist();
|
||||
}
|
||||
|
||||
$this->updateConfiguredVersion($sVersionTo);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -74,61 +74,81 @@ class Database extends \Flake\Core\Controller {
|
|||
|
||||
function morphologyHook(\Formal\Form $oForm, \Formal\Form\Morphology $oMorpho) {
|
||||
if ($oForm->submitted()) {
|
||||
$bMySQL = (intval($oForm->postValue("mysql")) === 1);
|
||||
$bMySQL = ($oForm->postValue("backend") == 'mysql');
|
||||
$bPgSQL = ($oForm->postValue("backend") == 'pgsql');
|
||||
} else {
|
||||
try {
|
||||
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "baikal.yaml");
|
||||
} catch (\Exception $e) {
|
||||
error_log('Error reading baikal.yaml file : ' . $e->getMessage());
|
||||
}
|
||||
$bMySQL = $config['database']['mysql'] ?? true;
|
||||
$bMySQL = $config['database']['backend'] == 'mysql';
|
||||
$bPgSQL = $config['database']['backend'] == 'pgsql';
|
||||
}
|
||||
|
||||
if ($bMySQL === true) {
|
||||
if ($bMySQL === true || $bPgSQL === true) {
|
||||
$oMorpho->remove("sqlite_file");
|
||||
} else {
|
||||
}
|
||||
|
||||
if (!$bMySQL) {
|
||||
$oMorpho->remove("mysql_host");
|
||||
$oMorpho->remove("mysql_dbname");
|
||||
$oMorpho->remove("mysql_username");
|
||||
$oMorpho->remove("mysql_password");
|
||||
}
|
||||
|
||||
if (!$bPgSQL) {
|
||||
$oMorpho->remove("pgsql_host");
|
||||
$oMorpho->remove("pgsql_dbname");
|
||||
$oMorpho->remove("pgsql_username");
|
||||
$oMorpho->remove("pgsql_password");
|
||||
}
|
||||
}
|
||||
|
||||
function validationHook(\Formal\Form $oForm, \Formal\Form\Morphology $oMorpho) {
|
||||
if ($oForm->refreshed()) {
|
||||
return true;
|
||||
}
|
||||
if (intval($oForm->modelInstance()->get("mysql")) === 1) {
|
||||
# We have to check the MySQL connection
|
||||
$sHost = $oForm->modelInstance()->get("mysql_host");
|
||||
$sDbName = $oForm->modelInstance()->get("mysql_dbname");
|
||||
$sUsername = $oForm->modelInstance()->get("mysql_username");
|
||||
$sPassword = $oForm->modelInstance()->get("mysql_password");
|
||||
if ($oForm->modelInstance()->get("backend") == 'mysql' || $oForm->modelInstance()->get("backend") == 'pgsql') {
|
||||
$dbBackendName = $oForm->modelInstance()->get("backend") == 'pgsql' ? 'PostgreSQL' : 'MySQL';
|
||||
$dbBackendPrefix = $oForm->modelInstance()->get("backend");
|
||||
|
||||
# We have to check the MySQL or PostgreSQL connection
|
||||
$sHost = $oForm->modelInstance()->get("{$dbBackendPrefix}_host");
|
||||
$sDbName = $oForm->modelInstance()->get("{$dbBackendPrefix}_dbname");
|
||||
$sUsername = $oForm->modelInstance()->get("{$dbBackendPrefix}_username");
|
||||
$sPassword = $oForm->modelInstance()->get("{$dbBackendPrefix}_password");
|
||||
|
||||
try {
|
||||
$oDB = new \Flake\Core\Database\Mysql(
|
||||
$oDB = (($oForm->modelInstance()->get("backend")) == 'pgsql'
|
||||
) ? new \Flake\Core\Database\Pgsql(
|
||||
$sHost,
|
||||
$sDbName,
|
||||
$sUsername,
|
||||
$sPassword
|
||||
) : new \Flake\Core\Database\Mysql(
|
||||
$sHost,
|
||||
$sDbName,
|
||||
$sUsername,
|
||||
$sPassword
|
||||
);
|
||||
} catch (\Exception $e) {
|
||||
$sMessage = "<strong>MySQL error:</strong> " . $e->getMessage();
|
||||
$sMessage = "<strong>{$dbBackendName} error:</strong> " . $e->getMessage();
|
||||
$sMessage .= "<br /><strong>Nothing has been saved</strong>";
|
||||
$oForm->declareError($oMorpho->element("mysql_host"), $sMessage);
|
||||
$oForm->declareError($oMorpho->element("mysql_dbname"));
|
||||
$oForm->declareError($oMorpho->element("mysql_username"));
|
||||
$oForm->declareError($oMorpho->element("mysql_password"));
|
||||
$oForm->declareError($oMorpho->element("{$dbBackendPrefix}_host"), $sMessage);
|
||||
$oForm->declareError($oMorpho->element("{$dbBackendPrefix}_dbname"));
|
||||
$oForm->declareError($oMorpho->element("{$dbBackendPrefix}_username"));
|
||||
$oForm->declareError($oMorpho->element("{$dbBackendPrefix}_password"));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (($aMissingTables = \Baikal\Core\Tools::isDBStructurallyComplete($oDB)) !== true) {
|
||||
$sMessage = "<strong>MySQL error:</strong> These tables, required by Baïkal, are missing: <strong>" . implode(", ", $aMissingTables) . "</strong><br />";
|
||||
$sMessage .= "You may want create these tables using the file <strong>Core/Resources/Db/MySQL/db.sql</strong>";
|
||||
$sMessage = "<strong>{$dbBackendName} error:</strong> These tables, required by Baïkal, are missing: <strong>" . implode(", ", $aMissingTables) . "</strong><br />";
|
||||
$sMessage .= "You may want create these tables using the file <strong>Core/Resources/Db/{$dbBackendName}/db.sql</strong>";
|
||||
$sMessage .= "<br /><br /><strong>Nothing has been saved</strong>";
|
||||
|
||||
$oForm->declareError($oMorpho->element("mysql"), $sMessage);
|
||||
$oForm->declareError($oMorpho->element("backend"), $sMessage);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
68
Core/Frameworks/Flake/Core/Database/Pgsql.php
Normal file
68
Core/Frameworks/Flake/Core/Database/Pgsql.php
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
#################################################################
|
||||
# Copyright notice
|
||||
#
|
||||
# (c) 2013 Kim Lidström <kim@dxtr.im>
|
||||
# All rights reserved
|
||||
#
|
||||
# http://flake.codr.fr
|
||||
#
|
||||
# This script is part of the Flake project. The Flake
|
||||
# project is free software; you can redistribute it
|
||||
# and/or modify it under the terms of the GNU General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 of the License, or (at your option) any later version.
|
||||
#
|
||||
# The GNU General Public License can be found at
|
||||
# http://www.gnu.org/copyleft/gpl.html.
|
||||
#
|
||||
# This script is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# This copyright notice MUST APPEAR in all copies of the script!
|
||||
#################################################################
|
||||
|
||||
namespace Flake\Core\Database;
|
||||
|
||||
class Pgsql extends \Flake\Core\Database {
|
||||
protected $oDb = false; // current DB link
|
||||
protected $debugOutput = false;
|
||||
protected $store_lastBuiltQuery = true;
|
||||
protected $debug_lastBuiltQuery = "";
|
||||
protected $sHost = "";
|
||||
protected $sDbName = "";
|
||||
protected $sUsername = "";
|
||||
protected $sPassword = "";
|
||||
|
||||
public function __construct($sHost, $sDbName, $sUsername, $sPassword) {
|
||||
$this->sHost = $sHost;
|
||||
$this->sDbName = $sDbName;
|
||||
$this->sUsername = $sUsername;
|
||||
$this->sPassword = $sPassword;
|
||||
|
||||
$this->oDb = new \PDO(
|
||||
'pgsql:host=' . $this->sHost . ';dbname=' . $this->sDbName,
|
||||
$this->sUsername,
|
||||
$this->sPassword
|
||||
);
|
||||
}
|
||||
|
||||
public function tables() {
|
||||
$aTables = [];
|
||||
|
||||
$sSql = "SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = 'public'";
|
||||
$oStmt = $this->query($sSql);
|
||||
|
||||
while (($aRs = $oStmt->fetch()) !== false) {
|
||||
$aTables[] = array_shift($aRs);
|
||||
}
|
||||
|
||||
asort($aTables);
|
||||
reset($aTables);
|
||||
|
||||
return $aTables;
|
||||
}
|
||||
}
|
|
@ -273,8 +273,12 @@ class Framework extends \Flake\Core\Framework {
|
|||
if (defined("BAIKAL_CONTEXT_INSTALL") && (!isset($config['system']['configured_version']) || $config['system']['configured_version'] === BAIKAL_VERSION)) {
|
||||
return true;
|
||||
}
|
||||
if ($config['database']['mysql'] === true) {
|
||||
# Config key 'mysql' kept for backwards compatibility
|
||||
$legacyMysql = key_exists('mysql', $config['database']) && $config['database']['mysql'] === true;
|
||||
if ($legacyMysql || $config['database']['backend'] === 'mysql') {
|
||||
self::initDbMysql($config);
|
||||
} elseif ($config['database']['backend'] === 'pgsql') {
|
||||
self::initDbPgsql($config);
|
||||
} else {
|
||||
self::initDbSqlite($config);
|
||||
}
|
||||
|
@ -339,6 +343,38 @@ class Framework extends \Flake\Core\Framework {
|
|||
return true;
|
||||
}
|
||||
|
||||
protected static function initDbPgsql(array $config) {
|
||||
if (!$config['database']['pgsql_host']) {
|
||||
exit("<h3>The constant PROJECT_DB_PGSQL_HOST, containing the PostgreSQL host name, is not set.<br />You should set it in config/baikal.yaml</h3>");
|
||||
}
|
||||
|
||||
if (!$config['database']['pgsql_dbname']) {
|
||||
exit("<h3>The constant PROJECT_DB_PGSQL_DBNAME, containing the PostgreSQL database name, is not set.<br />You should set it in config/baikal.yaml</h3>");
|
||||
}
|
||||
|
||||
try {
|
||||
$GLOBALS["DB"] = new \Flake\Core\Database\Pgsql(
|
||||
$config['database']['pgsql_host'],
|
||||
$config['database']['pgsql_dbname'],
|
||||
$config['database']['pgsql_username'],
|
||||
$config['database']['pgsql_password']
|
||||
);
|
||||
|
||||
$GLOBALS["DB"]->query("SET NAMES 'UTF8'");
|
||||
} catch (\Exception $e) {
|
||||
$message = "Baïkal was not able to establish a connection to the configured PostgreSQL database (as configured in config/baikal.yaml).";
|
||||
if (!$config['database']['pgsql_username']) {
|
||||
exit("<h3>$message Note: The constant PROJECT_DB_PGSQL_USERNAME, containing the PostgreSQL database username, is not set. If your database requires a username you should set it in config/baikal.yaml.</h3>");
|
||||
}
|
||||
|
||||
if ($config['database']['pgsql_password'] === null) {
|
||||
exit("<h3>$message Note: The constant PROJECT_DB_PGSQL_PASSWORD, containing the PostgreSQL database password, is not set. If your database requires a password you should set it in config/baikal.yaml.</h3>");
|
||||
}
|
||||
|
||||
exit("<h3>$message</h3>");
|
||||
}
|
||||
}
|
||||
|
||||
static function isDBInitialized() {
|
||||
return isset($GLOBALS["DB"]) && \Flake\Util\Tools::is_a($GLOBALS["DB"], "\Flake\Core\Database");
|
||||
}
|
||||
|
|
142
Core/Resources/Db/PgSQL/db.sql
Normal file
142
Core/Resources/Db/PgSQL/db.sql
Normal file
|
@ -0,0 +1,142 @@
|
|||
|
||||
CREATE TABLE addressbooks (
|
||||
id SERIAL PRIMARY KEY,
|
||||
principaluri TEXT,
|
||||
displayname VARCHAR(255),
|
||||
uri TEXT,
|
||||
description TEXT,
|
||||
synctoken INT CHECK (synctoken > 0) NOT NULL DEFAULT '1'
|
||||
);
|
||||
|
||||
CREATE TABLE cards (
|
||||
id SERIAL PRIMARY KEY,
|
||||
addressbookid INT CHECK (addressbookid > 0) NOT NULL,
|
||||
carddata TEXT,
|
||||
uri TEXT,
|
||||
lastmodified INT CHECK (lastmodified > 0),
|
||||
etag TEXT,
|
||||
size INT CHECK (size > 0) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE addressbookchanges (
|
||||
id SERIAL PRIMARY KEY,
|
||||
uri TEXT NOT NULL,
|
||||
synctoken INT CHECK (synctoken > 0) NOT NULL,
|
||||
addressbookid INT CHECK (addressbookid > 0) NOT NULL,
|
||||
operation SMALLINT NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX addressbookid_synctoken ON addressbookchanges (addressbookid, synctoken);
|
||||
|
||||
CREATE TABLE calendarobjects (
|
||||
id SERIAL PRIMARY KEY,
|
||||
calendardata TEXT,
|
||||
uri TEXT,
|
||||
calendarid INTEGER CHECK (calendarid > 0) NOT NULL,
|
||||
lastmodified INT CHECK (lastmodified > 0),
|
||||
etag TEXT,
|
||||
size INT CHECK (size > 0) NOT NULL,
|
||||
componenttype TEXT,
|
||||
firstoccurence INT CHECK (firstoccurence > 0),
|
||||
lastoccurence INT CHECK (lastoccurence > 0),
|
||||
uid TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE calendars (
|
||||
id SERIAL PRIMARY KEY,
|
||||
synctoken INTEGER CHECK (synctoken > 0) NOT NULL DEFAULT '1',
|
||||
components TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE calendarinstances (
|
||||
id SERIAL PRIMARY KEY,
|
||||
calendarid INTEGER CHECK (calendarid > 0) NOT NULL,
|
||||
principaluri TEXT,
|
||||
access SMALLINT NOT NULL DEFAULT '1',
|
||||
displayname VARCHAR(100),
|
||||
uri TEXT,
|
||||
description TEXT,
|
||||
calendarorder INT CHECK (calendarorder >= 0) NOT NULL DEFAULT '0',
|
||||
calendarcolor TEXT,
|
||||
timezone TEXT,
|
||||
transparent SMALLINT NOT NULL DEFAULT '0',
|
||||
share_href TEXT,
|
||||
share_displayname VARCHAR(100),
|
||||
share_invitestatus SMALLINT NOT NULL DEFAULT '2'
|
||||
);
|
||||
|
||||
CREATE TABLE calendarchanges (
|
||||
id SERIAL PRIMARY KEY,
|
||||
uri TEXT NOT NULL,
|
||||
synctoken INT CHECK (synctoken > 0) NOT NULL,
|
||||
calendarid INT CHECK (calendarid > 0) NOT NULL,
|
||||
operation SMALLINT NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX calendarid_synctoken ON calendarchanges (calendarid, synctoken);
|
||||
|
||||
CREATE TABLE calendarsubscriptions (
|
||||
id SERIAL PRIMARY KEY,
|
||||
uri TEXT NOT NULL,
|
||||
principaluri TEXT NOT NULL,
|
||||
source TEXT,
|
||||
displayname VARCHAR(100),
|
||||
refreshrate VARCHAR(10),
|
||||
calendarorder INT CHECK (calendarorder >= 0) NOT NULL DEFAULT '0',
|
||||
calendarcolor TEXT,
|
||||
striptodos SMALLINT NULL,
|
||||
stripalarms SMALLINT NULL,
|
||||
stripattachments SMALLINT NULL,
|
||||
lastmodified INT CHECK (lastmodified > 0)
|
||||
);
|
||||
|
||||
CREATE TABLE schedulingobjects (
|
||||
id SERIAL PRIMARY KEY,
|
||||
principaluri TEXT,
|
||||
calendardata TEXT,
|
||||
uri TEXT,
|
||||
lastmodified INT CHECK (lastmodified > 0),
|
||||
etag TEXT,
|
||||
size INT CHECK (size > 0) NOT NULL
|
||||
);
|
||||
CREATE TABLE locks (
|
||||
id SERIAL PRIMARY KEY,
|
||||
owner VARCHAR(100),
|
||||
timeout INTEGER CHECK (timeout > 0),
|
||||
created INTEGER,
|
||||
token TEXT,
|
||||
scope SMALLINT,
|
||||
depth SMALLINT,
|
||||
uri TEXT
|
||||
);
|
||||
|
||||
CREATE INDEX ON locks (token);
|
||||
CREATE INDEX ON locks (uri);
|
||||
|
||||
CREATE TABLE principals (
|
||||
id SERIAL PRIMARY KEY,
|
||||
uri TEXT NOT NULL,
|
||||
email TEXT,
|
||||
displayname VARCHAR(80)
|
||||
);
|
||||
|
||||
CREATE TABLE groupmembers (
|
||||
id SERIAL PRIMARY KEY,
|
||||
principal_id INTEGER CHECK (principal_id > 0) NOT NULL,
|
||||
member_id INTEGER CHECK (member_id > 0) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE propertystorage (
|
||||
id SERIAL PRIMARY KEY,
|
||||
path TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
valuetype INT CHECK (valuetype > 0),
|
||||
value TEXT
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX path_property ON propertystorage (path, name);
|
||||
CREATE TABLE users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
username TEXT,
|
||||
digesta1 TEXT
|
||||
);
|
|
@ -11,9 +11,13 @@ system:
|
|||
base_uri: ''
|
||||
database:
|
||||
encryption_key: 5d3f0fa0192e3058ea70f1bb20924add
|
||||
backend: 'mysql'
|
||||
sqlite_file: "absolute/path/to/Specific/db/db.sqlite"
|
||||
mysql: true
|
||||
mysql_host: 'localhost'
|
||||
mysql_dbname: 'baikal'
|
||||
mysql_username: 'baikal'
|
||||
mysql_password: 'baikal'
|
||||
pgsql_host: 'localhost'
|
||||
pgsql_dbname: 'baikal'
|
||||
pgsql_username: 'baikal'
|
||||
pgsql_password: 'baikal'
|
||||
|
|
Loading…
Reference in a new issue