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

[jdbc] Fix tableCaseSensitiveItemNames for PostgreSQL/TimescaleDB #17587

Open
wants to merge 12 commits into
base: main
Choose a base branch
from

Conversation

JonathanvdGHU
Copy link

Case-sensitive tables working for TimescaleDB database via JDBC persistence service

Description

The following issue is resolved. My implementation is maybe not the best one because I didn't take the time to understand everything. So I don't mind if someone makes some small adjustments and makes a new pull request :)

@JonathanvdGHU JonathanvdGHU requested a review from a team as a code owner October 18, 2024 15:08
@jlaur jlaur linked an issue Oct 18, 2024 that may be closed by this pull request
Signed-off-by: JonathanvdGHU <jonathan.vandegiessen@student.hu.nl>
@jlaur
Copy link
Contributor

jlaur commented Oct 18, 2024

Thanks for the fix. I'll review this in the weekend.

@jlaur jlaur added the bug An unexpected problem or unintended behavior of an add-on label Oct 18, 2024
@JonathanvdGHU
Copy link
Author

Thanks for the fix. I'll review this in the weekend.

Good to hear. Is it a big problem I made a mess with the commits? I am trying to do a rebase but it's not really working.

@jlaur
Copy link
Contributor

jlaur commented Oct 18, 2024

Good to hear. Is it a big problem I made a mess with the commits?

It seems some commits are incorrectly signed. If there is at least one correctly signed commit, I can use that when squash-merging. Otherwise you will need to rebase to fix it.

Signed-off-by: JonathanvdGHU <jonathan.vandegiessen@student.hu.nl>
Signed-off-by: JonathanvdGHU <jonathan.vandegiessen@student.hu.nl>
@JonathanvdGHU
Copy link
Author

Good to hear. Is it a big problem I made a mess with the commits?

It seems some commits are incorrectly signed. If there is at least one correctly signed commit, I can use that when squash-merging. Otherwise you will need to rebase to fix it.

I fixed it. This was my first rebase so I am also a little proud about myself xD

Signed-off-by: JonathanvdGHU <jonathan.vandegiessen@student.hu.nl>
@jlaur jlaur changed the title Case-sensitive tables working for TimescaleDB database via JDBC persistence service [jdbc] Case-sensitive tables working for TimescaleDB database via JDBC persistence service Oct 18, 2024
Copy link
Contributor

@jlaur jlaur left a comment

Choose a reason for hiding this comment

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

The fix looks valid, but I have provided some feedback on the approach. I think it would be preferable to keep the DTO's unchanged and instead directly fix the queries which only concern PostgreSQL/TimescaleDB.

@jlaur jlaur changed the title [jdbc] Case-sensitive tables working for TimescaleDB database via JDBC persistence service [jdbc] Fix tableCaseSensitiveItemNames for PostgreSQL/TimescaleDB Oct 19, 2024
Signed-off-by: JonathanvdGHU <jonathan.vandegiessen@student.hu.nl>
@JonathanvdGHU
Copy link
Author

The fix looks valid, but I have provided some feedback on the approach. I think it would be preferable to keep the DTO's unchanged and instead directly fix the queries which only concern PostgreSQL/TimescaleDB.

I implemented your requested changes :)

Signed-off-by: JonathanvdGHU <jonathan.vandegiessen@student.hu.nl>
@jlaur
Copy link
Contributor

jlaur commented Oct 19, 2024

I implemented your requested changes :)

Thanks! I'll take one more look. In the meantime, I see there are formatting changes for comments, why is that? I just want to avoid having this changed back and forth depending on some individual IDE settings, if that's the case. It also disturbs diff'ing. 😉

Copy link
Contributor

@jlaur jlaur left a comment

Choose a reason for hiding this comment

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

Last batch of comments, I hope. 🙂

Comment on lines 171 to 182
@Override
public void doDropTable(String tableName) throws JdbcSQLException {
String sql = StringUtilsExt.replaceArrayMerge(this.sqlDropTable, new String[] { "#tableName#" },
new String[] { tableName });
logger.debug("JDBC::doDropTable sql={}", sql);
try {
Yank.execute(sql, null);
} catch (YankSQLException e) {
throw new JdbcSQLException(e);
}
}

Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like this method doesn't differ from the base implementation, so there should be no reason to override it?

Copy link
Author

Choose a reason for hiding this comment

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

The method doesn't differ but the query it uses does.

Copy link
Contributor

Choose a reason for hiding this comment

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

The overridden query will still be used by the base implementation. See for example query sqlIfTableExists which is overridden in JdbcPostgresqlDAO (and other subclasses), but doIfTableExists is only implemented in JdbcBaseDAO.

Copy link
Author

Choose a reason for hiding this comment

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

I didn't know that.

Comment on lines 235 to 247
@Override
public void doCreateItemTable(ItemVO vo) throws JdbcSQLException {
String sql = StringUtilsExt.replaceArrayMerge(this.sqlCreateItemTable,
new String[] { "#tableName#", "#dbType#", "#tablePrimaryKey#" },
new String[] { vo.getTableName(), vo.getDbType(), sqlTypes.get("tablePrimaryKey") });
logger.debug("JDBC::doCreateItemTable sql={}", sql);
try {
Yank.execute(sql, null);
} catch (YankSQLException e) {
throw new JdbcSQLException(e);
}
}

Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like this method doesn't differ from the base implementation, so there should be no reason to override it?

The comment above also refers to doAlterTableColumn, which is now below this method.

Copy link
Author

Choose a reason for hiding this comment

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

It's the same case here, I added the override because the query it uses needed to be changed.

@@ -226,7 +269,7 @@ public void doAlterTableColumn(String tableName, String columnName, String colum
@Override
public void doStoreItemValue(Item item, State itemState, ItemVO vo) throws JdbcSQLException {
ItemVO storedVO = storeItemValueProvider(item, itemState, vo);
String sql = StringUtilsExt.replaceArrayMerge(sqlInsertItemValue,
String sql = StringUtilsExt.replaceArrayMerge(this.sqlInsertItemValue,
Copy link
Contributor

Choose a reason for hiding this comment

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

Please revert:

Suggested change
String sql = StringUtilsExt.replaceArrayMerge(this.sqlInsertItemValue,
String sql = StringUtilsExt.replaceArrayMerge(sqlInsertItemValue,

We generally only use this. prefixes when necessary.

Copy link
Author

Choose a reason for hiding this comment

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

I used the this. because otherwise it uses the default implementation query.

Copy link
Contributor

Choose a reason for hiding this comment

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

It will be implicitly considered as this.sqlInsertItemValue. Otherwise you would have to reference it by super.sqlInsertItemValue.

@@ -241,7 +284,7 @@ public void doStoreItemValue(Item item, State itemState, ItemVO vo) throws JdbcS
@Override
public void doStoreItemValue(Item item, State itemState, ItemVO vo, ZonedDateTime date) throws JdbcSQLException {
ItemVO storedVO = storeItemValueProvider(item, itemState, vo);
String sql = StringUtilsExt.replaceArrayMerge(sqlInsertItemValue,
String sql = StringUtilsExt.replaceArrayMerge(this.sqlInsertItemValue,
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
String sql = StringUtilsExt.replaceArrayMerge(this.sqlInsertItemValue,
String sql = StringUtilsExt.replaceArrayMerge(sqlInsertItemValue,

Comment on lines 300 to 312
@Override
public long doGetRowCount(String tableName) throws JdbcSQLException {
final String sql = StringUtilsExt.replaceArrayMerge(this.sqlGetRowCount, new String[] { "#tableName#" },
new String[] { tableName });
logger.debug("JDBC::doGetRowCount sql={}", sql);
try {
final @Nullable Long result = Yank.queryScalar(sql, Long.class, null);
return Objects.requireNonNullElse(result, 0L);
} catch (YankSQLException e) {
throw new JdbcSQLException(e);
}
}

Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like this method doesn't differ from the base implementation, so there should be no reason to override it?


@Override
public List<ItemsVO> doGetItemTables(ItemsVO vo) throws JdbcSQLException {
String sql = StringUtilsExt.replaceArrayMerge(this.sqlGetItemTables, new String[] { "#itemsManageTable#" },
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
String sql = StringUtilsExt.replaceArrayMerge(this.sqlGetItemTables, new String[] { "#itemsManageTable#" },
String sql = StringUtilsExt.replaceArrayMerge(sqlGetItemTables, new String[] { "#itemsManageTable#" },

Comment on lines 75 to 80
// The PostgreSQL equivalent to MySQL columns.column_type is data_type (e.g.
// "timestamp with time zone") and
// udt_name which contains a shorter alias (e.g. "timestamptz"). We alias
// data_type as "column_type" and
// udt_name as "column_type_alias" to be compatible with the 'Column' class used
// in Yank.queryBeanList
Copy link
Contributor

Choose a reason for hiding this comment

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

Related to my other comment, this new line wrapping clearly does not improve formatting since not fully reformatted. Can you please revert all?

@jlaur
Copy link
Contributor

jlaur commented Oct 19, 2024

I think it would be preferable to keep the DTO's unchanged and instead directly fix the queries which only concern PostgreSQL/TimescaleDB.

I can see now after the latest changes the dilemma here when overridden queries differ only in table name being quoted. With the approach I suggested, those queries are now overridden, which feels like duplication. For example:

sqlDropTable = "DROP TABLE \"#tableName#\"";

overriding:

    protected String sqlDropTable = "DROP TABLE #tableName#";

With your original approach, instead we would have had to overload the methods only to call a different DTO method, which would have been even worse.

So it seems we would need to do something different to fully avoid duplication. What would you think about introducing a protected method getTableName in JdbcBaseDAO, something like this:

    protected String getTableName(ItemsVO vo) {
        return vo.getTableName();
    }

which could then be used from all query methods, i.e. getTableName(vo) rather than vo.getTableName()?

This would allow for overriding this method for PostgreSQL to return the quoted table name, but without changing any query methods or queries when they are not otherwise needed to be adapted for PostgreSQL?

This is just from the top of my head and all optional, and if you prefer to stick with your current implementation, that's fine as well.

Signed-off-by: JonathanvdGHU <jonathan.vandegiessen@student.hu.nl>
@JonathanvdGHU
Copy link
Author

I implemented your requested changes :)

Thanks! I'll take one more look. In the meantime, I see there are formatting changes for comments, why is that? I just want to avoid having this changed back and forth depending on some individual IDE settings, if that's the case. It also disturbs diff'ing. 😉

It was the IDE 😅.

@JonathanvdGHU
Copy link
Author

JonathanvdGHU commented Oct 19, 2024

I think it would be preferable to keep the DTO's unchanged and instead directly fix the queries which only concern PostgreSQL/TimescaleDB.

I can see now after the latest changes the dilemma here when overridden queries differ only in table name being quoted. With the approach I suggested, those queries are now overridden, which feels like duplication. For example:

sqlDropTable = "DROP TABLE \"#tableName#\"";

overriding:

    protected String sqlDropTable = "DROP TABLE #tableName#";

With your original approach, instead we would have had to overload the methods only to call a different DTO method, which would have been even worse.

So it seems we would need to do something different to fully avoid duplication. What would you think about introducing a protected method getTableName in JdbcBaseDAO, something like this:

    protected String getTableName(ItemsVO vo) {
        return vo.getTableName();
    }

which could then be used from all query methods, i.e. getTableName(vo) rather than vo.getTableName()?

This would allow for overriding this method for PostgreSQL to return the quoted table name, but without changing any query methods or queries when they are not otherwise needed to be adapted for PostgreSQL?

This is just from the top of my head and all optional, and if you prefer to stick with your current implementation, that's fine as well.

I also thought it was duplication so that's why I added the function getQuotedTableName to the DTO's. I think it's a good idea but to be honest, I don't have much time to do it. So maybe someone can change it later to improve the code.

Signed-off-by: JonathanvdGHU <jonathan.vandegiessen@student.hu.nl>
@JonathanvdGHU
Copy link
Author

Last batch of comments, I hope. 🙂

I think it's now done.

Signed-off-by: JonathanvdGHU <jonathan.vandegiessen@student.hu.nl>

re-added deleted changed from rebase

Signed-off-by: JonathanvdGHU <jonathan.vandegiessen@student.hu.nl>

removed not related code to the bug

Signed-off-by: JonathanvdGHU <jonathan.vandegiessen@student.hu.nl>

implemented feedback

Signed-off-by: JonathanvdGHU <jonathan.vandegiessen@student.hu.nl>

changes also implied on itemsmanagetable

Signed-off-by: JonathanvdGHU <jonathan.vandegiessen@student.hu.nl>

reverted notes

Signed-off-by: JonathanvdGHU <jonathan.vandegiessen@student.hu.nl>

reverted missed notes

removed unnecessary methods

Signed-off-by: JonathanvdGHU <jonathan.vandegiessen@student.hu.nl>
Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
Copy link
Contributor

@jlaur jlaur left a comment

Choose a reason for hiding this comment

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

LGTM - thanks! I'll wait for confirmation that everything still works correctly after the latest changes. 🙂

@jlaur
Copy link
Contributor

jlaur commented Oct 19, 2024

I also thought it was duplication so that's why I added the function getQuotedTableName to the DTO's.

The problem with that is that you would need to overload all methods in order to call the alternative DTO method, so that would generate even more duplication - it would just be duplicated methods rather than duplicated query strings.

I think it's a good idea but to be honest, I don't have much time to do it. So maybe someone can change it later to improve the code.

That's fine, I'll see if I can find some time to refactor this later.

@JonathanvdGHU
Copy link
Author

LGTM - thanks! I'll wait for confirmation that everything still works correctly after the latest changes. 🙂

Thanks for the patience for all this 😌

@jlaur
Copy link
Contributor

jlaur commented Oct 19, 2024

Thanks for the patience for all this 😌

Likewise. 😉 Before merging, besides test confirmation, there is one more thing needed: When checking the failed DCO, I noticed that your real (full) name is missing in your signoffs. You can fix both issues by rebasing your commits. If you click "Details" right to "DCO", you can see how to do that. If you are not comfortable with that, I can fix the signoff when squash-merging the PR. In that case I'd just need your full name. Thanks!

@JonathanvdGHU
Copy link
Author

JonathanvdGHU commented Oct 19, 2024

Thanks for the patience for all this 😌

Likewise. 😉 Before merging, besides test confirmation, there is one more thing needed: When checking the failed DCO, I noticed that your real (full) name is missing in your signoffs. You can fix both issues by rebasing your commits. If you click "Details" right to "DCO", you can see how to do that. If you are not comfortable with that, I can fix the signoff when squash-merging the PR. In that case I'd just need your full name. Thanks!

My full name is included in my email, that you can see in the signoff. I'll update it if I return for any future bug fixes! 😅. So you can use that name for squash-merging. I tested on another branch how to rebase successfully (there are a lot of merge conflicts) but I think it's the easiest way if you do it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug An unexpected problem or unintended behavior of an add-on
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[jdbc] TimescaleDB persistence didn’t create correct tables
2 participants