From bfc4615440a2ea36c9093cb922471833fc8e8dc3 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Thu, 28 Feb 2019 13:38:25 +0100 Subject: [PATCH] Initial DB Wrapper --- src/App.php | 3 +- src/Database/IDatabase.php | 185 ++++++++++++++++++++++++++++++ src/Database/IDatabaseLock.php | 22 ++++ src/Database/MysqlDatabase.php | 112 ++++++++++++++++++ src/Factory/DBFactory.php | 12 +- src/Factory/DependencyFactory.php | 4 +- 6 files changed, 330 insertions(+), 8 deletions(-) create mode 100644 src/Database/IDatabase.php create mode 100644 src/Database/IDatabaseLock.php create mode 100644 src/Database/MysqlDatabase.php diff --git a/src/App.php b/src/App.php index 2576cc5d8e..ea6111d80d 100644 --- a/src/App.php +++ b/src/App.php @@ -14,6 +14,7 @@ use Friendica\Core\Config\Configuration; use Friendica\Core\Hook; use Friendica\Core\Theme; use Friendica\Database\DBA; +use Friendica\Database\IDatabase; use Friendica\Model\Profile; use Friendica\Network\HTTPException\InternalServerErrorException; use Friendica\Util\Config\ConfigFileLoader; @@ -235,7 +236,7 @@ class App * * @throws Exception if the Basepath is not usable */ - public function __construct(Configuration $config, App\Mode $mode, App\Router $router, LoggerInterface $logger, Profiler $profiler, $isBackend = true) + public function __construct(Configuration $config, App\Mode $mode, App\Router $router, LoggerInterface $logger, Profiler $profiler, IDatabase $database, $isBackend = true) { BaseObject::setApp($this); diff --git a/src/Database/IDatabase.php b/src/Database/IDatabase.php new file mode 100644 index 0000000000..59ff9ffe41 --- /dev/null +++ b/src/Database/IDatabase.php @@ -0,0 +1,185 @@ + 1, 'network' => 'dspr']; + * or: + * $condition = ['`uid` = ? AND `network` IN (?, ?)', 1, 'dfrn', 'dspr']; + * + * $count = IDatabase->count($table, $condition); + * + * @param string $table The table name + * @param array $condition An array of fields for condition + * + * @return int The counted rows + */ + function count($table, array $condition = []); + + /** + * Fetch a single row + * @param mixed $stmt A statement object + * + * @return array The current row + */ + function fetch($stmt); + + /** + * Starts a transaction + * + * @return bool Was the command executed successfully? + */ + function transaction(); + + /** + * Does a commit + * + * @return bool Was the command executed successfully? + */ + function commit(); + + /** + * Does a rollback + * + * @return bool Was the command executed successfully? + */ + function rollback(); + + /** + * Insert a row into a table + * + * @param string $table The table name + * @param array $param An array of fields for inserting + * @param bool $on_duplicate_update Do an update on a duplicate entry + * + * @return bool Was the insert successful? + */ + function insert($table, array $param, $on_duplicate_update = false); + + /** + * Delete a row from a table + * + * @param string $table The table name + * @param array $conditions An array of fields for condition + * @param bool $cascade If true we delete records in other tables that depend on the one we're deleting through + * relations (default: true) + * + * @return bool Was the delete successful? + */ + function delete($table, array $conditions, $cascade = false); + + /** + * Updates rows in the database. + * + * When $old_fields is set to an array, the system will only do an update if the fields in that array changed. + * + * Attention: + * Only the values in $old_fields are compared. This is intentional behaviour. + * + * Example: + * We include the timestamp field in $fields but not in $old_fields. + * Then the row will only get the new timestamp when the other fields had changed. + * + * When $old_fields is set to a boolean value, the system will do this compare itself. + * When $old_fields is set to "true", the system will do an insert if the row doesn't exist. + * + * Attention: + * Only set $old_fields to a boolean value when you are sure that you will update a single row. + * When you set $old_fields to "true", then $fields must contain all relevant fields! + * + * @param string $table The table name + * @param array $fields An array of fields for updating + * @param array $condition An array of fields for condition + * @param array|bool $old_fields An array of old fields that are about to be replaced (true = update on duplicate) + * + * @return bool Was the update successful? + */ + function update($table, array $fields, array $condition, $old_fields = []); + + /** + * Select rows from a table. + * + * Example: + * $table = "item"; + * $fields = ['id', 'uri', 'uid', 'network']; + * + * $condition = ['uid' => 1, 'network' => 'dspr']; + * or: + * $condition = ['`uid` = ? AND `network` IN (?, ?)', 1, 'dfrn', 'dspr'); + * + * $params = ['order' => ['id', 'received' => true), 'limit' => 10]; + * + * $data = IDatabase->select($table, $fields, $condition, $params); + * + * @param string $table The table name + * @param array $fields An array of fields for selecting, empty for all + * @param array $condition An array of fields for condition + * @param array $params An array of fields of several parameters + * + * @return bool|object The result object or "false" if nothing was found. + */ + function select($table, array $fields = [], array $condition = [], array $params = []); + + /** + * Retrieve a single record from a table and returns it in an associative array + * + * @param string $table The table name + * @param array $fields An array of fields for selecting, empty for all + * @param array $condition An array of fields for condition + * @param array $params An array of fields of several parameters + * + * @return bool|array The result array or "false" if nothing was found. + */ + function selectFirst($table, array $fields = [], array $condition = [], array $params = []); +} diff --git a/src/Database/IDatabaseLock.php b/src/Database/IDatabaseLock.php new file mode 100644 index 0000000000..a23fb6ca59 --- /dev/null +++ b/src/Database/IDatabaseLock.php @@ -0,0 +1,22 @@ +connected = DBA::connect($configCache, $profiler, $serveraddr, $user, $pass, $db, $charset); + } + + function isConnected() + { + return $this->connected; + } + + function disconnect() + { + DBA::disconnect(); + } + + function reconnect() + { + DBA::reconnect(); + $this->connected = DBA::connected(); + } + + function getConnection() + { + return DBA::getConnection(); + } + + function serverInfo() + { + return DBA::serverInfo(); + } + + function databaseName() + { + return DBA::databaseName(); + } + + function exists($table, array $condition) + { + return DBA::exists($table, $condition); + } + + function count($table, array $condition = []) + { + return DBA::count($table, $condition); + } + + function fetch($stmt) + { + return DBA::fetch($stmt); + } + + function transaction() + { + return DBA::transaction(); + } + + function commit() + { + return DBA::commit(); + } + + function rollback() + { + return DBA::rollback(); + } + + function insert($table, array $param, $on_duplicate_update = false) + { + return DBA::insert($table, $param, $on_duplicate_update); + } + + function delete($table, array $conditions, $cascade = true) + { + return DBA::delete($table, $conditions, [$cascade]); + } + + function update($table, array $fields, array $condition, array $old_fields = []) + { + return DBA::delete($table, $fields, $condition, $old_fields); + } + + function select($table, array $fields = [], array $condition = [], array $params = []) + { + return DBA::select($table, $fields, $condition, $params); + } + + function selectFirst($table, array $fields = [], array $condition = [], $params = []) + { + return DBA::selectFirst($table, $fields, $condition, $params); + } + + function lock($table) + { + return DBA::lock($table); + } + + function unlock() + { + return DBA::unlock(); + } +} diff --git a/src/Factory/DBFactory.php b/src/Factory/DBFactory.php index b4f0c9e3c1..f88dedafa8 100644 --- a/src/Factory/DBFactory.php +++ b/src/Factory/DBFactory.php @@ -16,16 +16,14 @@ class DBFactory * @param Profiler $profiler The profiler * @param array $server The $_SERVER variables * + * @return Database\IDatabase + * * @throws \Exception if connection went bad * * @todo refactor basedir during https://github.com/friendica/friendica/issues/6720 */ public static function init($basePath, Cache\IConfigCache $configCache, Profiler $profiler, array $server) { - if (Database\DBA::connected()) { - return; - } - $db_host = $configCache->get('database', 'hostname'); $db_user = $configCache->get('database', 'username'); $db_pass = $configCache->get('database', 'password'); @@ -51,11 +49,15 @@ class DBFactory $db_data = $server['MYSQL_DATABASE']; } - if (Database\DBA::connect($basePath, $configCache, $profiler, $db_host, $db_user, $db_pass, $db_data, $charset)) { + $database = new Database\MysqlDatabase($basePath, $configCache, $profiler, $db_host, $db_user, $db_pass, $db_data, $charset); + + if ($database->isConnected()) { // Loads DB_UPDATE_VERSION constant Database\DBStructure::definition($basePath, false); } unset($db_host, $db_user, $db_pass, $db_data, $charset); + + return $database; } } diff --git a/src/Factory/DependencyFactory.php b/src/Factory/DependencyFactory.php index 0f33e095bc..a096a2feb5 100644 --- a/src/Factory/DependencyFactory.php +++ b/src/Factory/DependencyFactory.php @@ -28,13 +28,13 @@ class DependencyFactory $configLoader = new Config\ConfigFileLoader($basePath, $mode); $configCache = Factory\ConfigFactory::createCache($configLoader); $profiler = Factory\ProfilerFactory::create($configCache); - Factory\DBFactory::init($basePath, $configCache, $profiler, $_SERVER); + $database = Factory\DBFactory::init($basePath, $configCache, $profiler, $_SERVER); $config = Factory\ConfigFactory::createConfig($configCache); // needed to call PConfig::init() Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create($channel, $config, $profiler); Factory\LoggerFactory::createDev($channel, $config, $profiler); - return new App($config, $mode, $router, $logger, $profiler, $isBackend); + return new App($config, $mode, $router, $logger, $profiler, $database, $isBackend); } }