Repository navigation
Generate evolution scripts from which Play runs Ebean's statements - #922
Merged
Merged
Conversation
Ebean's DDL can contain statements with semicolons, like the stored procedures it creates on MySQL, MariaDB and SQL Server, the triggers for @history, the PL/SQL blocks for Oracle, or a column comment with a semicolon, and separates such statements with its own conventions, like `delimiter $$` or `GO`. Play's evolutions however split on every semicolon, so these scripts failed to apply. So the DDL is now split with Ebean's own DdlParser, which Ebean's DdlRunner uses as well, and statements with semicolons are written between `!split-semicolon` comments. DDL from which Play already runs Ebean's statements stays as it is, so a script only changes where Play would have split Ebean's statements differently. The configured DDL header, which can contain anything, always stays as it is. This needs the `!split-semicolon` directive of Play's evolutions (playframework/playframework#14346), so Play is updated to 3.1.0-M10-3968a052-SNAPSHOT. The docs explain this, and that the generated script of a production database should no longer be regenerated, especially when upgrading. A test checks for all of Ebean's platforms that Play runs Ebean's statements, and another one applies and reverts the scripts on H2 and SQLite, and on Postgres, MySQL, MariaDB, SQL Server and Oracle when configured. Fixes playframework#166 Fixes playframework#496
Contributor
|
This pull request does not currently match the merge queue conditions, so it cannot be queued from here. The box comes back if it matches again. |
EbeanEvolutionScriptDatabasesTest only runs on Postgres, MySQL, MariaDB, SQL Server and Oracle when environment variables configure the databases. The README now lists them, and shows how to start the databases with Docker and run the test.
This was referenced Oct 12, 2026
Closed
mkurz
added a commit
to playframework/playframework
that referenced
this pull request
Oct 12, 2026
Play Ebean 9 uses the new `!split-semicolon` directive in the evolution scripts it generates (playframework/play-ebean#922). The migration guide now explains that upgrading Play alone doesn't change any script, and what to do when a production database already uses a generated script, so that Play Ebean 9 doesn't change it. The highlights mention what Play Ebean 9 fixes with it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Some of the statements in Ebean's DDL contain semicolons:
@History(Postgres, MySQL)Ebean separates such statements with its own conventions, like
delimiter $$orGO. Play's evolutions split on every semicolon instead, so the generated1.sqlfailed to apply, e.g. with "near 'delimiter $$'" on MySQL and MariaDB, "Incorrect syntax near 'GO'" on SQL Server or "Unterminated dollar quote" on Postgres.Play now has a
!split-semicolondirective for evolution scripts:!split-semicolondirective to evolution scripts playframework#14346so Play is updated to
3.1.0-M10-3968a052-SNAPSHOT, which has it.Play Ebean now splits the DDL with Ebean's own
DdlParser, which Ebean'sDdlRunneruses as well, and writes each statement with a semicolon between comments, like this (from MySQL, shortened):ddl.headerproperty), which can contain anything, always stays as it is.The docs explain this. They also say that once a production database uses the generated script, the script should stop being regenerated: remove the
-- Created by Ebean DDLcomment, or turn off generating the script of that Ebean server withplay.ebean.db.<server>.generateEvolutionsScripts(or of all Ebean servers withplay.ebean.generateEvolutionsScripts), especially before upgrading to Play Ebean 9, whose scripts differ where the DDL has such statements. Upgrading Play alone doesn't regenerate anything.Tests:
EbeanEvolutionScriptTestgenerates the DDL offline for all of Ebean's platforms, with a sequence,@Historyand a comment with semicolons. It checks that Play runs the statements Ebean would run, for the Ups and the Downs. Without this change, this fails on MySQL, MariaDB, SQL Server, Postgres, HANA, NuoDB, YugabyteDB, Oracle and DB2. It also covers the DDL header and DDL that stays as it is.EbeanEvolutionScriptDatabasesTestapplies the generated script with Play's evolutions, uses the models (including@Historyversions and a stored procedure), and reverts the script, twice. It runs on H2 and SQLite always, and on Postgres, MySQL, MariaDB, SQL Server and Oracle whenPLAY_EBEAN_TEST_<DB>_URL,_USERand_PASSWORD(or_PASSWORD_FILE) are set.testFullpassed on Scala 2.13.x, 3.3.x, 3.9.x and 3.next. CI only runs the H2 and SQLite variants.How to run the database tests (also in the README, with Docker commands for each database):
PLAY_EBEAN_TEST_<DB>_URL,_USER, and_PASSWORDor_PASSWORD_FILE, where<DB>isPOSTGRES,MYSQL,MARIADB,SQLSERVERorORACLE. A database without them is skipped.With
--server, sbt starts on its own and sees the variables. Without it, sbt can connect to an sbt server that's already running, which doesn't see them.Before/after examples of the generated
1.sql, created offline from the test models. "Before" is what Play Ebean writes without this change, "after" what it writes with it:-- apply changes) are gone, since Ebean's parser drops them too, and statements are separated by blank lines.MySQL / MariaDB: stored procedures with
delimiter $$SQL Server:
GOand stored proceduresPostgres:
@Historytrigger function with$$Oracle: PL/SQL block in the Downs that drops a sequence
Any platform (here H2): column comment with
;and;;To see them side by side: this gist has the same scripts, and its revisions show before and after in a split view.