new: [database] New MySQL data source added for debugging

- MySQLObserver datasource added - prepends all queries with the requested controller/action and user ID for better debugging
pull/5560/head
iglocska 2020-04-14 15:04:33 +02:00
parent 9d63e427e6
commit 4ded5a73c4
No known key found for this signature in database
GPG Key ID: BEA224F1FEF113AC
5 changed files with 34 additions and 11 deletions

View File

@ -123,7 +123,7 @@ class AppModel extends Model
public function isAcceptedDatabaseError($errorMessage, $dataSource)
{
$isAccepted = false;
if ($dataSource == 'Database/Mysql') {
if ($dataSource == 'Database/Mysql' || $dataSource == 'Database/MysqlObserver') {
$errorDuplicateColumn = 'SQLSTATE[42S21]: Column already exists: 1060 Duplicate column name';
$errorDuplicateIndex = 'SQLSTATE[42000]: Syntax error or access violation: 1061 Duplicate key name';
$errorDropIndex = "/SQLSTATE\[42000\]: Syntax error or access violation: 1091 Can't DROP '[\w]+'; check that column\/key exists/";
@ -722,7 +722,7 @@ class AppModel extends Model
$sqlArray[] = "ALTER TABLE taxonomy_predicates ADD colour varchar(7) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '';";
break;
case '2.4.60':
if ($dataSource == 'Database/Mysql') {
if ($dataSource == 'Database/Mysql' || $dataSource == 'Database/MysqlObserver') {
$sqlArray[] = 'CREATE TABLE IF NOT EXISTS `attribute_tags` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`attribute_id` int(11) NOT NULL,
@ -1595,7 +1595,7 @@ class AppModel extends Model
$dataSource = $dataSourceConfig['datasource'];
$this->Log = ClassRegistry::init('Log');
$indexCheckResult = array();
if ($dataSource == 'Database/Mysql') {
if ($dataSource == 'Database/Mysql' || $dataSource == 'Database/MysqlObserver') {
$indexCheck = "SELECT INDEX_NAME FROM INFORMATION_SCHEMA.STATISTICS WHERE table_schema=DATABASE() AND table_name='" . $table . "' AND index_name LIKE '" . $field . "%';";
$indexCheckResult = $this->query($indexCheck);
} elseif ($dataSource == 'Database/Postgres') {
@ -1603,7 +1603,7 @@ class AppModel extends Model
$indexCheckResult[] = array('STATISTICS' => array('INDEX_NAME' => $pgIndexName));
}
foreach ($indexCheckResult as $icr) {
if ($dataSource == 'Database/Mysql') {
if ($dataSource == 'Database/Mysql' || $dataSource == 'Database/MysqlObserver') {
$dropIndex = 'ALTER TABLE ' . $table . ' DROP INDEX ' . $icr['STATISTICS']['INDEX_NAME'] . ';';
} elseif ($dataSource == 'Database/Postgres') {
$dropIndex = 'DROP INDEX IF EXISTS ' . $icr['STATISTICS']['INDEX_NAME'] . ';';

View File

@ -0,0 +1,23 @@
<?php
App::uses('Mysql', 'Model/Datasource/Database');
/*
* Overrides the default MySQL database implementation to prepend all queries with debug comments
* - Lightweight and doesn't affect default operations, like a protoss observer it remains cloaked
* whilst trying to help detect potential bugs burrowed in our queries
*/
class MysqlObserver extends Mysql {
public function execute($sql, $options = array(), $params = array()) {
$comment = sprintf(
'%s%s%s',
empty(Configure::read('CurrentUserId')) ? '' : sprintf(
'[User: %s] ',
intval(Configure::read('CurrentUserId'))
),
empty(Configure::read('CurrentController')) ? '' : preg_replace('/[^a-zA-Z0-9_]/', '', Configure::read('CurrentController')) . ' :: ',
empty(Configure::read('CurrentAction')) ? '' : preg_replace('/[^a-zA-Z0-9_]/', '', Configure::read('CurrentAction')),
);
$sql = '/* ' . $comment . ' */ ' . $sql;
return parent::execute($sql, $options, $params);
}
}

View File

@ -154,7 +154,7 @@ class Log extends AppModel
$conditions['org'] = $org['Organisation']['name'];
}
$conditions['AND']['NOT'] = array('action' => array('login', 'logout', 'changepw'));
if ($dataSource == 'Database/Mysql') {
if ($dataSource == 'Database/Mysql' || $dataSource == 'Database/MysqlObserver') {
$validDates = $this->find('all', array(
'fields' => array('DISTINCT UNIX_TIMESTAMP(DATE(created)) AS Date', 'count(id) AS count'),
'conditions' => $conditions,

View File

@ -292,7 +292,7 @@ class Organisation extends AppModel
$success = true;
foreach ($this->organisationAssociations as $model => $data) {
foreach ($data['fields'] as $field) {
if ($dataSource == 'Database/Mysql') {
if ($dataSource == 'Database/Mysql' || $dataSource == 'Database/MysqlObserver') {
$sql = 'SELECT `id` FROM `' . $data['table'] . '` WHERE `' . $field . '` = "' . $currentOrg['Organisation']['id'] . '"';
} elseif ($dataSource == 'Database/Postgres') {
$sql = 'SELECT "id" FROM "' . $data['table'] . '" WHERE "' . $field . '" = "' . $currentOrg['Organisation']['id'] . '"';
@ -303,13 +303,13 @@ class Organisation extends AppModel
if (!empty($dataMoved['values_changed'][$model][$field])) {
$this->Log->create();
try {
if ($dataSource == 'Database/Mysql') {
if ($dataSource == 'Database/Mysql' || $dataSource == 'Database/MysqlObserver') {
$sql = 'UPDATE `' . $data['table'] . '` SET `' . $field . '` = ' . $targetOrg['Organisation']['id'] . ' WHERE `' . $field . '` = ' . $currentOrg['Organisation']['id'] . ';';
} elseif ($dataSource == 'Database/Postgres') {
$sql = 'UPDATE "' . $data['table'] . '" SET "' . $field . '" = ' . $targetOrg['Organisation']['id'] . ' WHERE "' . $field . '" = ' . $currentOrg['Organisation']['id'] . ';';
}
$result = $this->query($sql);
if ($dataSource == 'Database/Mysql') {
if ($dataSource == 'Database/Mysql' || $dataSource == 'Database/MysqlObserver') {
$sql = 'UPDATE `' . $data['table'] . '` SET `' . $field . '` = ' . $currentOrg['Organisation']['id'] . ' WHERE `id` IN (' . implode(',', $dataMoved['values_changed'][$model][$field]) . ');';
} elseif ($dataSource == 'Database/Postgres') {
$sql = 'UPDATE "' . $data['table'] . '" SET "' . $field . '" = ' . $currentOrg['Organisation']['id'] . ' WHERE "id" IN (' . implode(',', $dataMoved['values_changed'][$model][$field]) . ');';

View File

@ -4411,7 +4411,7 @@ class Server extends AppModel
public function dbSpaceUsage()
{
$dataSource = $this->getDataSource()->config['datasource'];
if ($dataSource == 'Database/Mysql') {
if ($dataSource == 'Database/Mysql' || $dataSource == 'Database/MysqlObserver') {
$sql = sprintf(
'select TABLE_NAME, sum((DATA_LENGTH+INDEX_LENGTH)/1024/1024) AS used, sum(DATA_FREE)/1024/1024 AS reclaimable from information_schema.tables where table_schema = %s group by TABLE_NAME;',
"'" . $this->getDataSource()->config['database'] . "'"
@ -4487,7 +4487,7 @@ class Server extends AppModel
'update_fail_number_reached' => $this->UpdateFailNumberReached(),
'indexes' => array()
);
if ($dataSource == 'Database/Mysql') {
if ($dataSource == 'Database/Mysql' || $dataSource == 'Database/MysqlObserver') {
$dbActualSchema = $this->getActualDBSchema();
$dbExpectedSchema = $this->getExpectedDBSchema();
if ($dbExpectedSchema !== false) {
@ -4645,7 +4645,7 @@ class Server extends AppModel
$dbActualSchema = array();
$dbActualIndexes = array();
$dataSource = $this->getDataSource()->config['datasource'];
if ($dataSource == 'Database/Mysql') {
if ($dataSource == 'Database/Mysql' || $dataSource == 'Database/MysqlObserver') {
$sqlGetTable = sprintf('SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema = %s;', "'" . $this->getDataSource()->config['database'] . "'");
$sqlResult = $this->query($sqlGetTable);
$tables = HASH::extract($sqlResult, '{n}.tables.TABLE_NAME');