4

I have a set of Play! unit tests that I have been running against an H2 database. I have added some enum columns to my model, and the tests now fail because of the sql statements used to create my model tables.

The error message is:

14:42:10,435 ERROR ~ Unknown data type: "ENUM"; SQL statement:

Some searching shows that there are ways to emulate enums in H2 (eg: http://groups.google.com/group/h2-database/search?group=h2-database&q=enum&qt_g=Search+this+group)

Setting Play to use the H2Dialect for test mode does not fix the issue. It seems like the root cause is that H2 does not support enums, or maybe that the H2Dialect doesn't know about H2's pseudo-enums.

Is there a way in Play to test models with enums in H2?

Pere Villega
  • 16,429
  • 5
  • 63
  • 100
JTB
  • 95
  • 1
  • 5
  • This answer might be helpful: https://stackoverflow.com/questions/48955100/error-when-setting-up-h2-database/64044332#64044332 – Taras Melnyk Sep 24 '20 at 10:18

2 Answers2

5

Here a workaround that works for spring-boot with H2 - it doesn't depend on either though, so you can do something similar for play.

Please note that this is a fake and doesn't really allow you to test enums fully but it allows you to run tests against a pre-existing production DBs (where you cannot just go and change the schema) without having to write the entire DDL yourself.

So, instead of letting your test framework setup the connecting string for the in-memory db, do configure the H2 connection string yourself.

Here how the magic setting looks in my case:

# the next line is very important it names the ddl work
# H2 does not support enums
# In order to fake support for them we have to declare a
# domain called enum and mapped it to a varchar - the size
# I picked at random but it is "good enough" for now.
# H2 will run this before hibernate creates the schema and
# then the schema creation will succeed
spring.datasource.url=jdbc:h2:mem:test;MODE=MySQL;INIT=CREATE DOMAIN IF NOT EXISTS enum as VARCHAR(255);DB_CLOSE_ON_EXIT=FALSE

The magic is this:

CREATE DOMAIN IF NOT EXISTS enum as VARCHAR(255)

this tells H2 to treat the custom (domain) datatype enum as varchar - you can obviously change the size to whatever.

It as done as an INIT cause that makes sure it is executed before the first bit of ddl is executed against it by any framework

So, in case of Play! the setting would be db.default.jdbcUrl - or however you define your test database connection (e.g. as a trait)

JRomero
  • 4,878
  • 1
  • 27
  • 49
Eike D
  • 315
  • 2
  • 6
  • Hi I want to add multiple create domain statement as i have multiple enums, any idea how can we achieve it? I tried followoing but it is giving error. spring.datasource.url: jdbc:h2:mem:test;MODE=PostgreSQL;INIT=CREATE DOMAIN IF NOT EXISTS pgsql_enum as VARCHAR(255),CREATE DOMAIN IF NOT EXISTS value_type as VARCHAR(255);DB_CLOSE_ON_EXIT=FALSE – jagga Jan 13 '21 at 06:23
  • @jagga you need to use ";" as the separator between the "CREATE..." statements - however you also need to escape the ";" - so e.g. "\;" - see here for more details: https://stackoverflow.com/questions/5225700/can-i-have-h2-autocreate-a-schema-in-an-in-memory-database/5228564#5228564 If you have a lot of statements i would use a RUNSCRIPT instead. – Eike D Feb 22 '21 at 22:23
1

Normally JPA translate it for you into an basic-type. See Map enum in JPA with fixed values? or JPA Enum ORDINAL vs STRING. I think this is the only way to become database independent.

Community
  • 1
  • 1
niels
  • 7,321
  • 2
  • 38
  • 58