Skip to content

Commit

Permalink
Add support for custom sql queries
Browse files Browse the repository at this point in the history
  • Loading branch information
gggeek committed Jul 22, 2014
1 parent 4a03d1e commit ef8afbb
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 4 deletions.
30 changes: 29 additions & 1 deletion classes/ezdbischemachecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ public function loadChecksFile( $fileName, $fileFormat )
public function checkSchema( $returnData=false )
{
$violations = array(
'FK' => array()
'FK' => array(),
'Other' => array()
);

foreach( $this->checks->getForeignKeys() as $def )
Expand All @@ -84,6 +85,21 @@ public function checkSchema( $returnData=false )
}
}

foreach( $this->checks->getQueries() as $def )
{
$violatingRows = $this->countCustomQuery( $def['sql'] );

if ( $violatingRows )
{
$def['violatingRowCount'] = $violatingRows;
if ( $returnData && $violatingRows )
{
$def['violatingRows'] = $this->checkCustomQuery( $def['sql'] );
}
$violations['Other'][] = $def;
}
}

return $violations;
}

Expand Down Expand Up @@ -167,6 +183,18 @@ public function getFKViolations( $childTable, $childCol, $parentTable, $parentCo
return $this->db->arrayQuery( $sql );
}

public function countCustomQuery( $sql )
{
$sql = 'SELECT COUNT(*) AS rows FROM ( ' . $sql . ') AS subquery';
$results = $this->db->arrayQuery( $sql );
return $results[0]['rows'];
}

public function checkCustomQuery( $sql )
{
return $this->db->arrayQuery( $sql );
}

