question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Parameterized limit in update/delete statement doesn't work on MySQL proxy

See original GitHub issue

Bug Report

Which version of ShardingSphere did you use?

5.0.0-RC1-SNAPSHOT

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

ShardingSphere-Proxy

Expected behavior

Sql could be executed correctly, just like MySQL 5.7 server.

Actual behavior

Exception thrown:

Exception in thread "main" java.sql.SQLException: Parameter index out of bounds. 4 is not between valid values of 1 and 3
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:965)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:898)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:887)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:861)
	at com.mysql.jdbc.ServerPreparedStatement.getBinding(ServerPreparedStatement.java:867)
	at com.mysql.jdbc.ServerPreparedStatement.setInt(ServerPreparedStatement.java:1856)

Reason analyze (If you can)

mysql-connector-java-5.1.48
ServerPreparedStatement.java, serverPrepare(String sql)
                Buffer prepareResultPacket = mysql.sendCommand(MysqlDefs.COM_PREPARE, sql, null, false, characterEncoding, 0);

                if (this.connection.versionMeetsMinimum(4, 1, 1)) {
                    // 4.1.1 and newer use the first byte as an 'ok' or 'error' flag, so move the buffer pointer past it to start reading the statement id.
                    prepareResultPacket.setPosition(1);
                } else {
                    // 4.1.0 doesn't use the first byte as an 'ok' or 'error' flag
                    prepareResultPacket.setPosition(0);
                }

                this.serverStatementId = prepareResultPacket.readLong();
                this.fieldCount = prepareResultPacket.readInt();
                this.parameterCount = prepareResultPacket.readInt();
                this.parameterBindings = new BindValue[this.parameterCount];
this.parameterCount is 3, which is from proxy server side, but it's 4 in fact
org.apache.shardingsphere.proxy.frontend.mysql.command.query.binary.prepare.MySQLComStmtPrepareExecutor.java, execute()
        SQLStatement sqlStatement = schema.getRuntimeContext().getSqlParserEngine().parse(packet.getSql(), true);
        if (!MySQLComStmtPrepareChecker.isStatementAllowed(sqlStatement)) {
            result.add(new MySQLErrPacket(++currentSequenceId, MySQLServerErrorCode.ER_UNSUPPORTED_PS));
            return result;
        }
        int parametersCount = sqlStatement.getParameterCount();
parametersCount is 3 after parsing

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

Run sql via jdbc:

jdbcUrl:
jdbc:mysql://127.0.0.1:3307/sharding_db?serverTimezone=UTC&useSSL=false&useServerPrepStmts=true&cachePrepStmts=true

sql:
update t_order set status = ? where order_id = ? or (user_id = ? and status='PAID') limit ?
delete from t_order where order_id = ? or (user_id = ? and status = ?) limit ?

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

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:11 (11 by maintainers)

github_iconTop GitHub Comments

1reaction
strongduanmucommented, Aug 21, 2020

@sandynz Now the update statement and delete statement do not support limit clause parameterized parse, and I will try to implement this feature. Thanks again for your feedback. 😀

0reactions
strongduanmucommented, Aug 24, 2020

@sandynz Thanks for your rapid tests! That is precisely in our expectations. 😃 What do you think @strongduanmu ?

@tristaZero Yes, currently only support sharding route to single data node.

Read more comments on GitHub >

github_iconTop Results From Across the Web

MySQL 5.7 Reference Manual :: 5.1.7 Server System Variables
Each system variable has a default value. System variables can be set at server startup using options on the command line or in...
Read more >
Forcing a LIMIT to MySQL Queries using ProxySQL ...
We wanted to ensure every SELECT statement ends with a LIMIT 100000. I have thought of some regex to do this and some...
Read more >
How does 'LIMIT' parameter work in sql? - Stack Overflow
From MySQL Reference Manual: If you use LIMIT row_count with ORDER BY, MySQL ends the sorting as soon as it has found the...
Read more >
12. Data access with JDBC - Spring
The JdbcTemplate class executes SQL queries, update statements and stored procedure calls, performs iteration over ResultSet s and extraction of returned ...
Read more >
Database Engine events and errors - SQL Server
The maximum allowable is %d. 107, 15, No, The column prefix '%.*ls' does not match with a table name or alias name used...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found