aboutsummaryrefslogtreecommitdiff
path: root/lib/Minz/ModelPdo.php
diff options
context:
space:
mode:
authorGravatar Alexandre Alapetite <alexandre@alapetite.fr> 2019-09-29 16:22:50 +0200
committerGravatar GitHub <noreply@github.com> 2019-09-29 16:22:50 +0200
commite3e5954394f4523850c78e80e496f1b916622677 (patch)
tree2e20d9091735e1da1de85e273e19635f58111e0f /lib/Minz/ModelPdo.php
parentec4307c1a64a0f60648fdd7d0a2eb819bbf12965 (diff)
PDO refactoring for code simplification (#2522)
* PDO refactor * Automatic prefix when using the syntax `_tableName` * Uniformity: MySQL is now PDO::ATTR_EMULATE_PREPARES = false just like SQLite and PostgreSQL, with consequences such as only one statement per query * Use PDO methods exec(), query(), prepare() + execute() in a more efficient way * Remove auto-update SQL code for versions older than FreshRSS 1.5 (3 years old) * The name of the default category is set in PHP instead of in the DB (simplies SQL and allows changing the name according to the FreshRSS language) * Rename `->bd` to `->pdo` (less of a frenshism, and more informative) * Fix some requests, which were not compatible with MySQL prepared statements * Whitespace * Fix syntax for PostgreSQL sequences + MySQL install * Minor formatting * Fix lastInsertId for PostgreSQL * Use PHP 5.6+ const Take advantage of https://github.com/FreshRSS/FreshRSS/pull/2527 https://www.php.net/manual/en/migration56.new-features.php * A bit of forgotten PHP 5.6 simplification for cURL * Forgotten $s * Mini fix custom user config https://github.com/FreshRSS/FreshRSS/pull/2490/files#r326290346 * More work on install.php but not finished * install.php working * More cleaning of PDO in install * Even more simplification Take advantage of PDO->exec() to run multiple statements * Disallow changing the name of the default category https://github.com/FreshRSS/FreshRSS/pull/2522#discussion_r326967724
Diffstat (limited to 'lib/Minz/ModelPdo.php')
-rw-r--r--lib/Minz/ModelPdo.php132
1 files changed, 77 insertions, 55 deletions
diff --git a/lib/Minz/ModelPdo.php b/lib/Minz/ModelPdo.php
index 4d5e47da9..3fabb73c8 100644
--- a/lib/Minz/ModelPdo.php
+++ b/lib/Minz/ModelPdo.php
@@ -6,45 +6,35 @@
/**
* La classe Model_sql représente le modèle interragissant avec les bases de données
- * Seul la connexion MySQL est prise en charge pour le moment
*/
class Minz_ModelPdo {
/**
* Partage la connexion à la base de données entre toutes les instances.
*/
- public static $useSharedBd = true;
- private static $sharedBd = null;
+ public static $usesSharedPdo = true;
+ private static $sharedPdo = null;
private static $sharedPrefix;
private static $sharedCurrentUser;
- /**
- * $bd variable représentant la base de données
- */
- protected $bd;
-
+ protected $pdo;
protected $current_user;
- protected $prefix;
/**
* Créé la connexion à la base de données à l'aide des variables
* HOST, BASE, USER et PASS définies dans le fichier de configuration
*/
- public function __construct($currentUser = null, $currentPrefix = null, $currentDb = null) {
+ public function __construct($currentUser = null, $currentPdo = null) {
if ($currentUser === null) {
$currentUser = Minz_Session::param('currentUser');
}
- if ($currentPrefix !== null) {
- $this->prefix = $currentPrefix;
- }
- if ($currentDb != null) {
- $this->bd = $currentDb;
+ if ($currentPdo != null) {
+ $this->pdo = $currentPdo;
return;
}
- if (self::$useSharedBd && self::$sharedBd != null &&
- ($currentUser == null || $currentUser === self::$sharedCurrentUser)) {
- $this->bd = self::$sharedBd;
- $this->prefix = self::$sharedPrefix;
+ if (self::$usesSharedPdo && self::$sharedPdo != null &&
+ ($currentUser == '' || $currentUser === self::$sharedCurrentUser)) {
+ $this->pdo = self::$sharedPdo;
$this->current_user = self::$sharedCurrentUser;
return;
}
@@ -54,35 +44,39 @@ class Minz_ModelPdo {
$conf = Minz_Configuration::get('system');
$db = $conf->db;
- $driver_options = isset($conf->db['pdo_options']) && is_array($conf->db['pdo_options']) ? $conf->db['pdo_options'] : array();
+ $driver_options = isset($db['pdo_options']) && is_array($db['pdo_options']) ? $db['pdo_options'] : [];
$dbServer = parse_url('db://' . $db['host']);
+ $dsn = '';
try {
switch ($db['type']) {
case 'mysql':
- $string = 'mysql:host=' . (empty($dbServer['host']) ? $db['host'] : $dbServer['host']) . ';dbname=' . $db['base'] . ';charset=utf8mb4';
+ $dsn = 'mysql:host=' . (empty($dbServer['host']) ? $db['host'] : $dbServer['host']) . ';charset=utf8mb4';
+ if (!empty($db['base'])) {
+ $dsn .= ';dbname=' . $db['base'];
+ }
if (!empty($dbServer['port'])) {
- $string .= ';port=' . $dbServer['port'];
+ $dsn .= ';port=' . $dbServer['port'];
}
$driver_options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES utf8mb4';
- $this->prefix = $db['prefix'] . $currentUser . '_';
- $this->bd = new MinzPDOMySql($string, $db['user'], $db['password'], $driver_options);
- $this->bd->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
+ $this->pdo = new MinzPDOMySql($dsn, $db['user'], $db['password'], $driver_options);
+ $this->pdo->setPrefix($db['prefix'] . $currentUser . '_');
break;
case 'sqlite':
- $string = 'sqlite:' . join_path(DATA_PATH, 'users', $currentUser, 'db.sqlite');
- $this->prefix = '';
- $this->bd = new MinzPDOSQLite($string, $db['user'], $db['password'], $driver_options);
- $this->bd->exec('PRAGMA foreign_keys = ON;');
+ $dsn = 'sqlite:' . join_path(DATA_PATH, 'users', $currentUser, 'db.sqlite');
+ $this->pdo = new MinzPDOSQLite($dsn, $db['user'], $db['password'], $driver_options);
+ $this->pdo->setPrefix('');
break;
case 'pgsql':
- $string = 'pgsql:host=' . (empty($dbServer['host']) ? $db['host'] : $dbServer['host']) . ';dbname=' . $db['base'];
+ $dsn = 'pgsql:host=' . (empty($dbServer['host']) ? $db['host'] : $dbServer['host']);
+ if (!empty($db['base'])) {
+ $dsn .= ';dbname=' . $db['base'];
+ }
if (!empty($dbServer['port'])) {
- $string .= ';port=' . $dbServer['port'];
+ $dsn .= ';port=' . $dbServer['port'];
}
- $this->prefix = $db['prefix'] . $currentUser . '_';
- $this->bd = new MinzPDOPGSQL($string, $db['user'], $db['password'], $driver_options);
- $this->bd->exec("SET NAMES 'UTF8';");
+ $this->pdo = new MinzPDOPGSQL($dsn, $db['user'], $db['password'], $driver_options);
+ $this->pdo->setPrefix($db['prefix'] . $currentUser . '_');
break;
default:
throw new Minz_PDOConnectionException(
@@ -91,69 +85,86 @@ class Minz_ModelPdo {
);
break;
}
- self::$sharedBd = $this->bd;
- self::$sharedPrefix = $this->prefix;
+ self::$sharedPdo = $this->pdo;
} catch (Exception $e) {
throw new Minz_PDOConnectionException(
- $string,
+ $dsn,
$db['user'], Minz_Exception::ERROR
);
}
}
public function beginTransaction() {
- $this->bd->beginTransaction();
+ $this->pdo->beginTransaction();
}
public function inTransaction() {
- return $this->bd->inTransaction();
+ return $this->pdo->inTransaction();
}
public function commit() {
- $this->bd->commit();
+ $this->pdo->commit();
}
public function rollBack() {
- $this->bd->rollBack();
+ $this->pdo->rollBack();
}
public static function clean() {
- self::$sharedBd = null;
+ self::$sharedPdo = null;
self::$sharedCurrentUser = '';
- self::$sharedPrefix = '';
}
}
abstract class MinzPDO extends PDO {
- private static function check($statement) {
+ public function __construct($dsn, $username = null, $passwd = null, $options = null) {
+ parent::__construct($dsn, $username, $passwd, $options);
+ $this->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
+ }
+
+ abstract public function dbType();
+
+ private $prefix = '';
+ public function prefix() { return $this->prefix; }
+ public function setPrefix($prefix) { $this->prefix = $prefix; }
+
+ private function autoPrefix($sql) {
+ return str_replace('`_', '`' . $this->prefix, $sql);
+ }
+
+ protected function preSql($statement) {
if (preg_match('/^(?:UPDATE|INSERT|DELETE)/i', $statement)) {
invalidateHttpCache();
}
+ return $this->autoPrefix($statement);
}
- protected function compatibility($statement) {
- return $statement;
+ public function lastInsertId($name = null) {
+ if ($name != null) {
+ $name = $this->preSql($name);
+ }
+ return parent::lastInsertId($name);
}
- abstract public function dbType();
-
public function prepare($statement, $driver_options = array()) {
- MinzPDO::check($statement);
- $statement = $this->compatibility($statement);
+ $statement = $this->preSql($statement);
return parent::prepare($statement, $driver_options);
}
public function exec($statement) {
- MinzPDO::check($statement);
- $statement = $this->compatibility($statement);
+ $statement = $this->preSql($statement);
return parent::exec($statement);
}
public function query($statement) {
- MinzPDO::check($statement);
- $statement = $this->compatibility($statement);
+ $statement = $this->preSql($statement);
return parent::query($statement);
}
}
class MinzPDOMySql extends MinzPDO {
+ public function __construct($dsn, $username = null, $passwd = null, $options = null) {
+ parent::__construct($dsn, $username, $passwd, $options);
+ $this->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
+ }
+
public function dbType() {
return 'mysql';
}
@@ -164,6 +175,11 @@ class MinzPDOMySql extends MinzPDO {
}
class MinzPDOSQLite extends MinzPDO {
+ public function __construct($dsn, $username = null, $passwd = null, $options = null) {
+ parent::__construct($dsn, $username, $passwd, $options);
+ $this->exec('PRAGMA foreign_keys = ON;');
+ }
+
public function dbType() {
return 'sqlite';
}
@@ -174,11 +190,17 @@ class MinzPDOSQLite extends MinzPDO {
}
class MinzPDOPGSQL extends MinzPDO {
+ public function __construct($dsn, $username = null, $passwd = null, $options = null) {
+ parent::__construct($dsn, $username, $passwd, $options);
+ $this->exec("SET NAMES 'UTF8';");
+ }
+
public function dbType() {
return 'pgsql';
}
- protected function compatibility($statement) {
+ protected function preSql($statement) {
+ $statement = parent::preSql($statement);
return str_replace(array('`', ' LIKE '), array('"', ' ILIKE '), $statement);
}
}