Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Support for a customized schema merge #798

Open
NobleUplift opened this Issue Dec 2, 2013 · 3 comments

Comments

Projects
None yet
3 participants

Say I have this schema.xml:

<?xml version="1.0" encoding="utf-8"?>
<!--Autogenerated by PropelSchemaReverseTask class.-->
<database name="test" defaultIdMethod="native">
  <table name="user" phpName="User" idMethod="native">
    <column name="id" phpName="Id" type="INTEGER" primaryKey="true" required="true"/>
    <column name="parent_user_id" phpName="ParentUserId" type="INTEGER" required="true"/>
    <column name="name" phpName="Name" type="VARCHAR" size="45" required="true"/>
    <column name="description" phpName="Description" type="VARCHAR" size="45" required="true"/>
    <column name="user_class_id" phpName="UserClassId" type="INTEGER" required="true"/>
    <foreign-key foreignTable="user_class" name="fk_user_has_class">
      <reference local="user_class_id" foreign="id"/>
    </foreign-key>
    <foreign-key foreignTable="user" name="fk_user_has_parent" phpName="ParentUser">
      <reference local="parent_user_id" foreign="id"/>
    </foreign-key>
    <index name="fk_user_has_parent_idx">
      <index-column name="parent_user_id"/>
    </index>
    <index name="fk_user_has_class_idx">
      <index-column name="user_class_id"/>
    </index>
    <vendor type="mysql">
      <parameter name="Engine" value="InnoDB"/>
    </vendor>
  </table>
  <table name="user_class" phpName="UserClass" idMethod="native">
    <column name="id" phpName="Id" type="INTEGER" primaryKey="true" required="true"/>
    <column name="name" phpName="Name" type="VARCHAR" size="45" required="true"/>
    <column name="permissions" phpName="Permissions" type="VARCHAR" size="45" required="true"/>
    <vendor type="mysql">
      <parameter name="Engine" value="InnoDB"/>
    </vendor>
  </table>
</database>

Propel should then generate a custom.xml such as this:

<?xml version="1.0" encoding="utf-8"?>
<!--Autogenerated by PropelSchemaReverseTask class.-->
<database name="test">
  <table name="user">
    <column name="id" />
    <column name="parent_user_id" lazyLoad="true" />
    <column name="name" lazyLoad="true" />
    <column name="description" lazyLoad="true" />
    <column name="user_class_id" lazyLoad="true" />
    <foreign-key name="fk_user_has_class" phpName="UserClass" />
    <foreign-key name="fk_user_has_parent" phpName="ParentUser" />
    <index name="fk_user_has_parent_idx">
      <index-column name="parent_user_id"/>
    </index>
    <index name="fk_user_has_class_idx">
      <index-column name="user_class_id"/>
    </index>
  </table>
  <table name="user_class" phpName="UserClass" idMethod="native">
    <column name="id" />
    <column name="name" lazyLoad="true" />
    <column name="permissions" lazyLoad="true" />
    <vendor type="mysql">
      <parameter name="Engine" value="InnoDB"/>
    </vendor>
  </table>
</database>

When attributes are added to custom.xml, they will be merged into schema.xml. For instance, the user table will now have getParentUser() and getUserClass() methods because the phpName columns were merged.

This is my first try at a merge script:

$file1 = 'schema.xml';
$file2 = 'custom.xml';
$xml1 = simplexml_load_file( $file1 );
$xml2 = simplexml_load_file( $file2 );  // loop through the FOO and add them and their attributes to xml1

/* @var $xml2Table SimpleXMLElement */
foreach( $xml2->children() as $xml2Table ) {
    /*
     * Find the table in custom.xml that corresponds to schema.xml
     */

    /* @var $table SimpleXMLElement */
    $table = null;
    /* @var $xml1Table SimpleXMLElement */
    foreach ($xml1->children() as $xml1Table) {
        $xml1TableName = $xml1Table->attributes()['name']->__toString();
        $xml2TableName = $xml2Table->attributes()['name']->__toString();
        if ($xml1TableName == $xml2TableName) {
            $table = $xml1Table;
            break;
        }
    }

    if ($table == null) {
        echo "Skipping table $xml2TableName, not found in schema.\n";
        continue;
    }

    /*
     * Now that we found the table in schema.xml, find the right column
     */

    /* @var $xml2Column SimpleXMLElement */
    foreach( $xml2Table->children() as $xml2Column ) {
        /* @var $column SimpleXMLElement */
        $column = null;
        foreach ($table->children() as $xml1Column) {
            $xml1ColumnName = $xml1Column->attributes()['name']->__toString();
            $xml2ColumnName = $xml2Column->attributes()['name']->__toString();

            if ($xml1ColumnName == $xml2ColumnName) {
                $column = $xml1Column;
                break;
            }
        }

        if ($column == null) {
            echo "Skipping column $xml2ColumnName, not found in schema.\n";
            continue;
        }

        foreach ($xml2Column->attributes() as $key => $value) {
            @$column->addAttribute($key, $value);
        }
    }
}
$fh = fopen( $file1, 'w') or die ( "Cannot write to file $file1" );
fwrite( $fh, $xml1->asXML() );
fclose( $fh );

It would be great if Propel generated the custom.xml for me and added the merge to the reverse or om task, because otherwise it's a lot of work.

Owner

marcj commented Dec 2, 2013

I don't get the point here. Why should Propel generate a custom.xml that contains less information? I don't see any merging here from schema.xml to custom.xml, only information omission. Why should Propel do this? I don't see a advantage or even a purpose. Maybe its just me, but I don't understand this issue at all. Perhaps you can describe in more words what the purpose is of this "conversion".

Member

staabm commented Dec 2, 2013

what do you try to achieve?

You can already have several schema files to group things e.g. by package, see http://propelorm.org/cookbook/multi-component-data-model.html

Generate the above schema.xml and you will find that it only has getParentUserId() and getUserClassId(), it is missing getParentUser() and getUserClass() methods. Either the phpName attribute needs to be manually added to each foreign key, or you can add it with a custom script like I did.

I added lazyLoad attributes to further my point. These attributes will be copied from the custom.xml into the schema.xml on merge.

EDIT: staabm, I just read that whole page and I don't believe packaged schemas have anything to do with the attributes of their tables and columns, or am I wrong?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment