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

ShardingSphere incorrectly handles table INFORMATION_SCHEMA for H2Database 2.X #15327

Closed
linghengqian opened this issue Feb 9, 2022 · 8 comments · Fixed by #19964
Closed

Comments

@linghengqian
Copy link
Member

linghengqian commented Feb 9, 2022

Bug Report

For English only, other languages will not accept.

Before report a bug, make sure you have:

Please pay attention on issues you submitted, because we maybe need more details.
If no response anymore and we cannot reproduce it on current information, we will close it.

Please answer these questions before submitting your issue. Thanks!

Which version of ShardingSphere did you use?

5.1.0

Which project did you use? ShardingSphere-JDBC or ShardingSphere-Proxy?

ShardingSphere-JDBC

Expected behavior

This Issue is an addition to #14617. The expected result is a normal integration of ShardingSphere JDBC 5.1.0 with H2database 2.X. I provide a reproducible Example Source at the end .

Actual behavior

ShardingSphere incorrectly handles table INFORMATION_SCHEMA for H2Database 2.X. When the SpringBoot project started, ShardingSphere executed the wrong SQL. Log as follows

2022-02-17 19:03:45.678  INFO 14512 --- [           main] c.lingh.ShardingsphereH2TestApplication  : No active profile set, falling back to default profiles: default
2022-02-17 19:03:46.617  INFO 14512 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'stringToNoneShardingStrategyConfigurationConverter' of type [org.apache.shardingsphere.spring.boot.converter.StringToNoneShardingStrategyConfigurationConverter] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2022-02-17 19:03:46.633  INFO 14512 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'spring.shardingsphere-org.apache.shardingsphere.spring.boot.prop.SpringBootPropertiesConfiguration' of type [org.apache.shardingsphere.spring.boot.prop.SpringBootPropertiesConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2022-02-17 19:03:46.945  INFO 14512 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.apache.shardingsphere.spring.boot.ShardingSphereAutoConfiguration' of type [org.apache.shardingsphere.spring.boot.ShardingSphereAutoConfiguration$$EnhancerBySpringCGLIB$$fe587a8a] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2022-02-17 19:03:47.133  INFO 14512 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-02-17 19:03:47.149  INFO 14512 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-02-17 19:03:47.149  INFO 14512 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.56]
2022-02-17 19:03:47.258  INFO 14512 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-02-17 19:03:47.258  INFO 14512 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1377 ms
2022-02-17 19:03:47.774  INFO 14512 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2022-02-17 19:03:47.961  INFO 14512 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2022-02-17 19:03:47.961  INFO 14512 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-2 - Starting...
2022-02-17 19:03:47.977  INFO 14512 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-2 - Start completed.
2022-02-17 19:03:47.977  INFO 14512 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-3 - Starting...
2022-02-17 19:03:47.977  INFO 14512 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-3 - Start completed.
2022-02-17 19:03:48.040 ERROR 14512 --- [           main] .a.s.i.m.s.b.l.TableMetaDataLoaderEngine : Dialect load table meta data error

org.h2.jdbc.JdbcSQLSyntaxErrorException: Column "type_name" not found; SQL statement:
SELECT TABLE_CATALOG, TABLE_NAME, COLUMN_NAME, DATA_TYPE, TYPE_NAME, ORDINAL_POSITION FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_CATALOG=? AND TABLE_SCHEMA=? AND TABLE_NAME IN ('t_order0') ORDER BY ORDINAL_POSITION [42122-210]
	at org.h2.message.DbException.getJdbcSQLException(DbException.java:521) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.message.DbException.getJdbcSQLException(DbException.java:496) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.message.DbException.get(DbException.java:227) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.message.DbException.get(DbException.java:203) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.expression.ExpressionColumn.getColumnException(ExpressionColumn.java:248) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.expression.ExpressionColumn.optimizeOther(ExpressionColumn.java:230) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.expression.ExpressionColumn.optimize(ExpressionColumn.java:213) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.command.query.Select.optimizeExpressionsAndPreserveAliases(Select.java:1281) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.command.query.Select.prepare(Select.java:1174) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.command.Parser.prepareCommand(Parser.java:557) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.engine.SessionLocal.prepareLocal(SessionLocal.java:615) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.engine.SessionLocal.prepareCommand(SessionLocal.java:553) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1116) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.jdbc.JdbcPreparedStatement.<init>(JdbcPreparedStatement.java:92) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:288) ~[h2-2.1.210.jar:2.1.210]
	at com.zaxxer.hikari.pool.ProxyConnection.prepareStatement(ProxyConnection.java:337) ~[HikariCP-4.0.3.jar:na]
	at com.zaxxer.hikari.pool.HikariProxyConnection.prepareStatement(HikariProxyConnection.java) ~[HikariCP-4.0.3.jar:na]
	at org.apache.shardingsphere.infra.metadata.schema.builder.loader.dialect.H2TableMetaDataLoader.loadColumnMetaDataMap(H2TableMetaDataLoader.java:81) ~[shardingsphere-infra-common-5.1.0.jar:5.1.0]
	at org.apache.shardingsphere.infra.metadata.schema.builder.loader.dialect.H2TableMetaDataLoader.load(H2TableMetaDataLoader.java:70) ~[shardingsphere-infra-common-5.1.0.jar:5.1.0]
	at org.apache.shardingsphere.infra.metadata.schema.builder.loader.TableMetaDataLoaderEngine.lambda$loadByDialect$0(TableMetaDataLoaderEngine.java:88) ~[shardingsphere-infra-common-5.1.0.jar:5.1.0]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_312]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_312]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_312]
	at java.lang.Thread.run(Thread.java:853) ~[na:1.8.0_312]

2022-02-17 19:03:48.055 ERROR 14512 --- [           main] .a.s.i.m.s.b.l.TableMetaDataLoaderEngine : Dialect load table meta data error

org.h2.jdbc.JdbcSQLSyntaxErrorException: Column "type_name" not found; SQL statement:
SELECT TABLE_CATALOG, TABLE_NAME, COLUMN_NAME, DATA_TYPE, TYPE_NAME, ORDINAL_POSITION FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_CATALOG=? AND TABLE_SCHEMA=? AND TABLE_NAME IN ('user') ORDER BY ORDINAL_POSITION [42122-210]
	at org.h2.message.DbException.getJdbcSQLException(DbException.java:521) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.message.DbException.getJdbcSQLException(DbException.java:496) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.message.DbException.get(DbException.java:227) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.message.DbException.get(DbException.java:203) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.expression.ExpressionColumn.getColumnException(ExpressionColumn.java:248) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.expression.ExpressionColumn.optimizeOther(ExpressionColumn.java:230) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.expression.ExpressionColumn.optimize(ExpressionColumn.java:213) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.command.query.Select.optimizeExpressionsAndPreserveAliases(Select.java:1281) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.command.query.Select.prepare(Select.java:1174) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.command.Parser.prepareCommand(Parser.java:557) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.engine.SessionLocal.prepareLocal(SessionLocal.java:615) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.engine.SessionLocal.prepareCommand(SessionLocal.java:553) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1116) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.jdbc.JdbcPreparedStatement.<init>(JdbcPreparedStatement.java:92) ~[h2-2.1.210.jar:2.1.210]
	at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:288) ~[h2-2.1.210.jar:2.1.210]
	at com.zaxxer.hikari.pool.ProxyConnection.prepareStatement(ProxyConnection.java:337) ~[HikariCP-4.0.3.jar:na]
	at com.zaxxer.hikari.pool.HikariProxyConnection.prepareStatement(HikariProxyConnection.java) ~[HikariCP-4.0.3.jar:na]
	at org.apache.shardingsphere.infra.metadata.schema.builder.loader.dialect.H2TableMetaDataLoader.loadColumnMetaDataMap(H2TableMetaDataLoader.java:81) ~[shardingsphere-infra-common-5.1.0.jar:5.1.0]
	at org.apache.shardingsphere.infra.metadata.schema.builder.loader.dialect.H2TableMetaDataLoader.load(H2TableMetaDataLoader.java:70) ~[shardingsphere-infra-common-5.1.0.jar:5.1.0]
	at org.apache.shardingsphere.infra.metadata.schema.builder.loader.TableMetaDataLoaderEngine.lambda$loadByDialect$0(TableMetaDataLoaderEngine.java:88) ~[shardingsphere-infra-common-5.1.0.jar:5.1.0]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_312]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_312]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_312]
	at java.lang.Thread.run(Thread.java:853) ~[na:1.8.0_312]

2022-02-17 19:03:49.165  INFO 14512 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-02-17 19:03:49.165  INFO 14512 --- [           main] c.lingh.ShardingsphereH2TestApplication  : Started ShardingsphereH2TestApplication in 3.892 seconds (JVM running for 4.686)

Reason analyze (If you can)

H2 Database 2.X changes the structure of the table INFORMATION_SCHEMA, and it behaves normally on H2 Database 1.X. Also give you relevant information. @jeremie1112

I honestly don't know why the select statement is used instead of partly using the DatabaseMetaData class to handle metadata needed in ShardingSphere JDBC. Related to #11994 ?

Steps to reproduce the behavior, such as: SQL to execute, sharding rule configuration, when exception occur etc.

The executed SQL isSELECT TABLE_CATALOG, TABLE_NAME, COLUMN_NAME, DATA_TYPE, TYPE_NAME, ORDINAL_POSITION FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_CATALOG=? AND TABLE_SCHEMA=? AND TABLE_NAME IN ('user') ORDER BY ORDINAL_POSITION

Example codes for reproduce this issue (such as a github link).

I provide a minimal reproduction sample. Just execute the startup class directly. https://github.com/linghengqian/shardingsphere-h2-test

@tuichenchuxin
Copy link
Contributor

This sql is to load tables and columns from database.
But the sql can't be used in H2database 2.X.
Maybe we need to use different sql according to different versions.
Btw, it can work normally. because when the dialect load has error, then we'll use default load.

@linghengqian
Copy link
Member Author

This sql is to load tables and columns from database.
But the sql can't be used in H2database 2.X.
Maybe we need to use different sql according to different versions.
Btw, it can work normally. because when the dialect load has error, then we'll use default load.

This leads to a topic I don't understand. If I need to fetch a class from H2Database in JUnit, how do I get the version, artifactId, groupId of the corresponding component of the class? Does this require a specific Maven plugin?

@tuichenchuxin
Copy link
Contributor

I think we can use mock() currently, and test it yourself.

@linghengqian
Copy link
Member Author

linghengqian commented Jul 12, 2022

  • In my personal testing case, using the 1.x H2database client, which is the client used by the current ShardingSphere master branch, to access the server side of 2.x's H2DataBase is not allowed, and vice versa seems to have a similar problem.

  • update in 2022.07.15: Considering that ShardingSphere's master branch is using JOOQ 3.4, it does not support H2DataBase 2.x. So I tend to solve this problem softly, that is, only change the SQL that corresponds to the execution, without upgrading H2DataBase to 2.x.

  • update in 2022.07.20: Some important classes are changed in the master branch, refer to Merge memory and standalone mode #19001 . I'll try something else after the release of Apache ShardingSphere 5.1.3.

  • update in 2022.08.02: Wait for Redesign JDBCRepository and H2Repository #19655 to be resolved. Then I can see if I need to write an extra class for H2DataBase 2.x.

@huangxinjian
Copy link

You are very patient and I admire your ability to keep track of issues!

@linghengqian
Copy link
Member Author

You are very patient and I admire your ability to keep track of issues!

  • In fact, there is a simplest fix for this issue, but I have not been able to write a reasonable unit test for it. 🤦‍♂️ Because this involves two different versions of H2Database. I pushed the relevant PR a while ago . I can only guarantee that the PR is passed in my local test example.

  • I'd appreciate it if anyone would be willing to write unit tests.

@terrymanu
Copy link
Member

terrymanu commented Aug 3, 2022

I just carry my comments from the PR:

The H2 database is the substitute for test only of MySQL, and version 1.x is the explicit dependency. So it is unnecessary to judge the major database version.
If the version 2.x of H2 is not compatible, I wonder how to test MySQL in memory.

To sum up, what is the proposal to upgrade H2 version from 1.x to 2.x?

@linghengqian
Copy link
Member Author

linghengqian commented Aug 3, 2022

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment