Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds support to Postgres #44

Closed
wants to merge 7 commits into from
Closed

Conversation

pgeadas
Copy link
Contributor

@pgeadas pgeadas commented Jun 19, 2024

Description

Adds support for postgres driver:

  • org.postgresql.Driver

Caveats

Backticks are a non-standard used by MySQL. Postgres does not support them by default.

@pgeadas pgeadas force-pushed the notask-add-support-to-postgres branch 5 times, most recently from 9558e5b to cb76924 Compare June 19, 2024 20:43
@pgeadas pgeadas force-pushed the notask-add-support-to-postgres branch from cb76924 to 911a817 Compare June 19, 2024 21:03
src/main/java/io/seqera/migtool/Driver.java Outdated Show resolved Hide resolved
src/main/java/io/seqera/migtool/MigTool.java Outdated Show resolved Hide resolved
src/main/java/io/seqera/migtool/Helper.java Outdated Show resolved Hide resolved
src/main/java/io/seqera/migtool/MigTool.java Outdated Show resolved Hide resolved
@pgeadas pgeadas force-pushed the notask-add-support-to-postgres branch from c7a3638 to 8bd78dc Compare June 20, 2024 15:29
src/main/java/io/seqera/migtool/Dialect.java Outdated Show resolved Hide resolved
README.md Show resolved Hide resolved
@pgeadas pgeadas force-pushed the notask-add-support-to-postgres branch 2 times, most recently from ffd9512 to ba83f79 Compare June 21, 2024 10:48
@pgeadas pgeadas requested a review from pditommaso June 28, 2024 15:29
@pgeadas
Copy link
Contributor Author

pgeadas commented Jul 26, 2024

Are we merging this at some point? @swampie @pditommaso @tcrespog

@tcrespog
Copy link
Contributor

Are we merging this at some point? @swampie @pditommaso @tcrespog

It's okay for me (I approved it). Should we wait for @swampie and @pditommaso to check it? Please, Matteo & Paolo, let us know.

