You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Evolution can't be run due to "delimiter $$" DDL parsing bug - Play 3, Ebean 8 #496
We've been using play 2.8.1 with play-ebean 6.0.0 and java 1.8 for years now.
Recently, we decided to upgrade to play 3.0.5, play-ebean 8.3.0 and java 21, but it's been a nightmare due to the play architectural bug which has been ironically unresolved since 2018 (Originally raised: Issue #166 ).
No matter what I do, I can't get rid of the bug.
My question is why the plugin's DDL parser does not properly replace back the "delimiter $$ " to '' and "$$" to a semicolon when it must before executing the SQL?
Like why did you even release the plugin if it can't simply work?
Is there gonna be any solution for this? Let me know, otherwise, I'd have to downgrade back to play 2.8.1.
Config file:
`ebean {
default = ["models.global."]
local = ["models.local."]
}
playEbeanModels in Compile := Seq("models.global.", "models.local.")
`
Issue
Solutions tried:
I tried a lot of solutions like setting ebean.ddl.generate and run in config file as well as settings values of ebean.migration.xxx, but always gave me "ddl is type OBJECT rather than LIST" etc etc.
I also tried importing io.ebean agents, ddl-generator, ddl-parser and a lot of different stuff.
I also tried using ebean-platform.
I also tried "-Debean.ddl.generateProcedures=false" in javacOptions.
I also tried creating a custom evolution parser to somehow run it after creating SQL and before executing SQL to replace the 'delimiter $$' issues.
P.s. I'm only seeking an automatic solution (and not manually removing the separators by hand.)
I also tried "-Debean.ddl.generateProcedures=false" in javacOptions.
This will not work.
First its not a compiler option.
Second you need to set it on the jvm instance that is running ebean, which in dev mode (where the jvm does not get forked), is the same jvm which runs sbt. To pass the flag to the jvm in dev mode create a file .jvmopts in your project's root folder with the content:
Is there any proper solution of this bug apart from turning off generating procedures (which is unclear what exactly to do as I don’t have much knowledge about jvm options)
You say you have an existing application that you migrate, so i think you already have evolution files? Just 1 or more?
Or what, with Play 2.8 is your current workflow? Like if you have this application in production, you probably always add to add new evolution files when you update the schema or not?
On development, we used to get new evolution files generated and applied automatically whenever there's a change in one or more entities.
This was because we have:
I think the simplest solution is to parse the sql script returned by ebean and convert it to play evolutions compatible sql. It's not the nicest solution, but it will work.
which will be part of the next Play Ebean 9 release (for Play 3.1). As suggested above, Play Ebean now converts the DDL that Ebean returns into a script that Play's evolutions run correctly.
Cause: Ebean's DDL contains statements with semicolons inside them, and separates those with its own conventions, like delimiter $$ or GO:
the stored procedures that Ebean creates on MySQL, MariaDB and SQL Server
the triggers for @History
Oracle's PL/SQL blocks
column comments with a semicolon
Play's evolutions split the generated 1.sql on every semicolon, so these statements were cut apart.
Play Ebean now splits Ebean's DDL with Ebean's own DdlParser, like Ebean does itself. It writes each statement that contains semicolons between -- !split-semicolon: never and -- !split-semicolon: always comments, so that Play runs it as a whole.
Scripts that already worked stay byte-identical.
The generated scripts were tested by applying and reverting them on H2, SQLite, Postgres, MySQL, MariaDB, SQL Server and Oracle.
Upgrading: if a production database already uses a generated 1.sql, stop Play Ebean from regenerating it before you upgrade Play Ebean, or run the application in dev mode or its tests again:
Remove the -- Created by Ebean DDL comment (both lines) from that 1.sql. This doesn't change the evolution itself.
Or turn off generating the script of that Ebean server with play.ebean.db.<server>.generateEvolutionsScripts = false (since Play Ebean 8.6.0 and 7.6.0, and in the next Play Ebean 9 milestone), or of all Ebean servers with play.ebean.generateEvolutionsScripts = false.
Write further changes as new evolution scripts (2.sql and so on).
Otherwise, a dev mode start or a test run after the upgrade can rewrite 1.sql, and Play then sees a changed evolution. See Generating evolution scripts.
This needs the new directive of Play 3.1's evolutions, so it's only in Play Ebean 9, not in 8.x or 7.x.
If the generated scripts still fail for you after upgrading, please open a new issue.
Activity
adilaijazchohan commentedon Nov 13, 2024
And I think I don't even require procedures.
and there seems to be no way to turn off generating procedures
mkurz commentedon Nov 13, 2024
This will not work.
First its not a compiler option.
Second you need to set it on the jvm instance that is running ebean, which in dev mode (where the jvm does not get forked), is the same jvm which runs sbt. To pass the flag to the jvm in dev mode create a file
.jvmoptsin your project's root folder with the content:mkurz commentedon Nov 13, 2024
Also since 8.1.0 you can disable the generation of the evolutions scripts (in app conf):
adilaijazchohan commentedon Nov 13, 2024
I can’t turn off generating the evolution scripts, because I can’t write SQLs for like 20 schemas.
I want play-ebean to generate and execute them for me.
adilaijazchohan commentedon Nov 13, 2024
Is there any proper solution of this bug apart from turning off generating procedures (which is unclear what exactly to do as I don’t have much knowledge about jvm options)
mkurz commentedon Nov 13, 2024
You say you have an existing application that you migrate, so i think you already have evolution files? Just 1 or more?
Or what, with Play 2.8 is your current workflow? Like if you have this application in production, you probably always add to add new evolution files when you update the schema or not?
adilaijazchohan commentedon Nov 13, 2024
On development, we used to get new evolution files generated and applied automatically whenever there's a change in one or more entities.
This was because we have:
On production, we go to MySql workbench to update the schema manually if there's a change in it.
mkurz commentedon Nov 13, 2024
How? Like if you already have lets say 7 evolution files, was the 8th generated automatically? How? Who did generate that file?
adilaijazchohan commentedon Nov 13, 2024
play-ebean generates/replaces the evolution files in
"/evolutions/default/1.sql"
"/evolutions/local/1.sql"
so it's always one SQL file that's regenerated by play-ebean. We are not used to even touching those SQL files.
mkurz commentedon Nov 13, 2024
OK I get it. I try to figure something out.
adilaijazchohan commentedon Nov 13, 2024
btw, if I add
-Debean.ddl.generateProcedures=falseto .jvmopts file. I get the error "ddl has type OBJECT rather than LIST"mkurz commentedon Nov 13, 2024
Opened
Let's see if we can convince the ebean author to help out here a bit.
mkurz commentedon Nov 13, 2024
Please open a separate issue in this repo for that. Thanks!
mkurz commentedon Nov 26, 2024
I think the simplest solution is to parse the sql script returned by ebean and convert it to play evolutions compatible sql. It's not the nicest solution, but it will work.
play-ebean/play-ebean/src/main/java/play/db/ebean/EbeanDynamicEvolutions.java
Line 74 in a2bf530
mkurz commentedon Oct 12, 2026
Fixed by
which will be part of the next Play Ebean 9 release (for Play 3.1). As suggested above, Play Ebean now converts the DDL that Ebean returns into a script that Play's evolutions run correctly.
Cause: Ebean's DDL contains statements with semicolons inside them, and separates those with its own conventions, like
delimiter $$orGO:@HistoryPlay's evolutions split the generated
1.sqlon every semicolon, so these statements were cut apart.Fix:
!split-semicolondirective (Add a!split-semicolondirective to evolution scripts playframework#14346).DdlParser, like Ebean does itself. It writes each statement that contains semicolons between-- !split-semicolon: neverand-- !split-semicolon: alwayscomments, so that Play runs it as a whole.Upgrading: if a production database already uses a generated
1.sql, stop Play Ebean from regenerating it before you upgrade Play Ebean, or run the application in dev mode or its tests again:-- Created by Ebean DDLcomment (both lines) from that1.sql. This doesn't change the evolution itself.play.ebean.db.<server>.generateEvolutionsScripts = false(since Play Ebean 8.6.0 and 7.6.0, and in the next Play Ebean 9 milestone), or of all Ebean servers withplay.ebean.generateEvolutionsScripts = false.2.sqland so on).Otherwise, a dev mode start or a test run after the upgrade can rewrite
1.sql, and Play then sees a changed evolution. See Generating evolution scripts.This needs the new directive of Play 3.1's evolutions, so it's only in Play Ebean 9, not in 8.x or 7.x.
If the generated scripts still fail for you after upgrading, please open a new issue.
Generate evolution scripts from which Play runs Ebean's statements