public function getChecks()
{
return $this->checks;
Expand Down
16 changes: 16 additions & 0 deletions classes/ezdbischemachecks.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,18 @@
class ezdbiSchemaChecks
{
protected $FK = array();
protected $queries = array();

public function getForeignKeys()
{
return $this->FK;
}

public function getQueries()
{
return $this->queries;
}

public function addForeignKey( $childTable, $childCol, $parentTable, $parentCol, $filter=null, $name='' )
{
if ( $name != '' )
Expand All @@ -41,6 +47,16 @@ public function addForeignKey( $childTable, $childCol, $parentTable, $parentCol,
}
}

public function addQuery( $sql, $description, $longDesc='' /*, $expectedRows = 0*/ )
{
$this->queries[] = array(
'sql'=> $sql,
'description' => $description,
'longDesc' => $longDesc,
//'expectedRows' => $expectedRows
);
}

/**
* Adds checks from another set into this one
*
Expand Down
18 changes: 18 additions & 0 deletions classes/schemafileformat/ezdbiiniformat.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public function parseFile( $filename )
$ini = eZINI::instance( $filename );

$checks = new ezdbiSchemaChecks();

foreach( $ini->group( 'ForeignKeys' ) as $table => $value )
{
if ( !is_array( $value ) )
Expand All @@ -38,6 +39,12 @@ public function parseFile( $filename )
}
}
}

foreach( $ini->group( 'CustomQueries' ) as $name => $def )
{
$checks->addQuery( $def['sql'], str_replace( '_', ' ', $name ), @$def['description'] );
}

return $checks;
}

Expand All @@ -56,6 +63,17 @@ public function writeFile( $filename, ezdbiSchemaChecks $schemaDef )
$out .= $def['childTable'] . '[]=' . implode( $this->token, $defs ) . "\n";
}

$out .= "\n[CustomQueries]\n";
foreach( $schemaDef->getQueries() as $def )
{
$name = str_replace( ' ', '_', $def['description'] );
$out .= $name . '[sql]=' . str_replace( "\n", ' ', $def['sql'] ) . "\n";
if ( $def['longDesc'] != '' )
{
$out .= $name . '[description]=' . str_replace( "\n", ' ', $def['longDesc'] ) . "\n";
}
}

file_put_contents( $filename, $out );
}
}
Empty file.
3 changes: 3 additions & 0 deletions doc/changelogs/changelog-0.2-to-0.3
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
changelog from version 0.1 to 0.2 - released 2014.3.11

. added data validation for (some) attributes (aka datatypes)
8 changes: 7 additions & 1 deletion doc/todo
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

. start planning for the "bundle" version: load all field defs from services, use built-in validations etc...

. separate checks on data structure from checks on data


# attribute checking

Expand All @@ -20,7 +22,7 @@

. verify if there are more FKs than the ones we know about / some of the current ones to tweak

. add a module/view to display violations in GUI
. add a module/view to display violations in GUI (custom module in ggsysinfo)

. add per-ez-version inis for FKs and load those instead of generic one

Expand All @@ -37,3 +39,7 @@
# more checks

. check data in the db which must fit within ezini values, eg ezflow block types, max content versions, etc

. values we know must be unique but are not

. multi-column foreign keys
2 changes: 1 addition & 1 deletion extension.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<software>
<metadata>
<name>eZ DB Integrity extension</name>
<version>0.1</version>
<version>0.3</version>
<copyright>Copyright (C) 2014 Gaetano Giunta</copyright>
<license>GNU General Public License v2.0</license>
</metadata>
Expand Down
2 changes: 1 addition & 1 deletion ezinfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ static function info()
{
return array(
'Name' => "<a href=\"http://projects.ez.no/ezdbintegrity\">eZ DB Integrity extension</a>",
'Version' => "0.1",
'Version' => "0.3",
'Copyright' => "Copyright (C) 2014 Gaetano Giunta",
'License' => "GNU General Public License v2.0"
);
Expand Down
10 changes: 10 additions & 0 deletions settings/ezdbintegrity.ini
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,13 @@ ezworkflow_process[]=memento_key::ezoperation_memento::memento_key
ezworkflow_process[]=user_id::ezuser::contentobject_id
ezworkflow_process[]=workflow_id::ezworkflow::id
ezx_mbpaex[]=contentobject_id::ezcontentobject::id

[CustomQueries]
urlaliases_without_nodes[sql]=SELECT parent, text_md5, action FROM ezurlalias_ml WHERE ACTION_TYPE = 'eznode' AND is_original = 1 AND substr(action, 8) NOT IN ( SELECT node_id from ezcontentobject_tree )
nodes_without_urlaliases[sql]=SELECT node_id FROM ezcontentobject_tree WHERE depth > 0 AND node_id NOT IN ( SELECT distinct(substr(action, 8)) as node FROM ezurlalias_ml WHERE ACTION_TYPE = 'eznode' AND is_original = 1 );
objects_with_many_published_versions[sql]=SELECT contentobject_id, count(*) FROM ezcontentobject_version WHERE status = 1 GROUP BY contentobject_id HAVING COUNT(*) > 1
ezflow_blocks_with_invalid_zones[sql]=SELECT * FROM ezm_block WHERE zone_id NOT IN ( SELECT DISTINCT ( SUBSTRING( a.data_text, LOCATE( '<zone id="id_', a.data_text ) +13, 32 ) ) AS existing_zone_id FROM ezcontentobject_attribute a, ezcontentobject_version v WHERE a.version = v.version AND a.contentobject_id = v.contentobject_id AND a.data_type_string = 'ezpage' )
nodes_with_wrong_depth[sql]=SELECT c.node_id FROM ezcontentobject_tree c, ezcontentobject_tree p WHERE c.parent_node_id = p.node_id AND c.depth != ( p.depth + 1 ) AND c.node_id != 1
objects_with_multiple_main_nodes[sql]=SELECT id, COUNT(DISTINCT main_node_id) FROM o, ezcontentobject_tree n WHERE o.id = n.contentobject_id GROUP BY id, main_node_id HAVING COUNT(DISTINCT main_node_id) > 1
related_nodes_with_different_objects[sql]=SELECT main_node_id, COUNT(DISTINCT contentobject_id) FROM ezcontentobject_tree GROUP BY main_node_id HAVING COUNT(DISTINCT contentobject_id) > 1
visible_but_hidden_nodes[sql]=SELECT node_id, is_hidden, is_invisible FROM ezcontentobject_tree WHERE is_hidden=1 AND is_invisible=0

0 comments on commit ef8afbb

Please sign in to comment.