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

Fix create table if not exists when indexes already exist #6249

Merged
merged 5 commits into from
Jul 14, 2022

Conversation

sclubricants
Copy link
Member

@sclubricants sclubricants commented Jul 10, 2022

This fixes #6248

This removes all code for CREATE TABLE table IF NOT EXISTS. Because all platforms do not support this statement the current implementation queries the database first to determine if the table exists. If it does then it doesn't execute the create table statement. The problem occurs when the create indexes statements are executed after the create table statement and the indexes already exists. Rather then try and apply CREATE INDEX index IF NOT EXISTS and carry through the logic, this PR removes completely the IF NOT EXISTS regime and instead relies on the query table lookup. If the table exists then there is need to execute anything. This way the code is simpler and all the problems of index creation is averted.

All the magic happens in (base) Forge here:

    public function createTable(string $table, bool $ifNotExists = false, array $attributes = [])
    {
        if ($table === '') {
            throw new InvalidArgumentException('A table name is required for that operation.');
        }

        $table = $this->db->DBPrefix . $table;

        if ($this->fields === []) {
            throw new RuntimeException('Field information is required.');
        }

        // If table exists lets stop here
        if ($ifNotExists === true && $this->db->tableExists($table)) {
            $this->reset();

            return true;
        }

        $sql = $this->_createTable($table, $attributes);

Checklist:

  • Securely signed commits
  • Component(s) with PHPDoc blocks, only if necessary or adds value
  • Unit testing, with >80% coverage
  • User guide updated
  • Conforms to style guide

@sclubricants sclubricants mentioned this pull request Jul 10, 2022
5 tasks
@kenjis kenjis added bug Verified issues on the current code behavior or pull requests that will fix them database Issues or pull requests that affect the database layer labels Jul 11, 2022
@kenjis kenjis changed the title Fix create table if not exists when indexes already exist Bug #6248 Fix create table if not exists when indexes already exist Jul 11, 2022
Copy link
Member

@MGatner MGatner left a comment

Choose a reason for hiding this comment

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

A rewording suggestion. Please also add a note to the upgrade guide. That could wait until we decide on the parameter removal.

system/Database/Forge.php Outdated Show resolved Hide resolved
user_guide_src/source/dbmgmt/forge.rst Outdated Show resolved Hide resolved
@MGatner
Copy link
Member

MGatner commented Jul 11, 2022

@sclubricants Thanks for splitting this out! Your issue and this very specific PR makes it much easier to understand what is happening. I like this approach, I think the only drawback is a possible race condition but since forge operations should not ever be under load in production I think the benefits outweigh that slim possibility.

@kenjis kenjis added the breaking change Pull requests that may break existing functionalities label Jul 12, 2022
@kenjis
Copy link
Member

kenjis commented Jul 12, 2022

I don't agree that changing any existing method signature in develop (4.2.x).
These change should go at least 4.3, or 5.0.

I don't see anything particularly wrong with this PR, but it changes the behavior (SQL statements will change).
So I would like to hear a little more from others.

@MGatner
Copy link
Member

MGatner commented Jul 12, 2022

@michalsn any chance you have time for a review?

Copy link
Member

@michalsn michalsn left a comment

Choose a reason for hiding this comment

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

The proposed changes are reasonable and will solve the initial problem.

I can't see any real downsides maybe except for some performance decrease. But since the Forge class is mainly used during testing, we should be fine.

We just need some small tweaks.

system/Database/Forge.php Outdated Show resolved Hide resolved
system/Database/OCI8/Forge.php Outdated Show resolved Hide resolved
system/Database/SQLSRV/Forge.php Outdated Show resolved Hide resolved
user_guide_src/source/dbmgmt/forge.rst Outdated Show resolved Hide resolved
@sclubricants sclubricants requested a review from kenjis July 12, 2022 19:29
system/Database/Forge.php Outdated Show resolved Hide resolved
@sclubricants sclubricants requested a review from kenjis July 12, 2022 23:04
Copy link
Member

@kenjis kenjis left a comment

Choose a reason for hiding this comment

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

Thank you!
LGTM!

@sclubricants
Copy link
Member Author

@kenjis I just realized a couple more changes.

_createTable() no longer will return a bool.

    /**
     * @return string
     *
     * @deprecated $ifNotExists is no longer used, and will be removed.
     */
    protected function _createTable(string $table, bool $ifNotExists, array $attributes)
    {

And remove from createTable() logic to handle bool from _createTable().

        if (is_bool($sql)) {
            $this->reset();
            if ($sql === false) {
                if ($this->db->DBDebug) {
                    throw new DatabaseException('This feature is not available for the database you are using.');
                }

                return false;
            }

            return true;
        }

@kenjis
Copy link
Member

kenjis commented Jul 13, 2022

@sclubricants You are correct. Good catch!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking change Pull requests that may break existing functionalities bug Verified issues on the current code behavior or pull requests that will fix them database Issues or pull requests that affect the database layer
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bug: $forge->createTable('table', true) fails when table has indexes
4 participants