You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by li...@apache.org on 2015/06/11 04:51:04 UTC
[1/3] incubator-kylin git commit: KYLIN-812 Upgrade to Calcite 0.9.2
Repository: incubator-kylin
Updated Branches:
refs/heads/0.7-staging f37360de7 -> 6480a9a7a
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/6480a9a7/atopcalcite/src/main/java/org/eigenbase/sql2rel/SqlToRelConverter.java
----------------------------------------------------------------------
diff --git a/atopcalcite/src/main/java/org/eigenbase/sql2rel/SqlToRelConverter.java b/atopcalcite/src/main/java/org/eigenbase/sql2rel/SqlToRelConverter.java
index 796640c..dd7ee01 100644
--- a/atopcalcite/src/main/java/org/eigenbase/sql2rel/SqlToRelConverter.java
+++ b/atopcalcite/src/main/java/org/eigenbase/sql2rel/SqlToRelConverter.java
@@ -45,6 +45,7 @@ import org.eigenbase.util.mapping.Mappings;
import org.eigenbase.util14.*;
import net.hydromatic.linq4j.Ord;
+
import net.hydromatic.optiq.ModifiableTable;
import net.hydromatic.optiq.TranslatableTable;
import net.hydromatic.optiq.prepare.Prepare;
@@ -65,7 +66,6 @@ import static org.eigenbase.util.Static.RESOURCE;
* <p>The public entry points are: {@link #convertQuery},
* {@link #convertExpression(SqlNode)}.
*/
-@SuppressWarnings({"unused", "rawtypes", "unchecked", "incomplete-switch", "deprecation"})
public class SqlToRelConverter {
//~ Static fields/initializers ---------------------------------------------
@@ -1487,7 +1487,7 @@ public class SqlToRelConverter {
* node, only register it if it's a scalar
* subquery
*/
-private void findSubqueries(
+ private void findSubqueries(
Blackboard bb,
SqlNode node,
RelOptUtil.Logic logic,
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/6480a9a7/cube/src/main/java/org/apache/kylin/cube/model/CubeDesc.java
----------------------------------------------------------------------
diff --git a/cube/src/main/java/org/apache/kylin/cube/model/CubeDesc.java b/cube/src/main/java/org/apache/kylin/cube/model/CubeDesc.java
index a810376..b03268f 100644
--- a/cube/src/main/java/org/apache/kylin/cube/model/CubeDesc.java
+++ b/cube/src/main/java/org/apache/kylin/cube/model/CubeDesc.java
@@ -530,39 +530,6 @@ public class CubeDesc extends RootPersistentEntity {
*/
}
}
-
-
- {
- // drop those columns (like lookup table's PK but used as a dimension) that can be derived
- List<TblColRef> derivedCols = Lists.newArrayList();
- for (TblColRef col : dimensionColumns) {
- if (isDerived(col) == true)
- derivedCols.add(col);
- }
-
- if (derivedCols.size() > 0) {
- dimensionColumns.removeAll(derivedCols);
- }
- }
-
- {
- // for hierarchy columns, if a column can be derived, use the host col to replace
- for (DimensionDesc dim : dimensions) {
- if (dim.isHierarchy()) {
- for (int i = 0; i < dim.getColumnRefs().length; i++) {
- TblColRef colRef = dim.getColumnRefs()[i];
- if (isDerived(colRef)) {
- TblColRef[] hostCols = derivedToHostMap.get(colRef).columns;
- if (hostCols.length == 1) {
- dim.getHierarchy()[i].setColumnRef(hostCols[0]);
- } else {
- throw new IllegalStateException();
- }
- }
- }
- }
- }
- }
}
private String[][] splitDerivedColumnAndExtra(String[] derived) {
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/6480a9a7/jdbc/src/main/java/org/apache/kylin/jdbc/KylinPrepare.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/kylin/jdbc/KylinPrepare.java b/jdbc/src/main/java/org/apache/kylin/jdbc/KylinPrepare.java
index 7f20d5b..0e4fb35 100644
--- a/jdbc/src/main/java/org/apache/kylin/jdbc/KylinPrepare.java
+++ b/jdbc/src/main/java/org/apache/kylin/jdbc/KylinPrepare.java
@@ -1,98 +1,103 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.apache.kylin.jdbc;
-
-import java.util.List;
-
-import net.hydromatic.avatica.AvaticaParameter;
-import net.hydromatic.avatica.AvaticaPrepareResult;
-import net.hydromatic.avatica.ColumnMetaData;
-import net.hydromatic.avatica.Cursor;
-import net.hydromatic.linq4j.Enumerator;
-import net.hydromatic.optiq.runtime.EnumeratorCursor;
-
-/**
- * Interface of kylin prepare statement implementation
- *
- * @author xduo
- *
- */
-public interface KylinPrepare {
-
- PrepareResult prepare(String sql);
-
- /**
- * The result of preparing a query. It gives the Avatica driver framework
- * the information it needs to create a prepared statement, or to execute a
- * statement directly, without an explicit prepare step.
- */
- public static class PrepareResult implements AvaticaPrepareResult {
- public final String sql; // for debug
- public final ColumnMetaData.StructType structType;
- public final Enumerator<Object[]> enumerator;
- public final List<AvaticaParameter> parameterList;
-
- public PrepareResult(String sql, List<AvaticaParameter> parameterList, Enumerator<Object[]> enumerator, ColumnMetaData.StructType structType) {
- super();
- this.sql = sql;
- this.parameterList = parameterList;
- this.enumerator = enumerator;
- this.structType = structType;
- }
-
- public Cursor createCursor() {
- return new EnumeratorCursor<Object[]>(enumerator) {
- @Override
- protected Getter createGetter(int ordinal) {
- return new ArrayEnumeratorGetter(ordinal);
- }
-
- /**
- * Row field accessor via index
- */
- class ArrayEnumeratorGetter extends AbstractGetter {
- protected final int field;
-
- public ArrayEnumeratorGetter(int field) {
- this.field = field;
- }
-
- public Object getObject() {
- Object o = current()[field];
- wasNull[0] = o == null;
- return o;
- }
- }
- };
- }
-
- public List<ColumnMetaData> getColumnList() {
- return structType.columns;
- }
-
- public List<AvaticaParameter> getParameterList() {
- return parameterList;
- }
-
- public String getSql() {
- return sql;
- }
- }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.kylin.jdbc;
+
+import java.util.List;
+import java.util.Map;
+
+import net.hydromatic.avatica.AvaticaParameter;
+import net.hydromatic.avatica.AvaticaPrepareResult;
+import net.hydromatic.avatica.ColumnMetaData;
+import net.hydromatic.avatica.Cursor;
+import net.hydromatic.linq4j.Enumerator;
+import net.hydromatic.optiq.runtime.EnumeratorCursor;
+
+/**
+ * Interface of kylin prepare statement implementation
+ *
+ * @author xduo
+ *
+ */
+public interface KylinPrepare {
+
+ PrepareResult prepare(String sql);
+
+ /**
+ * The result of preparing a query. It gives the Avatica driver framework
+ * the information it needs to create a prepared statement, or to execute a
+ * statement directly, without an explicit prepare step.
+ */
+ public static class PrepareResult implements AvaticaPrepareResult {
+ public final String sql; // for debug
+ public final ColumnMetaData.StructType structType;
+ public final Enumerator<Object[]> enumerator;
+ public final List<AvaticaParameter> parameterList;
+
+ public PrepareResult(String sql, List<AvaticaParameter> parameterList, Enumerator<Object[]> enumerator, ColumnMetaData.StructType structType) {
+ super();
+ this.sql = sql;
+ this.parameterList = parameterList;
+ this.enumerator = enumerator;
+ this.structType = structType;
+ }
+
+ public Cursor createCursor() {
+ return new EnumeratorCursor<Object[]>(enumerator) {
+ @Override
+ protected Getter createGetter(int ordinal) {
+ return new ArrayEnumeratorGetter(ordinal);
+ }
+
+ /**
+ * Row field accessor via index
+ */
+ class ArrayEnumeratorGetter extends AbstractGetter {
+ protected final int field;
+
+ public ArrayEnumeratorGetter(int field) {
+ this.field = field;
+ }
+
+ public Object getObject() {
+ Object o = current()[field];
+ wasNull[0] = o == null;
+ return o;
+ }
+ }
+ };
+ }
+
+ public List<ColumnMetaData> getColumnList() {
+ return structType.columns;
+ }
+
+ public List<AvaticaParameter> getParameterList() {
+ return parameterList;
+ }
+
+ public Map<String, Object> getInternalParameters() {
+ return null;
+ }
+
+ public String getSql() {
+ return sql;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/6480a9a7/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index cf776db..5748328 100644
--- a/pom.xml
+++ b/pom.xml
@@ -84,7 +84,7 @@
<spring.framework.version>3.1.2.RELEASE</spring.framework.version>
<!-- Optiq Version -->
- <optiq.version>0.9.1-incubating</optiq.version>
+ <optiq.version>0.9.2-incubating</optiq.version>
<linq4j.version>0.4</linq4j.version>
<!-- Metrics Codahale Version -->
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/6480a9a7/query/src/main/java/org/apache/kylin/query/relnode/OLAPAggregateRel.java
----------------------------------------------------------------------
diff --git a/query/src/main/java/org/apache/kylin/query/relnode/OLAPAggregateRel.java b/query/src/main/java/org/apache/kylin/query/relnode/OLAPAggregateRel.java
index 83723c2..e228d82 100644
--- a/query/src/main/java/org/apache/kylin/query/relnode/OLAPAggregateRel.java
+++ b/query/src/main/java/org/apache/kylin/query/relnode/OLAPAggregateRel.java
@@ -49,6 +49,7 @@ import org.eigenbase.reltype.RelDataTypeFactory;
import org.eigenbase.reltype.RelDataTypeField;
import org.eigenbase.sql.SqlAggFunction;
import org.eigenbase.sql.SqlIdentifier;
+import org.eigenbase.sql.fun.SqlStdOperatorTable;
import org.eigenbase.sql.fun.SqlSumEmptyIsZeroAggFunction;
import org.eigenbase.sql.parser.SqlParserPos;
import org.eigenbase.sql.type.InferTypes;
@@ -59,6 +60,7 @@ import org.eigenbase.sql.validate.SqlUserDefinedAggFunction;
import org.eigenbase.util.Util;
import com.google.common.base.Preconditions;
+
import org.apache.kylin.metadata.model.ColumnDesc;
import org.apache.kylin.metadata.model.TableDesc;
import org.apache.kylin.metadata.model.FunctionDesc;
@@ -304,7 +306,8 @@ public class OLAPAggregateRel extends AggregateRelBase implements OLAPRel, Enume
if (func.isCountDistinct()) {
newAgg = createHyperLogLogAggFunction(fieldType);
} else if (func.isCount()) {
- newAgg = new SqlSumEmptyIsZeroAggFunction(fieldType);
+ //newAgg = new SqlSumEmptyIsZeroAggFunction(fieldType);
+ newAgg = SqlStdOperatorTable.SUM0;
}
// rebuild aggregate call
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/6480a9a7/query/src/main/java/org/apache/kylin/query/relnode/OLAPRel.java
----------------------------------------------------------------------
diff --git a/query/src/main/java/org/apache/kylin/query/relnode/OLAPRel.java b/query/src/main/java/org/apache/kylin/query/relnode/OLAPRel.java
index 3c34ab4..06cad92 100644
--- a/query/src/main/java/org/apache/kylin/query/relnode/OLAPRel.java
+++ b/query/src/main/java/org/apache/kylin/query/relnode/OLAPRel.java
@@ -18,6 +18,7 @@
package org.apache.kylin.query.relnode;
+import java.util.LinkedHashMap;
import java.util.Stack;
import net.hydromatic.optiq.rules.java.EnumerableRel;
@@ -139,7 +140,7 @@ public interface OLAPRel extends RelNode {
private OLAPContext parentContext;
public JavaImplementor(EnumerableRelImplementor enumImplementor) {
- super(enumImplementor.getRexBuilder());
+ super(enumImplementor.getRexBuilder(), new LinkedHashMap<String, Object>());
}
public OLAPContext getParentContext() {
[2/3] incubator-kylin git commit: KYLIN-812 Upgrade to Calcite 0.9.2
Posted by li...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/6480a9a7/atopcalcite/src/main/java/net/hydromatic/optiq/runtime/SqlFunctions.java
----------------------------------------------------------------------
diff --git a/atopcalcite/src/main/java/net/hydromatic/optiq/runtime/SqlFunctions.java b/atopcalcite/src/main/java/net/hydromatic/optiq/runtime/SqlFunctions.java
index ad65aa2..db99c83 100644
--- a/atopcalcite/src/main/java/net/hydromatic/optiq/runtime/SqlFunctions.java
+++ b/atopcalcite/src/main/java/net/hydromatic/optiq/runtime/SqlFunctions.java
@@ -52,1569 +52,1654 @@ import java.util.regex.Pattern;
* If null arguments are possible, the code-generation framework checks for
* nulls before calling the functions.</p>
*/
-@SuppressWarnings({ "unused", "rawtypes", "unchecked" })
+@SuppressWarnings("UnnecessaryUnboxing")
@Deterministic
public class SqlFunctions {
- private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("0.0E0");
+ private static final DecimalFormat DOUBLE_FORMAT =
+ new DecimalFormat("0.0E0");
- /** The julian date of the epoch, 1970-01-01. */
- public static final int EPOCH_JULIAN = 2440588;
+ /** The julian date of the epoch, 1970-01-01. */
+ public static final int EPOCH_JULIAN = 2440588;
- private static final TimeZone LOCAL_TZ = TimeZone.getDefault();
+ private static final TimeZone LOCAL_TZ = TimeZone.getDefault();
- private static final Function1<List<Object>, Enumerable<Object>> LIST_AS_ENUMERABLE = new Function1<List<Object>, Enumerable<Object>>() {
+ private static final Function1<List<Object>, Enumerable<Object>>
+ LIST_AS_ENUMERABLE =
+ new Function1<List<Object>, Enumerable<Object>>() {
public Enumerable<Object> apply(List<Object> list) {
- return Linq4j.asEnumerable(list);
+ return Linq4j.asEnumerable(list);
}
- };
-
- private SqlFunctions() {
- }
-
- /** SQL SUBSTRING(string FROM ... FOR ...) function. */
- public static String substring(String s, int from, int for_) {
- return s.substring(from - 1, Math.min(from - 1 + for_, s.length()));
- }
-
- /** SQL SUBSTRING(string FROM ...) function. */
- public static String substring(String s, int from) {
- return s.substring(from - 1);
- }
-
- /** SQL UPPER(string) function. */
- public static String upper(String s) {
- return s.toUpperCase();
- }
-
- /** SQL LOWER(string) function. */
- public static String lower(String s) {
- return s.toLowerCase();
- }
-
- /** SQL INITCAP(string) function. */
- public static String initcap(String s) {
- // Assumes Alpha as [A-Za-z0-9]
- // white space is treated as everything else.
- final int len = s.length();
- boolean start = true;
- final StringBuilder newS = new StringBuilder();
-
- for (int i = 0; i < len; i++) {
- char curCh = s.charAt(i);
- final int c = (int) curCh;
- if (start) { // curCh is whitespace or first character of word.
- if (c > 47 && c < 58) { // 0-9
- start = false;
- } else if (c > 64 && c < 91) { // A-Z
- start = false;
- } else if (c > 96 && c < 123) { // a-z
- start = false;
- curCh = (char) (c - 32); // Uppercase this character
- }
- // else {} whitespace
- } else { // Inside of a word or white space after end of word.
- if (c > 47 && c < 58) { // 0-9
- // noop
- } else if (c > 64 && c < 91) { // A-Z
- curCh = (char) (c + 32); // Lowercase this character
- } else if (c > 96 && c < 123) { // a-z
- // noop
- } else { // whitespace
- start = true;
- }
- }
- newS.append(curCh);
- } // for each character in s
- return newS.toString();
- }
-
- /** SQL CHARACTER_LENGTH(string) function. */
- public static int charLength(String s) {
- return s.length();
- }
-
- /** SQL {@code string || string} operator. */
- public static String concat(String s0, String s1) {
- return s0 + s1;
- }
-
- /** SQL {@code binary || binary} operator. */
- public static ByteString concat(ByteString s0, ByteString s1) {
- return s0.concat(s1);
- }
-
- /** SQL {@code RTRIM} function applied to string. */
- public static String rtrim(String s) {
- return trim_(s, false, true, ' ');
- }
-
- /** SQL {@code LTRIM} function. */
- public static String ltrim(String s) {
- return trim_(s, true, false, ' ');
- }
-
- /** SQL {@code TRIM(... seek FROM s)} function. */
- public static String trim(boolean leading, boolean trailing, String seek, String s) {
- return trim_(s, leading, trailing, seek.charAt(0));
- }
-
- /** SQL {@code TRIM} function. */
- private static String trim_(String s, boolean left, boolean right, char c) {
- int j = s.length();
- if (right) {
- for (;;) {
- if (j == 0) {
- return "";
- }
- if (s.charAt(j - 1) != c) {
- break;
- }
- --j;
- }
- }
- int i = 0;
- if (left) {
- for (;;) {
- if (i == j) {
- return "";
- }
- if (s.charAt(i) != c) {
- break;
- }
- ++i;
- }
- }
- return s.substring(i, j);
- }
-
- /** SQL {@code TRIM} function applied to binary string. */
- public static ByteString trim(ByteString s) {
- return trim_(s, true, true);
- }
-
- /** Helper for CAST. */
- public static ByteString rtrim(ByteString s) {
- return trim_(s, false, true);
- }
-
- /** SQL {@code TRIM} function applied to binary string. */
- private static ByteString trim_(ByteString s, boolean left, boolean right) {
- int j = s.length();
- if (right) {
- for (;;) {
- if (j == 0) {
- return ByteString.EMPTY;
- }
- if (s.byteAt(j - 1) != 0) {
- break;
- }
- --j;
- }
- }
- int i = 0;
- if (left) {
- for (;;) {
- if (i == j) {
- return ByteString.EMPTY;
- }
- if (s.byteAt(i) != 0) {
- break;
- }
- ++i;
- }
- }
- return s.substring(i, j);
- }
-
- /** SQL {@code OVERLAY} function. */
- public static String overlay(String s, String r, int start) {
- if (s == null || r == null) {
- return null;
- }
- return s.substring(0, start - 1) + r + s.substring(start - 1 + r.length());
- }
-
- /** SQL {@code OVERLAY} function. */
- public static String overlay(String s, String r, int start, int length) {
- if (s == null || r == null) {
- return null;
- }
- return s.substring(0, start - 1) + r + s.substring(start - 1 + length);
- }
-
- /** SQL {@code OVERLAY} function applied to binary strings. */
- public static ByteString overlay(ByteString s, ByteString r, int start) {
- if (s == null || r == null) {
- return null;
- }
- return s.substring(0, start - 1).concat(r).concat(s.substring(start - 1 + r.length()));
- }
-
- /** SQL {@code OVERLAY} function applied to binary strings. */
- public static ByteString overlay(ByteString s, ByteString r, int start, int length) {
- if (s == null || r == null) {
- return null;
- }
- return s.substring(0, start - 1).concat(r).concat(s.substring(start - 1 + length));
- }
-
- /** SQL {@code LIKE} function. */
- public static boolean like(String s, String pattern) {
- final String regex = Like.sqlToRegexLike(pattern, null);
- return Pattern.matches(regex, s);
- }
-
- /** SQL {@code LIKE} function with escape. */
- public static boolean like(String s, String pattern, String escape) {
- final String regex = Like.sqlToRegexLike(pattern, escape);
- return Pattern.matches(regex, s);
- }
-
- /** SQL {@code SIMILAR} function. */
- public static boolean similar(String s, String pattern) {
- final String regex = Like.sqlToRegexSimilar(pattern, null);
- return Pattern.matches(regex, s);
- }
-
- /** SQL {@code SIMILAR} function with escape. */
- public static boolean similar(String s, String pattern, String escape) {
- final String regex = Like.sqlToRegexSimilar(pattern, escape);
- return Pattern.matches(regex, s);
- }
-
- // =
-
- /** SQL = operator applied to Object values (including String; neither
- * side may be null). */
- public static boolean eq(Object b0, Object b1) {
- return b0.equals(b1);
- }
-
- /** SQL = operator applied to BigDecimal values (neither may be null). */
- public static boolean eq(BigDecimal b0, BigDecimal b1) {
- return b0.stripTrailingZeros().equals(b1.stripTrailingZeros());
- }
-
- // <>
-
- /** SQL <> operator applied to Object values (including String;
- * neither side may be null). */
- public static boolean ne(Object b0, Object b1) {
- return !b0.equals(b1);
- }
-
- /** SQL <> operator applied to BigDecimal values. */
- public static boolean ne(BigDecimal b0, BigDecimal b1) {
- return b0.compareTo(b1) != 0;
- }
-
- // <
-
- /** SQL < operator applied to boolean values. */
- public static boolean lt(boolean b0, boolean b1) {
- return compare(b0, b1) < 0;
- }
-
- /** SQL < operator applied to String values. */
- public static boolean lt(String b0, String b1) {
- return b0.compareTo(b1) < 0;
- }
-
- /** SQL < operator applied to ByteString values. */
- public static boolean lt(ByteString b0, ByteString b1) {
- return b0.compareTo(b1) < 0;
- }
-
- /** SQL < operator applied to BigDecimal values. */
- public static boolean lt(BigDecimal b0, BigDecimal b1) {
- return b0.compareTo(b1) < 0;
- }
-
- // <=
-
- /** SQL ≤ operator applied to boolean values. */
- public static boolean le(boolean b0, boolean b1) {
- return compare(b0, b1) <= 0;
- }
-
- /** SQL ≤ operator applied to String values. */
- public static boolean le(String b0, String b1) {
- return b0.compareTo(b1) <= 0;
- }
-
- /** SQL ≤ operator applied to ByteString values. */
- public static boolean le(ByteString b0, ByteString b1) {
- return b0.compareTo(b1) <= 0;
- }
-
- /** SQL ≤ operator applied to BigDecimal values. */
- public static boolean le(BigDecimal b0, BigDecimal b1) {
- return b0.compareTo(b1) <= 0;
- }
-
- // >
-
- /** SQL > operator applied to boolean values. */
- public static boolean gt(boolean b0, boolean b1) {
- return compare(b0, b1) > 0;
- }
-
- /** SQL > operator applied to String values. */
- public static boolean gt(String b0, String b1) {
- return b0.compareTo(b1) > 0;
- }
-
- /** SQL > operator applied to ByteString values. */
- public static boolean gt(ByteString b0, ByteString b1) {
- return b0.compareTo(b1) > 0;
- }
-
- /** SQL > operator applied to BigDecimal values. */
- public static boolean gt(BigDecimal b0, BigDecimal b1) {
- return b0.compareTo(b1) > 0;
- }
-
- // >=
-
- /** SQL ≥ operator applied to boolean values. */
- public static boolean ge(boolean b0, boolean b1) {
- return compare(b0, b1) >= 0;
- }
-
- /** SQL ≥ operator applied to String values. */
- public static boolean ge(String b0, String b1) {
- return b0.compareTo(b1) >= 0;
- }
-
- /** SQL ≥ operator applied to ByteString values. */
- public static boolean ge(ByteString b0, ByteString b1) {
- return b0.compareTo(b1) >= 0;
- }
-
- /** SQL ≥ operator applied to BigDecimal values. */
- public static boolean ge(BigDecimal b0, BigDecimal b1) {
- return b0.compareTo(b1) >= 0;
- }
-
- // +
-
- /** SQL <code>+</code> operator applied to int values. */
- public static int plus(int b0, int b1) {
- return b0 + b1;
- }
-
- /** SQL <code>+</code> operator applied to int values; left side may be
- * null. */
- public static Integer plus(Integer b0, int b1) {
- return b0 == null ? null : (b0 + b1);
- }
-
- /** SQL <code>+</code> operator applied to int values; right side may be
- * null. */
- public static Integer plus(int b0, Integer b1) {
- return b1 == null ? null : (b0 + b1);
- }
-
- /** SQL <code>+</code> operator applied to nullable int values. */
- public static Integer plus(Integer b0, Integer b1) {
- return (b0 == null || b1 == null) ? null : (b0 + b1);
- }
-
- /** SQL <code>+</code> operator applied to nullable long and int values. */
- public static Long plus(Long b0, Integer b1) {
- return (b0 == null || b1 == null) ? null : (b0.longValue() + b1.longValue());
- }
-
- /** SQL <code>+</code> operator applied to nullable int and long values. */
- public static Long plus(Integer b0, Long b1) {
- return (b0 == null || b1 == null) ? null : (b0.longValue() + b1.longValue());
- }
-
- /** SQL <code>+</code> operator applied to BigDecimal values. */
- public static BigDecimal plus(BigDecimal b0, BigDecimal b1) {
- return (b0 == null || b1 == null) ? null : b0.add(b1);
- }
-
- // -
-
- /** SQL <code>-</code> operator applied to int values. */
- public static int minus(int b0, int b1) {
- return b0 - b1;
- }
-
- /** SQL <code>-</code> operator applied to int values; left side may be
- * null. */
- public static Integer minus(Integer b0, int b1) {
- return b0 == null ? null : (b0 - b1);
- }
-
- /** SQL <code>-</code> operator applied to int values; right side may be
- * null. */
- public static Integer minus(int b0, Integer b1) {
- return b1 == null ? null : (b0 - b1);
- }
-
- /** SQL <code>-</code> operator applied to nullable int values. */
- public static Integer minus(Integer b0, Integer b1) {
- return (b0 == null || b1 == null) ? null : (b0 - b1);
- }
-
- /** SQL <code>-</code> operator applied to nullable long and int values. */
- public static Long minus(Long b0, Integer b1) {
- return (b0 == null || b1 == null) ? null : (b0.longValue() - b1.longValue());
- }
-
- /** SQL <code>-</code> operator applied to nullable int and long values. */
- public static Long minus(Integer b0, Long b1) {
- return (b0 == null || b1 == null) ? null : (b0.longValue() - b1.longValue());
- }
-
- /** SQL <code>-</code> operator applied to BigDecimal values. */
- public static BigDecimal minus(BigDecimal b0, BigDecimal b1) {
- return (b0 == null || b1 == null) ? null : b0.subtract(b1);
- }
-
- // /
-
- /** SQL <code>/</code> operator applied to int values. */
- public static int divide(int b0, int b1) {
- return b0 / b1;
- }
-
- /** SQL <code>/</code> operator applied to int values; left side may be
- * null. */
- public static Integer divide(Integer b0, int b1) {
- return b0 == null ? null : (b0 / b1);
- }
-
- /** SQL <code>/</code> operator applied to int values; right side may be
- * null. */
- public static Integer divide(int b0, Integer b1) {
- return b1 == null ? null : (b0 / b1);
- }
-
- /** SQL <code>/</code> operator applied to nullable int values. */
- public static Integer divide(Integer b0, Integer b1) {
- return (b0 == null || b1 == null) ? null : (b0 / b1);
- }
-
- /** SQL <code>/</code> operator applied to nullable long and int values. */
- public static Long divide(Long b0, Integer b1) {
- return (b0 == null || b1 == null) ? null : (b0.longValue() / b1.longValue());
- }
-
- /** SQL <code>/</code> operator applied to nullable int and long values. */
- public static Long divide(Integer b0, Long b1) {
- return (b0 == null || b1 == null) ? null : (b0.longValue() / b1.longValue());
- }
-
- /** SQL <code>/</code> operator applied to BigDecimal values. */
- public static BigDecimal divide(BigDecimal b0, BigDecimal b1) {
- // OVERRIDE POINT
- return (b0 == null || b1 == null) ? null : b0.divide(b1, MathContext.DECIMAL64);
- }
-
- // *
-
- /** SQL <code>*</code> operator applied to int values. */
- public static int multiply(int b0, int b1) {
- return b0 * b1;
- }
-
- /** SQL <code>*</code> operator applied to int values; left side may be
- * null. */
- public static Integer multiply(Integer b0, int b1) {
- return b0 == null ? null : (b0 * b1);
- }
-
- /** SQL <code>*</code> operator applied to int values; right side may be
- * null. */
- public static Integer multiply(int b0, Integer b1) {
- return b1 == null ? null : (b0 * b1);
- }
-
- /** SQL <code>*</code> operator applied to nullable int values. */
- public static Integer multiply(Integer b0, Integer b1) {
- return (b0 == null || b1 == null) ? null : (b0 * b1);
- }
-
- /** SQL <code>*</code> operator applied to nullable long and int values. */
- public static Long multiply(Long b0, Integer b1) {
- return (b0 == null || b1 == null) ? null : (b0.longValue() * b1.longValue());
- }
-
- /** SQL <code>*</code> operator applied to nullable int and long values. */
- public static Long multiply(Integer b0, Long b1) {
- return (b0 == null || b1 == null) ? null : (b0.longValue() * b1.longValue());
- }
-
- /** SQL <code>*</code> operator applied to BigDecimal values. */
- public static BigDecimal multiply(BigDecimal b0, BigDecimal b1) {
- return (b0 == null || b1 == null) ? null : b0.multiply(b1);
- }
-
- // EXP
-
- /** SQL <code>EXP</code> operator applied to double values. */
- public static double exp(double b0) {
- return Math.exp(b0);
- }
-
- public static double exp(long b0) {
- return Math.exp(b0);
- }
-
- // POWER
-
- /** SQL <code>POWER</code> operator applied to double values. */
- public static double power(double b0, double b1) {
- return Math.pow(b0, b1);
- }
-
- public static double power(long b0, long b1) {
- return Math.pow(b0, b1);
- }
-
- public static double power(long b0, BigDecimal b1) {
- return Math.pow(b0, b1.doubleValue());
- }
-
- // LN
-
- /** SQL {@code LN(number)} function applied to double values. */
- public static double ln(double d) {
- return Math.log(d);
- }
-
- /** SQL {@code LN(number)} function applied to long values. */
- public static double ln(long b0) {
- return Math.log(b0);
- }
-
- /** SQL {@code LN(number)} function applied to BigDecimal values. */
- public static double ln(BigDecimal d) {
- return Math.log(d.doubleValue());
- }
-
- // LOG10
-
- /** SQL <code>LOG10(numeric)</code> operator applied to double values. */
- public static double log10(double b0) {
- return Math.log10(b0);
- }
-
- /** SQL {@code LOG10(number)} function applied to long values. */
- public static double log10(long b0) {
- return Math.log10(b0);
- }
-
- /** SQL {@code LOG10(number)} function applied to BigDecimal values. */
- public static double log10(BigDecimal d) {
- return Math.log10(d.doubleValue());
- }
-
- // MOD
-
- /** SQL <code>MOD</code> operator applied to byte values. */
- public static byte mod(byte b0, byte b1) {
- return (byte) (b0 % b1);
- }
-
- /** SQL <code>MOD</code> operator applied to short values. */
- public static short mod(short b0, short b1) {
- return (short) (b0 % b1);
- }
-
- /** SQL <code>MOD</code> operator applied to int values. */
- public static int mod(int b0, int b1) {
- return b0 % b1;
- }
-
- /** SQL <code>MOD</code> operator applied to long values. */
- public static long mod(long b0, long b1) {
- return b0 % b1;
- }
-
- // temporary
- public static BigDecimal mod(BigDecimal b0, int b1) {
- return mod(b0, BigDecimal.valueOf(b1));
- }
-
- // temporary
- public static int mod(int b0, BigDecimal b1) {
- return mod(b0, b1.intValue());
- }
-
- public static BigDecimal mod(BigDecimal b0, BigDecimal b1) {
- final BigDecimal[] bigDecimals = b0.divideAndRemainder(b1);
- return bigDecimals[1];
- }
-
- // ABS
-
- /** SQL <code>ABS</code> operator applied to byte values. */
- public static byte abs(byte b0) {
- return (byte) Math.abs(b0);
- }
-
- /** SQL <code>ABS</code> operator applied to short values. */
- public static short abs(short b0) {
- return (short) Math.abs(b0);
- }
-
- /** SQL <code>ABS</code> operator applied to int values. */
- public static int abs(int b0) {
- return Math.abs(b0);
- }
-
- /** SQL <code>ABS</code> operator applied to long values. */
- public static long abs(long b0) {
- return Math.abs(b0);
- }
-
- /** SQL <code>ABS</code> operator applied to float values. */
- public static float abs(float b0) {
- return Math.abs(b0);
- }
-
- /** SQL <code>ABS</code> operator applied to double values. */
- public static double abs(double b0) {
- return Math.abs(b0);
- }
-
- /** SQL <code>ABS</code> operator applied to BigDecimal values. */
- public static BigDecimal abs(BigDecimal b0) {
- return b0.abs();
- }
-
- // Helpers
-
- /** Helper for implementing MIN. Somewhat similar to LEAST operator. */
- public static <T extends Comparable<T>> T lesser(T b0, T b1) {
- return b0 == null || b0.compareTo(b1) > 0 ? b1 : b0;
- }
-
- /** LEAST operator. */
- public static <T extends Comparable<T>> T least(T b0, T b1) {
- return b0 == null || b1 != null && b0.compareTo(b1) > 0 ? b1 : b0;
- }
-
- public static boolean greater(boolean b0, boolean b1) {
- return b0 || b1;
- }
-
- public static boolean lesser(boolean b0, boolean b1) {
- return b0 && b1;
- }
-
- public static byte greater(byte b0, byte b1) {
- return b0 > b1 ? b0 : b1;
- }
-
- public static byte lesser(byte b0, byte b1) {
- return b0 > b1 ? b1 : b0;
- }
-
- public static char greater(char b0, char b1) {
- return b0 > b1 ? b0 : b1;
- }
-
- public static char lesser(char b0, char b1) {
- return b0 > b1 ? b1 : b0;
- }
-
- public static short greater(short b0, short b1) {
- return b0 > b1 ? b0 : b1;
- }
-
- public static short lesser(short b0, short b1) {
- return b0 > b1 ? b1 : b0;
- }
-
- public static int greater(int b0, int b1) {
- return b0 > b1 ? b0 : b1;
- }
-
- public static int lesser(int b0, int b1) {
- return b0 > b1 ? b1 : b0;
- }
-
- public static long greater(long b0, long b1) {
- return b0 > b1 ? b0 : b1;
- }
-
- public static long lesser(long b0, long b1) {
- return b0 > b1 ? b1 : b0;
- }
-
- public static float greater(float b0, float b1) {
- return b0 > b1 ? b0 : b1;
- }
-
- public static float lesser(float b0, float b1) {
- return b0 > b1 ? b1 : b0;
- }
-
- public static double greater(double b0, double b1) {
- return b0 > b1 ? b0 : b1;
- }
-
- public static double lesser(double b0, double b1) {
- return b0 > b1 ? b1 : b0;
- }
-
- /** Helper for implementing MAX. Somewhat similar to GREATEST operator. */
- public static <T extends Comparable<T>> T greater(T b0, T b1) {
- return b0 == null || b0.compareTo(b1) < 0 ? b1 : b0;
- }
-
- /** GREATEST operator. */
- public static <T extends Comparable<T>> T greatest(T b0, T b1) {
- return b0 == null || b1 != null && b0.compareTo(b1) < 0 ? b1 : b0;
- }
-
- /** Boolean comparison. */
- public static int compare(boolean x, boolean y) {
- return x == y ? 0 : x ? 1 : -1;
- }
-
- /** CAST(FLOAT AS VARCHAR). */
- public static String toString(float x) {
- if (x == 0) {
- return "0E0";
+ };
+
+ private SqlFunctions() {
+ }
+
+ /** SQL SUBSTRING(string FROM ... FOR ...) function. */
+ public static String substring(String s, int from, int for_) {
+ return s.substring(from - 1, Math.min(from - 1 + for_, s.length()));
+ }
+
+ /** SQL SUBSTRING(string FROM ...) function. */
+ public static String substring(String s, int from) {
+ return s.substring(from - 1);
+ }
+
+ /** SQL UPPER(string) function. */
+ public static String upper(String s) {
+ return s.toUpperCase();
+ }
+
+ /** SQL LOWER(string) function. */
+ public static String lower(String s) {
+ return s.toLowerCase();
+ }
+
+ /** SQL INITCAP(string) function. */
+ public static String initcap(String s) {
+ // Assumes Alpha as [A-Za-z0-9]
+ // white space is treated as everything else.
+ final int len = s.length();
+ boolean start = true;
+ final StringBuilder newS = new StringBuilder();
+
+ for (int i = 0; i < len; i++) {
+ char curCh = s.charAt(i);
+ final int c = (int) curCh;
+ if (start) { // curCh is whitespace or first character of word.
+ if (c > 47 && c < 58) { // 0-9
+ start = false;
+ } else if (c > 64 && c < 91) { // A-Z
+ start = false;
+ } else if (c > 96 && c < 123) { // a-z
+ start = false;
+ curCh = (char) (c - 32); // Uppercase this character
}
- BigDecimal bigDecimal = new BigDecimal(x, MathContext.DECIMAL32).stripTrailingZeros();
- final String s = bigDecimal.toString();
- return s.replaceAll("0*E", "E").replace("E+", "E");
- }
-
- /** CAST(DOUBLE AS VARCHAR). */
- public static String toString(double x) {
- if (x == 0) {
- return "0E0";
+ // else {} whitespace
+ } else { // Inside of a word or white space after end of word.
+ if (c > 47 && c < 58) { // 0-9
+ // noop
+ } else if (c > 64 && c < 91) { // A-Z
+ curCh = (char) (c + 32); // Lowercase this character
+ } else if (c > 96 && c < 123) { // a-z
+ // noop
+ } else { // whitespace
+ start = true;
}
- BigDecimal bigDecimal = new BigDecimal(x, MathContext.DECIMAL64).stripTrailingZeros();
- final String s = bigDecimal.toString();
- return s.replaceAll("0*E", "E").replace("E+", "E");
- }
-
- /** CAST(DECIMAL AS VARCHAR). */
- public static String toString(BigDecimal x) {
- final String s = x.toString();
- if (s.startsWith("0")) {
- // we want ".1" not "0.1"
- return s.substring(1);
- } else if (s.startsWith("-0")) {
- // we want "-.1" not "-0.1"
- return "-" + s.substring(2);
- } else {
- return s;
+ }
+ newS.append(curCh);
+ } // for each character in s
+ return newS.toString();
+ }
+
+ /** SQL CHARACTER_LENGTH(string) function. */
+ public static int charLength(String s) {
+ return s.length();
+ }
+
+ /** SQL {@code string || string} operator. */
+ public static String concat(String s0, String s1) {
+ return s0 + s1;
+ }
+
+ /** SQL {@code binary || binary} operator. */
+ public static ByteString concat(ByteString s0, ByteString s1) {
+ return s0.concat(s1);
+ }
+
+ /** SQL {@code RTRIM} function applied to string. */
+ public static String rtrim(String s) {
+ return trim_(s, false, true, ' ');
+ }
+
+ /** SQL {@code LTRIM} function. */
+ public static String ltrim(String s) {
+ return trim_(s, true, false, ' ');
+ }
+
+ /** SQL {@code TRIM(... seek FROM s)} function. */
+ public static String trim(boolean leading, boolean trailing, String seek,
+ String s) {
+ return trim_(s, leading, trailing, seek.charAt(0));
+ }
+
+ /** SQL {@code TRIM} function. */
+ private static String trim_(String s, boolean left, boolean right, char c) {
+ int j = s.length();
+ if (right) {
+ for (;;) {
+ if (j == 0) {
+ return "";
}
- }
-
- /** CAST(BOOLEAN AS VARCHAR). */
- public static String toString(boolean x) {
- // Boolean.toString returns lower case -- no good.
- return x ? "TRUE" : "FALSE";
- }
-
- @NonDeterministic
- private static Object cannotConvert(Object o, Class toType) {
- throw new RuntimeException("Cannot convert " + o + " to " + toType);
- }
-
- /** CAST(VARCHAR AS BOOLEAN). */
- public static boolean toBoolean(String s) {
- s = trim_(s, true, true, ' ');
- if (s.equalsIgnoreCase("TRUE")) {
- return true;
- } else if (s.equalsIgnoreCase("FALSE")) {
- return false;
- } else {
- throw new RuntimeException("Invalid character for cast");
+ if (s.charAt(j - 1) != c) {
+ break;
}
- }
-
- public static boolean toBoolean(Number number) {
- return !number.equals(0);
- }
-
- public static boolean toBoolean(Object o) {
- return o instanceof Boolean ? (Boolean) o : o instanceof Number ? toBoolean((Number) o) : o instanceof String ? toBoolean((String) o) : (Boolean) cannotConvert(o, boolean.class);
- }
-
- // Don't need parseByte etc. - Byte.parseByte is sufficient.
-
- public static byte toByte(Object o) {
- return o instanceof Byte ? (Byte) o : o instanceof Number ? toByte((Number) o) : Byte.parseByte(o.toString());
- }
-
- public static byte toByte(Number number) {
- return number.byteValue();
- }
-
- public static char toChar(String s) {
- return s.charAt(0);
- }
-
- public static Character toCharBoxed(String s) {
- return s.charAt(0);
- }
-
- public static short toShort(String s) {
- return Short.parseShort(s.trim());
- }
-
- public static short toShort(Number number) {
- return number.shortValue();
- }
-
- public static short toShort(Object o) {
- return o instanceof Short ? (Short) o : o instanceof Number ? toShort((Number) o) : o instanceof String ? toShort((String) o) : (Short) cannotConvert(o, short.class);
- }
-
- public static int toInt(java.util.Date v) {
- return toInt(v, LOCAL_TZ);
- }
-
- public static int toInt(java.util.Date v, TimeZone timeZone) {
- return (int) (toLong(v, timeZone) / DateTimeUtil.MILLIS_PER_DAY);
- }
-
- public static Integer toIntOptional(java.util.Date v) {
- return v == null ? null : toInt(v);
- }
-
- public static Integer toIntOptional(java.util.Date v, TimeZone timeZone) {
- return v == null ? null : toInt(v, timeZone);
- }
-
- public static long toLong(Date v) {
- return toLong(v, LOCAL_TZ);
- }
-
- public static int toInt(java.sql.Time v) {
- return (int) (toLong(v) % DateTimeUtil.MILLIS_PER_DAY);
- }
-
- public static Integer toIntOptional(java.sql.Time v) {
- return v == null ? null : toInt(v);
- }
-
- public static int toInt(String s) {
- return Integer.parseInt(s.trim());
- }
-
- public static int toInt(Number number) {
- return number.intValue();
- }
-
- public static int toInt(Object o) {
- return o instanceof Integer ? (Integer) o : o instanceof Number ? toInt((Number) o) : o instanceof String ? toInt((String) o) : (Integer) cannotConvert(o, int.class);
- }
-
- public static long toLong(Timestamp v) {
- return toLong(v, LOCAL_TZ);
- }
-
- // mainly intended for java.sql.Timestamp but works for other dates also
- public static long toLong(java.util.Date v, TimeZone timeZone) {
- final long time = v.getTime();
- return time + timeZone.getOffset(time);
- }
-
- // mainly intended for java.sql.Timestamp but works for other dates also
- public static Long toLongOptional(java.util.Date v) {
- return v == null ? null : toLong(v, LOCAL_TZ);
- }
-
- public static Long toLongOptional(Timestamp v, TimeZone timeZone) {
- if (v == null) {
- return null;
+ --j;
+ }
+ }
+ int i = 0;
+ if (left) {
+ for (;;) {
+ if (i == j) {
+ return "";
}
- return toLong(v, LOCAL_TZ);
- }
-
- public static long toLong(String s) {
- if (s.startsWith("199") && s.contains(":")) {
- return Timestamp.valueOf(s).getTime();
+ if (s.charAt(i) != c) {
+ break;
}
- return Long.parseLong(s.trim());
- }
-
- public static long toLong(Number number) {
- return number.longValue();
- }
-
- public static long toLong(Object o) {
- return o instanceof Long ? (Long) o : o instanceof Number ? toLong((Number) o) : o instanceof String ? toLong((String) o) : (Long) cannotConvert(o, long.class);
- }
-
- public static float toFloat(String s) {
- return Float.parseFloat(s.trim());
- }
-
- public static float toFloat(Number number) {
- return number.floatValue();
- }
-
- public static float toFloat(Object o) {
- return o instanceof Float ? (Float) o : o instanceof Number ? toFloat((Number) o) : o instanceof String ? toFloat((String) o) : (Float) cannotConvert(o, float.class);
- }
-
- public static double toDouble(String s) {
- return Double.parseDouble(s.trim());
- }
-
- public static double toDouble(Number number) {
- return number.doubleValue();
- }
-
- public static double toDouble(Object o) {
- return o instanceof Double ? (Double) o : o instanceof Number ? toDouble((Number) o) : o instanceof String ? toDouble((String) o) : (Double) cannotConvert(o, double.class);
- }
-
- public static BigDecimal toBigDecimal(String s) {
- return new BigDecimal(s.trim());
- }
-
- public static BigDecimal toBigDecimal(Number number) {
- // There are some values of "long" that cannot be represented as "double".
- // Not so "int". If it isn't a long, go straight to double.
- return number instanceof BigDecimal ? (BigDecimal) number : number instanceof BigInteger ? new BigDecimal((BigInteger) number) : number instanceof Long ? new BigDecimal(number.longValue()) : new BigDecimal(number.doubleValue());
- }
-
- public static BigDecimal toBigDecimal(Object o) {
- return o instanceof Number ? toBigDecimal((Number) o) : toBigDecimal(o.toString());
- }
-
- // Don't need shortValueOf etc. - Short.valueOf is sufficient.
-
- /** Helper for CAST(... AS VARCHAR(maxLength)). */
- public static String truncate(String s, int maxLength) {
- return s == null ? null : s.length() > maxLength ? s.substring(0, maxLength) : s;
- }
-
- /** Helper for CAST(... AS VARBINARY(maxLength)). */
- public static ByteString truncate(ByteString s, int maxLength) {
- return s == null ? null : s.length() > maxLength ? s.substring(0, maxLength) : s;
- }
-
- /** SQL {@code POSITION(seek IN string)} function. */
- public static int position(String seek, String s) {
- return s.indexOf(seek) + 1;
- }
-
- /** SQL {@code POSITION(seek IN string)} function. */
- public static int position(ByteString seek, ByteString s) {
- return s.indexOf(seek) + 1;
- }
-
- /** Cheap, unsafe, long power. power(2, 3) returns 8. */
- public static long powerX(long a, long b) {
- long x = 1;
- while (b > 0) {
- x *= a;
- --b;
- }
- return x;
- }
-
- /** Helper for rounding. Truncate(12345, 1000) returns 12000. */
- public static long round(long v, long x) {
- return truncate(v + x / 2, x);
- }
-
- /** Helper for rounding. Truncate(12345, 1000) returns 12000. */
- public static long truncate(long v, long x) {
- long remainder = v % x;
- if (remainder < 0) {
- remainder += x;
+ ++i;
+ }
+ }
+ return s.substring(i, j);
+ }
+
+ /** SQL {@code TRIM} function applied to binary string. */
+ public static ByteString trim(ByteString s) {
+ return trim_(s, true, true);
+ }
+
+ /** Helper for CAST. */
+ public static ByteString rtrim(ByteString s) {
+ return trim_(s, false, true);
+ }
+
+ /** SQL {@code TRIM} function applied to binary string. */
+ private static ByteString trim_(ByteString s, boolean left, boolean right) {
+ int j = s.length();
+ if (right) {
+ for (;;) {
+ if (j == 0) {
+ return ByteString.EMPTY;
}
- return v - remainder;
- }
-
- /** Helper for rounding. Truncate(12345, 1000) returns 12000. */
- public static int round(int v, int x) {
- return truncate(v + x / 2, x);
- }
-
- /** Helper for rounding. Truncate(12345, 1000) returns 12000. */
- public static int truncate(int v, int x) {
- int remainder = v % x;
- if (remainder < 0) {
- remainder += x;
- }
- return v - remainder;
- }
-
- /** Helper for CAST({timestamp} AS VARCHAR(n)). */
- public static String unixTimestampToString(long timestamp) {
- final StringBuilder buf = new StringBuilder(17);
- int date = (int) (timestamp / DateTimeUtil.MILLIS_PER_DAY);
- int time = (int) (timestamp % DateTimeUtil.MILLIS_PER_DAY);
- if (time < 0) {
- --date;
- time += DateTimeUtil.MILLIS_PER_DAY;
+ if (s.byteAt(j - 1) != 0) {
+ break;
}
- unixDateToString(buf, date);
- buf.append(' ');
- unixTimeToString(buf, time);
- return buf.toString();
- }
-
- /** Helper for CAST({timestamp} AS VARCHAR(n)). */
- public static String unixTimeToString(int time) {
- final StringBuilder buf = new StringBuilder(8);
- unixTimeToString(buf, time);
- return buf.toString();
- }
-
- private static void unixTimeToString(StringBuilder buf, int time) {
- int h = time / 3600000;
- int time2 = time % 3600000;
- int m = time2 / 60000;
- int time3 = time2 % 60000;
- int s = time3 / 1000;
- int ms = time3 % 1000;
- int2(buf, h);
- buf.append(':');
- int2(buf, m);
- buf.append(':');
- int2(buf, s);
- }
-
- /** SQL {@code CURRENT_TIMESTAMP} function. */
- @NonDeterministic
- public static long currentTimestamp(DataContext root) {
- // Cast required for JDK 1.6.
- return (Long) DataContext.Variable.CURRENT_TIMESTAMP.get(root);
- }
-
- /** SQL {@code CURRENT_TIME} function. */
- @NonDeterministic
- public static int currentTime(DataContext root) {
- int time = (int) (currentTimestamp(root) % DateTimeUtil.MILLIS_PER_DAY);
- if (time < 0) {
- time += DateTimeUtil.MILLIS_PER_DAY;
+ --j;
+ }
+ }
+ int i = 0;
+ if (left) {
+ for (;;) {
+ if (i == j) {
+ return ByteString.EMPTY;
}
- return time;
- }
-
- /** SQL {@code CURRENT_DATE} function. */
- @NonDeterministic
- public static int currentDate(DataContext root) {
- final long timestamp = currentTimestamp(root);
- int date = (int) (timestamp / DateTimeUtil.MILLIS_PER_DAY);
- final int time = (int) (timestamp % DateTimeUtil.MILLIS_PER_DAY);
- if (time < 0) {
- --date;
+ if (s.byteAt(i) != 0) {
+ break;
}
- return date;
- }
-
- /** SQL {@code LOCAL_TIMESTAMP} function. */
- @NonDeterministic
- public static long localTimestamp(DataContext root) {
- // Cast required for JDK 1.6.
- return (Long) DataContext.Variable.LOCAL_TIMESTAMP.get(root);
- }
-
- /** SQL {@code LOCAL_TIME} function. */
- @NonDeterministic
- public static int localTime(DataContext root) {
- return (int) (localTimestamp(root) % DateTimeUtil.MILLIS_PER_DAY);
- }
-
- private static void int2(StringBuilder buf, int i) {
- buf.append((char) ('0' + (i / 10) % 10));
- buf.append((char) ('0' + i % 10));
- }
-
- private static void int4(StringBuilder buf, int i) {
- buf.append((char) ('0' + (i / 1000) % 10));
- buf.append((char) ('0' + (i / 100) % 10));
- buf.append((char) ('0' + (i / 10) % 10));
- buf.append((char) ('0' + i % 10));
- }
-
- public static int dateStringToUnixDate(String s) {
- int hyphen1 = s.indexOf('-');
- int y;
- int m;
- int d;
- if (hyphen1 < 0) {
- y = Integer.parseInt(s.trim());
- m = 1;
- d = 1;
- } else {
- y = Integer.parseInt(s.substring(0, hyphen1).trim());
- final int hyphen2 = s.indexOf('-', hyphen1 + 1);
- if (hyphen2 < 0) {
- m = Integer.parseInt(s.substring(hyphen1 + 1).trim());
- d = 1;
- } else {
- m = Integer.parseInt(s.substring(hyphen1 + 1, hyphen2).trim());
- d = Integer.parseInt(s.substring(hyphen2 + 1).trim());
- }
- }
- return ymdToUnixDate(y, m, d);
- }
-
- public static int timeStringToUnixDate(String v) {
- return timeStringToUnixDate(v, 0);
- }
-
- public static int timeStringToUnixDate(String v, int start) {
- final int colon1 = v.indexOf(':', start);
- int hour;
- int minute;
- int second;
- int milli;
- if (colon1 < 0) {
- hour = Integer.parseInt(v.trim());
- minute = 1;
- second = 1;
- milli = 0;
- } else {
- hour = Integer.parseInt(v.substring(start, colon1).trim());
- final int colon2 = v.indexOf(':', colon1 + 1);
- if (colon2 < 0) {
- minute = Integer.parseInt(v.substring(colon1 + 1).trim());
- second = 1;
- milli = 0;
- } else {
- minute = Integer.parseInt(v.substring(colon1 + 1, colon2).trim());
- int dot = v.indexOf('.', colon2);
- if (dot < 0) {
- second = Integer.parseInt(v.substring(colon2 + 1).trim());
- milli = 0;
- } else {
- second = Integer.parseInt(v.substring(colon2 + 1, dot).trim());
- milli = Integer.parseInt(v.substring(dot + 1).trim());
- }
- }
- }
- return hour * (int) DateTimeUtil.MILLIS_PER_HOUR + minute * (int) DateTimeUtil.MILLIS_PER_MINUTE + second * (int) DateTimeUtil.MILLIS_PER_SECOND + milli;
- }
-
- public static long timestampStringToUnixDate(String s) {
- final long d;
- final long t;
- s = s.trim();
- int space = s.indexOf(' ');
- if (space >= 0) {
- d = dateStringToUnixDate(s.substring(0, space));
- t = timeStringToUnixDate(s, space + 1);
+ ++i;
+ }
+ }
+ return s.substring(i, j);
+ }
+
+ /** SQL {@code OVERLAY} function. */
+ public static String overlay(String s, String r, int start) {
+ if (s == null || r == null) {
+ return null;
+ }
+ return s.substring(0, start - 1)
+ + r
+ + s.substring(start - 1 + r.length());
+ }
+
+ /** SQL {@code OVERLAY} function. */
+ public static String overlay(String s, String r, int start, int length) {
+ if (s == null || r == null) {
+ return null;
+ }
+ return s.substring(0, start - 1)
+ + r
+ + s.substring(start - 1 + length);
+ }
+
+ /** SQL {@code OVERLAY} function applied to binary strings. */
+ public static ByteString overlay(ByteString s, ByteString r, int start) {
+ if (s == null || r == null) {
+ return null;
+ }
+ return s.substring(0, start - 1)
+ .concat(r)
+ .concat(s.substring(start - 1 + r.length()));
+ }
+
+ /** SQL {@code OVERLAY} function applied to binary strings. */
+ public static ByteString overlay(ByteString s, ByteString r, int start,
+ int length) {
+ if (s == null || r == null) {
+ return null;
+ }
+ return s.substring(0, start - 1)
+ .concat(r)
+ .concat(s.substring(start - 1 + length));
+ }
+
+ /** SQL {@code LIKE} function. */
+ public static boolean like(String s, String pattern) {
+ final String regex = Like.sqlToRegexLike(pattern, null);
+ return Pattern.matches(regex, s);
+ }
+
+ /** SQL {@code LIKE} function with escape. */
+ public static boolean like(String s, String pattern, String escape) {
+ final String regex = Like.sqlToRegexLike(pattern, escape);
+ return Pattern.matches(regex, s);
+ }
+
+ /** SQL {@code SIMILAR} function. */
+ public static boolean similar(String s, String pattern) {
+ final String regex = Like.sqlToRegexSimilar(pattern, null);
+ return Pattern.matches(regex, s);
+ }
+
+ /** SQL {@code SIMILAR} function with escape. */
+ public static boolean similar(String s, String pattern, String escape) {
+ final String regex = Like.sqlToRegexSimilar(pattern, escape);
+ return Pattern.matches(regex, s);
+ }
+
+ // =
+
+ /** SQL = operator applied to Object values (including String; neither
+ * side may be null). */
+ public static boolean eq(Object b0, Object b1) {
+ return b0.equals(b1);
+ }
+
+ /** SQL = operator applied to BigDecimal values (neither may be null). */
+ public static boolean eq(BigDecimal b0, BigDecimal b1) {
+ return b0.stripTrailingZeros().equals(b1.stripTrailingZeros());
+ }
+
+ // <>
+
+ /** SQL <> operator applied to Object values (including String;
+ * neither side may be null). */
+ public static boolean ne(Object b0, Object b1) {
+ return !b0.equals(b1);
+ }
+
+ /** SQL <> operator applied to BigDecimal values. */
+ public static boolean ne(BigDecimal b0, BigDecimal b1) {
+ return b0.compareTo(b1) != 0;
+ }
+
+ // <
+
+ /** SQL < operator applied to boolean values. */
+ public static boolean lt(boolean b0, boolean b1) {
+ return compare(b0, b1) < 0;
+ }
+
+ /** SQL < operator applied to String values. */
+ public static boolean lt(String b0, String b1) {
+ return b0.compareTo(b1) < 0;
+ }
+
+ /** SQL < operator applied to ByteString values. */
+ public static boolean lt(ByteString b0, ByteString b1) {
+ return b0.compareTo(b1) < 0;
+ }
+
+ /** SQL < operator applied to BigDecimal values. */
+ public static boolean lt(BigDecimal b0, BigDecimal b1) {
+ return b0.compareTo(b1) < 0;
+ }
+
+ // <=
+
+ /** SQL ≤ operator applied to boolean values. */
+ public static boolean le(boolean b0, boolean b1) {
+ return compare(b0, b1) <= 0;
+ }
+
+ /** SQL ≤ operator applied to String values. */
+ public static boolean le(String b0, String b1) {
+ return b0.compareTo(b1) <= 0;
+ }
+
+ /** SQL ≤ operator applied to ByteString values. */
+ public static boolean le(ByteString b0, ByteString b1) {
+ return b0.compareTo(b1) <= 0;
+ }
+
+ /** SQL ≤ operator applied to BigDecimal values. */
+ public static boolean le(BigDecimal b0, BigDecimal b1) {
+ return b0.compareTo(b1) <= 0;
+ }
+
+ // >
+
+ /** SQL > operator applied to boolean values. */
+ public static boolean gt(boolean b0, boolean b1) {
+ return compare(b0, b1) > 0;
+ }
+
+ /** SQL > operator applied to String values. */
+ public static boolean gt(String b0, String b1) {
+ return b0.compareTo(b1) > 0;
+ }
+
+ /** SQL > operator applied to ByteString values. */
+ public static boolean gt(ByteString b0, ByteString b1) {
+ return b0.compareTo(b1) > 0;
+ }
+
+ /** SQL > operator applied to BigDecimal values. */
+ public static boolean gt(BigDecimal b0, BigDecimal b1) {
+ return b0.compareTo(b1) > 0;
+ }
+
+ // >=
+
+ /** SQL ≥ operator applied to boolean values. */
+ public static boolean ge(boolean b0, boolean b1) {
+ return compare(b0, b1) >= 0;
+ }
+
+ /** SQL ≥ operator applied to String values. */
+ public static boolean ge(String b0, String b1) {
+ return b0.compareTo(b1) >= 0;
+ }
+
+ /** SQL ≥ operator applied to ByteString values. */
+ public static boolean ge(ByteString b0, ByteString b1) {
+ return b0.compareTo(b1) >= 0;
+ }
+
+ /** SQL ≥ operator applied to BigDecimal values. */
+ public static boolean ge(BigDecimal b0, BigDecimal b1) {
+ return b0.compareTo(b1) >= 0;
+ }
+
+ // +
+
+ /** SQL <code>+</code> operator applied to int values. */
+ public static int plus(int b0, int b1) {
+ return b0 + b1;
+ }
+
+ /** SQL <code>+</code> operator applied to int values; left side may be
+ * null. */
+ public static Integer plus(Integer b0, int b1) {
+ return b0 == null ? null : (b0 + b1);
+ }
+
+ /** SQL <code>+</code> operator applied to int values; right side may be
+ * null. */
+ public static Integer plus(int b0, Integer b1) {
+ return b1 == null ? null : (b0 + b1);
+ }
+
+ /** SQL <code>+</code> operator applied to nullable int values. */
+ public static Integer plus(Integer b0, Integer b1) {
+ return (b0 == null || b1 == null) ? null : (b0 + b1);
+ }
+
+ /** SQL <code>+</code> operator applied to nullable long and int values. */
+ public static Long plus(Long b0, Integer b1) {
+ return (b0 == null || b1 == null)
+ ? null
+ : (b0.longValue() + b1.longValue());
+ }
+
+ /** SQL <code>+</code> operator applied to nullable int and long values. */
+ public static Long plus(Integer b0, Long b1) {
+ return (b0 == null || b1 == null)
+ ? null
+ : (b0.longValue() + b1.longValue());
+ }
+
+ /** SQL <code>+</code> operator applied to BigDecimal values. */
+ public static BigDecimal plus(BigDecimal b0, BigDecimal b1) {
+ return (b0 == null || b1 == null) ? null : b0.add(b1);
+ }
+
+ // -
+
+ /** SQL <code>-</code> operator applied to int values. */
+ public static int minus(int b0, int b1) {
+ return b0 - b1;
+ }
+
+ /** SQL <code>-</code> operator applied to int values; left side may be
+ * null. */
+ public static Integer minus(Integer b0, int b1) {
+ return b0 == null ? null : (b0 - b1);
+ }
+
+ /** SQL <code>-</code> operator applied to int values; right side may be
+ * null. */
+ public static Integer minus(int b0, Integer b1) {
+ return b1 == null ? null : (b0 - b1);
+ }
+
+ /** SQL <code>-</code> operator applied to nullable int values. */
+ public static Integer minus(Integer b0, Integer b1) {
+ return (b0 == null || b1 == null) ? null : (b0 - b1);
+ }
+
+ /** SQL <code>-</code> operator applied to nullable long and int values. */
+ public static Long minus(Long b0, Integer b1) {
+ return (b0 == null || b1 == null)
+ ? null
+ : (b0.longValue() - b1.longValue());
+ }
+
+ /** SQL <code>-</code> operator applied to nullable int and long values. */
+ public static Long minus(Integer b0, Long b1) {
+ return (b0 == null || b1 == null)
+ ? null
+ : (b0.longValue() - b1.longValue());
+ }
+
+ /** SQL <code>-</code> operator applied to BigDecimal values. */
+ public static BigDecimal minus(BigDecimal b0, BigDecimal b1) {
+ return (b0 == null || b1 == null) ? null : b0.subtract(b1);
+ }
+
+ // /
+
+ /** SQL <code>/</code> operator applied to int values. */
+ public static int divide(int b0, int b1) {
+ return b0 / b1;
+ }
+
+ /** SQL <code>/</code> operator applied to int values; left side may be
+ * null. */
+ public static Integer divide(Integer b0, int b1) {
+ return b0 == null ? null : (b0 / b1);
+ }
+
+ /** SQL <code>/</code> operator applied to int values; right side may be
+ * null. */
+ public static Integer divide(int b0, Integer b1) {
+ return b1 == null ? null : (b0 / b1);
+ }
+
+ /** SQL <code>/</code> operator applied to nullable int values. */
+ public static Integer divide(Integer b0, Integer b1) {
+ return (b0 == null || b1 == null) ? null : (b0 / b1);
+ }
+
+ /** SQL <code>/</code> operator applied to nullable long and int values. */
+ public static Long divide(Long b0, Integer b1) {
+ return (b0 == null || b1 == null)
+ ? null
+ : (b0.longValue() / b1.longValue());
+ }
+
+ /** SQL <code>/</code> operator applied to nullable int and long values. */
+ public static Long divide(Integer b0, Long b1) {
+ return (b0 == null || b1 == null)
+ ? null
+ : (b0.longValue() / b1.longValue());
+ }
+
+ /** SQL <code>/</code> operator applied to BigDecimal values. */
+ public static BigDecimal divide(BigDecimal b0, BigDecimal b1) {
+ // OVERRIDE POINT
+ return (b0 == null || b1 == null) ? null : b0.divide(b1, MathContext.DECIMAL64);
+ }
+
+ // *
+
+ /** SQL <code>*</code> operator applied to int values. */
+ public static int multiply(int b0, int b1) {
+ return b0 * b1;
+ }
+
+ /** SQL <code>*</code> operator applied to int values; left side may be
+ * null. */
+ public static Integer multiply(Integer b0, int b1) {
+ return b0 == null ? null : (b0 * b1);
+ }
+
+ /** SQL <code>*</code> operator applied to int values; right side may be
+ * null. */
+ public static Integer multiply(int b0, Integer b1) {
+ return b1 == null ? null : (b0 * b1);
+ }
+
+ /** SQL <code>*</code> operator applied to nullable int values. */
+ public static Integer multiply(Integer b0, Integer b1) {
+ return (b0 == null || b1 == null) ? null : (b0 * b1);
+ }
+
+ /** SQL <code>*</code> operator applied to nullable long and int values. */
+ public static Long multiply(Long b0, Integer b1) {
+ return (b0 == null || b1 == null)
+ ? null
+ : (b0.longValue() * b1.longValue());
+ }
+
+ /** SQL <code>*</code> operator applied to nullable int and long values. */
+ public static Long multiply(Integer b0, Long b1) {
+ return (b0 == null || b1 == null)
+ ? null
+ : (b0.longValue() * b1.longValue());
+ }
+
+ /** SQL <code>*</code> operator applied to BigDecimal values. */
+ public static BigDecimal multiply(BigDecimal b0, BigDecimal b1) {
+ return (b0 == null || b1 == null) ? null : b0.multiply(b1);
+ }
+
+ // EXP
+
+ /** SQL <code>EXP</code> operator applied to double values. */
+ public static double exp(double b0) {
+ return Math.exp(b0);
+ }
+
+ public static double exp(long b0) {
+ return Math.exp(b0);
+ }
+
+ // POWER
+
+ /** SQL <code>POWER</code> operator applied to double values. */
+ public static double power(double b0, double b1) {
+ return Math.pow(b0, b1);
+ }
+
+ public static double power(long b0, long b1) {
+ return Math.pow(b0, b1);
+ }
+
+ public static double power(long b0, BigDecimal b1) {
+ return Math.pow(b0, b1.doubleValue());
+ }
+
+ // LN
+
+ /** SQL {@code LN(number)} function applied to double values. */
+ public static double ln(double d) {
+ return Math.log(d);
+ }
+
+ /** SQL {@code LN(number)} function applied to long values. */
+ public static double ln(long b0) {
+ return Math.log(b0);
+ }
+
+ /** SQL {@code LN(number)} function applied to BigDecimal values. */
+ public static double ln(BigDecimal d) {
+ return Math.log(d.doubleValue());
+ }
+
+ // LOG10
+
+ /** SQL <code>LOG10(numeric)</code> operator applied to double values. */
+ public static double log10(double b0) {
+ return Math.log10(b0);
+ }
+
+ /** SQL {@code LOG10(number)} function applied to long values. */
+ public static double log10(long b0) {
+ return Math.log10(b0);
+ }
+
+ /** SQL {@code LOG10(number)} function applied to BigDecimal values. */
+ public static double log10(BigDecimal d) {
+ return Math.log10(d.doubleValue());
+ }
+
+ // MOD
+
+ /** SQL <code>MOD</code> operator applied to byte values. */
+ public static byte mod(byte b0, byte b1) {
+ return (byte) (b0 % b1);
+ }
+
+ /** SQL <code>MOD</code> operator applied to short values. */
+ public static short mod(short b0, short b1) {
+ return (short) (b0 % b1);
+ }
+
+ /** SQL <code>MOD</code> operator applied to int values. */
+ public static int mod(int b0, int b1) {
+ return b0 % b1;
+ }
+
+ /** SQL <code>MOD</code> operator applied to long values. */
+ public static long mod(long b0, long b1) {
+ return b0 % b1;
+ }
+
+ // temporary
+ public static BigDecimal mod(BigDecimal b0, int b1) {
+ return mod(b0, BigDecimal.valueOf(b1));
+ }
+
+ // temporary
+ public static int mod(int b0, BigDecimal b1) {
+ return mod(b0, b1.intValue());
+ }
+
+ public static BigDecimal mod(BigDecimal b0, BigDecimal b1) {
+ final BigDecimal[] bigDecimals = b0.divideAndRemainder(b1);
+ return bigDecimals[1];
+ }
+
+ // ABS
+
+ /** SQL <code>ABS</code> operator applied to byte values. */
+ public static byte abs(byte b0) {
+ return (byte) Math.abs(b0);
+ }
+
+ /** SQL <code>ABS</code> operator applied to short values. */
+ public static short abs(short b0) {
+ return (short) Math.abs(b0);
+ }
+
+ /** SQL <code>ABS</code> operator applied to int values. */
+ public static int abs(int b0) {
+ return Math.abs(b0);
+ }
+
+ /** SQL <code>ABS</code> operator applied to long values. */
+ public static long abs(long b0) {
+ return Math.abs(b0);
+ }
+
+ /** SQL <code>ABS</code> operator applied to float values. */
+ public static float abs(float b0) {
+ return Math.abs(b0);
+ }
+
+ /** SQL <code>ABS</code> operator applied to double values. */
+ public static double abs(double b0) {
+ return Math.abs(b0);
+ }
+
+ /** SQL <code>ABS</code> operator applied to BigDecimal values. */
+ public static BigDecimal abs(BigDecimal b0) {
+ return b0.abs();
+ }
+
+ // Helpers
+
+ /** Helper for implementing MIN. Somewhat similar to LEAST operator. */
+ public static <T extends Comparable<T>> T lesser(T b0, T b1) {
+ return b0 == null || b0.compareTo(b1) > 0 ? b1 : b0;
+ }
+
+ /** LEAST operator. */
+ public static <T extends Comparable<T>> T least(T b0, T b1) {
+ return b0 == null || b1 != null && b0.compareTo(b1) > 0 ? b1 : b0;
+ }
+
+ public static boolean greater(boolean b0, boolean b1) {
+ return b0 || b1;
+ }
+
+ public static boolean lesser(boolean b0, boolean b1) {
+ return b0 && b1;
+ }
+
+ public static byte greater(byte b0, byte b1) {
+ return b0 > b1 ? b0 : b1;
+ }
+
+ public static byte lesser(byte b0, byte b1) {
+ return b0 > b1 ? b1 : b0;
+ }
+
+ public static char greater(char b0, char b1) {
+ return b0 > b1 ? b0 : b1;
+ }
+
+ public static char lesser(char b0, char b1) {
+ return b0 > b1 ? b1 : b0;
+ }
+
+ public static short greater(short b0, short b1) {
+ return b0 > b1 ? b0 : b1;
+ }
+
+ public static short lesser(short b0, short b1) {
+ return b0 > b1 ? b1 : b0;
+ }
+
+ public static int greater(int b0, int b1) {
+ return b0 > b1 ? b0 : b1;
+ }
+
+ public static int lesser(int b0, int b1) {
+ return b0 > b1 ? b1 : b0;
+ }
+
+ public static long greater(long b0, long b1) {
+ return b0 > b1 ? b0 : b1;
+ }
+
+ public static long lesser(long b0, long b1) {
+ return b0 > b1 ? b1 : b0;
+ }
+
+ public static float greater(float b0, float b1) {
+ return b0 > b1 ? b0 : b1;
+ }
+
+ public static float lesser(float b0, float b1) {
+ return b0 > b1 ? b1 : b0;
+ }
+
+ public static double greater(double b0, double b1) {
+ return b0 > b1 ? b0 : b1;
+ }
+
+ public static double lesser(double b0, double b1) {
+ return b0 > b1 ? b1 : b0;
+ }
+
+ /** Helper for implementing MAX. Somewhat similar to GREATEST operator. */
+ public static <T extends Comparable<T>> T greater(T b0, T b1) {
+ return b0 == null || b0.compareTo(b1) < 0 ? b1 : b0;
+ }
+
+ /** GREATEST operator. */
+ public static <T extends Comparable<T>> T greatest(T b0, T b1) {
+ return b0 == null || b1 != null && b0.compareTo(b1) < 0 ? b1 : b0;
+ }
+
+ /** Boolean comparison. */
+ public static int compare(boolean x, boolean y) {
+ return x == y ? 0 : x ? 1 : -1;
+ }
+
+ /** CAST(FLOAT AS VARCHAR). */
+ public static String toString(float x) {
+ if (x == 0) {
+ return "0E0";
+ }
+ BigDecimal bigDecimal =
+ new BigDecimal(x, MathContext.DECIMAL32).stripTrailingZeros();
+ final String s = bigDecimal.toString();
+ return s.replaceAll("0*E", "E").replace("E+", "E");
+ }
+
+ /** CAST(DOUBLE AS VARCHAR). */
+ public static String toString(double x) {
+ if (x == 0) {
+ return "0E0";
+ }
+ BigDecimal bigDecimal =
+ new BigDecimal(x, MathContext.DECIMAL64).stripTrailingZeros();
+ final String s = bigDecimal.toString();
+ return s.replaceAll("0*E", "E").replace("E+", "E");
+ }
+
+ /** CAST(DECIMAL AS VARCHAR). */
+ public static String toString(BigDecimal x) {
+ final String s = x.toString();
+ if (s.startsWith("0")) {
+ // we want ".1" not "0.1"
+ return s.substring(1);
+ } else if (s.startsWith("-0")) {
+ // we want "-.1" not "-0.1"
+ return "-" + s.substring(2);
+ } else {
+ return s;
+ }
+ }
+
+ /** CAST(BOOLEAN AS VARCHAR). */
+ public static String toString(boolean x) {
+ // Boolean.toString returns lower case -- no good.
+ return x ? "TRUE" : "FALSE";
+ }
+
+ @NonDeterministic
+ private static Object cannotConvert(Object o, Class toType) {
+ throw new RuntimeException("Cannot convert " + o + " to " + toType);
+ }
+
+ /** CAST(VARCHAR AS BOOLEAN). */
+ public static boolean toBoolean(String s) {
+ s = trim_(s, true, true, ' ');
+ if (s.equalsIgnoreCase("TRUE")) {
+ return true;
+ } else if (s.equalsIgnoreCase("FALSE")) {
+ return false;
+ } else {
+ throw new RuntimeException("Invalid character for cast");
+ }
+ }
+
+ public static boolean toBoolean(Number number) {
+ return !number.equals(0);
+ }
+
+ public static boolean toBoolean(Object o) {
+ return o instanceof Boolean ? (Boolean) o
+ : o instanceof Number ? toBoolean((Number) o)
+ : o instanceof String ? toBoolean((String) o)
+ : (Boolean) cannotConvert(o, boolean.class);
+ }
+
+ // Don't need parseByte etc. - Byte.parseByte is sufficient.
+
+ public static byte toByte(Object o) {
+ return o instanceof Byte ? (Byte) o
+ : o instanceof Number ? toByte((Number) o)
+ : Byte.parseByte(o.toString());
+ }
+
+ public static byte toByte(Number number) {
+ return number.byteValue();
+ }
+
+ public static char toChar(String s) {
+ return s.charAt(0);
+ }
+
+ public static Character toCharBoxed(String s) {
+ return s.charAt(0);
+ }
+
+ public static short toShort(String s) {
+ return Short.parseShort(s.trim());
+ }
+
+ public static short toShort(Number number) {
+ return number.shortValue();
+ }
+
+ public static short toShort(Object o) {
+ return o instanceof Short ? (Short) o
+ : o instanceof Number ? toShort((Number) o)
+ : o instanceof String ? toShort((String) o)
+ : (Short) cannotConvert(o, short.class);
+ }
+
+ public static int toInt(java.util.Date v) {
+ return toInt(v, LOCAL_TZ);
+ }
+
+ public static int toInt(java.util.Date v, TimeZone timeZone) {
+ return (int) (toLong(v, timeZone) / DateTimeUtil.MILLIS_PER_DAY);
+ }
+
+ public static Integer toIntOptional(java.util.Date v) {
+ return v == null ? null : toInt(v);
+ }
+
+ public static Integer toIntOptional(java.util.Date v, TimeZone timeZone) {
+ return v == null
+ ? null
+ : toInt(v, timeZone);
+ }
+
+ public static long toLong(Date v) {
+ return toLong(v, LOCAL_TZ);
+ }
+
+ public static int toInt(java.sql.Time v) {
+ return (int) (toLong(v) % DateTimeUtil.MILLIS_PER_DAY);
+ }
+
+ public static Integer toIntOptional(java.sql.Time v) {
+ return v == null ? null : toInt(v);
+ }
+
+ public static int toInt(String s) {
+ return Integer.parseInt(s.trim());
+ }
+
+ public static int toInt(Number number) {
+ return number.intValue();
+ }
+
+ public static int toInt(Object o) {
+ return o instanceof Integer ? (Integer) o
+ : o instanceof Number ? toInt((Number) o)
+ : o instanceof String ? toInt((String) o)
+ : (Integer) cannotConvert(o, int.class);
+ }
+
+ public static long toLong(Timestamp v) {
+ return toLong(v, LOCAL_TZ);
+ }
+
+ // mainly intended for java.sql.Timestamp but works for other dates also
+ public static long toLong(java.util.Date v, TimeZone timeZone) {
+ final long time = v.getTime();
+ return time + timeZone.getOffset(time);
+ }
+
+ // mainly intended for java.sql.Timestamp but works for other dates also
+ public static Long toLongOptional(java.util.Date v) {
+ return v == null ? null : toLong(v, LOCAL_TZ);
+ }
+
+ public static Long toLongOptional(Timestamp v, TimeZone timeZone) {
+ if (v == null) {
+ return null;
+ }
+ return toLong(v, LOCAL_TZ);
+ }
+
+ public static long toLong(String s) {
+ if (s.startsWith("199") && s.contains(":")) {
+ return Timestamp.valueOf(s).getTime();
+ }
+ return Long.parseLong(s.trim());
+ }
+
+ public static long toLong(Number number) {
+ return number.longValue();
+ }
+
+ public static long toLong(Object o) {
+ return o instanceof Long ? (Long) o
+ : o instanceof Number ? toLong((Number) o)
+ : o instanceof String ? toLong((String) o)
+ : (Long) cannotConvert(o, long.class);
+ }
+
+ public static float toFloat(String s) {
+ return Float.parseFloat(s.trim());
+ }
+
+ public static float toFloat(Number number) {
+ return number.floatValue();
+ }
+
+ public static float toFloat(Object o) {
+ return o instanceof Float ? (Float) o
+ : o instanceof Number ? toFloat((Number) o)
+ : o instanceof String ? toFloat((String) o)
+ : (Float) cannotConvert(o, float.class);
+ }
+
+ public static double toDouble(String s) {
+ return Double.parseDouble(s.trim());
+ }
+
+ public static double toDouble(Number number) {
+ return number.doubleValue();
+ }
+
+ public static double toDouble(Object o) {
+ return o instanceof Double ? (Double) o
+ : o instanceof Number ? toDouble((Number) o)
+ : o instanceof String ? toDouble((String) o)
+ : (Double) cannotConvert(o, double.class);
+ }
+
+ public static BigDecimal toBigDecimal(String s) {
+ return new BigDecimal(s.trim());
+ }
+
+ public static BigDecimal toBigDecimal(Number number) {
+ // There are some values of "long" that cannot be represented as "double".
+ // Not so "int". If it isn't a long, go straight to double.
+ return number instanceof BigDecimal ? (BigDecimal) number
+ : number instanceof BigInteger ? new BigDecimal((BigInteger) number)
+ : number instanceof Long ? new BigDecimal(number.longValue())
+ : new BigDecimal(number.doubleValue());
+ }
+
+ public static BigDecimal toBigDecimal(Object o) {
+ return o instanceof Number ? toBigDecimal((Number) o)
+ : toBigDecimal(o.toString());
+ }
+
+ // Don't need shortValueOf etc. - Short.valueOf is sufficient.
+
+ /** Helper for CAST(... AS VARCHAR(maxLength)). */
+ public static String truncate(String s, int maxLength) {
+ return s == null ? null
+ : s.length() > maxLength ? s.substring(0, maxLength)
+ : s;
+ }
+
+ /** Helper for CAST(... AS VARBINARY(maxLength)). */
+ public static ByteString truncate(ByteString s, int maxLength) {
+ return s == null ? null
+ : s.length() > maxLength ? s.substring(0, maxLength)
+ : s;
+ }
+
+ /** SQL {@code POSITION(seek IN string)} function. */
+ public static int position(String seek, String s) {
+ return s.indexOf(seek) + 1;
+ }
+
+ /** SQL {@code POSITION(seek IN string)} function. */
+ public static int position(ByteString seek, ByteString s) {
+ return s.indexOf(seek) + 1;
+ }
+
+ /** Cheap, unsafe, long power. power(2, 3) returns 8. */
+ public static long powerX(long a, long b) {
+ long x = 1;
+ while (b > 0) {
+ x *= a;
+ --b;
+ }
+ return x;
+ }
+
+ /** Helper for rounding. Truncate(12345, 1000) returns 12000. */
+ public static long round(long v, long x) {
+ return truncate(v + x / 2, x);
+ }
+
+ /** Helper for rounding. Truncate(12345, 1000) returns 12000. */
+ public static long truncate(long v, long x) {
+ long remainder = v % x;
+ if (remainder < 0) {
+ remainder += x;
+ }
+ return v - remainder;
+ }
+
+ /** Helper for rounding. Truncate(12345, 1000) returns 12000. */
+ public static int round(int v, int x) {
+ return truncate(v + x / 2, x);
+ }
+
+ /** Helper for rounding. Truncate(12345, 1000) returns 12000. */
+ public static int truncate(int v, int x) {
+ int remainder = v % x;
+ if (remainder < 0) {
+ remainder += x;
+ }
+ return v - remainder;
+ }
+
+ /** Helper for CAST({timestamp} AS VARCHAR(n)). */
+ public static String unixTimestampToString(long timestamp) {
+ final StringBuilder buf = new StringBuilder(17);
+ int date = (int) (timestamp / DateTimeUtil.MILLIS_PER_DAY);
+ int time = (int) (timestamp % DateTimeUtil.MILLIS_PER_DAY);
+ if (time < 0) {
+ --date;
+ time += DateTimeUtil.MILLIS_PER_DAY;
+ }
+ unixDateToString(buf, date);
+ buf.append(' ');
+ unixTimeToString(buf, time);
+ return buf.toString();
+ }
+
+ /** Helper for CAST({timestamp} AS VARCHAR(n)). */
+ public static String unixTimeToString(int time) {
+ final StringBuilder buf = new StringBuilder(8);
+ unixTimeToString(buf, time);
+ return buf.toString();
+ }
+
+ private static void unixTimeToString(StringBuilder buf, int time) {
+ int h = time / 3600000;
+ int time2 = time % 3600000;
+ int m = time2 / 60000;
+ int time3 = time2 % 60000;
+ int s = time3 / 1000;
+ int ms = time3 % 1000;
+ int2(buf, h);
+ buf.append(':');
+ int2(buf, m);
+ buf.append(':');
+ int2(buf, s);
+ }
+
+ /** SQL {@code CURRENT_TIMESTAMP} function. */
+ @NonDeterministic
+ public static long currentTimestamp(DataContext root) {
+ // Cast required for JDK 1.6.
+ return (Long) DataContext.Variable.CURRENT_TIMESTAMP.get(root);
+ }
+
+ /** SQL {@code CURRENT_TIME} function. */
+ @NonDeterministic
+ public static int currentTime(DataContext root) {
+ int time = (int) (currentTimestamp(root) % DateTimeUtil.MILLIS_PER_DAY);
+ if (time < 0) {
+ time += DateTimeUtil.MILLIS_PER_DAY;
+ }
+ return time;
+ }
+
+ /** SQL {@code CURRENT_DATE} function. */
+ @NonDeterministic
+ public static int currentDate(DataContext root) {
+ final long timestamp = currentTimestamp(root);
+ int date = (int) (timestamp / DateTimeUtil.MILLIS_PER_DAY);
+ final int time = (int) (timestamp % DateTimeUtil.MILLIS_PER_DAY);
+ if (time < 0) {
+ --date;
+ }
+ return date;
+ }
+
+ /** SQL {@code LOCAL_TIMESTAMP} function. */
+ @NonDeterministic
+ public static long localTimestamp(DataContext root) {
+ // Cast required for JDK 1.6.
+ return (Long) DataContext.Variable.LOCAL_TIMESTAMP.get(root);
+ }
+
+ /** SQL {@code LOCAL_TIME} function. */
+ @NonDeterministic
+ public static int localTime(DataContext root) {
+ return (int) (localTimestamp(root) % DateTimeUtil.MILLIS_PER_DAY);
+ }
+
+ private static void int2(StringBuilder buf, int i) {
+ buf.append((char) ('0' + (i / 10) % 10));
+ buf.append((char) ('0' + i % 10));
+ }
+
+ private static void int4(StringBuilder buf, int i) {
+ buf.append((char) ('0' + (i / 1000) % 10));
+ buf.append((char) ('0' + (i / 100) % 10));
+ buf.append((char) ('0' + (i / 10) % 10));
+ buf.append((char) ('0' + i % 10));
+ }
+
+ public static int dateStringToUnixDate(String s) {
+ int hyphen1 = s.indexOf('-');
+ int y;
+ int m;
+ int d;
+ if (hyphen1 < 0) {
+ y = Integer.parseInt(s.trim());
+ m = 1;
+ d = 1;
+ } else {
+ y = Integer.parseInt(s.substring(0, hyphen1).trim());
+ final int hyphen2 = s.indexOf('-', hyphen1 + 1);
+ if (hyphen2 < 0) {
+ m = Integer.parseInt(s.substring(hyphen1 + 1).trim());
+ d = 1;
+ } else {
+ m = Integer.parseInt(s.substring(hyphen1 + 1, hyphen2).trim());
+ d = Integer.parseInt(s.substring(hyphen2 + 1).trim());
+ }
+ }
+ return ymdToUnixDate(y, m, d);
+ }
+
+ public static int timeStringToUnixDate(String v) {
+ return timeStringToUnixDate(v, 0);
+ }
+
+ public static int timeStringToUnixDate(String v, int start) {
+ final int colon1 = v.indexOf(':', start);
+ int hour;
+ int minute;
+ int second;
+ int milli;
+ if (colon1 < 0) {
+ hour = Integer.parseInt(v.trim());
+ minute = 1;
+ second = 1;
+ milli = 0;
+ } else {
+ hour = Integer.parseInt(v.substring(start, colon1).trim());
+ final int colon2 = v.indexOf(':', colon1 + 1);
+ if (colon2 < 0) {
+ minute = Integer.parseInt(v.substring(colon1 + 1).trim());
+ second = 1;
+ milli = 0;
+ } else {
+ minute = Integer.parseInt(v.substring(colon1 + 1, colon2).trim());
+ int dot = v.indexOf('.', colon2);
+ if (dot < 0) {
+ second = Integer.parseInt(v.substring(colon2 + 1).trim());
+ milli = 0;
} else {
- d = dateStringToUnixDate(s);
- t = 0;
+ second = Integer.parseInt(v.substring(colon2 + 1, dot).trim());
+ milli = Integer.parseInt(v.substring(dot + 1).trim());
}
- return d * DateTimeUtil.MILLIS_PER_DAY + t;
- }
-
- /** Helper for CAST({date} AS VARCHAR(n)). */
- public static String unixDateToString(int date) {
- final StringBuilder buf = new StringBuilder(10);
- unixDateToString(buf, date);
- return buf.toString();
- }
-
- private static void unixDateToString(StringBuilder buf, int date) {
- julianToString(buf, date + EPOCH_JULIAN);
- }
-
- private static void julianToString(StringBuilder buf, int julian) {
- // this shifts the epoch back to astronomical year -4800 instead of the
- // start of the Christian era in year AD 1 of the proleptic Gregorian
- // calendar.
- int j = julian + 32044;
- int g = j / 146097;
- int dg = j % 146097;
- int c = (dg / 36524 + 1) * 3 / 4;
- int dc = dg - c * 36524;
- int b = dc / 1461;
- int db = dc % 1461;
- int a = (db / 365 + 1) * 3 / 4;
- int da = db - a * 365;
-
- // integer number of full years elapsed since March 1, 4801 BC
- int y = g * 400 + c * 100 + b * 4 + a;
- // integer number of full months elapsed since the last March 1
- int m = (da * 5 + 308) / 153 - 2;
- // number of days elapsed since day 1 of the month
- int d = da - (m + 4) * 153 / 5 + 122;
- int year = y - 4800 + (m + 2) / 12;
- int month = (m + 2) % 12 + 1;
- int day = d + 1;
- int4(buf, year);
- buf.append('-');
- int2(buf, month);
- buf.append('-');
- int2(buf, day);
- }
-
- public static long unixDateExtract(TimeUnitRange range, long date) {
- return julianExtract(range, (int) date + EPOCH_JULIAN);
- }
-
- private static int julianExtract(TimeUnitRange range, int julian) {
- // this shifts the epoch back to astronomical year -4800 instead of the
- // start of the Christian era in year AD 1 of the proleptic Gregorian
- // calendar.
- int j = julian + 32044;
- int g = j / 146097;
- int dg = j % 146097;
- int c = (dg / 36524 + 1) * 3 / 4;
- int dc = dg - c * 36524;
- int b = dc / 1461;
- int db = dc % 1461;
- int a = (db / 365 + 1) * 3 / 4;
- int da = db - a * 365;
-
- // integer number of full years elapsed since March 1, 4801 BC
- int y = g * 400 + c * 100 + b * 4 + a;
- // integer number of full months elapsed since the last March 1
- int m = (da * 5 + 308) / 153 - 2;
- // number of days elapsed since day 1 of the month
- int d = da - (m + 4) * 153 / 5 + 122;
- int year = y - 4800 + (m + 2) / 12;
- int month = (m + 2) % 12 + 1;
- int day = d + 1;
- switch (range) {
- case YEAR:
- return year;
- case MONTH:
- return month;
- case DAY:
- return day;
- default:
- throw new AssertionError(range);
- }
- }
-
- public static int ymdToUnixDate(int year, int month, int day) {
- final int julian = ymdToJulian(year, month, day);
- return julian - EPOCH_JULIAN;
- }
-
- public static int ymdToJulian(int year, int month, int day) {
- int a = (14 - month) / 12;
- int y = year + 4800 - a;
- int m = month + 12 * a - 3;
- int j = day + (153 * m + 2) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 32045;
- if (j < 2299161) {
- j = day + (153 * m + 2) / 5 + 365 * y + y / 4 - 32083;
- }
- return j;
- }
-
- public static String intervalYearMonthToString(int v, TimeUnitRange range) {
- final StringBuilder buf = new StringBuilder();
- if (v >= 0) {
- buf.append('+');
- } else {
- buf.append('-');
- v = -v;
- }
- final int y;
- final int m;
- switch (range) {
- case YEAR:
- v = roundUp(v, 12);
- y = v / 12;
- buf.append(y);
- break;
- case YEAR_TO_MONTH:
- y = v / 12;
- buf.append(y);
- buf.append('-');
- m = v % 12;
- number(buf, m, 2);
- break;
- case MONTH:
- m = v;
- buf.append(m);
- break;
- default:
- throw new AssertionError(range);
- }
- return buf.toString();
- }
-
- private static StringBuilder number(StringBuilder buf, int v, int n) {
- for (int k = digitCount(v); k < n; k++) {
- buf.append('0');
- }
- return buf.append(v);
- }
-
- public static int digitCount(int v) {
- for (int n = 1;; n++) {
- v /= 10;
- if (v == 0) {
- return n;
- }
- }
- }
-
- public static String intervalDayTimeToString(long v, TimeUnitRange range, int scale) {
- final StringBuilder buf = new StringBuilder();
- if (v >= 0) {
- buf.append('+');
- } else {
- buf.append('-');
- v = -v;
- }
- final long ms;
- final long s;
- final long m;
- final long h;
- final long d;
- switch (range) {
- case DAY_TO_SECOND:
- v = roundUp(v, powerX(10, 3 - scale));
- ms = v % 1000;
- v /= 1000;
- s = v % 60;
- v /= 60;
- m = v % 60;
- v /= 60;
- h = v % 24;
- v /= 24;
- d = v;
- buf.append((int) d);
- buf.append(' ');
- number(buf, (int) h, 2);
- buf.append(':');
- number(buf, (int) m, 2);
- buf.append(':');
- number(buf, (int) s, 2);
- fraction(buf, scale, ms);
- break;
- case DAY_TO_MINUTE:
- v = roundUp(v, 1000 * 60);
- v /= 1000;
- v /= 60;
- m = v % 60;
- v /= 60;
- h = v % 24;
- v /= 24;
- d = v;
- buf.append((int) d);
- buf.append(' ');
- number(buf, (int) h, 2);
- buf.append(':');
- number(buf, (int) m, 2);
- break;
- case DAY_TO_HOUR:
- v = roundUp(v, 1000 * 60 * 60);
- v /= 1000;
- v /= 60;
- v /= 60;
- h = v % 24;
- v /= 24;
- d = v;
- buf.append((int) d);
- buf.append(' ');
- number(buf, (int) h, 2);
- break;
- case DAY:
- v = roundUp(v, 1000 * 60 * 60 * 24);
- d = v / (1000 * 60 * 60 * 24);
- buf.append((int) d);
- break;
- case HOUR:
- v = roundUp(v, 1000 * 60 * 60);
- v /= 1000;
- v /= 60;
- v /= 60;
- h = v;
- buf.append((int) h);
- break;
- case HOUR_TO_MINUTE:
- v = roundUp(v, 1000 * 60);
- v /= 1000;
- v /= 60;
- m = v % 60;
- v /= 60;
- h = v;
- buf.append((int) h);
- buf.append(':');
- number(buf, (int) m, 2);
- break;
- case HOUR_TO_SECOND:
- v = roundUp(v, powerX(10, 3 - scale));
- ms = v % 1000;
- v /= 1000;
- s = v % 60;
- v /= 60;
- m = v % 60;
- v /= 60;
- h = v;
- buf.append((int) h);
- buf.append(':');
- number(buf, (int) m, 2);
- buf.append(':');
- number(buf, (int) s, 2);
- fraction(buf, scale, ms);
- break;
- case MINUTE_TO_SECOND:
- v = roundUp(v, powerX(10, 3 - scale));
- ms = v % 1000;
- v /= 1000;
- s = v % 60;
- v /= 60;
- m = v;
- buf.append((int) m);
- buf.append(':');
- number(buf, (int) s, 2);
- fraction(buf, scale, ms);
- break;
- case MINUTE:
- v = roundUp(v, 1000 * 60);
- v /= 1000;
- v /= 60;
- m = v;
- buf.append((int) m);
- break;
- case SECOND:
- v = roundUp(v, powerX(10, 3 - scale));
- ms = v % 1000;
- v /= 1000;
- s = v;
- buf.append((int) s);
- fraction(buf, scale, ms);
- break;
- default:
- throw new AssertionError(range);
- }
- return buf.toString();
- }
-
- /**
- * Rounds a dividend to the nearest divisor.
- * For example roundUp(31, 10) yields 30; roundUp(37, 10) yields 40.
- * @param dividend Number to be divided
- * @param divisor Number to divide by
- * @return Rounded dividend
- */
- private static long roundUp(long dividend, long divisor) {
- long remainder = dividend % divisor;
- dividend -= remainder;
- if (remainder * 2 > divisor) {
- dividend += divisor;
- }
- return dividend;
- }
-
- private static int roundUp(int dividend, int divisor) {
- int remainder = dividend % divisor;
- dividend -= remainder;
- if (remainder * 2 > divisor) {
- dividend += divisor;
- }
- return dividend;
- }
-
- private static void fraction(StringBuilder buf, int scale, long ms) {
- if (scale > 0) {
- buf.append('.');
- long v1 = scale == 3 ? ms : scale == 2 ? ms / 10 : scale == 1 ? ms / 100 : 0;
- number(buf, (int) v1, scale);
- }
- }
-
- /** Helper for "array element reference". Caller has already ensured that
- * array and index are not null. Index is 1-based, per SQL. */
- public static Object arrayItem(List list, int item) {
- if (item < 1 || item > list.size()) {
- return null;
- }
- return list.get(item - 1);
- }
-
- /** Helper for "map element reference". Caller has already ensured that
- * array and index are not null. Index is 1-based, per SQL. */
- public static Object mapItem(Map map, Object item) {
- return map.get(item);
- }
-
- /** Implements the {@code [ ... ]} operator on an object whose type is not
- * known until runtime.
- */
- public static Object item(Object object, Object index) {
- if (object instanceof Map) {
- return ((Map) object).get(index);
- }
- if (object instanceof List && index instanceof Number) {
- List list = (List) object;
- return list.get(((Number) index).intValue());
- }
- return null;
- }
-
- /** NULL → FALSE, FALSE → FALSE, TRUE → TRUE. */
- public static boolean isTrue(Boolean b) {
- return b != null && b;
- }
-
- /** NULL → TRUE, FALSE → FALSE, TRUE → TRUE. */
- public static boolean isNotFalse(Boolean b) {
- return b == null || b;
- }
-
- /** NULL → NULL, FALSE → TRUE, TRUE → FALSE. */
- public static Boolean not(Boolean b) {
- return (b == null) ? null : !b;
- }
-
- /** Converts a JDBC array to a list. */
- public static List arrayToList(final java.sql.Array a) {
- if (a == null) {
- return null;
- }
- try {
- return Primitive.asList(a.getArray());
- } catch (SQLException e) {
- throw new RuntimeException(e);
- }
- }
-
- /** Support the SLICE function. */
- public static List slice(List list) {
- return list;
- }
-
- /** Support the ELEMENT function. */
- public static Object element(List list) {
- switch (list.size()) {
- case 0:
- return null;
- case 1:
- return list.get(0);
- default:
- throw new RuntimeException("more than one value");
- }
- }
-
- /** Returns a lambda that converts a list to an enumerable. */
- public static <E> Function1<List<E>, Enumerable<E>> listToEnumerable() {
- //noinspection unchecked
- return (Function1<List<E>, Enumerable<E>>) (Function1) LIST_AS_ENUMERABLE;
- }
-
- /** A range of time units. The first is more significant than the
- * other (e.g. year-to-day) or the same as the other
- * (e.g. month). */
- public enum TimeUnitRange {
- YEAR, YEAR_TO_MONTH, MONTH, DAY, DAY_TO_HOUR, DAY_TO_MINUTE, DAY_TO_SECOND, HOUR, HOUR_TO_MINUTE, HOUR_TO_SECOND, MINUTE, MINUTE_TO_SECOND, SECOND;
-
- /** Whether this is in the YEAR-TO-MONTH family of intervals. */
- public boolean monthly() {
- return ordinal() <= MONTH.ordinal();
- }
- }
+ }
+ }
+ return hour * (int) DateTimeUtil.MILLIS_PER_HOUR
+ + minute * (int) DateTimeUtil.MILLIS_PER_MINUTE
+ + second * (int) DateTimeUtil.MILLIS_PER_SECOND
+ + milli;
+ }
+
+ public static long timestampStringToUnixDate(String s) {
+ final long d;
+ final long t;
+ s = s.trim();
+ int space = s.indexOf(' ');
+ if (space >= 0) {
+ d = dateStringToUnixDate(s.substring(0, space));
+ t = timeStringToUnixDate(s, space + 1);
+ } else {
+ d = dateStringToUnixDate(s);
+ t = 0;
+ }
+ return d * DateTimeUtil.MILLIS_PER_DAY + t;
+ }
+
+ /** Helper for CAST({date} AS VARCHAR(n)). */
+ public static String unixDateToString(int date) {
+ final StringBuilder buf = new StringBuilder(10);
+ unixDateToString(buf, date);
+ return buf.toString();
+ }
+
+ private static void unixDateToString(StringBuilder buf, int date) {
+ julianToString(buf, date + EPOCH_JULIAN);
+ }
+
+ private static void julianToString(StringBuilder buf, int julian) {
+ // this shifts the epoch back to astronomical year -4800 instead of the
+ // start of the Christian era in year AD 1 of the proleptic Gregorian
+ // calendar.
+ int j = julian + 32044;
+ int g = j / 146097;
+ int dg = j % 146097;
+ int c = (dg / 36524 + 1) * 3 / 4;
+ int dc = dg - c * 36524;
+ int b = dc / 1461;
+ int db = dc % 1461;
+ int a = (db / 365 + 1) * 3 / 4;
+ int da = db - a * 365;
+
+ // integer number of full years elapsed since March 1, 4801 BC
+ int y = g * 400 + c * 100 + b * 4 + a;
+ // integer number of full months elapsed since the last March 1
+ int m = (da * 5 + 308) / 153 - 2;
+ // number of days elapsed since day 1 of the month
+ int d = da - (m + 4) * 153 / 5 + 122;
+ int year = y - 4800 + (m + 2) / 12;
+ int month = (m + 2) % 12 + 1;
+ int day = d + 1;
+ int4(buf, year);
+ buf.append('-');
+ int2(buf, month);
+ buf.append('-');
+ int2(buf, day);
+ }
+
+ public static long unixDateExtract(TimeUnitRange range, long date) {
+ return julianExtract(range, (int) date + EPOCH_JULIAN);
+ }
+
+ private static int julianExtract(TimeUnitRange range, int julian) {
+ // this shifts the epoch back to astronomical year -4800 instead of the
+ // start of the Christian era in year AD 1 of the proleptic Gregorian
+ // calendar.
+ int j = julian + 32044;
+ int g = j / 146097;
+ int dg = j % 146097;
+ int c = (dg / 36524 + 1) * 3 / 4;
+ int dc = dg - c * 36524;
+ int b = dc / 1461;
+ int db = dc % 1461;
+ int a = (db / 365 + 1) * 3 / 4;
+ int da = db - a * 365;
+
+ // integer number of full years elapsed since March 1, 4801 BC
<TRUNCATED>
[3/3] incubator-kylin git commit: KYLIN-812 Upgrade to Calcite 0.9.2
Posted by li...@apache.org.
KYLIN-812 Upgrade to Calcite 0.9.2
Project: http://git-wip-us.apache.org/repos/asf/incubator-kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-kylin/commit/6480a9a7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-kylin/tree/6480a9a7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-kylin/diff/6480a9a7
Branch: refs/heads/0.7-staging
Commit: 6480a9a7ab2241e068bec8e3927adb483c4208fc
Parents: f37360d
Author: Li, Yang <ya...@ebay.com>
Authored: Thu Jun 11 10:49:00 2015 +0800
Committer: Li, Yang <ya...@ebay.com>
Committed: Thu Jun 11 10:50:42 2015 +0800
----------------------------------------------------------------------
.../hydromatic/optiq/runtime/SqlFunctions.java | 3173 +++++++++---------
.../eigenbase/sql2rel/SqlToRelConverter.java | 4 +-
.../org/apache/kylin/cube/model/CubeDesc.java | 33 -
.../org/apache/kylin/jdbc/KylinPrepare.java | 201 +-
pom.xml | 2 +-
.../kylin/query/relnode/OLAPAggregateRel.java | 5 +-
.../org/apache/kylin/query/relnode/OLAPRel.java | 3 +-
7 files changed, 1741 insertions(+), 1680 deletions(-)
----------------------------------------------------------------------