Skip to content

Support for Partial Indexes for PostgreSql and Sqlite#600

Merged
deeky666 merged 8 commits intodoctrine:masterfrom
PowerKiKi:feature-partial-indexes
Aug 19, 2014
Merged

Support for Partial Indexes for PostgreSql and Sqlite#600
deeky666 merged 8 commits intodoctrine:masterfrom
PowerKiKi:feature-partial-indexes

Conversation

@PowerKiKi
Copy link
Contributor

Support for Partial Indexes was available in Doctrine 1 following
http://www.doctrine-project.org/jira/browse/DC-82. This commit
reintroduce support for Doctrine 2. We use the same syntax with an
optionnal "where" attribute for Index and UniqueConstraint.

It is unit-tests covered and documented in manual.

@doctrinebot
Copy link

Hello,

thank you for creating this pull request. I have automatically opened an issue
on our Jira Bug Tracker for you. See the issue link:

http://www.doctrine-project.org/jira/browse/DBAL-900

We use Jira to track the state of pull requests and the versions they got
included in.

@guilhermeblanco
Copy link
Member

Hi, I know that Oracle also supports partial indexes too.
Could you please evaluate each driver we support and update the implementation to match them?

@PowerKiKi
Copy link
Contributor Author

Hey,

I already had a look at all platforms supporting this feature and only
found out about PostgreSQL and Sqlite, which confirms what is found on
http://en.wikipedia.org/wiki/Partial_index#Support.

Maybe you could point me to Oracle documentation mentioning those ? Also
since I don't have access to any Oracle installation I am not exactly sure
how to go about testing. But I'll gladly make the effort if you help me
with that.

On a side-note, SQL Server do support partial indexes, but I did not
implement them. This is because there already is what seems to be a
workaround that actual use partial indexes implicitly. It was introduced in
commit 6197492. And from what I understand
it implicitly force all indexes to be ignored if all columns are NULL (see
_appendUniqueConstraintDefinition()). At first glance, I would say it
would be better to leave that up to the end-user, but I may be mistaken.
Most importantly modifying this would probably be a huge compatibility
break.

To sum up, since I was not sure if this feature would be merged, I didn't
put much effort in other platforms, but if you can confirm that it is of
interest, we can complete it.

PS: I forced push a few modification in the last few days. What is the
preferred way of working, pushing new commits and squashing when everything
is ready or force pushing new version of the PR ?

@deeky666 deeky666 closed this May 16, 2014
@deeky666 deeky666 reopened this May 16, 2014
@deeky666
Copy link
Member

Sorry pushed the wrong button ^^

@PowerKiKi
Copy link
Contributor Author

@PowerKiKi the commit you are referncing refers to a legacy class which does not exist anymore

The file does not exists anymore because it was renamed from MsSqlPlatform.php to SQLServerPlatform.php. However the method mentioned, _appendUniqueConstraintDefinition(), still exists in master today.

@Ocramius
Copy link
Member

Needs a rebase...

@PowerKiKi
Copy link
Contributor Author

Done ! Nothing major was changed. Thanks for your interest.

To come back on other platforms support, I think we should first focus on this PR and add other platforms later on if there is any interest. Not try to do everything at once.

@Ocramius
Copy link
Member

Looks good to me, @deeky666?

Copy link
Member

Choose a reason for hiding this comment

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

Please use {@inheritdoc} for this DocBlock here

@bakura10
Copy link
Member

Any news regarding this feature? Would be nice to have :)

Support for Partial Indexes was available in Doctrine 1 following
http://www.doctrine-project.org/jira/browse/DC-82. This commit
reintroduce support for Doctrine 2. We use the same syntax with an
optionnal "where" attribute for Index and UniqueConstraint.
This coherent with what is done for Table. All platform specific things
are grouped into an options array. Eventually flags should be migrated
into options as well.
@PowerKiKi
Copy link
Contributor Author

So I fixed the few things mentioned and rebased my work on master. I believe it is ready to be merged.

@PowerKiKi
Copy link
Contributor Author

@Ocramius, @deeky666 could you have a look again before it needs to be rebased again ? I believe I fixed everything you asked for and it should be mergeable now.

@Ocramius
Copy link
Member

Ocramius commented Aug 2, 2014

I think this is good to go, but I'll have to defer pressing the big green button to @deeky666:

Copy link
Member

Choose a reason for hiding this comment

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

No need for else here.

if ($this->supportsPartialIndexes() && $index->hasOption('where')) {
    return ' WHERE ' . $index->getOption('where');
}

return '';

@PowerKiKi
Copy link
Contributor Author

Sure, I should have noticed those... fixed !

@PowerKiKi
Copy link
Contributor Author

And don't forget to merge doctrine/orm#1027 as well, since it would not be very useful otherwise

@deeky666
Copy link
Member

deeky666 commented Aug 5, 2014

@PowerKiKi sure we have it in our minds ;)

