Liquibase plugin - Replace one change by multiple changes

I am having an issue. I’m currently working on a Liquibase plugin. The plugin makes use of CustomTaskChange by implementing it. Before this change is executed, I’m trying to add a new column which the CustomTaskChange refers to. However, I’m combining both in a single change class and generate the statements one after the other. When the generateStatements -method is called, it seems to already execute the CustomTaskChange before adding the new column. Therefore, the CustomTaskChange gives an error that the column does not exist. I hope my explanation is understandable.

The CustomTaskChange is wrapped in a CustomChangeWrapper . Basically, I’m asking, is there a way to not call execute on the CustomTaskChange when generateStatements is called, but only when it needs to execute.

Is there someone that knows a solution to this problem? Is a possible idea maybe to remove the wrapping change class from the ChangeSet and then add the individual changes separately? So instead of having the wrapping class contain both the AddColumnChange and the CustomChangeWrapper , the ChangeSet contains these individually and will execute them one after the other. I think that could possibly fix it, but I’m not sure how nice that is.

I’m not quite sure what you mean by “combining both in a single class”. It sounds like you are refactoring your old separate CustomTaskChange into a new CustomTaskChange class which contains the logic from both? But some of that logic gets ran too early?

liquibase/CustomChangeWrapper.java at c6ed3fed61efe0dcf30e0713f4ed10ee2fff8b96 · liquibase/liquibase · GitHub is the “driving” code that calls out to CustomTaskChange, where it ends up running the execute() command. That should just be called once during execution.

Can you give me a bit more information?

Thanks,
Nathan

1 Like

Hi Nathan,

Thank you for your reaction.
I have already been able to solve the problem.

What I mean with “combining both in a single class” is that I have created my own Change class which performs multiple changes one after the other. I.e. the generateStatements-method generates a large set of statements for several Change objects, one of which is a CustomChange within a CustomChangeWrapper. Therefore, my generateStatements-method generates several statements, but when it comes to the CustomTaskChange, it is executed instead of generated. For my case this does not work, since the CustomTaskChange depends on some database objects that are added in earlier statements.

I have fixed this issue by rewriting the CustomChangeWrapper to generate a statement for the CustomTaskChange. An additional generator then executes this statement. Since execution is done in order, after calling generateStatements, it now first executes the dependant statements, after which it can execute the CustomTaskChange.

I would make a suggestion to update the CustomChangeWrapper like this, since it seems to conform better with the rest of the codebase as well. Let me know what you think of this.

Coen

1 Like

OK, I think I get what you mean. And glad you got it figured out.

I agree that we do need a better way to encapsulate the change logic that is not SQL but still should be ran after it’s “generated”. More of a Runnable-type function. That will be a larger API-changing thing, so we’re being careful about when and how to make it. Probably as part of making the same API less SQL-based to better work with nosql databases.

Nathan