Skip to content

Commit

Permalink
[CONJ-368] performance improvement storing data in result-set - part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
rusher committed Mar 29, 2017
1 parent 03478c5 commit e507689
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 83 deletions.
2 changes: 1 addition & 1 deletion src/main/java/org/mariadb/jdbc/MariaDbStatement.java
Expand Up @@ -906,7 +906,7 @@ public void setCursorName(final String name) throws SQLException {
* @return the connection
* @throws SQLException if connection is invalid
*/
public Connection getConnection() throws SQLException {
public MariaDbConnection getConnection() throws SQLException {
return this.connection;
}

Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/mariadb/jdbc/internal/ColumnType.java
Expand Up @@ -357,4 +357,5 @@ public int getType() {
public String getJavaTypeName() {
return javaTypeName;
}

}
Expand Up @@ -67,7 +67,6 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWIS
import org.mariadb.jdbc.internal.com.read.dao.ColumnNameMap;
import org.mariadb.jdbc.internal.com.read.dao.Results;
import org.mariadb.jdbc.internal.io.input.PacketInputStream;
import org.mariadb.jdbc.internal.util.ExceptionCode;
import org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper;
import org.mariadb.jdbc.internal.util.Options;
import org.mariadb.jdbc.internal.com.read.Buffer;
Expand Down Expand Up @@ -147,8 +146,8 @@ public class SelectResultSet implements ResultSet {
private int dataFetchTime;
private boolean streaming;
private int columnInformationLength;
private List<byte[]> resultSet;
private int resultSetSize;
private byte[][] data;
private int dataSize;
private int fetchSize;
private int resultSetScrollType;
private int rowPointer;
Expand Down Expand Up @@ -199,19 +198,19 @@ public SelectResultSet(ColumnInformation[] columnInformation, Results results, P
}
this.fetchSize = results.getFetchSize();
this.resultSetScrollType = results.getResultSetScrollType();
this.resultSet = new ArrayList<>();
this.resultSetSize = 0;
this.dataSize = 0;
this.dataFetchTime = 0;
this.rowPointer = -1;
this.callableResult = callableResult;

if (fetchSize == 0 || callableResult) {
this.data = new byte[10][];
fetchAllResults();
streaming = false;
} else {
cursorFetch = results.getCursorFetch();
protocol.setActiveStreamingResult(results);
resultSet = new ArrayList<>(fetchSize);
data = new byte[Math.max(10, fetchSize)][];
nextStreamingValue();
streaming = true;
}
Expand Down Expand Up @@ -252,8 +251,8 @@ public SelectResultSet(ColumnInformation[] columnInformation, List<byte[]> resul
this.isBinaryEncoded = false;
this.fetchSize = 1;
this.resultSetScrollType = resultSetScrollType;
this.resultSet = resultSet;
this.resultSetSize = this.resultSet.size();
this.data = resultSet.toArray(new byte[10][]);
this.dataSize = resultSet.size();
this.dataFetchTime = 0;
this.rowPointer = -1;
this.callableResult = false;
Expand Down Expand Up @@ -334,13 +333,11 @@ public static SelectResultSet createEmptyResultSet() {

private void fetchAllResults() throws IOException, SQLException {

final List<byte[]> valueObjects = new ArrayList<>();
while (readNextValue(valueObjects)) {
dataSize = 0;
while (readNextValue()) {
//fetch all results
}
dataFetchTime++;
resultSet = valueObjects;
this.resultSetSize = resultSet.size();
}

/**
Expand All @@ -359,7 +356,6 @@ public void fetchRemaining() throws SQLException {
while (!isEof) {
addStreamingValue();
}
resultSetSize = resultSet.size();
} finally {
lock.unlock();
}
Expand Down Expand Up @@ -405,7 +401,7 @@ private void nextStreamingValue() throws IOException, SQLException {
lastRowPointer = -1;

//if resultSet can be back to some previous value
if (resultSetScrollType == TYPE_FORWARD_ONLY) resultSet.clear();
if (resultSetScrollType == TYPE_FORWARD_ONLY) dataSize = 0;

addStreamingValue();

Expand All @@ -424,8 +420,9 @@ private void addStreamingValue() throws IOException, SQLException {
try {
//use COM_STMT_FETCH to ask next resultSet with fetchSize rows
cursorFetch.send(protocol.getWriter(), fetchSize);

//fetch the whole next resultSet
while (readNextValue(resultSet)) {
while (readNextValue()) {
//read all
}
} finally {
Expand All @@ -435,26 +432,23 @@ private void addStreamingValue() throws IOException, SQLException {
} else {
//read only fetchSize values
int fetchSizeTmp = fetchSize;
while (fetchSizeTmp > 0 && readNextValue(resultSet)) {
while (fetchSizeTmp > 0 && readNextValue()) {
fetchSizeTmp--;
}

}

dataFetchTime++;
this.resultSetSize = resultSet.size();

}

/**
* Read next value.
*
* @param values values
* @return true if have a new value
* @throws IOException exception
* @throws SQLException exception
*/
public boolean readNextValue(List<byte[]> values) throws IOException, SQLException {
public boolean readNextValue() throws IOException, SQLException {
byte[] buf = reader.getPacketArray(false);

//is error Packet
Expand Down Expand Up @@ -488,10 +482,22 @@ public boolean readNextValue(List<byte[]> values) throws IOException, SQLExcepti
return false;
}

values.add(buf);
if (dataSize + 1 >= data.length) growDataArray();
data[dataSize++] = buf;
return true;
}

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

/**
* Grow data array.
*/
private void growDataArray() {
int newCapacity = data.length + (data.length >> 1);
if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = MAX_ARRAY_SIZE;
data = Arrays.copyOf(data, newCapacity);
}

/**
* Close resultSet.
*/
Expand Down Expand Up @@ -543,18 +549,19 @@ public void close() throws SQLException {
isEof = true;
}

resultSet.clear();
//keep garbage easy
for (int i = 0; i < data.length; i++) data[i] = null;

if (statement != null) {
((MariaDbStatement) statement).checkCloseOnCompletion(this);
statement.checkCloseOnCompletion(this);
statement = null;
}
}

@Override
public boolean next() throws SQLException {
if (isClosed) throw new SQLException("Operation not permit on a closed resultSet", "HY000");
if (rowPointer < resultSetSize - 1) {
if (rowPointer < dataSize - 1) {
rowPointer++;
return true;
} else {
Expand All @@ -575,48 +582,41 @@ public boolean next() throws SQLException {
if (resultSetScrollType == TYPE_FORWARD_ONLY) {
//resultSet has been cleared. next value is pointer 0.
rowPointer = 0;
return resultSetSize > 0;
return dataSize > 0;
} else {
// cursor can move backward, so driver must keep the results.
// results have been added to current resultSet
rowPointer++;
return resultSetSize > rowPointer;
return dataSize > rowPointer;
}
}

//all data are reads and pointer is after last
rowPointer = resultSetSize;
rowPointer = dataSize;
return false;
}
}

protected void checkObjectRange(int position) throws SQLException {
if (this.rowPointer < 0) {
throwError("Current position is before the first row", ExceptionCode.INVALID_PARAMETER_VALUE);
private void checkObjectRange(int position) throws SQLException {
if (rowPointer < 0) {
throw new SQLDataException("Current position is before the first row", "22023");
}
if (this.rowPointer >= resultSetSize) {
throwError("Current position is after the last row", ExceptionCode.INVALID_PARAMETER_VALUE);

if (rowPointer >= dataSize) {
throw new SQLDataException("Current position is after the last row", "22023");
}

if (position <= 0 || position > columnsInformation.length) {
throwError("No such column: " + position, ExceptionCode.INVALID_PARAMETER_VALUE);
if (position <= 0 || position > columnInformationLength) {
throw new SQLDataException("No such column: " + position, "22023");
}

if (lastRowPointer != rowPointer) {
row.resetRow(resultSet.get(this.rowPointer));
row.resetRow(data[rowPointer]);
lastRowPointer = rowPointer;
}
this.lastValueNull = row.setPosition(position - 1);
}

private void throwError(String message, ExceptionCode exceptionCode) throws SQLException {
if (statement != null) {
ExceptionMapper.throwException(new SQLException(message, ExceptionCode.INVALID_PARAMETER_VALUE.sqlState),
(MariaDbConnection) this.statement.getConnection(), this.statement);
} else {
throw new SQLException(message, exceptionCode.sqlState);
}
}

@Override
public SQLWarning getWarnings() throws SQLException {
if (this.statement == null) {
Expand All @@ -635,13 +635,13 @@ public void clearWarnings() throws SQLException {
@Override
public boolean isBeforeFirst() throws SQLException {
checkClose();
return (dataFetchTime > 0) ? rowPointer == -1 && resultSetSize > 0 : rowPointer == -1;
return (dataFetchTime > 0) ? rowPointer == -1 && dataSize > 0 : rowPointer == -1;
}

@Override
public boolean isAfterLast() throws SQLException {
checkClose();
if (rowPointer < resultSetSize) {
if (rowPointer < dataSize) {

//has remaining results
return false;
Expand All @@ -666,29 +666,29 @@ public boolean isAfterLast() throws SQLException {
lock.unlock();
}

return resultSetSize == rowPointer;
return dataSize == rowPointer;
}

//has read all data and pointer is after last result
//so result would have to always to be true,
//but when result contain no row at all jdbc say that must return false
return resultSetSize > 0 || dataFetchTime > 1;
return dataSize > 0 || dataFetchTime > 1;
}
}

@Override
public boolean isFirst() throws SQLException {
checkClose();
return dataFetchTime == 1 && rowPointer == 0 && resultSetSize > 0;
return dataFetchTime == 1 && rowPointer == 0 && dataSize > 0;
}

@Override
public boolean isLast() throws SQLException {
checkClose();
if (rowPointer < resultSetSize - 1) {
if (rowPointer < dataSize - 1) {
return false;
} else if (isEof) {
return rowPointer == resultSetSize - 1 && resultSetSize > 0;
return rowPointer == dataSize - 1 && dataSize > 0;
} else {
//when streaming and not having read all results,
//must read next packet to know if next packet is an EOF packet or some additional data
Expand All @@ -707,7 +707,7 @@ public boolean isLast() throws SQLException {

if (isEof) {
//now driver is sure when data ends.
return rowPointer == resultSetSize - 1 && resultSetSize > 0;
return rowPointer == dataSize - 1 && dataSize > 0;
}

//There is data remaining
Expand All @@ -729,7 +729,7 @@ public void beforeFirst() throws SQLException {
public void afterLast() throws SQLException {
checkClose();
fetchRemainingLock();
rowPointer = resultSetSize;
rowPointer = dataSize;
}

@Override
Expand All @@ -741,14 +741,14 @@ public boolean first() throws SQLException {
}

rowPointer = 0;
return resultSetSize > 0;
return dataSize > 0;
}

@Override
public boolean last() throws SQLException {
checkClose();
fetchRemainingLock();
rowPointer = resultSetSize - 1;
rowPointer = dataSize - 1;
return rowPointer > 0;
}

Expand All @@ -769,7 +769,7 @@ public boolean absolute(int row) throws SQLException {
throw new SQLException("Invalid operation for result set type TYPE_FORWARD_ONLY");
}

if (row >= 0 && row <= resultSetSize) {
if (row >= 0 && row <= dataSize) {
rowPointer = row - 1;
return true;
}
Expand All @@ -779,19 +779,19 @@ public boolean absolute(int row) throws SQLException {

if (row >= 0) {

if (row <= resultSetSize) {
if (row <= dataSize) {
rowPointer = row - 1;
return true;
}

rowPointer = resultSetSize; //go to afterLast() position
rowPointer = dataSize; //go to afterLast() position
return false;

} else {

if (resultSetSize + row >= 0) {
if (dataSize + row >= 0) {
//absolute position reverse from ending resultSet
rowPointer = resultSetSize + row;
rowPointer = dataSize + row;
return true;
}

Expand All @@ -809,7 +809,7 @@ public boolean relative(int rows) throws SQLException {
throw new SQLException("Invalid operation for result set type TYPE_FORWARD_ONLY");
}
int newPos = rowPointer + rows;
if (newPos > -1 && newPos <= resultSetSize) {
if (newPos > -1 && newPos <= dataSize) {
rowPointer = newPos;
return true;
}
Expand Down Expand Up @@ -946,6 +946,13 @@ private String getInternalString(ColumnInformation columnInfo, Calendar cal) thr
if (lastValueNull) return null;

switch (columnInfo.getColumnType()) {
case STRING:
if (row.getMaxFieldSize() > 0) {
return new String(row.buf, row.pos, Math.max(row.getMaxFieldSize() * 3, row.length), StandardCharsets.UTF_8)
.substring(0, row.getMaxFieldSize());
}
return new String(row.buf, row.pos, row.length, StandardCharsets.UTF_8);

case BIT:
if (options.tinyInt1isBit && columnInfo.getLength() == 1) {
return (row.buf[row.pos] == 0) ? "0" : "1";
Expand Down

0 comments on commit e507689

Please sign in to comment.