Copy link
Member

Choose a reason for hiding this comment

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

He have another BC break here. @PowerKiKi can you please also mention this change in the UPGRADE.md?

Copy link
Member

Choose a reason for hiding this comment

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

Please add an array typehint on the argument here

@PowerKiKi
Copy link
Contributor Author

Both remarks were fixed.

@deeky666
Copy link
Member

@PowerKiKi I am missing the schema introspection part for partial indexes in SQLite. As far as I know you can get the information from the system table sqlite_master . Can you please evaluate? I think you can adopt the logic from SqliteSchemaManager::listTableForeignKeys(). Also a simple functional test might be useful to verify the schema introspection.

Copy link
Member

Choose a reason for hiding this comment

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

Hmmm you are also skipping SQL generation tests for getUniqueConstraintDeclarationSQL() and getCreateIndexSQL() which actually is supported...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I actually get the following errors:

  • getIndexDeclarationSQL()
    • Doctrine\DBAL\DBALException: Operation 'Doctrine\DBAL\Platforms\SQLAnywherePlatform::getIndexDeclarationSQL' is not supported by platform.``
  • getIndexDeclarationSQL()
    • InvalidArgumentException: Can only create unique constraint declarations, no common index declarations with getUniqueConstraintDeclarationSQL().
  • getCreateIndexSQL()
    • passed !

So it seems, there is only getCreateIndexSQL() which could be tested. And since this test was entirely written by me and getCreateIndexSQL() is already tested elsewhere, I don't think we "lose" coverage, nor that the effort would be worth it. What do you think ?

@PowerKiKi
Copy link
Contributor Author

Index options are now covered by unit tests.

Regarding Sqlite, I already had look at it, and re-confirmed it. Unfortunately the state of Sqlite platform seems to be less well maintained. Not even speaking of partial indexes, but plain vanilla indexes already fail miserably the schema introspection. But it does not appear anywhere in unit tests AFAIK. When switching my current project to Sqlite all indexes are always deleted and re-created from scratch when doing things like orm:schema-tool:update --force.

I would actually consider dropping Sqlite support from this PR, and in another PR fix vanilla indexes first, and then re-consider the partial indexes. What do you think ? Also I am not sure how to unit tests against "real" database... what the best practice about it ?

@deeky666
Copy link
Member

@PowerKiKi thanks for applying the changes and investigating concerning SQLite. I was not aware that SQLite fails the schema introspection on indexes so you might be right and we should defer that issue on another PR to move forward here. We need to reinvestigate support for other platforms anyway so yeah I'm fine with your suggestion to drop partial index support on SQLite for now.
Concerning SQL Anywhere, I can live with that too. So if you could remove SQLite support and maybe squash commits, I will merge if @Ocramius does not have any remarks left :)
Thanks alot!

@deeky666
Copy link
Member

Btw concerning functional tests, have a look at schema manager functional tests. They cover real schema introspection test cases.

@Ocramius
Copy link
Member

I don't feel like squashing commits is required here: we'd lose valuable history IMO

While technically it could work, the schema introspection of Sqlite
platform has severe flaws preventing us to provide reliable support
of partial (and non-partial) indexes for the moment.
@PowerKiKi
Copy link
Contributor Author

So I just pushed the de-activation of Sqlite.

As for squashing I don't have any preferences. What should we do ?

@deeky666
Copy link
Member

@PowerKiKi no need to squash then. I'll merge as soon as Travis goes green :) Thank you.

@PowerKiKi
Copy link
Contributor Author

You're very welcome. You were very thorough while reviewing this PR. It's nice to see that code quality is an important factor for Doctrine. And I am glad we were able to fix everything that needed fixing.

deeky666 added a commit that referenced this pull request Aug 19, 2014
Support for Partial Indexes for PostgreSql and Sqlite
@deeky666 deeky666 merged commit c1c3353 into doctrine:master Aug 19, 2014
@Ocramius
Copy link
Member

\o/

@deeky666
Copy link
Member

@PowerKiKi we got a serious problem here in PostgreSQL >= 9.5. See #2565
The problem is revealed here. Seems they have changed the decompilation algorithm for partial index expressions.

PostgreSQL < 9.5

(((id IS NOT NULL) AND (name IS NULL)) AND (email IS NULL))

PostgreSQL >= 9.5

((id IS NOT NULL) AND (name IS NULL) AND (email IS NULL))

This makes the comparator freak out -.-
Question is what to do. pg_get_expr() takes a third argument pretty_print which when set results in:

id IS NOT NULL AND name IS NULL AND email IS NULL
id IS NOT NULL AND name IS NULL AND email IS NULL

But that option will convert the original expression, too. I do not know how to retrieve the original definition. @Ocramius should we simply adjust our test suite to return the same result on all platform versions and leave the expression as "fragile"?

@Ocramius
Copy link
Member

Ocramius commented Jan 18, 2017 via email

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 19, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants