Skip to content
New issue

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

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

set foreignSchema when schema is public #1326

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

domcar
Copy link

@domcar domcar commented Jan 5, 2017

Since Propel ignore the public schema of Postgres, there is a problem when in the schema.xml there is a foreign-key with reference to a foreignTable that is located in the public schema.

In this example the table approvals is in schema1 while the foreignTable orders is located in public, this generates a problem because the reverse-engineer will look for the foreignTable in schema1:

<table name="approvals" schema="schema1" idMethod="native" >
    <column name="orderid" phpName="Orderid" required="true"/>
    <foreign-key foreignTable="orders" name="approvals_orderid_fk">
      ..........
    </foreign-key>

With this fix it is possible to reference a foreignTable when it is in the public schema:

<table name="approvals" schema="schema1" idMethod="native" >
    <column name="orderid" phpName="Orderid" required="true"/>
    <foreign-key foreignTable="orders" foreignSchema="public" name="approvals_orderid_fk">
      ..........
    </foreign-key>

$fk->setForeignSchemaName($foreignTable->getSchema());
if($foreignTable->getSchema())
$fk->setForeignSchemaName($foreignTable->getSchema());
elseif($foreignTable->getSchema() == 'public')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is "the public" schema in pg exactly? something internal?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As stated by the Postgres documentation:

tables created without specifying any schema names, by default such tables (and other objects) are automatically put into a schema named "public". Every new database contains such a schema

Here is the link: https://www.postgresql.org/docs/9.1/static/ddl-schemas.html Section 5.7.2

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code can not work. When First condition if($foreignTable->getSchema()) evaluates to false it never can be true for $foreignTable->getSchema() == 'public'.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why shouldn't it work? If the condition is false then we have no schema for the foreignTable, that's it (although there should always be a schema).
But if it evaluates to true AND it is equal to public, then the foreignSchemaName will be set to public. (Maybe instead of elseif I should have used only if).
Without it, the public schema will not be set.

Copy link
Member

@marcj marcj Jan 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if($foreignTable->getSchema())
    $fk->setForeignSchemaName($foreignTable->getSchema());

When getSchema() returns a value it will be set. If it does not return a value you check via elseif($foreignTable->getSchema() == 'public') again, which can never be truely because you checked already in the previous if that $foreignTable->getSchema() returns falsely. Falsely means it can never be == 'public'. If you would use instead of elseif simple if, you would set it twice. Too illustrate it:

$schema = 'public';
if ($schema)
    $fk->setForeignSchema($schema);
if ($schema == 'public')
    $fk->setForeignSchema('public');

As you see, the second check is redundant.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, because the public schema doesn't get set, this is the problem. I don't know why but it doesn't get set!

Copy link
Member

@marcj marcj Jan 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is weird. It should be set via the first setForeignSchema() call. If that is not the case, then the bug hides in that method. Calling however the same method twice with the same arguments directly after each other is really not a bugfix, and it is currently not logical at all. I just don't see how this fixes anything. Maybe you can provide a unit-test that proves that this code fixes it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Marc, sorry you were right, i uploaded the wrong commit, please have a look at it now

@marcj
Copy link
Member

marcj commented May 26, 2017

Mh, the thing is: Setting the schema to "public" per default can be wrong, since "public" is not always the default schema in Postgres. We should actually find out in which schema the target table is located and place it in "schema" attribute if it differs to the default schema (which we need to find out by querying the database using SHOW search_path;). But about the last part I'm not so sure, because if we do not specify a schema, it should already use the search_path to find it in public.

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

Successfully merging this pull request may close these issues.

4 participants