question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Mysql parser error with CASE operator and IF function

See original GitHub issue
Which version and edition of Flyway are you using?

Flyway Community Edition 6.5.5 by Redgate

If this is not the latest version, can you reproduce the issue with the latest one as well?

(Many bugs are fixed in newer releases and upgrading will often resolve the issue)

Which client are you using? (Command-line, Java API, Maven plugin, Gradle plugin)

Command-line and Java API

Which database are you using (type & version)?

mysql 5.7.31 (installed from homebrew)

Which operating system are you using?

Mac OS 10.15.6

What did you do?

(Please include the content causing the issue, any relevant configuration settings, the SQL statement that failed (if relevant) and the command you ran.)

We recently upgraded the Flyway version we use via the Java API from 4.1.2 to 6.5.2 which caused an existing migration script to fail when initialising a new database. Confirmed that the issue is still present in 6.5.5 with both the Java API and command-line versions.

Sample script that generates a parse error:

CREATE TABLE `test_table` (
    `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
    `field` varchar(64) DEFAULT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `test_join` (
    `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
    `test_table_id` bigint(20) unsigned NOT NULL,
    `field1` varchar(64) NOT NULL DEFAULT '',
    `field2` varchar(64) NOT NULL DEFAULT '',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

UPDATE `test_table` t
LEFT JOIN test_join j
    ON t.id=j.test_table_id and j.field1 in ('VALUE_1', 'VALUE_2', 'VALUE_3')
SET t.field =
    CASE j.field1
        WHEN 'VALUE_1' THEN IF(STRCMP(j.field2, 'A')=0, 'VALUE_A1', 'VALUE_A2')
        WHEN 'VALUE_2' THEN 'VALUE_B'
        WHEN 'VALUE_3' THEN 'VALUE_C'
        ELSE NULL
    END;
What did you expect to see?

Database migration script successfully applied.

What did you see instead?

Parse error:

ERROR: Unable to parse statement in /Users/amccarthy/Temp/flyway-parse/V002__Test.sql at line 15 col 1. See https://flywaydb.org/documentation/knownparserlimitations for more information: Incomplete statement at line 15 col 1: UPDATE `test_table` t
LEFT JOIN test_join j
    ON t.id=j.test_table_id and j.field1 in ('VALUE_1', 'VALUE_2', 'VALUE_3')
SET t.field =
    CASE j.field1
        WHEN 'VALUE_1' THEN IF(STRCMP(j.field2, 'A')=0, 'VALUE_A1', 'VALUE_A2')
        WHEN 'VALUE_2' THEN 'VALUE_B'
        WHEN 'VALUE_3' THEN 'VALUE_C'
        ELSE NULL
    END;


Caused by: Incomplete statement at line 15 col 1: UPDATE `test_table` t
LEFT JOIN test_join j
    ON t.id=j.test_table_id and j.field1 in ('VALUE_1', 'VALUE_2', 'VALUE_3')
SET t.field =
    CASE j.field1
        WHEN 'VALUE_1' THEN IF(STRCMP(j.field2, 'A')=0, 'VALUE_A1', 'VALUE_A2')
        WHEN 'VALUE_2' THEN 'VALUE_B'
        WHEN 'VALUE_3' THEN 'VALUE_C'
        ELSE NULL
    END;

The script is valid mysql sql. The parse error can be worked around by surrounding the CASE operator with parentheses, but this is not a solution as that would cause checksum errors on existing deployments.

CREATE TABLE `test_table` (
    `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
    `field` varchar(64) DEFAULT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `test_join` (
    `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
    `test_table_id` bigint(20) unsigned NOT NULL,
    `field1` varchar(64) NOT NULL DEFAULT '',
    `field2` varchar(64) NOT NULL DEFAULT '',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

UPDATE `test_table` t
LEFT JOIN test_join j
    ON t.id=j.test_table_id and j.field1 in ('VALUE_1', 'VALUE_2', 'VALUE_3')
SET t.field =
    (CASE j.field1
        WHEN 'VALUE_1' THEN IF(STRCMP(j.field2, 'A')=0, 'VALUE_A1', 'VALUE_A2')
        WHEN 'VALUE_2' THEN 'VALUE_B'
        WHEN 'VALUE_3' THEN 'VALUE_C'
        ELSE NULL
    END);

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
amccarthycommented, Sep 17, 2020

Hi @Lyeeedar,

This doesn’t appear to be fixed with the command-line version. Attempting to apply the first script to an empty database still produces the error.

Additionally other scripts that use the CASE operator are no also failing. These scripts were parsed and applied successfully in version 6.5.5. For example this script which create a stored procedure with an ORDER BY CASE. As with the previous example the parser error does not happen if the CASE operator is wrapped in parentheses.

DELIMITER //
CREATE PROCEDURE test_procedure(in startTime dateTime, in endTime dateTime, in showTotals enum('Y','N'))
BEGIN
    IF showTotals = 'Y' THEN
        SELECT * FROM test_table
        ORDER BY CASE WHEN `name` is null then 1 else 0 end, `name`;
    ELSE
        SELECT * from test_table;
    END IF;
END //
DELIMITER ;

The error:

ERROR: Unable to parse statement in /Users/amccarthy/Temp/flyway-parse/V003__Test.sql at line 2 col 1. See https://flywaydb.org/documentation/knownparserlimitations for more information: Delimiter changed inside statement at line 2 col 1: CREATE PROCEDURE test_procedure(in startTime dateTime, in endTime dateTime, in showTotals enum('Y','N'))
BEGIN
    IF showTotals = 'Y' THEN
        SELECT * FROM test_table
        ORDER BY CASE WHEN `name` is null then 1 else 0 end, `name`;
    ELSE
        SELECT * from test_table;
    END IF;
END //

Caused by: Delimiter changed inside statement at line 2 col 1: CREATE PROCEDURE test_procedure(in startTime dateTime, in endTime dateTime, in showTotals enum('Y','N'))
BEGIN
    IF showTotals = 'Y' THEN
        SELECT * FROM test_table
        ORDER BY CASE WHEN `name` is null then 1 else 0 end, `name`;
    ELSE
        SELECT * from test_table;
    END IF;
END //
0reactions
Lyeeedarcommented, Sep 18, 2020

@yuvalprtn @amccarthy Thank you for these examples, I will make sure that our next fix fully supports these cases. If you are happy to share more of your scripts, you can post them here or email them to me at philip.liddell@red-gate.com

Read more comments on GitHub >

github_iconTop Results From Across the Web

Developers - Mysql parser error with CASE operator and IF function -
We recently upgraded the Flyway version we use via the Java API from 4.1.2 to 6.5.2 which caused an existing migration script to...
Read more >
mysql parse exception in simple case statement - Stack Overflow
this simple case statement would throw a parse exception Always provide complete error message text. And investigate it - server citates the ...
Read more >
9.2.5 Function Name Parsing and Resolution
An error occurs if you try to create a loadable function with the same name as a built-in function. IF NOT EXISTS (available...
Read more >
2 Server Error Message Reference - MySQL :: Developer Zone
This error occurs for attempts to select from and modify the same table within a single statement. If the select attempt occurs within...
Read more >
MySQL 8.0 Reference Manual :: 12.4.3 Logical Operators
Logical AND. Evaluates to 1 if all operands are nonzero and not NULL , to 0 if one or more operands are 0...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found