sqldelight icon indicating copy to clipboard operation
sqldelight copied to clipboard

improve errors when create statement not found for a drop statement

Open tropikoder opened this issue 3 years ago • 13 comments

When the create for a drop can't be found, at the moment the user gets this error:

Caused by: java.util.NoSuchElementException: Collection contains no element matching the predicate.
        at app.cash.sqldelight.gradle.squash.AnsiSqlMigrationSquasher.squish(AnsiSqlMigrationSquasher.kt:144)

Not only does that line not exist, it's impossible to know which drop was not matched with a create. This PR adds the drop statement to the exception

tropikoder avatar Sep 01 '22 16:09 tropikoder

Nice! But could you please add a test?

hfhbd avatar Sep 02 '22 10:09 hfhbd

Nice! But could you please add a test?

Where could i look in the code base for an example of a test that expects an exception? Thanks

tropikoder avatar Sep 02 '22 14:09 tropikoder

You could just add a project to the integration tests folder: https://github.com/cashapp/sqldelight/tree/dc1080a72202566ef3a1281b74f2d72b59910950/sqldelight-gradle-plugin/src/test I would just copy this test https://github.com/cashapp/sqldelight/tree/dc1080a72202566ef3a1281b74f2d72b59910950/sqldelight-gradle-plugin/src/test/migration-failure After adding the test project, all you need is to call it in the Kotlin test code: https://github.com/cashapp/sqldelight/blob/752599954abd78e0db90ccbe5cb8b523ea4f6cf1/sqldelight-gradle-plugin/src/test/kotlin/app/cash/sqldelight/tests/MigrationTest.kt#L39 Feel free to ask for help :)

hfhbd avatar Sep 04 '22 12:09 hfhbd

Hm, after testing the test project locally I don't get the error. And I think the test case is still a little buggy.

First, you need a dialect supporting DROP COLUMN. If you don't specify a dialect, sqldelight uses sqlite 3.18, which does not support drop columns. dialect("app.cash.sqldelight:sqlite-3-35-dialect:${app.cash.sqldelight.VersionKt.VERSION}") supports DROP COLUMN but it works...

AFAIK Migration squashing is useless with only one sqm file. So you need two migration files to squish them into one file. If you use migrations, you should enable deriveSchemaFromMigrations and move your CREATE statements in an initial migration file too (1.sqm) and your DROP COLUMN into 2.sqm.

If you do this, I don't get this error java.util.NoSuchElementException: Collection contains no element matching the predicate. but no error, which looks like a bug too, because it should fail when referencing a missing column...

While I understand your initial fix in the ANSI Sql-squasher, I am curious how you got this error at all.

hfhbd avatar Sep 07 '22 04:09 hfhbd

Thanks for the help. You are correct in your suggestions. I asked a colleague who has Android Studio to run the pipeline and his machine gets an out of memory error. The PR would be better if we could actually run locally.

I suspect I got the error because we may have an index in the DB that was not created via a migration. We have hundreds of migrations (hence the desire to squash) so it's hard to know which one causes the error (hence the PR).

tropikoder avatar Sep 07 '22 14:09 tropikoder

Also, there are some things in the tests that i've never used and I didn't find docs for, such as 1.db. I made a new commit that removes it.

tropikoder avatar Sep 07 '22 14:09 tropikoder

@tropikoder You don't need Android Studio, I don't use it too. For debugging just link the project by right-click the gradle.build file and test it. Or simple run the test.

If you get OOM errors, the cause is often dokka and you need to increase the heap:

org.gradle.jvmargs=-Xmx2048m
org.gradle.parallel=true

I am fine with the actual fix, but I would like to have 1) a working test :) and 2) the config causing your crash, because I don't understand why the crash happened at all. AFAIK this method is always overwritten.

hfhbd avatar Sep 07 '22 17:09 hfhbd

Is there a way to build just the jvm jars so i can run my fork locally from my main project (which has the hundreds of migrations and squash problem)? Thanks!

tropikoder avatar Sep 12 '22 22:09 tropikoder

@tropikoder Sure, just use either publishAllPublicationsToInstallLocallyRepository (the folder will be at sqldelight/build/localMaven or use publishToMavenLocal and use repositories { mavenLocal() }. And be sure to update your version to 2.0.0-SNAPSHOT.

hfhbd avatar Sep 13 '22 06:09 hfhbd

Thanks @hfhbd

My colleague was able to run the locally installed jars from our fork. It seems that there's a bug when migrations drop views (they get mixed up with tables). With our changes, we are able to generate exceptions like this: Create statement not found for drop table statement View_Product_ProductPriceAndStock

tropikoder avatar Sep 14 '22 19:09 tropikoder

using the local jars we noticed that the matching of create/drop statements fails when the View drop statement has IF EXISTS

tropikoder avatar Sep 15 '22 14:09 tropikoder

using the local jars we noticed that the matching of create/drop statements fails when the View drop statement has IF EXISTS

Actually there are mismatches even without IF EXISTS

tropikoder avatar Sep 15 '22 14:09 tropikoder

@tropikoder

It seems that there's a bug when migrations drop views (they get mixed up with tables)

Do you have a sample? Or does the test work?

hfhbd avatar Sep 20 '22 15:09 hfhbd

@hfhbd i couldn't make a PR that reproduces the error.

We gave up on the automated squash and did it manually.

tropikoder avatar Oct 08 '22 15:10 tropikoder