Skip to content
Snippets Groups Projects
Commit 5424a9c8 authored by Laurent Lecluse's avatar Laurent Lecluse
Browse files

On retire le BddCheck de BddAdmin : trop dépendant de OSE

parent 18e1271f
Branches
Tags
1 merge request!55Ll bug report services
<?php
namespace BddAdmin;
class BddCheck
{
use BddAwareTrait;
/**
* @var array
*/
private $errors;
/**
* PHP 5 allows developers to declare constructor methods for classes.
* Classes which have a constructor method call this method on each newly-created object,
* so it is suitable for any initialization that the object may need before it is used.
*
* Note: Parent constructors are not called implicitly if the child class defines a constructor.
* In order to run a parent constructor, a call to parent::__construct() within the child constructor is required.
*
* param [ mixed $args [, $... ]]
*
* @return void
* @link http://php.net/manual/en/language.oop5.decon.php
*/
public function __construct(Bdd $bdd = null)
{
if ($bdd) {
$this->bdd = $bdd;
}
}
public function check(array $rules = null)
{
$this->errors = [];
if (null === $rules) {
$rules = [];
$rs = scandir(__DIR__ . '/BddCheck');
foreach ($rs as $rule) {
if (!in_array($rule, ['.', '..', 'BddCheckRule.php'])) {
$rules[] = substr($rule, 0, -4);
}
}
}
foreach ($rules as $rule) {
$className = 'BddAdmin\\BddCheck\\' . $rule;
$rule = new $className($this);
$ds = $this->bdd->select($rule->sql());
foreach ($ds as $d) {
foreach ($d as $k => $v) {
$property = '';
$chars = str_split($k);
$last_ = false;
foreach ($chars as $c) {
if ('_' != $c) {
if ($last_) {
$property .= strtoupper($c);
} else {
$property .= strtolower($c);
}
}
$last_ = ('_' == $c);
}
$rule->$property = $v;
}
$rule->check();
}
}
return $this->errors;
}
public function addError($table, $column, array $error)
{
if (!isset($this->errors[$table][$column])) {
$this->errors[$table][$column] = [];
}
$this->errors[$table][$column][] = $error;
return $this;
}
}
\ No newline at end of file
<?php
namespace BddAdmin\BddCheck;
use BddAdmin\BddCheck;
abstract class BddCheckRule
{
public $tableName;
public $columnName;
/**
* @var BddCheck
*/
private $collector;
/**
* PHP 5 allows developers to declare constructor methods for classes.
* Classes which have a constructor method call this method on each newly-created object,
* so it is suitable for any initialization that the object may need before it is used.
*
* Note: Parent constructors are not called implicitly if the child class defines a constructor.
* In order to run a parent constructor, a call to parent::__construct() within the child constructor is required.
*
* param [ mixed $args [, $... ]]
*
* @return void
* @link http://php.net/manual/en/language.oop5.decon.php
*/
public function __construct(BddCheck $collector)
{
$this->collector = $collector;
}
/**
* @return string
*/
abstract public function sql();
abstract public function check();
protected function error($error, $sqlRes = null)
{
$rule = str_replace('BddAdmin\\BddCheck\\', '', get_class($this));
$this->collector->addError($this->tableName, $this->columnName, compact('rule', 'error', 'sqlRes'));
}
}
\ No newline at end of file
<?php
namespace BddAdmin\BddCheck;
class ForeignSansIndex extends BddCheckRule
{
public $nullable;
public $consNormName;
public $constraintName;
public $status;
public $cols;
public function sql()
{
return "
WITH fks AS (
SELECT
c.constraint_name,
c.table_name,
c.status,
cc.column_name,
listagg(cc.column_name, ',') WITHIN GROUP (ORDER BY cc.column_name) OVER (PARTITION BY cc.constraint_name) cols
FROM
user_constraints c
JOIN user_cons_columns cc ON cc.constraint_name = c.constraint_name
WHERE
c.index_name IS NULL AND c.constraint_type = 'R'
), inds as (
SELECT
i.*,
listagg(ic.column_name, ',') WITHIN GROUP (ORDER BY ic.column_name) OVER (PARTITION BY ic.index_name) cols
FROM
USER_INDEXES i
JOIN user_ind_columns ic ON ic.index_name = i.index_name
)
SELECT
fks.*, inds.index_name
FROM
fks
LEFT JOIN inds ON inds.table_name = fks.table_name AND inds.cols = fks.cols";
}
public function check()
{
if (!$this->indexName) {
$this->error('Pas d\'index',
"CREATE INDEX $this->constraintName ON $this->tableName($this->cols ASC);"
);
return;
}
if ($this->indexName != $this->constraintName) {
$this->error(
'Index à renommer',
"ALTER INDEX $this->indexName RENAME TO $this->constraintName;"
);
}
}
}
\ No newline at end of file
<?php
namespace BddAdmin\BddCheck;
class IndexOrphelins extends BddCheckRule
{
public $nullable;
public $consNormName;
public $constraintName;
public $status;
public $cols;
public function sql()
{
return "
SELECT
I.TABLE_NAME,
I.INDEX_NAME,
C.CONSTRAINT_NAME
FROM
USER_INDEXES I
LEFT JOIN USER_CONSTRAINTS C ON C.CONSTRAINT_NAME = I.INDEX_NAME
WHERE
C.CONSTRAINT_NAME IS NULL
AND I.INDEX_TYPE = 'NORMAL'
AND I.INDEX_NAME NOT IN (
'CC_ACTIVITE_FI', 'CC_ACTIVITE_FA', 'CC_ACTIVITE_FC', 'CC_ACTIVITE_REF',
'TYPE_RESSOURCE_FI', 'TYPE_RESSOURCE_FA', 'TYPE_RESSOURCE_FC', 'TYPE_RESSOURCE_REF',
'INTERVENANT_NOM_PATRONYMIQUE', 'INTERVENANT_NOM_USUEL', 'INTERVENANT_PRENOM', 'INTERVENANT_RECHERCHE',
'INTERVENANT_CODE', 'FORMULE_RESULTAT_TYPE_INT', 'TBL_NOEUD_ANNEE_IDX', 'TBL_NOEUD_ETAPE_IDX', 'TBL_NOEUD_GTF_IDX',
'TBL_NOEUD_NETAPE_IDX', 'TBL_NOEUD_NOEUD_IDX', 'TBL_NOEUD_STRUCTURE_IDX', 'TBL_LIEN_ACTIF'
)
ORDER BY
I.INDEX_NAME
";
}
public function check()
{
$this->error("Index $this->indexName Orphelin");
}
}
\ No newline at end of file
<?php
namespace BddAdmin\BddCheck;
class RefsSansCles extends BddCheckRule
{
public $nullable;
public $consNormName;
public $constraintName;
public $status;
public $cols;
public function sql()
{
return "
with cc as (
SELECT
cc.column_name,
c.table_name,
c.constraint_name
FROM
user_cons_columns cc
JOIN user_constraints c ON c.constraint_name = cc.constraint_name AND c.constraint_type = 'R'
)
select
tc.table_name,
tc.column_name
from
user_tables t
JOIN user_tab_cols tc ON tc.table_name = t.table_name
LEFT JOIN cc ON cc.column_name = tc.column_name AND cc.table_name = tc.table_name
LEFT JOIN user_mviews mv ON mv.mview_name = t.table_name
where
tc.column_name like '%_ID'
AND cc.constraint_name IS NULL
AND mv.mview_name IS NULL
";
}
public function check()
{
$this->error('Clé étrangère manquante');
}
}
\ No newline at end of file
<?php
namespace BddAdmin\BddCheck;
class SourceCode extends BddCheckRule
{
public $nullable;
public $consNormName;
public $constraintName;
public $status;
public $cols;
public function sql()
{
return "
WITH fks AS (
SELECT
c.constraint_name,
c.table_name,
c.status,
cc.column_name,
listagg(cc.column_name, ',') WITHIN GROUP (ORDER BY cc.column_name) OVER (PARTITION BY cc.constraint_name) cols
FROM
user_constraints c
JOIN user_cons_columns cc ON cc.constraint_name = c.constraint_name
WHERE
c.constraint_type = 'U'
)
SELECT
t.table_name,
tc.column_name,
tc.nullable,
substr(t.table_name,1,30-10) || '_SOURCE_UN' cons_norm_name,
fks.constraint_name,
fks.status,
cols
FROM
user_tables t
JOIN user_tab_cols tc ON tc.table_name = t.table_name
LEFT JOIN fks ON fks.table_name = t.table_name AND fks.column_name = tc.column_name
WHERE
tc.column_name = 'SOURCE_CODE'
AND t.table_name NOT IN ('SYNC_LOG')
AND t.table_name NOT LIKE 'MV_%'
ORDER BY
t.table_name
";
}
public function check()
{
if (!$this->constraintName) {
$this->error('Pas de contrainte d\'unicité');
return;
}
if ('Y' == $this->nullable) {
//$this->error('Le champ est obligatoire');
}
if ($this->consNormName != $this->constraintName) {
$this->error(
'Contrainte d\'unicité mal nommée',
"ALTER TABLE {$this->tableName} RENAME CONSTRAINT {$this->constraintName} TO {$this->consNormName};"
);
}
if (!in_array($this->cols, [
'ANNEE_ID,HISTO_DESTRUCTION,SOURCE_CODE',
'HISTO_DESTRUCTION,SOURCE_CODE'
])) {
$this->error("Il manque des colonnes pour la contrainte (trouvées : {$this->cols})");
}
{
if ($this->status != 'ENABLED') {
$this->error('Contrainte d\'unicité désactivée');
}
}
}
}
\ No newline at end of file
<?php
namespace BddAdmin\BddCheck;
class SourceId extends BddCheckRule
{
public $nullable;
public $consNormName;
public $constraintName;
public $rConstraintName;
public $deleteRule;
public $status;
public function sql()
{
return "
WITH fks AS (
SELECT
c.constraint_name,
c.table_name,
c.r_constraint_name,
c.delete_rule,
c.status,
cc.column_name
FROM
user_constraints c
JOIN user_cons_columns cc ON cc.constraint_name = c.constraint_name
WHERE
c.constraint_type = 'R'
)
SELECT
t.table_name,
tc.column_name,
tc.nullable,
substr(t.table_name,1,30-10) || '_SOURCE_FK' cons_norm_name,
fks.constraint_name,
fks.r_constraint_name,
fks.delete_rule,
fks.status
FROM
user_tables t
JOIN user_tab_cols tc ON tc.table_name = t.table_name
LEFT JOIN fks ON fks.table_name = t.table_name AND fks.column_name = tc.column_name
WHERE
tc.column_name = 'SOURCE_ID'
ORDER BY
t.table_name
";
}
public function check()
{
if (!$this->constraintName) {
$this->error('Pas de clé étrangère');
return;
}
if ('Y' == $this->nullable){
$this->error('Le champ n\'est pas obligatoire');
}
if ($this->consNormName != $this->constraintName){
$this->error(
'Contrainte mal nommée',
"ALTER TABLE {$this->tableName} RENAME CONSTRAINT {$this->constraintName} TO {$this->consNormName};"
);
}
if ($this->deleteRule != 'NO ACTION'){
$this->error('Règle de destruction à positionner sur "RESTRICT"');
}
if ($this->status != 'ENABLED'){
$this->error('Contrainte désactivée');
}
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment