Skip to content

Commit e35441e

Browse files
authored
Merge branch 'apache:main' into correlate_subquery_fix
2 parents ca190f4 + bbd083f commit e35441e

35 files changed

Lines changed: 429 additions & 133 deletions

File tree

arrow/build.gradle.kts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ dependencies {
2929

3030
testImplementation("org.apache.arrow:arrow-jdbc")
3131
testImplementation("net.hydromatic:scott-data-hsqldb")
32-
testImplementation("org.apache.commons:commons-lang3")
3332
testImplementation(project(":core"))
3433
testImplementation(project(":testkit"))
3534
}

bom/build.gradle.kts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ dependencies {
106106
apiv("org.apache.calcite.avatica:avatica-server", "calcite.avatica")
107107
apiv("org.apache.cassandra:cassandra-all")
108108
apiv("org.apache.commons:commons-dbcp2")
109-
apiv("org.apache.commons:commons-lang3")
110109
apiv("org.apache.commons:commons-math3")
111110
apiv("org.apache.commons:commons-pool2")
112111
apiv("org.apache.commons:commons-collections4")

cassandra/src/test/java/org/apache/calcite/test/CassandraExtension.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@
1919
import org.apache.calcite.config.CalciteSystemProperty;
2020
import org.apache.calcite.util.Sources;
2121
import org.apache.calcite.util.TestUtil;
22+
import org.apache.calcite.util.Util;
2223

2324
import org.apache.cassandra.concurrent.Stage;
2425
import org.apache.cassandra.config.DatabaseDescriptor;
2526
import org.apache.cassandra.service.CassandraDaemon;
2627
import org.apache.cassandra.service.StorageService;
27-
import org.apache.commons.lang3.SystemUtils;
2828

2929
import com.datastax.oss.driver.api.core.CqlSession;
3030
import com.google.common.collect.ImmutableMap;
@@ -134,7 +134,7 @@ private static CassandraResource getOrCreate(ExtensionContext context) {
134134
boolean compatibleGuava = TestUtil.getGuavaMajorVersion() >= 23;
135135
// remove JVM check once Cassandra supports Eclipse OpenJ9 JVM
136136
boolean compatibleJVM = !"Eclipse OpenJ9".equals(TestUtil.getJavaVirtualMachineVendor());
137-
boolean compatibleOS = !SystemUtils.IS_OS_WINDOWS;
137+
boolean compatibleOS = !Util.isWindows();
138138
if (enabled && compatibleJdk && compatibleGuava && compatibleJVM && compatibleOS) {
139139
return ConditionEvaluationResult.enabled("Cassandra tests enabled");
140140
}

core/build.gradle.kts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ dependencies {
6969
implementation("commons-codec:commons-codec")
7070
implementation("net.hydromatic:aggdesigner-algorithm")
7171
implementation("org.apache.commons:commons-dbcp2")
72-
implementation("org.apache.commons:commons-lang3")
7372
implementation("org.apache.commons:commons-math3")
7473
implementation("org.apache.commons:commons-text")
7574
implementation("org.jooq:joou-java-6")

core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,6 @@
5555
import org.apache.calcite.util.Pair;
5656
import org.apache.calcite.util.Util;
5757

58-
import org.apache.commons.lang3.mutable.MutableBoolean;
59-
6058
import com.google.common.collect.ImmutableList;
6159
import com.google.common.collect.ImmutableSet;
6260

@@ -571,17 +569,17 @@ private static void addInputRefIfOtherConstant(ImmutableBitSet.Builder builder,
571569
*/
572570
private static boolean isConstantScalarQuery(RexNode rexNode) {
573571
if (rexNode.getKind() == SqlKind.SCALAR_QUERY) {
574-
MutableBoolean hasCorrelatingVars = new MutableBoolean(false);
572+
final boolean[] hasCorrelatingVars = {false};
575573
((RexSubQuery) rexNode).rel.accept(new RelShuttleImpl() {
576574
@Override public RelNode visit(final LogicalFilter filter) {
577575
if (RexUtil.containsCorrelation(filter.getCondition())) {
578-
hasCorrelatingVars.setTrue();
576+
hasCorrelatingVars[0] = true;
579577
return filter;
580578
}
581579
return super.visit(filter);
582580
}
583581
});
584-
return hasCorrelatingVars.isFalse();
582+
return !hasCorrelatingVars[0];
585583
}
586584
return false;
587585
}

core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,10 @@
6666
import org.apache.calcite.sql.JoinType;
6767
import org.apache.calcite.sql.SqlAggFunction;
6868
import org.apache.calcite.sql.SqlBasicCall;
69+
import org.apache.calcite.sql.SqlBasicTypeNameSpec;
6970
import org.apache.calcite.sql.SqlBinaryOperator;
7071
import org.apache.calcite.sql.SqlCall;
72+
import org.apache.calcite.sql.SqlDataTypeSpec;
7173
import org.apache.calcite.sql.SqlDialect;
7274
import org.apache.calcite.sql.SqlDynamicParam;
7375
import org.apache.calcite.sql.SqlIdentifier;
@@ -1536,8 +1538,16 @@ public static SqlNode toSql(RexLiteral literal) {
15361538
case NUMERIC:
15371539
case EXACT_NUMERIC: {
15381540
if (SqlTypeName.APPROX_TYPES.contains(typeName)) {
1539-
return SqlLiteral.createApproxNumeric(
1540-
castNonNull(literal.getValueAs(Double.class)).toString(), POS);
1541+
final Double d = castNonNull(literal.getValueAs(Double.class));
1542+
// BigDecimal cannot represent IEEE 754 special values (NaN, ±Infinity).
1543+
if (!Double.isFinite(d)) {
1544+
final SqlNode strLiteral =
1545+
SqlLiteral.createCharString(d.toString(), POS);
1546+
final SqlDataTypeSpec typeSpec =
1547+
new SqlDataTypeSpec(new SqlBasicTypeNameSpec(typeName, POS), POS);
1548+
return SqlStdOperatorTable.CAST.createCall(POS, strLiteral, typeSpec);
1549+
}
1550+
return SqlLiteral.createApproxNumeric(d.toString(), POS);
15411551
} else {
15421552
return SqlLiteral.createExactNumeric(
15431553
castNonNull(literal.getValueAs(BigDecimal.class)).toPlainString(), POS);

core/src/main/java/org/apache/calcite/runtime/CompressionFunctions.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818

1919
import org.apache.calcite.avatica.util.ByteString;
2020

21-
import org.apache.commons.lang3.StringUtils;
22-
2321
import org.checkerframework.checker.nullness.qual.Nullable;
2422

2523
import java.io.ByteArrayOutputStream;
@@ -47,7 +45,7 @@ private CompressionFunctions() {
4745
if (data == null) {
4846
return null;
4947
}
50-
if (StringUtils.isEmpty(data)) {
48+
if (data.isEmpty()) {
5149
return new ByteString(new byte[0]);
5250
}
5351
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@
6060
import org.apache.commons.codec.binary.Hex;
6161
import org.apache.commons.codec.digest.DigestUtils;
6262
import org.apache.commons.codec.language.Soundex;
63-
import org.apache.commons.lang3.ObjectUtils;
6463
import org.apache.commons.math3.util.CombinatoricsUtils;
6564
import org.apache.commons.text.StringEscapeUtils;
6665
import org.apache.commons.text.similarity.LevenshteinDistance;
@@ -6521,7 +6520,7 @@ public static long customTimestampCeil(DataContext root,
65216520
/** SQL {@code TRANSLATE(string, search_chars, replacement_chars)}
65226521
* function. */
65236522
public static String translate3(String s, String search, String replacement) {
6524-
return org.apache.commons.lang3.StringUtils.replaceChars(s, search, replacement);
6523+
return Util.replaceChars(s, search, replacement);
65256524
}
65266525

65276526
/** SQL {@code REPLACE(string, search, replacement)} function. */
@@ -6534,7 +6533,7 @@ public static String replace(String s, String search, String replacement,
65346533
return s.replace(search, replacement);
65356534
}
65366535
// for MSSQL's REPLACE function, search pattern is case-insensitive during matching
6537-
return org.apache.commons.lang3.Strings.CI.replace(s, search, replacement);
6536+
return Util.replaceIgnoreCase(s, search, replacement);
65386537
}
65396538

65406539
/** Helper for "array element reference". Caller has already ensured that
@@ -7699,7 +7698,7 @@ private static String age(long timestamp1, long timestamp2) {
76997698
sb.append(
77007699
String.format(Locale.ROOT, "%02d:%02d:%02d.%s", hours, minutes, seconds,
77017700
millisString));
7702-
} else if (ObjectUtils.isNotEmpty(sb)
7701+
} else if (sb.length() != 0
77037702
&& hours == 0 && minutes == 0 && seconds == 0 && millis == 0) {
77047703
return sb.toString().trim();
77057704
} else {

core/src/main/java/org/apache/calcite/runtime/XmlFunctions.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818

1919
import org.apache.calcite.util.SimpleNamespaceContext;
2020
import org.apache.calcite.util.TryThreadLocal;
21-
22-
import org.apache.commons.lang3.StringUtils;
21+
import org.apache.calcite.util.Util;
2322

2423
import org.checkerframework.checker.nullness.qual.Nullable;
2524
import org.w3c.dom.Node;
@@ -133,7 +132,7 @@ private XmlFunctions() {
133132
() -> "firstChild of node " + item);
134133
result.add(firstChild.getTextContent());
135134
}
136-
return StringUtils.join(result, " ");
135+
return Util.joinNullable(result, " ");
137136
} catch (XPathExpressionException e) {
138137
return xpathExpression.evaluate(documentNode);
139138
}
@@ -189,7 +188,7 @@ private XmlFunctions() {
189188
for (int i = 0; i < nodes.getLength(); i++) {
190189
result.add(convertNodeToString(castNonNull(nodes.item(i))));
191190
}
192-
return StringUtils.join(result, "");
191+
return Util.joinNullable(result, "");
193192
} catch (XPathExpressionException e) {
194193
Node node = (Node) xpathExpression
195194
.evaluate(documentNode, XPathConstants.NODE);

core/src/main/java/org/apache/calcite/util/Util.java

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.apache.calcite.sql.util.SqlBasicVisitor;
3232

3333
import com.google.common.base.Preconditions;
34+
import com.google.common.base.Strings;
3435
import com.google.common.base.Throwables;
3536
import com.google.common.cache.CacheBuilder;
3637
import com.google.common.cache.CacheLoader;
@@ -642,6 +643,106 @@ public static String replace(
642643
return sb.toString();
643644
}
644645

646+
/** Right-pads a string with {@code padChar} until it reaches {@code size}.
647+
*
648+
* <p>Equivalent to {@code org.apache.commons.lang3.StringUtils#rightPad(String, int, char)}
649+
* for non-null inputs.
650+
*/
651+
public static String rightPad(String s, int size, char padChar) {
652+
return Strings.padEnd(s, size, padChar);
653+
}
654+
655+
/** Joins {@code parts} using {@code sep}.
656+
*
657+
* <p>Null elements are treated as empty strings.
658+
*/
659+
public static String joinNullable(Iterable<? extends @Nullable Object> parts, String sep) {
660+
final List<String> strings = new ArrayList<>();
661+
for (Object o : parts) {
662+
strings.add(o == null ? "" : o.toString());
663+
}
664+
return String.join(sep, strings);
665+
}
666+
667+
/** Returns whether the current runtime is Windows.
668+
*
669+
* <p>Derived from system property {@code os.name}, using case-insensitive
670+
* prefix match against {@code "Windows"}.
671+
*
672+
* <p>This method is intended to replace commons-lang3's
673+
* {@code SystemUtils#IS_OS_WINDOWS}.
674+
*/
675+
public static boolean isWindows() {
676+
final String osName = System.getProperty("os.name");
677+
return osName != null
678+
&& osName.regionMatches(true, 0, "Windows", 0, "Windows".length());
679+
}
680+
681+
/** Replaces characters in {@code s} according to {@code search}/{@code replacement} mapping.
682+
*
683+
* <p>Semantics are aligned with {@code org.apache.commons.lang3.StringUtils#replaceChars}:
684+
* characters found in {@code search} are replaced by the character in the same position in
685+
* {@code replacement}; if {@code replacement} is shorter, remaining matches are removed.
686+
*/
687+
public static @PolyNull String replaceChars(@PolyNull String s, @Nullable String search,
688+
@Nullable String replacement) {
689+
if (s == null || s.isEmpty() || search == null || search.isEmpty()) {
690+
return s;
691+
}
692+
final String repl = replacement == null ? "" : replacement;
693+
boolean modified = false;
694+
final StringBuilder b = new StringBuilder(s.length());
695+
for (int i = 0; i < s.length(); i++) {
696+
final char ch = s.charAt(i);
697+
final int j = search.indexOf(ch);
698+
if (j >= 0) {
699+
modified = true;
700+
if (j < repl.length()) {
701+
b.append(repl.charAt(j));
702+
}
703+
// else: delete character
704+
} else {
705+
b.append(ch);
706+
}
707+
}
708+
return modified ? b.toString() : s;
709+
}
710+
711+
/** Case-insensitive replace of all occurrences of {@code search} in {@code s}.
712+
*
713+
* <p>Equivalent to commons-lang's {@code StringUtils.replaceIgnoreCase}, but only supports
714+
* non-null inputs.
715+
*/
716+
public static String replaceIgnoreCase(String s, String search, String replacement) {
717+
if (search.isEmpty()) {
718+
return s;
719+
}
720+
final int replLength = search.length();
721+
int start = 0;
722+
int end = indexOfIgnoreCase(s, search, start);
723+
if (end < 0) {
724+
return s;
725+
}
726+
final StringBuilder out = new StringBuilder(s.length());
727+
while (end >= 0) {
728+
out.append(s, start, end).append(replacement);
729+
start = end + replLength;
730+
end = indexOfIgnoreCase(s, search, start);
731+
}
732+
out.append(s, start, s.length());
733+
return out.toString();
734+
}
735+
736+
private static int indexOfIgnoreCase(String str, String search, int fromIndex) {
737+
final int max = str.length() - search.length();
738+
for (int i = Math.max(0, fromIndex); i <= max; i++) {
739+
if (str.regionMatches(true, i, search, 0, search.length())) {
740+
return i;
741+
}
742+
}
743+
return -1;
744+
}
745+
645746
/**
646747
* Creates a file-protocol URL for the given file.
647748
*/

0 commit comments

Comments
 (0)