Repairing dropped index during compare schemas on sqlitewriter
--------------------------------------------------------------

                 Key: ZETACOMP-107
                 URL: https://issues.apache.org/jira/browse/ZETACOMP-107
             Project: Zeta Components
          Issue Type: Improvement
          Components: DatabaseSchema
         Environment: Ubuntu Natty
PHP 5.3.6
SimpleTest
            Reporter: Suwandi Tanuwijaya
            Priority: Critical


I need improvement of this component since implementation of sqlitewriter has 
been trying to emulate ALTER FIELD ( Sqlite had not native syntax to achieve 
this ).
ezcDbSchemaComparator component emulate this altering field with this logic:
  * reading the schema of changed table
  * create temporary table, and then copy data of the changed table to temporary
  * drop the original change table
  * create new schema of the original table with modified schema
  * transfer back the data from temporary to the new one

Unfortunately, this logic forgot to restore indexes that attached to the table.

And, testingApply1 on ezcDatabaseSchemaGenericDiffTest should be failed because 
some index was not found.

So, I need improvement ( or bug fixes, depends on your point of view ) of this 
database schema components.

My quickhacked is, put repairingDroppedIndex function on dbschema writer, on 
this case Sqlitewriter. This function reads the index structure using pragma 
method. I bound this function on applyDiffToDb method on 
ezcDbSchemaSqliteWriter.

The idea is, to put DDL ( with repairing dropped index sql syntax on it ) 
before the loop. 
And, for this purpose, I modify the index naming by default to include its 
table name with underscore ( tablename_indexname ) to avoid clashes with other 
same naming index ( instead of. just _pri for primary index ) .

The Complete of my quickhacked code is:

repairedDroppedIndex method:
{{{
protected function repaireDroppedIndex( Abstraction\PdoHandler $db, $schemas, 
$tableName )
    {
        $indexes = $this->generateIndexFromPragmaSql( $db, $tableName );
        if( count( $indexes ) > 0 )
        {
            foreach( $indexes as $indexName => $indexDefinition )
            {
                $query = $this->generateDropIndexSql( $tableName, $indexName );
                $schemas [] = $query;
                
                $needle = array( 'CREATE INDEX ', 'CREATE UNIQUE INDEX ' );
                $replace = array( 'CREATE INDEX IF NOT EXISTS ', 'CREATE UNIQUE 
INDEX IF NOT EXISTS ' ); 
                
                $query = str_replace( $needle, $replace, 
$this->generateAddIndexSql( $tableName, $indexName, $indexDefinition ));
                $schemas [] = $query;
            }
        }
        
        return $schemas;
    }
}}}

generateIndexFromPragmaSql method:
{{{
protected function generateIndexFromPragmaSql( Abstraction\PdoHandler $db, 
$tableName )
    {
        $query = 'PRAGMA INDEX_LIST (\''.$tableName.'\');';
        $statement = $db->query( $query );
        $statement->setFetchMode( \PDO::FETCH_ASSOC );
        $resultArray = $statement->fetchAll();
        
        $indexes = array();
        $indexFields = array();
        foreach( $resultArray as $key => $index )
        {
            $query = 'PRAGMA INDEX_INFO (\''.$index['name'].'\');';
            $indexArray = $db->query( $query );
            $indexArray->setFetchMode( \PDO::FETCH_ASSOC );
            
            foreach( $indexArray as $dummy => $indexField )
            {
                $indexFields [$indexField['name']] = new 
Entity\DbSchemaIndexField();
            }
            
            $primary = FALSE;
            if( strstr( $index['name'], '_pri') ) $primary = TRUE;
            
            $unique = FALSE;
            if( $index['unique'] === '1' OR $index['unique'] === TRUE ) $unique 
= TRUE;
            
            $indexes[$index['name']] = new Entity\DbSchemaIndex(
                $indexFields, $primary, $unique
            );
        }
        
        return $indexes;
    }
}}}

and modified applyDiffToDb method:
{{{
...

        $schemas = $this->convertDiffToDDL( $dbSchemaDiff );
        
        foreach( $schemas as $query )
        {
            if( strstr( $query, 'DROP COLUMN' ) )
            {
                preg_match( '@ALTER TABLE (.*) DROP COLUMN (.*)@', $query, 
$matches );
                if( ! $matches ) throw new 
Entity\DbSchemaSqliteDropFieldException( 
                'Can\'t fetch field for droping from SQL query: '.$query );
                        
                $tableName = trim( $matches[1], "'" );
                $schemas = $this->repaireDroppedIndex( $db, $schemas, 
$tableName );
            }
            elseif( strstr( $query, 'CHANGE' ) )
            {
                preg_match( '@ALTER TABLE (.*) CHANGE (.*?) (.*?) (.*)@', 
$query, $matches );
                if( ! $matches ) throw new 
Entity\DbSchemaSqliteDropFieldException( 
                'Can\'t fetch field for droping from SQL query: '.$query );
                
                $tableName = trim( $matches[1], "'" );
                $schemas = $this->repaireDroppedIndex( $db, $schemas, 
$tableName );
            }
        }

/* and so on  */
...
}}}




--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: 
https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

Reply via email to