while( itr.hasNext() ) {
Path it = itr.next();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(Paths.get(path))) {
for (Path it : stream) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WHat's the value of this change? don't see related to the support for Postgress

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from clarity, it uses try with resources which automatically closes the stream after usage.

Comment on lines +490 to +548
public static class Builder {
private String driverName;
private Driver driver;
private String url;
private String user;
private String password;
private String dialectName;
private Dialect dialect;
private String locations;
private ClassLoader classLoader;
private Pattern pattern;

public Builder withDriver(String driverName) {
this.driverName = driverName;
return this;
}

public Builder withUrl(String url) {
this.url = url;
return this;
}

public Builder withUser(String user) {
this.user = user;
return this;
}

public Builder withPassword(String password) {
this.password = password;
return this;
}

public Builder withDialect(String dialectName) {
this.dialectName = dialectName;
return this;
}

public Builder withLocations(String locations) {
this.locations = locations;
return this;
}

public Builder withClassLoader(ClassLoader loader) {
this.classLoader = loader;
return this;
}

public Builder withPattern(String pattern) {
if(pattern != null && !pattern.isEmpty())
this.pattern = Pattern.compile(pattern);
return this;
}

public MigTool build() {
this.driver = driverName != null ? Driver.fromDriverName(driverName) : Driver.fromUrl(url);
this.dialect = dialectName != null ? Dialect.fromDialectName(dialectName) : Dialect.fromUrl(url);
return new MigTool(this);
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bit useless. It was avoid on purpose to not implement the builder pattern because it's just redundant

Copy link
Contributor Author

@pgeadas pgeadas Aug 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two main points for this change:

  1. As it is, although it looks like a builder pattern, it is not which is confusing.
  2. The app will fail to run if we do not set up the url first, since there are other fields that depend on it.
    .withUrl(url)
    .withDialect(dialect!=null ? dialect : dialectFromUrl(url))
    .withDriver(driver!=null ? driver : driverFromUrl(url))

    It might "work" in this case since we receive the url as a parameter and configure it directly with those parameters, but to instantiate MigTool from another application without a cli (like the seqera compute manager service), this is just a source of potential issues and bugs (as it happened, hence the change).

* Since the other dialects supported allow the use of backticks, only two builders are added
* {@link PostgresQueryBuilder} and {@link NotPostgresQueryBuilder}.
**/
public abstract class DialectQueryBuilder {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found this solution overkill. It would be enough to have a driver pattern having a default implementation (a couple of methods) covering the current statement and the version for Postgres.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is a driver pattern? Could you provide an example of what you mean?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That kind of things that's simpler to implement, that to describe. If we want to adhere to GoF definition, it would be a template pattern, but also Jdbc driver using a similar approach, this is why I had used that term.

Compare this implementation with the one in this PR (I hadn't time to add tests)

Copy link
Contributor Author

@pgeadas pgeadas Aug 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered this approach, but I don't like it because the common SQL needs to be duplicated in both implementations. Meaning that if we need to change one of the queries in one place, we need to change it in both files (Default and Postgres).

In the end, we also needed to add 3 classes here, so I don't see what we gained using this approach. :)

And this is not a template pattern. As I explain here.

I am proposing a solution now that solves both issues: the one regarding being overkill (since we only have 2 implementations) and the one that implies having the sql string repeated in the subclasses.

Would this be acceptable in your opinion? I think it merges the best of both worlds @pditommaso .

import jakarta.annotation.Nullable;
import java.util.List;

public enum Dialect {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what value adds Dialect and Driver as enum. it would make more sense to implement a driver pattern that can both the type and the method specialisation for the statement specific for postgres. Likely it would require a Driver interface, plus an abstract implementation for the common stuff, and concrete class for each support DB.

An alternative approach could be using a delegate pattern and passing the concrete class as "argument"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that any approach is better than having the names of the drivers/dialects hardcoded as strings, so I just typed them. An enum seemed simple enough for this purpose.

An alternative approach could be using a delegate pattern and passing the concrete class as "argument"

Why are we trying to find alternative approaches here? What is the issue with this one? There are multiple ways of solving the same thing, and as I said, this is already an improvement over what we had.

@pgeadas
Copy link
Contributor Author

pgeadas commented Aug 6, 2024

@pditommaso Could you review my comments please?

@pgeadas pgeadas force-pushed the notask-add-support-to-postgres branch from faf697f to 9b14cd3 Compare August 7, 2024 11:10
@pgeadas pgeadas requested a review from pditommaso August 8, 2024 15:27
@@ -40,6 +40,16 @@ static Language from(String fileName) {
boolean isPatch;
boolean isOverride;

/**
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For example this is missing @pditommaso , otherwise it won't work from Java...

Copy link
Contributor

@pditommaso pditommaso Aug 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this related to Postgres?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this related to Postgres?

image

This won't work from Java, but I guess it is not needed for Postgres.

@pditommaso
Copy link
Contributor

Sorry Pedro, I'm closing in favour of #49. While I'm sure this work correctly, I believe is not a good PR because it conflates together many different things: support for Postres, support for Java, general refactoring, unnecessary complexity, changes the MigTool public API, etc.

Why I think this is bad:

  • make difficult if not impossible to make an effective code review, because there are too many unrelated changes;
  • make it difficult to recreate the history and the rationale of the changes;
  • it can introduce unexpected bugs or side-effects;
  • it's contrary to simplicity and frugality principles;
  • last and even more importantly, software source code is a collaborative effort and shared knowledge. it represents a mental model for all the people that have worked with it and know how to deal with it. Making a radical refactoring - without a substantial reason - it means that all these people (me, Thomas, Veronica, whoever) will need to spend time to learn new data structures, new behaviours, etc for no clear reason.

I don't want to be further pedantic, but I'b be happy to discuss more if needed.

@pditommaso pditommaso closed this Aug 8, 2024
@pgeadas
Copy link
Contributor Author

pgeadas commented Aug 8, 2024

  • make difficult if not impossible to make an effective code review, because there are too many unrelated changes;

This point I can agree with. Some changes are unrelated to Postgres and were done just to make it easier to implement that change. I can split this in different PR's if this is the issue.

Three PR's refactors with:

  • adding the enums instead of hardcoded Strings in the code
  • adding the real builder pattern (as it is, we need to do things from the outside to build the MigTool every time)
  • adding the real template pattern (as it is, the queries are not following any template, if the query changes we need to manually change two classes)

But this is by no means a radical refactor, this is just a cleanup.

it's contrary to simplicity and frugality principles;

I don't think hardcoded strings and methods that do 3 or 4 things at the same time, can be considered simplicity.

it means that all these people (me, Thomas, Veronica, whoever) will need to spend time to learn new data structures, new behaviours, etc for no clear reason.
unnecessary complexity

I think an enum to replace hardcoded Strings and encapsulate behaviours that right now exist on a static helper class, is not "for no reason" and removes complexity, does not increase it. 🤷🏻‍♂️
In fact, I assure you it would be way easier to understand for new people and even the old ones when they need to come back to it.

last and even more importantly, software source code is a collaborative effort and shared knowledge.

I don't think that I am the one missing this point here 👼🏻 The PR already has several approvals from other team members...

Actually me and @tcrespog had discussed these improvements together, in a collaborative way...

I don't want to be further pedantic, but I'b be happy to discuss more if needed.

I could give you all the reasons in the world that it would not have made a difference, so I don't think it is worth discussing more, you are right @pditommaso 🥲

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants