Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix for CONJ-116: Make SQLException prettier when too large packet is…
… sent to the server
  • Loading branch information
massimosiani committed Dec 12, 2014
1 parent 80ca861 commit 8e507c4
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 3 deletions.
Expand Up @@ -66,7 +66,6 @@ public class StreamedQueryPacket implements CommandPacket
public StreamedQueryPacket(final Query query)
{
this.query = query;

}

public int send(final OutputStream ostream) throws IOException,
Expand All @@ -79,4 +78,8 @@ public int send(final OutputStream ostream) throws IOException,
pos.finishPacket();
return 0;
}

public int getPacketLength() {
return query.getPacketLength();
}
}
Expand Up @@ -199,4 +199,27 @@ public String toSQL() {
}
}

private String toSQL2() throws UnsupportedEncodingException {
if(queryPartsArray.length == 0) {
return "";
}
String result;
result = new String(queryPartsArray[0], "UTF-8");
for(int i = 1; i<queryPartsArray.length; i++) {
result += parameters[i-1];
if(queryPartsArray[i].length != 0)
result += new String(queryPartsArray[i], "UTF-8");
}
return result;
}

@Override
public int getPacketLength() {
try {
return toSQL2().getBytes("UTF-8").length;
} catch (UnsupportedEncodingException e) {
return -1;
}
}

}
Expand Up @@ -115,5 +115,10 @@ public String toString() {
return query;
}

@Override
public int getPacketLength() {
return length();
}


}
Expand Up @@ -60,4 +60,5 @@ public interface Query {
String getQuery();
QueryType getQueryType();
void validate() throws QueryException;
int getPacketLength();
}
10 changes: 10 additions & 0 deletions src/main/java/org/mariadb/jdbc/internal/mysql/MySQLProtocol.java
Expand Up @@ -1006,6 +1006,16 @@ public QueryResult executeQuery(final Query dQuery, boolean streaming) throws Qu
this.moreResults = false;
final StreamedQueryPacket packet = new StreamedQueryPacket(dQuery);

int packetLength = packet.getPacketLength();
if (this.maxAllowedPacket > 0 && packetLength > 0 && packetLength > this.maxAllowedPacket) {
throw new QueryException("Packet for query is too large ("
+ packetLength
+ " > "
+ this.maxAllowedPacket
+ "). You can change this value on the server by setting the max_allowed_packet' variable.",
-1, SQLExceptionMapper.SQLStates.UNDEFINED_SQLSTATE.getSqlState());
}

try {
packet.send(writer);
} catch (IOException e) {
Expand Down
43 changes: 42 additions & 1 deletion src/test/java/org/mariadb/jdbc/ConnectionTest.java
Expand Up @@ -2,6 +2,8 @@

import static org.junit.Assert.*;

import java.io.UnsupportedEncodingException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLPermission;
import java.sql.Statement;
Expand Down Expand Up @@ -49,7 +51,7 @@ public void abortTest() throws SQLException {
try {
securityManager.checkPermission(sqlPermission);
} catch (SecurityException se) {
System.out.println("test 'aborttest' skipped due to missing policy");
System.out.println("test 'abortTest' skipped due to missing policy");
return;
}
}
Expand All @@ -70,5 +72,44 @@ public void execute(Runnable command) {
stmt.close();
}
}

/**
* CONJ-116: Make SQLException prettier when too large packet is sent to the server
* @throws SQLException
* @throws UnsupportedEncodingException
*/
@Test
public void maxAllowedPackedExceptionIsPrettyTest() throws SQLException, UnsupportedEncodingException {
int maxAllowedPacket = 1024 * 1024;
Statement statement = connection.createStatement();
ResultSet rs = statement.executeQuery("SHOW VARIABLES LIKE 'max_allowed_packet'");
if (rs.next()) {
maxAllowedPacket = rs.getInt(2);
}
rs.close();
statement.execute("DROP TABLE IF EXISTS dummy");
statement.execute("CREATE TABLE dummy (a BLOB)");
//Create a SQL packet bigger than maxAllowedPacket
StringBuilder sb = new StringBuilder();
String rowData = "('this is a dummy row values')";
int rowsToWrite = (maxAllowedPacket / rowData.getBytes("UTF-8").length) + 1;
for (int row = 1; row <= rowsToWrite; row++) {
if (row >= 2) {
sb.append(", ");
}
sb.append(rowData);
}
String sql = "INSERT INTO dummy VALUES " + sb.toString();
try {
statement.executeUpdate(sql);
fail("The previous statement should throw an SQLException");
} catch (SQLException e) {
assertTrue(e.getMessage().contains("max_allowed_packet"));
} catch (Exception e) {
fail("The previous statement should throw an SQLException not a general Exception");
} finally {
statement.execute("DROP TABLE dummy");
}
}

}
2 changes: 1 addition & 1 deletion src/test/java/org/mariadb/jdbc/DriverTest.java
Expand Up @@ -1603,8 +1603,8 @@ public void emptyBatch() throws Exception {
@Test
public void createDbWithSpacesTest() throws SQLException {
String oldDb = mDatabase;
setParameters("&createDB=true");
setDatabase("test with spaces");
setConnection("&createDB=true");
DatabaseMetaData dbmd = connection.getMetaData();
ResultSet rs = dbmd.getCatalogs();
boolean foundDb = false;
Expand Down

0 comments on commit 8e507c4

Please sign in to comment.