diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractQuery.java b/jOOQ/src/main/java/org/jooq/impl/AbstractQuery.java index 355746908a..e1670e3a64 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractQuery.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractQuery.java @@ -80,6 +80,7 @@ import org.jooq.conf.SettingsTools; import org.jooq.conf.StatementType; import org.jooq.exception.ControlFlowSignal; import org.jooq.exception.DetachedException; +import org.jooq.tools.Ints; import org.jooq.tools.JooqLogger; /** @@ -160,7 +161,7 @@ abstract class AbstractQuery extends AbstractQueryPart implements Query { @SuppressWarnings("deprecation") @Override public Query bind(String param, Object value) { - Integer index = Tools.tryParseInt(param); + Integer index = Ints.tryParse(param); if (index != null) return bind(index, value); diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java index 825c407a3d..f475c10fbc 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java @@ -172,6 +172,7 @@ import org.jooq.exception.MappingException; import org.jooq.exception.SQLDialectNotSupportedException; import org.jooq.tools.Convert; import org.jooq.tools.JooqLogger; +import org.jooq.tools.Longs; import org.jooq.tools.StringUtils; import org.jooq.tools.jdbc.JDBCUtils; import org.jooq.tools.jdbc.MockArray; @@ -443,7 +444,7 @@ public class DefaultBinding implements Binding { private static final long parse(Class type, String date) throws SQLException { // Try reading a plain number first - Long number = Tools.tryParseLong(date); + Long number = Longs.tryParse(date); if (number != null) return number; diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index cce95f1b94..0e06e4a734 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -255,6 +255,7 @@ import org.jooq.exception.NoDataFoundException; import org.jooq.exception.TooManyRowsException; import org.jooq.impl.ResultsImpl.ResultOrRowsImpl; import org.jooq.impl.Tools.Cache.CachedOperation; +import org.jooq.tools.Ints; import org.jooq.tools.JooqLogger; import org.jooq.tools.StringUtils; import org.jooq.tools.jdbc.JDBCUtils; @@ -1752,91 +1753,6 @@ final class Tools { return result; } - static Integer tryParseInt(String string) { - return tryParseInt(string, 0, string.length()); - } - - // adapted from com.google.common.primitives.Longs#tryParse() - private static Integer tryParseInt(String string, int begin, int end) { - if (string == null || end - begin < 1) - return null; - - int radix = 10; - char firstChar = string.charAt(begin); - boolean negative = firstChar == '-'; - int index = negative || firstChar == '+' ? begin + 1 : begin; - if (index == end) - return null; - - int digit = Character.digit(string.charAt(index++), 10); - if (digit < 0 || digit >= radix) - return null; - - int accum = -digit; - - int cap = Integer.MIN_VALUE / radix; - - while (index < end) { - digit = Character.digit(string.charAt(index++), 10); - if (digit < 0 || digit >= radix || accum < cap) - return null; - - accum *= radix; - if (accum < Integer.MIN_VALUE + digit) - return null; - - accum -= digit; - } - - if (negative) - return accum; - else if (accum == Integer.MIN_VALUE) - return null; - else - return -accum; - } - - // adapted from com.google.common.primitives.Longs#tryParse() - static Long tryParseLong(String string) { - if (string == null || string.isEmpty()) - return null; - - int radix = 10; - char firstChar = string.charAt(0); - boolean negative = firstChar == '-'; - int index = negative || firstChar == '+' ? 1 : 0; - int length = string.length(); - if (index == length) - return null; - - int digit = Character.digit(string.charAt(index++), 10); - if (digit < 0 || digit >= radix) - return null; - - long accum = -digit; - - long cap = Long.MIN_VALUE / radix; - - while (index < length) { - digit = Character.digit(string.charAt(index++), 10); - if (digit < 0 || digit >= radix || accum < cap) - return null; - - accum *= radix; - if (accum < Long.MIN_VALUE + digit) - return null; - - accum -= digit; - } - - if (negative) - return accum; - else if (accum == Long.MIN_VALUE) - return null; - else - return -accum; - } - static final List> inline(T[] values) { if (values == null) return new ArrayList>(); @@ -2514,7 +2430,7 @@ final class Tools { int end = i; // Try getting the {numbered placeholder} - Integer index = tryParseInt(sql, start, end); + Integer index = Ints.tryParse(sql, start, end); if (index != null) { QueryPart substitute = substitutes.get(index); render.visit(substitute); diff --git a/jOOQ/src/main/java/org/jooq/tools/Convert.java b/jOOQ/src/main/java/org/jooq/tools/Convert.java index 9fa31c0c94..7282f1165a 100644 --- a/jOOQ/src/main/java/org/jooq/tools/Convert.java +++ b/jOOQ/src/main/java/org/jooq/tools/Convert.java @@ -580,7 +580,9 @@ public final class Convert { return (U) (((Boolean) from) ? Byte.valueOf((byte) 1) : Byte.valueOf((byte) 0)); try { - return (U) Byte.valueOf(new BigDecimal(from.toString().trim()).byteValue()); + String fromString = from.toString().trim(); + Integer asInt = Ints.tryParse(fromString); + return (U) Byte.valueOf(asInt != null ? asInt.byteValue() : new BigDecimal(fromString).byteValue()); } catch (NumberFormatException e) { return Reflect.initValue(toClass); @@ -594,7 +596,9 @@ public final class Convert { return (U) (((Boolean) from) ? Short.valueOf((short) 1) : Short.valueOf((short) 0)); try { - return (U) Short.valueOf(new BigDecimal(from.toString().trim()).shortValue()); + String fromString = from.toString().trim(); + Integer asInt = Ints.tryParse(fromString); + return (U) Short.valueOf(asInt != null ? asInt.shortValue() : new BigDecimal(fromString).shortValue()); } catch (NumberFormatException e) { return Reflect.initValue(toClass); @@ -608,7 +612,9 @@ public final class Convert { return (U) (((Boolean) from) ? Integer.valueOf(1) : Integer.valueOf(0)); try { - return (U) Integer.valueOf(new BigDecimal(from.toString().trim()).intValue()); + String fromString = from.toString().trim(); + Integer asInt = Ints.tryParse(fromString); + return (U) Integer.valueOf(asInt != null ? asInt.intValue() : new BigDecimal(fromString).intValue()); } catch (NumberFormatException e) { return Reflect.initValue(toClass); @@ -632,7 +638,9 @@ public final class Convert { try { - return (U) Long.valueOf(new BigDecimal(from.toString().trim()).longValue()); + String fromString = from.toString().trim(); + Long asLong = Longs.tryParse(fromString); + return (U) Long.valueOf(asLong != null ? asLong.longValue() : new BigDecimal(fromString).longValue()); } catch (NumberFormatException e) { return Reflect.initValue(toClass); @@ -648,7 +656,9 @@ public final class Convert { if (wrapperFrom == Boolean.class) return (U) (((Boolean) from) ? ubyte(1) : ubyte(0)); - return (U) ubyte(new BigDecimal(from.toString().trim()).shortValue()); + String fromString = from.toString().trim(); + Integer asInt = Ints.tryParse(fromString); + return (U) ubyte(asInt != null ? asInt.shortValue() : new BigDecimal(fromString).shortValue()); } catch (NumberFormatException e) { return null; @@ -662,7 +672,9 @@ public final class Convert { if (wrapperFrom == Boolean.class) return (U) (((Boolean) from) ? ushort(1) : ushort(0)); - return (U) ushort(new BigDecimal(from.toString().trim()).intValue()); + String fromString = from.toString().trim(); + Integer asInt = Ints.tryParse(fromString); + return (U) ushort(asInt != null ? asInt.intValue() : new BigDecimal(fromString).intValue()); } catch (NumberFormatException e) { return null; @@ -676,7 +688,9 @@ public final class Convert { if (wrapperFrom == Boolean.class) return (U) (((Boolean) from) ? uint(1) : uint(0)); - return (U) uint(new BigDecimal(from.toString().trim()).longValue()); + String fromString = from.toString().trim(); + Long asLong = Longs.tryParse(fromString); + return (U) uint(asLong != null ? asLong.longValue() : new BigDecimal(fromString).longValue()); } catch (NumberFormatException e) { return null; @@ -695,7 +709,10 @@ public final class Convert { try { - return (U) ulong(new BigDecimal(from.toString().trim()).toBigInteger().toString()); + String fromString = from.toString().trim(); + // tryParse() will return null in case of overflow + Long asLong = Longs.tryParse(fromString); + return asLong != null ? (U) ulong(asLong.longValue()) : (U) ulong(new BigDecimal(fromString).toBigInteger()); } catch (NumberFormatException e) { return null; diff --git a/jOOQ/src/main/java/org/jooq/tools/Ints.java b/jOOQ/src/main/java/org/jooq/tools/Ints.java new file mode 100644 index 0000000000..739ecf45e2 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/tools/Ints.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2008 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package org.jooq.tools; + +import java.util.Arrays; + +/** + * Static utility methods pertaining to {@code int} primitives, that are not already found in either + * {@link Integer} or {@link Arrays}. + * + *

See the Guava User Guide article on primitive utilities. + * + * @author Kevin Bourrillion + * @since 1.0 + */ +public final class Ints { + private Ints() {} + + public static Integer tryParse(String string) { + return tryParse(string, 0, string.length()); + } + + // adapted from com.google.common.primitives.Longs#tryParse() + // modified for performance and to allow parsing numbers with leading '+' + public static Integer tryParse(String string, int begin, int end) { + if (begin < 0 || end > string.length() || end - begin < 1) + return null; + + int radix = 10; + char firstChar = string.charAt(begin); + boolean negative = firstChar == '-'; + int index = negative || firstChar == '+' ? begin + 1 : begin; + if (index == end) + return null; + + int digit = Character.digit(string.charAt(index++), 10); + if (digit < 0 || digit >= radix) + return null; + + int accum = -digit; + + int cap = Integer.MIN_VALUE / radix; + + while (index < end) { + digit = Character.digit(string.charAt(index++), 10); + if (digit < 0 || digit >= radix || accum < cap) + return null; + + accum *= radix; + if (accum < Integer.MIN_VALUE + digit) + return null; + + accum -= digit; + } + + if (negative) + return accum; + else if (accum == Integer.MIN_VALUE) + return null; + else + return -accum; + } + + +} diff --git a/jOOQ/src/main/java/org/jooq/tools/Longs.java b/jOOQ/src/main/java/org/jooq/tools/Longs.java new file mode 100644 index 0000000000..55199996d4 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/tools/Longs.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2008 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package org.jooq.tools; + +import java.util.Arrays; + +/** + * Static utility methods pertaining to {@code long} primitives, that are not already found in + * either {@link Long} or {@link Arrays}. + * + *

See the Guava User Guide article on primitive utilities. + * + * @author Kevin Bourrillion + * @since 1.0 + */ +public final class Longs { + private Longs() {} + + // adapted from com.google.common.primitives.Longs#tryParse() + // modified for performance and to allow parsing numbers with leading '+' + public static Long tryParse(String string) { + if (string.isEmpty()) + return null; + + int radix = 10; + char firstChar = string.charAt(0); + boolean negative = firstChar == '-'; + int index = negative || firstChar == '+' ? 1 : 0; + int length = string.length(); + if (index == length) + return null; + + int digit = Character.digit(string.charAt(index++), 10); + if (digit < 0 || digit >= radix) + return null; + + long accum = -digit; + + long cap = Long.MIN_VALUE / radix; + + while (index < length) { + digit = Character.digit(string.charAt(index++), 10); + if (digit < 0 || digit >= radix || accum < cap) + return null; + + accum *= radix; + if (accum < Long.MIN_VALUE + digit) + return null; + + accum -= digit; + } + + if (negative) + return accum; + else if (accum == Long.MIN_VALUE) + return null; + else + return -accum; + } + +} diff --git a/jOOQ/src/main/java/org/jooq/tools/StringUtils.java b/jOOQ/src/main/java/org/jooq/tools/StringUtils.java index 0f04a232a7..8f3ede9fac 100644 --- a/jOOQ/src/main/java/org/jooq/tools/StringUtils.java +++ b/jOOQ/src/main/java/org/jooq/tools/StringUtils.java @@ -1424,4 +1424,5 @@ public final class StringUtils { String[] result = new String[matchList.size()]; return matchList.toArray(result); } + }