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

perf: improve performance of PgResultSet getByte/getShort/getInt/getLong for float-typed columns #2634

Merged
merged 1 commit into from Oct 8, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
89 changes: 35 additions & 54 deletions pgjdbc/src/main/java/org/postgresql/jdbc/PgResultSet.java
Expand Up @@ -2327,6 +2327,14 @@ public byte getByte(@Positive int columnIndex) throws SQLException {
Byte.MAX_VALUE, "byte");
}

Encoding encoding = connection.getEncoding();
if (encoding.hasAsciiNumbers()) {
try {
return (byte) getFastLong(value, Byte.MIN_VALUE, Byte.MAX_VALUE);
} catch (NumberFormatException ignored) {
}
}

String s = getString(columnIndex);

if (s != null) {
Expand Down Expand Up @@ -2376,7 +2384,13 @@ public short getShort(@Positive int columnIndex) throws SQLException {
}
return (short) readLongValue(value, oid, Short.MIN_VALUE, Short.MAX_VALUE, "short");
}

Encoding encoding = connection.getEncoding();
if (encoding.hasAsciiNumbers()) {
try {
return (short) getFastLong(value, Short.MIN_VALUE, Short.MAX_VALUE);
} catch (NumberFormatException ignored) {
}
}
return toShort(getFixedString(columnIndex));
}

Expand All @@ -2401,7 +2415,7 @@ public int getInt(@Positive int columnIndex) throws SQLException {
Encoding encoding = connection.getEncoding();
if (encoding.hasAsciiNumbers()) {
try {
return getFastInt(value);
return (int) getFastLong(value, Integer.MIN_VALUE, Integer.MAX_VALUE);
} catch (NumberFormatException ignored) {
}
}
Expand Down Expand Up @@ -2429,7 +2443,7 @@ public long getLong(@Positive int columnIndex) throws SQLException {
Encoding encoding = connection.getEncoding();
if (encoding.hasAsciiNumbers()) {
try {
return getFastLong(value);
return getFastLong(value, Long.MIN_VALUE, Long.MAX_VALUE);
} catch (NumberFormatException ignored) {
}
}
Expand Down Expand Up @@ -2463,7 +2477,7 @@ public synchronized Throwable fillInStackTrace() {
* @throws NumberFormatException If the number is invalid or the out of range for fast parsing.
* The value must then be parsed by {@link #toLong(String)}.
*/
private long getFastLong(byte[] bytes) throws NumberFormatException {
private long getFastLong(byte[] bytes, long minVal, long maxVal) throws NumberFormatException {
if (bytes.length == 0) {
throw FAST_NUMBER_FAILED;
}
Expand All @@ -2485,68 +2499,35 @@ private long getFastLong(byte[] bytes) throws NumberFormatException {
}
}

int periodsSeen = 0;
while (start < bytes.length) {
byte b = bytes[start++];
if (b < '0' || b > '9') {
throw FAST_NUMBER_FAILED;
}

val *= 10;
val += b - '0';
}

if (neg) {
val = -val;
}

return val;
}

/**
* Optimised byte[] to number parser. This code does not handle null values, so the caller must do
* checkResultSet and handle null values prior to calling this function.
*
* @param bytes integer represented as a sequence of ASCII bytes
* @return The parsed number.
* @throws NumberFormatException If the number is invalid or the out of range for fast parsing.
* The value must then be parsed by {@link #toInt(String)}.
*/
private int getFastInt(byte[] bytes) throws NumberFormatException {
if (bytes.length == 0) {
throw FAST_NUMBER_FAILED;
}

int val = 0;
int start;
boolean neg;
if (bytes[0] == '-') {
neg = true;
start = 1;
if (bytes.length == 1 || bytes.length > 10) {
throw FAST_NUMBER_FAILED;
if (b == '.' && periodsSeen == 0) {
periodsSeen++;
continue;
} else {
throw FAST_NUMBER_FAILED;
}
}
} else {
start = 0;
neg = false;
if (bytes.length > 9) {
throw FAST_NUMBER_FAILED;
if (periodsSeen == 0) {
val *= 10;
val += b - '0';
}
}

while (start < bytes.length) {
byte b = bytes[start++];
if (b < '0' || b > '9') {
throw FAST_NUMBER_FAILED;
}

val *= 10;
val += b - '0';
int numNonSignChars = neg ? bytes.length - 1 : bytes.length;
if (periodsSeen > 1 || periodsSeen == numNonSignChars) {
throw FAST_NUMBER_FAILED;
}

if (neg) {
val = -val;
}

if (val < minVal || val > maxVal) {
throw FAST_NUMBER_FAILED;
}
return val;
}

Expand Down Expand Up @@ -2586,7 +2567,7 @@ private BigDecimal getFastBigDecimal(byte[] bytes) throws NumberFormatException
while (start < bytes.length) {
byte b = bytes[start++];
if (b < '0' || b > '9') {
if (b == '.') {
if (b == '.' && periodsSeen == 0) {
scale = bytes.length - start;
periodsSeen++;
continue;
Expand Down