Return-Path: X-Original-To: apmail-kylin-commits-archive@minotaur.apache.org Delivered-To: apmail-kylin-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 5D3DE183A0 for ; Fri, 10 Jul 2015 23:27:09 +0000 (UTC) Received: (qmail 10317 invoked by uid 500); 10 Jul 2015 23:27:09 -0000 Delivered-To: apmail-kylin-commits-archive@kylin.apache.org Received: (qmail 10287 invoked by uid 500); 10 Jul 2015 23:27:09 -0000 Mailing-List: contact commits-help@kylin.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@kylin.incubator.apache.org Delivered-To: mailing list commits@kylin.incubator.apache.org Received: (qmail 10278 invoked by uid 99); 10 Jul 2015 23:27:09 -0000 Received: from Unknown (HELO spamd2-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 10 Jul 2015 23:27:09 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd2-us-west.apache.org (ASF Mail Server at spamd2-us-west.apache.org) with ESMTP id B46501A6B34 for ; Fri, 10 Jul 2015 23:27:08 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd2-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 1.77 X-Spam-Level: * X-Spam-Status: No, score=1.77 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, T_RP_MATCHES_RCVD=-0.01] autolearn=disabled Received: from mx1-us-east.apache.org ([10.40.0.8]) by localhost (spamd2-us-west.apache.org [10.40.0.9]) (amavisd-new, port 10024) with ESMTP id jziPnO_ZqSD7 for ; Fri, 10 Jul 2015 23:26:50 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-us-east.apache.org (ASF Mail Server at mx1-us-east.apache.org) with SMTP id 998D24C0CA for ; Fri, 10 Jul 2015 23:26:48 +0000 (UTC) Received: (qmail 7858 invoked by uid 99); 10 Jul 2015 23:26:48 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 10 Jul 2015 23:26:48 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id EE910E6843; Fri, 10 Jul 2015 23:26:47 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: liyang@apache.org To: commits@kylin.incubator.apache.org Date: Fri, 10 Jul 2015 23:27:20 -0000 Message-Id: <4ca2cb4c081f4141a84a08891c4b05d9@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [34/50] [abbrv] incubator-kylin git commit: KYLIN-780 Upgrade query module, all query test pass KYLIN-780 Upgrade query module, all query test pass Project: http://git-wip-us.apache.org/repos/asf/incubator-kylin/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-kylin/commit/f4be1526 Tree: http://git-wip-us.apache.org/repos/asf/incubator-kylin/tree/f4be1526 Diff: http://git-wip-us.apache.org/repos/asf/incubator-kylin/diff/f4be1526 Branch: refs/heads/0.7 Commit: f4be1526e86d737998e26c6f533a7b615a5e65d0 Parents: 725bde5 Author: Yang Li Authored: Tue Jun 16 07:53:53 2015 +0800 Committer: Li, Yang Committed: Mon Jul 6 13:48:09 2015 +0800 ---------------------------------------------------------------------- .../hydromatic/optiq/runtime/SqlFunctions.java | 1705 ------ .../adapter/enumerable/EnumerableJoin.java | 187 + .../apache/calcite/runtime/SqlFunctions.java | 1261 +++++ .../calcite/sql2rel/SqlToRelConverter.java | 4978 ++++++++++++++++++ .../eigenbase/sql2rel/SqlToRelConverter.java | 4795 ----------------- jdbc/pom.xml | 2 +- .../main/java/org/apache/kylin/jdbc/Driver.java | 12 +- .../apache/kylin/jdbc/KylinConnectionImpl.java | 12 +- .../org/apache/kylin/jdbc/KylinEnumerator.java | 2 +- .../apache/kylin/jdbc/KylinJdbc41Factory.java | 20 +- .../org/apache/kylin/jdbc/KylinMetaImpl.java | 24 +- .../org/apache/kylin/jdbc/KylinPrepare.java | 10 +- .../org/apache/kylin/jdbc/KylinResultSet.java | 6 +- .../apache/kylin/jdbc/KylinStatementImpl.java | 6 +- .../org/apache/kylin/jdbc/stub/DataSet.java | 4 +- .../org/apache/kylin/jdbc/stub/KylinClient.java | 8 +- .../apache/kylin/jdbc/stub/RemoteClient.java | 2 +- .../apache/kylin/metadata/model/DataType.java | 3 +- .../kylin/metadata/model/FunctionDesc.java | 8 +- .../kylin/metadata/project/ProjectL2Cache.java | 2 +- pom.xml | 19 +- query/pom.xml | 6 +- .../kylin/query/enumerator/CubeEnumerator.java | 20 +- .../kylin/query/enumerator/HiveEnumerator.java | 8 +- .../query/enumerator/LookupTableEnumerator.java | 9 +- .../kylin/query/enumerator/OLAPQuery.java | 12 +- .../kylin/query/optrule/OLAPAggregateRule.java | 22 +- .../kylin/query/optrule/OLAPFilterRule.java | 18 +- .../kylin/query/optrule/OLAPJoinRule.java | 28 +- .../kylin/query/optrule/OLAPLimitRule.java | 19 +- .../kylin/query/optrule/OLAPProjectRule.java | 18 +- .../kylin/query/optrule/OLAPSortRule.java | 19 +- .../optrule/OLAPToEnumerableConverterRule.java | 13 +- .../kylin/query/relnode/OLAPAggregateRel.java | 136 +- .../apache/kylin/query/relnode/OLAPContext.java | 8 +- .../kylin/query/relnode/OLAPFilterRel.java | 98 +- .../apache/kylin/query/relnode/OLAPJoinRel.java | 91 +- .../kylin/query/relnode/OLAPLimitRel.java | 54 +- .../kylin/query/relnode/OLAPProjectRel.java | 122 +- .../org/apache/kylin/query/relnode/OLAPRel.java | 62 +- .../apache/kylin/query/relnode/OLAPSortRel.java | 62 +- .../kylin/query/relnode/OLAPTableScan.java | 106 +- .../relnode/OLAPToEnumerableConverter.java | 57 +- .../apache/kylin/query/schema/OLAPSchema.java | 6 +- .../kylin/query/schema/OLAPSchemaFactory.java | 22 +- .../apache/kylin/query/schema/OLAPTable.java | 60 +- .../apache/kylin/query/sqlfunc/QuarterBase.java | 38 - .../apache/kylin/query/sqlfunc/QuarterFunc.java | 34 - .../apache/kylin/query/test/KylinTestBase.java | 2 +- .../apache/kylin/rest/service/QueryService.java | 16 +- .../storage/hbase/CubeSegmentTupleIterator.java | 2 +- .../endpoint/EndpointTupleIterator.java | 2 +- 52 files changed, 7015 insertions(+), 7221 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/f4be1526/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 deleted file mode 100644 index db99c83..0000000 --- a/atopcalcite/src/main/java/net/hydromatic/optiq/runtime/SqlFunctions.java +++ /dev/null @@ -1,1705 +0,0 @@ -/* - * OVERRIDE POINT: - * - divide(BigDecimal,BigDecimal), was `b0.divide(b1)`, now `b0.divide(b1, MathContext.DECIMAL64);` - */ - -/* - * 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 net.hydromatic.optiq.runtime; - -import net.hydromatic.avatica.ByteString; - -import net.hydromatic.linq4j.Enumerable; -import net.hydromatic.linq4j.Linq4j; -import net.hydromatic.linq4j.expressions.Primitive; -import net.hydromatic.linq4j.function.Deterministic; -import net.hydromatic.linq4j.function.Function1; -import net.hydromatic.linq4j.function.NonDeterministic; - -import net.hydromatic.optiq.DataContext; - -import org.eigenbase.util14.DateTimeUtil; - -import java.math.*; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.text.DecimalFormat; -import java.util.*; -import java.util.regex.Pattern; - -/** - * Helper methods to implement SQL functions in generated code. - * - *

Not present: and, or, not (builtin operators are better, because they - * use lazy evaluation. Implementations do not check for null values; the - * calling code must do that.

- * - *

Many of the functions do not check for null values. This is intentional. - * If null arguments are possible, the code-generation framework checks for - * nulls before calling the functions.

- */ -@SuppressWarnings("UnnecessaryUnboxing") -@Deterministic -public class SqlFunctions { - 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; - - private static final TimeZone LOCAL_TZ = TimeZone.getDefault(); - - private static final Function1, Enumerable> - LIST_AS_ENUMERABLE = - new Function1, Enumerable>() { - public Enumerable apply(List 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 + operator applied to int values. */ - public static int plus(int b0, int b1) { - return b0 + b1; - } - - /** SQL + 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 + 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 + operator applied to nullable int values. */ - public static Integer plus(Integer b0, Integer b1) { - return (b0 == null || b1 == null) ? null : (b0 + b1); - } - - /** SQL + 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 + 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 + operator applied to BigDecimal values. */ - public static BigDecimal plus(BigDecimal b0, BigDecimal b1) { - return (b0 == null || b1 == null) ? null : b0.add(b1); - } - - // - - - /** SQL - operator applied to int values. */ - public static int minus(int b0, int b1) { - return b0 - b1; - } - - /** SQL - 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 - 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 - operator applied to nullable int values. */ - public static Integer minus(Integer b0, Integer b1) { - return (b0 == null || b1 == null) ? null : (b0 - b1); - } - - /** SQL - 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 - 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 - operator applied to BigDecimal values. */ - public static BigDecimal minus(BigDecimal b0, BigDecimal b1) { - return (b0 == null || b1 == null) ? null : b0.subtract(b1); - } - - // / - - /** SQL / operator applied to int values. */ - public static int divide(int b0, int b1) { - return b0 / b1; - } - - /** SQL / 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 / 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 / operator applied to nullable int values. */ - public static Integer divide(Integer b0, Integer b1) { - return (b0 == null || b1 == null) ? null : (b0 / b1); - } - - /** SQL / 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 / 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 / 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 * operator applied to int values. */ - public static int multiply(int b0, int b1) { - return b0 * b1; - } - - /** SQL * 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 * 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 * operator applied to nullable int values. */ - public static Integer multiply(Integer b0, Integer b1) { - return (b0 == null || b1 == null) ? null : (b0 * b1); - } - - /** SQL * 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 * 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 * operator applied to BigDecimal values. */ - public static BigDecimal multiply(BigDecimal b0, BigDecimal b1) { - return (b0 == null || b1 == null) ? null : b0.multiply(b1); - } - - // EXP - - /** SQL EXP 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 POWER 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 LOG10(numeric) 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 MOD operator applied to byte values. */ - public static byte mod(byte b0, byte b1) { - return (byte) (b0 % b1); - } - - /** SQL MOD operator applied to short values. */ - public static short mod(short b0, short b1) { - return (short) (b0 % b1); - } - - /** SQL MOD operator applied to int values. */ - public static int mod(int b0, int b1) { - return b0 % b1; - } - - /** SQL MOD 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 ABS operator applied to byte values. */ - public static byte abs(byte b0) { - return (byte) Math.abs(b0); - } - - /** SQL ABS operator applied to short values. */ - public static short abs(short b0) { - return (short) Math.abs(b0); - } - - /** SQL ABS operator applied to int values. */ - public static int abs(int b0) { - return Math.abs(b0); - } - - /** SQL ABS operator applied to long values. */ - public static long abs(long b0) { - return Math.abs(b0); - } - - /** SQL ABS operator applied to float values. */ - public static float abs(float b0) { - return Math.abs(b0); - } - - /** SQL ABS operator applied to double values. */ - public static double abs(double b0) { - return Math.abs(b0); - } - - /** SQL ABS 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 lesser(T b0, T b1) { - return b0 == null || b0.compareTo(b1) > 0 ? b1 : b0; - } - - /** LEAST operator. */ - public static > 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 greater(T b0, T b1) { - return b0 == null || b0.compareTo(b1) < 0 ? b1 : b0; - } - - /** GREATEST operator. */ - public static > 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 { - 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); - } 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 - 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 Function1, Enumerable> listToEnumerable() { - //noinspection unchecked - return (Function1, Enumerable>) (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(); - } - } -} - -// End SqlFunctions.java http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/f4be1526/atopcalcite/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableJoin.java ---------------------------------------------------------------------- diff --git a/atopcalcite/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableJoin.java b/atopcalcite/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableJoin.java new file mode 100644 index 0000000..918b4bf --- /dev/null +++ b/atopcalcite/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableJoin.java @@ -0,0 +1,187 @@ +/* + * OVERRIDE POINT: + * - constructor was private instead of public + */ + +/* + * 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.calcite.adapter.enumerable; + +import org.apache.calcite.linq4j.tree.BlockBuilder; +import org.apache.calcite.linq4j.tree.Expression; +import org.apache.calcite.linq4j.tree.Expressions; +import org.apache.calcite.plan.RelOptCluster; +import org.apache.calcite.plan.RelOptCost; +import org.apache.calcite.plan.RelOptPlanner; +import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.InvalidRelException; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.RelNodes; +import org.apache.calcite.rel.core.JoinInfo; +import org.apache.calcite.rel.core.JoinRelType; +import org.apache.calcite.rel.metadata.RelMetadataQuery; +import org.apache.calcite.rel.rules.EquiJoin; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.util.BuiltInMethod; +import org.apache.calcite.util.ImmutableIntList; +import org.apache.calcite.util.Util; + +import com.google.common.collect.ImmutableList; + +import java.util.Set; + +/** Implementation of {@link org.apache.calcite.rel.core.Join} in + * {@link org.apache.calcite.adapter.enumerable.EnumerableConvention enumerable calling convention}. */ +public class EnumerableJoin extends EquiJoin implements EnumerableRel { + public EnumerableJoin( // OVERRIDE POINT, the constructor was private + RelOptCluster cluster, + RelTraitSet traits, + RelNode left, + RelNode right, + RexNode condition, + ImmutableIntList leftKeys, + ImmutableIntList rightKeys, + JoinRelType joinType, + Set variablesStopped) + throws InvalidRelException { + super( + cluster, + traits, + left, + right, + condition, + leftKeys, + rightKeys, + joinType, + variablesStopped); + } + + @Override public EnumerableJoin copy(RelTraitSet traitSet, RexNode condition, + RelNode left, RelNode right, JoinRelType joinType, + boolean semiJoinDone) { + final JoinInfo joinInfo = JoinInfo.of(left, right, condition); + assert joinInfo.isEqui(); + try { + return new EnumerableJoin(getCluster(), traitSet, left, right, + condition, joinInfo.leftKeys, joinInfo.rightKeys, joinType, + variablesStopped); + } catch (InvalidRelException e) { + // Semantic error not possible. Must be a bug. Convert to + // internal error. + throw new AssertionError(e); + } + } + + @Override public RelOptCost computeSelfCost(RelOptPlanner planner) { + double rowCount = RelMetadataQuery.getRowCount(this); + + // Joins can be flipped, and for many algorithms, both versions are viable + // and have the same cost. To make the results stable between versions of + // the planner, make one of the versions slightly more expensive. + switch (joinType) { + case RIGHT: + rowCount = addEpsilon(rowCount); + break; + default: + if (RelNodes.COMPARATOR.compare(left, right) > 0) { + rowCount = addEpsilon(rowCount); + } + } + + // Cheaper if the smaller number of rows is coming from the LHS. + // Model this by adding L log L to the cost. + final double rightRowCount = right.getRows(); + final double leftRowCount = left.getRows(); + if (Double.isInfinite(leftRowCount)) { + rowCount = leftRowCount; + } else { + rowCount += Util.nLogN(leftRowCount); + } + if (Double.isInfinite(rightRowCount)) { + rowCount = rightRowCount; + } else { + rowCount += rightRowCount; + } + return planner.getCostFactory().makeCost(rowCount, 0, 0); + } + + private double addEpsilon(double d) { + assert d >= 0d; + final double d0 = d; + if (d < 10) { + // For small d, adding 1 would change the value significantly. + d *= 1.001d; + if (d != d0) { + return d; + } + } + // For medium d, add 1. Keeps integral values integral. + ++d; + if (d != d0) { + return d; + } + // For large d, adding 1 might not change the value. Add .1%. + // If d is NaN, this still will probably not change the value. That's OK. + d *= 1.001d; + return d; + } + + public Result implement(EnumerableRelImplementor implementor, Prefer pref) { + BlockBuilder builder = new BlockBuilder(); + final Result leftResult = + implementor.visitChild(this, 0, (EnumerableRel) left, pref); + Expression leftExpression = + builder.append( + "left", leftResult.block); + final Result rightResult = + implementor.visitChild(this, 1, (EnumerableRel) right, pref); + Expression rightExpression = + builder.append( + "right", rightResult.block); + final PhysType physType = + PhysTypeImpl.of( + implementor.getTypeFactory(), getRowType(), pref.preferArray()); + final PhysType keyPhysType = + leftResult.physType.project( + leftKeys, JavaRowFormat.LIST); + return implementor.result( + physType, + builder.append( + Expressions.call( + leftExpression, + BuiltInMethod.JOIN.method, + Expressions.list( + rightExpression, + leftResult.physType.generateAccessor(leftKeys), + rightResult.physType.generateAccessor(rightKeys), + EnumUtils.joinSelector(joinType, + physType, + ImmutableList.of( + leftResult.physType, rightResult.physType))) + .append( + Util.first(keyPhysType.comparer(), + Expressions.constant(null))) + .append( + Expressions.constant(joinType.generatesNullsOnLeft())) + .append( + Expressions.constant( + joinType.generatesNullsOnRight())))).toBlock()); + } + +} + +// End EnumerableJoin.java