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

Add handling for adding/modifying columns with FIRST/AFTER #147

Merged

Conversation

JanJakes
Copy link
Collaborator

@JanJakes JanJakes commented Aug 7, 2024

Add handling for adding/modifying columns with FIRST/AFTER, such as:

ALTER TABLE _tmp_table ADD COLUMN new_first_column VARCHAR(255) NOT NULL DEFAULT '' FIRST;
ALTER TABLE _tmp_table ADD COLUMN new_column VARCHAR(255) NOT NULL DEFAULT '' AFTER id;
ALTER TABLE _tmp_table CHANGE id id int(11) NOT NULL FIRST;
ALTER TABLE _tmp_table CHANGE id id int(11) NOT NULL AFTER name;

SQLite doesn't support FIRST/AFTER, so this implementation simply ignores these. Previously, for ADD COLUMN statements, it ended up with SQLSTATE[HY000]: General error: 1 near "FIRST": syntax error. and SQLSTATE[HY000]: General error: 1 near "AFTER": syntax error.; for CHANGE statements, this was already ignored and I only added a test.

@JanJakes JanJakes force-pushed the add-column-first-and-after branch from c9753ec to 2d21a4a Compare August 7, 2024 10:48
@JanJakes JanJakes force-pushed the add-column-first-and-after branch from 2d21a4a to 0cbf391 Compare August 7, 2024 10:52
@JanJakes JanJakes force-pushed the add-column-first-and-after branch from 0cbf391 to 3f4246c Compare August 7, 2024 11:35

$this->assertQuery(
"ALTER TABLE _tmp_table ADD COLUMN new_first_column VARCHAR(255) NOT NULL DEFAULT '' FIRST"
);
Copy link
Member

Choose a reason for hiding this comment

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

It would be good to also make assertions about the resulting table structure like this:

$this->assertQuery( 'DESCRIBE _tmp_table;' );
$results = $this->engine->get_query_results();
$this->assertEquals(
array(
(object) array(
'Field' => 'name',
'Type' => 'varchar(20)',
'Null' => 'NO',
'Key' => '',
'Default' => '',
'Extra' => '',
),
(object) array(
'Field' => 'column',
'Type' => 'int',
'Null' => 'YES',
'Key' => '',
'Default' => null,
'Extra' => '',
),
),
$results
);

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

👍 Added in c4efdfd.

Copy link
Member

Choose a reason for hiding this comment

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

👍 Let's add them after each assertQuery() here to check each is doing what is expected.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

OK! Added in 4615adc.

)
);

if ( $column_position && ( ! $comma || $column_position->position < $comma->position ) ) {
Copy link
Member

Choose a reason for hiding this comment

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

What kind of SQL syntax is this comma check intended to address? Could you provide an example?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@brandonpayton Without the check, it can consume too much, up to the following column definitions.

E.g., for a query like this one:

ALTER TABLE _tmp_table
ADD COLUMN new1 VARCHAR(255),
ADD COLUMN new2 VARCHAR(255) FIRST

You would get a SQLSTATE[HY000]: General error: 1 near ",": syntax error., since you've consumed up to FIRST from the second column when processing the first column.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, I see. I hadn't noticed that the translator loops to support the comma-separated MySQL ALTER TABLE syntax.

Let's add a test for comma-separated syntax as well.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for explaining!

Copy link
Collaborator Author

@JanJakes JanJakes Aug 7, 2024

Choose a reason for hiding this comment

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

Added a test in 31ecd65.

Copy link
Member

@brandonpayton brandonpayton left a comment

Choose a reason for hiding this comment

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

Thanks for this PR, @JanJakes!

I left a comment about the tests and a question about part of the implementation.

@brandonpayton brandonpayton added the bug Something isn't working label Aug 7, 2024
@JanJakes
Copy link
Collaborator Author

JanJakes commented Aug 7, 2024

@brandonpayton Thanks! I added a commit and tried the to explain the need for the comma check.

@JanJakes JanJakes force-pushed the add-column-first-and-after branch from 2c1fe61 to 31ecd65 Compare August 7, 2024 20:03
Copy link
Member

@brandonpayton brandonpayton left a comment

Choose a reason for hiding this comment

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

IIUC, something must not be working properly because the column order in the tests do not appear to be changing.

$this->assertEquals(
array(
(object) array(
'Field' => 'id',
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't new_first_column be first now?

'Extra' => '',
),
(object) array(
'Field' => 'name',
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't new_column be after id now, so the resulting column order would be:

  • new_first_column
  • id
  • new_column
  • name

'Default' => '',
'Extra' => '',
),
),
Copy link
Member

Choose a reason for hiding this comment

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

After this change, I think the resulting column order should be:

  • id
  • new_first_column
  • new_column
  • name

Am I missing something?

'Default' => '',
'Extra' => '',
),
),
Copy link
Member

Choose a reason for hiding this comment

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

After this change, I think the resulting column order should be:

  • new_first_column
  • new_column
  • name
  • id

Am I missing something?

'Default' => '',
'Extra' => '',
),
),
Copy link
Member

Choose a reason for hiding this comment

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

After this change, shouldn't the resulting column order be the following?

  • new2
  • id
  • new1
  • new3

@JanJakes
Copy link
Collaborator Author

JanJakes commented Aug 7, 2024

@brandonpayton Please, see the description of the PR. As it says, "SQLite doesn't support FIRST/AFTER, so this implementation simply ignores these".

Actually implementing the order would mean changing simple ADD COLUMN rewriting to CHANGE-like copy-table behavior.

Copy link
Member

@brandonpayton brandonpayton left a comment

Choose a reason for hiding this comment

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

@brandonpayton Please, see the description of the PR. As it says, "SQLite doesn't support FIRST/AFTER, so this implementation simply ignores these".

🤦‍♂️ Right. I read that originally but lost the detail while multi-tasking.

These changes look reasonable to me and test well.

@brandonpayton brandonpayton merged commit 4c63355 into WordPress:develop Aug 7, 2024
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

3 participants