You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by ja...@apache.org on 2015/06/16 00:54:16 UTC
[2/2] phoenix git commit: PHOENIX-1660 Implement missing math
built-in functions ABS, POWER, LN, LOG, SQRT, CBRT, EXP (Shuxiong Ye)
PHOENIX-1660 Implement missing math built-in functions ABS, POWER, LN, LOG, SQRT, CBRT, EXP (Shuxiong Ye)
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/c2927dde
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/c2927dde
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/c2927dde
Branch: refs/heads/master
Commit: c2927ddec5ab954dd779516ed29b4b7fa4b011d9
Parents: d1934af
Author: James Taylor <ja...@apache.org>
Authored: Mon Jun 15 15:53:44 2015 -0700
Committer: James Taylor <ja...@apache.org>
Committed: Mon Jun 15 15:53:44 2015 -0700
----------------------------------------------------------------------
.../phoenix/end2end/AbsFunctionEnd2EndIT.java | 108 +++++++++++
.../phoenix/end2end/CbrtFunctionEnd2EndIT.java | 143 +++++++++++++++
.../phoenix/end2end/ExpFunctionEnd2EndIT.java | 128 +++++++++++++
.../phoenix/end2end/LnLogFunctionEnd2EndIT.java | 143 +++++++++++++++
.../phoenix/end2end/PowerFunctionEnd2EndIT.java | 144 +++++++++++++++
.../phoenix/expression/ExpressionType.java | 14 +-
.../expression/function/AbsFunction.java | 66 +++++++
.../expression/function/CbrtFunction.java | 55 ++++++
.../expression/function/ExpFunction.java | 55 ++++++
.../function/JavaMathOneArgumentFunction.java | 43 ++---
.../function/JavaMathTwoArgumentFunction.java | 69 +++++++
.../phoenix/expression/function/LnFunction.java | 55 ++++++
.../expression/function/LogFunction.java | 56 ++++++
.../expression/function/PowerFunction.java | 51 ++++++
.../expression/function/ScalarFunction.java | 4 +-
.../expression/function/SqrtFunction.java | 8 +-
.../apache/phoenix/schema/types/PDecimal.java | 11 ++
.../phoenix/schema/types/PNumericType.java | 8 +
.../phoenix/schema/types/PRealNumber.java | 8 +
.../phoenix/schema/types/PWholeNumber.java | 8 +
.../phoenix/compile/QueryCompilerTest.java | 68 ++++++-
.../phoenix/expression/AbsFunctionTest.java | 180 ++++++++++++++++++
.../phoenix/expression/CbrtFunctionTest.java | 127 +++++++++++++
.../phoenix/expression/ExpFunctionTest.java | 150 +++++++++++++++
.../phoenix/expression/LnLogFunctionTest.java | 182 +++++++++++++++++++
.../phoenix/expression/PowerFunctionTest.java | 182 +++++++++++++++++++
26 files changed, 2036 insertions(+), 30 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/it/java/org/apache/phoenix/end2end/AbsFunctionEnd2EndIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AbsFunctionEnd2EndIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AbsFunctionEnd2EndIT.java
new file mode 100644
index 0000000..0c6204c
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AbsFunctionEnd2EndIT.java
@@ -0,0 +1,108 @@
+/*
+ * 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.phoenix.end2end;
+
+import static org.apache.phoenix.util.TestUtil.closeStmtAndConn;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+
+import org.apache.phoenix.expression.function.AbsFunction;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * End to end tests for {@link AbsFunction}
+ */
+public class AbsFunctionEnd2EndIT extends BaseHBaseManagedTimeIT {
+
+ private static final String KEY = "key";
+
+ @Before
+ public void initTable() throws Exception {
+ Connection conn = null;
+ PreparedStatement stmt = null;
+ try {
+ conn = DriverManager.getConnection(getUrl());
+ String ddl;
+ ddl = "CREATE TABLE testSigned (k VARCHAR NOT NULL PRIMARY KEY, dec DECIMAL, doub DOUBLE, fl FLOAT, inte INTEGER, lon BIGINT, smalli SMALLINT, tinyi TINYINT)";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ } finally {
+ closeStmtAndConn(stmt, conn);
+ }
+ }
+
+ private void updateSignedTable(Connection conn, double data) throws Exception {
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO testSigned VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
+ stmt.setString(1, KEY);
+ Double d = Double.valueOf(data);
+ stmt.setBigDecimal(2, BigDecimal.valueOf(data));
+ stmt.setDouble(3, d.doubleValue());
+ stmt.setFloat(4, d.floatValue());
+ stmt.setInt(5, d.intValue());
+ stmt.setLong(6, d.longValue());
+ stmt.setShort(7, d.shortValue());
+ stmt.setByte(8, d.byteValue());
+ stmt.executeUpdate();
+ conn.commit();
+ }
+
+ private void testSignedNumberSpec(Connection conn, double data) throws Exception {
+ updateSignedTable(conn, data);
+ ResultSet rs = conn.createStatement() .executeQuery("SELECT ABS(dec),ABS(doub),ABS(fl),ABS(inte),ABS(lon),ABS(smalli),ABS(tinyi) FROM testSigned");
+ assertTrue(rs.next());
+ Double d = Double.valueOf(data);
+ assertEquals(rs.getBigDecimal(1).compareTo(BigDecimal.valueOf(data).abs()), 0);
+ assertEquals(rs.getDouble(2), Math.abs(data), 1e-6);
+ assertEquals(rs.getFloat(3), Math.abs(d.floatValue()), 1e-6);
+ assertEquals(rs.getInt(4), Math.abs(d.intValue()));
+ assertEquals(rs.getLong(5), Math.abs(d.longValue()));
+ assertEquals(rs.getShort(6), Math.abs(d.shortValue()));
+ assertEquals(rs.getByte(7), Math.abs(d.byteValue()));
+ assertTrue(!rs.next());
+
+ PreparedStatement stmt = conn.prepareStatement("SELECT k FROM testSigned WHERE ABS(dec)=? AND ABS(doub)=? AND ABS(fl)=? AND ABS(inte)=? AND ABS(lon)=? AND ABS(smalli)=? AND ABS(tinyi)=?");
+ stmt.setBigDecimal(1, BigDecimal.valueOf(data).abs());
+ stmt.setDouble(2, Math.abs(d.doubleValue()));
+ stmt.setFloat(3, Math.abs(d.floatValue()));
+ stmt.setInt(4, Math.abs(d.intValue()));
+ stmt.setLong(5, Math.abs(d.longValue()));
+ stmt.setShort(6, (short) Math.abs(d.shortValue()));
+ stmt.setByte(7, (byte) Math.abs(d.byteValue()));
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(KEY, rs.getString(1));
+ assertTrue(!rs.next());
+ }
+
+ @Test
+ public void testSignedNumber() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ testSignedNumberSpec(conn, 0.0);
+ testSignedNumberSpec(conn, 1.0);
+ testSignedNumberSpec(conn, -1.0);
+ testSignedNumberSpec(conn, 123.1234);
+ testSignedNumberSpec(conn, -123.1234);
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/it/java/org/apache/phoenix/end2end/CbrtFunctionEnd2EndIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/CbrtFunctionEnd2EndIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CbrtFunctionEnd2EndIT.java
new file mode 100644
index 0000000..a632104
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CbrtFunctionEnd2EndIT.java
@@ -0,0 +1,143 @@
+/*
+ * 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.phoenix.end2end;
+
+import static org.apache.phoenix.util.TestUtil.closeStmtAndConn;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+
+import org.apache.phoenix.expression.function.CbrtFunction;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * End to end tests for {@link CbrtFunction}
+ */
+public class CbrtFunctionEnd2EndIT extends BaseHBaseManagedTimeIT {
+
+ private static final String KEY = "key";
+ private static final double ZERO = 1e-8;
+
+ @Before
+ public void initTable() throws Exception {
+ Connection conn = null;
+ PreparedStatement stmt = null;
+ try {
+ conn = DriverManager.getConnection(getUrl());
+ String ddl;
+ ddl = "CREATE TABLE testSigned (k VARCHAR NOT NULL PRIMARY KEY, doub DOUBLE, fl FLOAT, inte INTEGER, lon BIGINT, smalli SMALLINT, tinyi TINYINT)";
+ conn.createStatement().execute(ddl);
+ ddl = "CREATE TABLE testUnsigned (k VARCHAR NOT NULL PRIMARY KEY, doub UNSIGNED_DOUBLE, fl UNSIGNED_FLOAT, inte UNSIGNED_INT, lon UNSIGNED_LONG, smalli UNSIGNED_SMALLINT, tinyi UNSIGNED_TINYINT)";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ } finally {
+ closeStmtAndConn(stmt, conn);
+ }
+ }
+
+ private void updateSignedTable(Connection conn, double data) throws Exception {
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO testSigned VALUES (?, ?, ?, ?, ?, ?, ?)");
+ stmt.setString(1, KEY);
+ Double d = Double.valueOf(data);
+ stmt.setDouble(2, d.doubleValue());
+ stmt.setFloat(3, d.floatValue());
+ stmt.setInt(4, d.intValue());
+ stmt.setLong(5, d.longValue());
+ stmt.setShort(6, d.shortValue());
+ stmt.setByte(7, d.byteValue());
+ stmt.executeUpdate();
+ conn.commit();
+ }
+
+ private void updateUnsignedTable(Connection conn, double data) throws Exception {
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO testUnsigned VALUES (?, ?, ?, ?, ?, ?, ?)");
+ stmt.setString(1, KEY);
+ Double d = Double.valueOf(data);
+ stmt.setDouble(2, d.doubleValue());
+ stmt.setFloat(3, d.floatValue());
+ stmt.setInt(4, d.intValue());
+ stmt.setLong(5, d.longValue());
+ stmt.setShort(6, d.shortValue());
+ stmt.setByte(7, d.byteValue());
+ stmt.executeUpdate();
+ conn.commit();
+ }
+
+ private void testSignedNumberSpec(Connection conn, double data) throws Exception {
+ updateSignedTable(conn, data);
+ ResultSet rs = conn.createStatement().executeQuery("SELECT CBRT(doub),CBRT(fl),CBRT(inte),CBRT(lon),CBRT(smalli),CBRT(tinyi) FROM testSigned");
+ assertTrue(rs.next());
+ Double d = Double.valueOf(data);
+ assertTrue(Math.abs(rs.getDouble(1) - Math.cbrt(d.doubleValue())) < ZERO);
+ assertTrue(Math.abs(rs.getDouble(2) - Math.cbrt(d.floatValue())) < ZERO);
+ assertTrue(Math.abs(rs.getDouble(3) - Math.cbrt(d.intValue())) < ZERO);
+ assertTrue(Math.abs(rs.getDouble(4) - Math.cbrt(d.longValue())) < ZERO);
+ assertTrue(Math.abs(rs.getDouble(5) - Math.cbrt(d.shortValue())) < ZERO);
+ assertTrue(Math.abs(rs.getDouble(6) - Math.cbrt(d.byteValue())) < ZERO);
+ assertTrue(!rs.next());
+ PreparedStatement stmt = conn.prepareStatement("SELECT k FROM testSigned WHERE CBRT(doub)>0 AND CBRT(fl)>0 AND CBRT(inte)>0 AND CBRT(lon)>0 AND CBRT(smalli)>0 AND CBRT(tinyi)>0");
+ rs = stmt.executeQuery();
+ if (data > 0) {
+ assertTrue(rs.next());
+ assertEquals(KEY, rs.getString(1));
+ }
+ assertTrue(!rs.next());
+ }
+
+ private void testUnsignedNumberSpec(Connection conn, double data) throws Exception {
+ updateUnsignedTable(conn, data);
+ ResultSet rs = conn.createStatement().executeQuery("SELECT CBRT(doub),CBRT(fl),CBRT(inte),CBRT(lon),CBRT(smalli),CBRT(tinyi) FROM testUnsigned");
+ assertTrue(rs.next());
+ Double d = Double.valueOf(data);
+ assertTrue(Math.abs(rs.getDouble(1) - Math.cbrt(d.doubleValue())) < ZERO);
+ assertTrue(Math.abs(rs.getDouble(2) - Math.cbrt(d.floatValue())) < ZERO);
+ assertTrue(Math.abs(rs.getDouble(3) - Math.cbrt(d.intValue())) < ZERO);
+ assertTrue(Math.abs(rs.getDouble(4) - Math.cbrt(d.longValue())) < ZERO);
+ assertTrue(Math.abs(rs.getDouble(5) - Math.cbrt(d.shortValue())) < ZERO);
+ assertTrue(Math.abs(rs.getDouble(6) - Math.cbrt(d.byteValue())) < ZERO);
+ assertTrue(!rs.next());
+ PreparedStatement stmt = conn.prepareStatement("SELECT k FROM testUnsigned WHERE CBRT(doub)>0 AND CBRT(fl)>0 AND CBRT(inte)>0 AND CBRT(lon)>0 AND CBRT(smalli)>0 AND CBRT(tinyi)>0");
+ rs = stmt.executeQuery();
+ if (data > 0) {
+ assertTrue(rs.next());
+ assertEquals(KEY, rs.getString(1));
+ }
+ assertTrue(!rs.next());
+ }
+
+ @Test
+ public void testSignedNumber() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ for (double d : new double[] { 0.0, 1.0, -1.0, 123.1234, -123.1234 }) {
+ testSignedNumberSpec(conn, d);
+ }
+ }
+
+ @Test
+ public void testUnsignedNumber() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ for (double d : new double[] { 0.0, 1.0, 123.1234 }) {
+ testUnsignedNumberSpec(conn, d);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/it/java/org/apache/phoenix/end2end/ExpFunctionEnd2EndIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ExpFunctionEnd2EndIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ExpFunctionEnd2EndIT.java
new file mode 100644
index 0000000..8772400
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ExpFunctionEnd2EndIT.java
@@ -0,0 +1,128 @@
+/*
+ * 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.phoenix.end2end;
+
+import static org.apache.phoenix.util.TestUtil.closeStmtAndConn;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+
+import org.apache.phoenix.expression.function.ExpFunction;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * End to end tests for {@link ExpFunction}
+ */
+public class ExpFunctionEnd2EndIT extends BaseHBaseManagedTimeIT {
+
+ private static final String KEY = "key";
+ private static final double ZERO = 1e-8;
+
+ @Before
+ public void initTable() throws Exception {
+ Connection conn = null;
+ PreparedStatement stmt = null;
+ try {
+ conn = DriverManager.getConnection(getUrl());
+ String ddl;
+ ddl = "CREATE TABLE testSigned (k VARCHAR NOT NULL PRIMARY KEY, doub DOUBLE, fl FLOAT, inte INTEGER, lon BIGINT, smalli SMALLINT, tinyi TINYINT)";
+ conn.createStatement().execute(ddl);
+ ddl = "CREATE TABLE testUnsigned (k VARCHAR NOT NULL PRIMARY KEY, doub UNSIGNED_DOUBLE, fl UNSIGNED_FLOAT, inte UNSIGNED_INT, lon UNSIGNED_LONG, smalli UNSIGNED_SMALLINT, tinyi UNSIGNED_TINYINT)";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ } finally {
+ closeStmtAndConn(stmt, conn);
+ }
+ }
+
+ private void updateSignedTable(Connection conn, double data) throws Exception {
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO testSigned VALUES (?, ?, ?, ?, ?, ?, ?)");
+ stmt.setString(1, KEY);
+ Double d = Double.valueOf(data);
+ stmt.setDouble(2, d.doubleValue());
+ stmt.setFloat(3, d.floatValue());
+ stmt.setInt(4, d.intValue());
+ stmt.setLong(5, d.longValue());
+ stmt.setShort(6, d.shortValue());
+ stmt.setByte(7, d.byteValue());
+ stmt.executeUpdate();
+ conn.commit();
+ }
+
+ private void updateUnsignedTable(Connection conn, double data) throws Exception {
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO testUnsigned VALUES (?, ?, ?, ?, ?, ?, ?)");
+ stmt.setString(1, KEY);
+ Double d = Double.valueOf(data);
+ stmt.setDouble(2, d.doubleValue());
+ stmt.setFloat(3, d.floatValue());
+ stmt.setInt(4, d.intValue());
+ stmt.setLong(5, d.longValue());
+ stmt.setShort(6, d.shortValue());
+ stmt.setByte(7, d.byteValue());
+ stmt.executeUpdate();
+ conn.commit();
+ }
+
+ private void testSignedNumberSpec(Connection conn, double data) throws Exception {
+ updateSignedTable(conn, data);
+ ResultSet rs = conn.createStatement().executeQuery("SELECT EXP(doub),EXP(fl),EXP(inte),EXP(lon),EXP(smalli),EXP(tinyi) FROM testSigned");
+ assertTrue(rs.next());
+ Double d = Double.valueOf(data);
+ assertTrue(Math.abs(rs.getDouble(1) - Math.exp(d.doubleValue())) < ZERO);
+ assertTrue(Math.abs(rs.getDouble(2) - Math.exp(d.floatValue())) < ZERO);
+ assertTrue(Math.abs(rs.getDouble(3) - Math.exp(d.intValue())) < ZERO);
+ assertTrue(Math.abs(rs.getDouble(4) - Math.exp(d.longValue())) < ZERO);
+ assertTrue(Math.abs(rs.getDouble(5) - Math.exp(d.shortValue())) < ZERO);
+ assertTrue(Math.abs(rs.getDouble(6) - Math.exp(d.byteValue())) < ZERO);
+ assertTrue(!rs.next());
+ }
+
+ private void testUnsignedNumberSpec(Connection conn, double data) throws Exception {
+ updateUnsignedTable(conn, data);
+ ResultSet rs = conn.createStatement().executeQuery("SELECT EXP(doub),EXP(fl),EXP(inte),EXP(lon),EXP(smalli),EXP(tinyi) FROM testUnsigned");
+ assertTrue(rs.next());
+ Double d = Double.valueOf(data);
+ assertTrue(Math.abs(rs.getDouble(1) - Math.exp(d.doubleValue())) < ZERO);
+ assertTrue(Math.abs(rs.getDouble(2) - Math.exp(d.floatValue())) < ZERO);
+ assertTrue(Math.abs(rs.getDouble(3) - Math.exp(d.intValue())) < ZERO);
+ assertTrue(Math.abs(rs.getDouble(4) - Math.exp(d.longValue())) < ZERO);
+ assertTrue(Math.abs(rs.getDouble(5) - Math.exp(d.shortValue())) < ZERO);
+ assertTrue(Math.abs(rs.getDouble(6) - Math.exp(d.byteValue())) < ZERO);
+ assertTrue(!rs.next());
+ }
+
+ @Test
+ public void testSignedNumber() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ for (double d : new double[] { 0.0, 1.0, 123.1234}) {
+ testSignedNumberSpec(conn, d);
+ }
+ }
+
+ @Test
+ public void testUnsignedNumber() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ for (double d : new double[] { 0.0, 1.0, 123.1234 }) {
+ testUnsignedNumberSpec(conn, d);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/it/java/org/apache/phoenix/end2end/LnLogFunctionEnd2EndIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/LnLogFunctionEnd2EndIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/LnLogFunctionEnd2EndIT.java
new file mode 100644
index 0000000..e2c72ca
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/LnLogFunctionEnd2EndIT.java
@@ -0,0 +1,143 @@
+/*
+ * 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.phoenix.end2end;
+
+import static org.apache.phoenix.util.TestUtil.closeStmtAndConn;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+
+import org.apache.phoenix.expression.function.LnFunction;
+import org.apache.phoenix.expression.function.LogFunction;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * End to end tests for {@link LnFunction} and {@link LogFunction}
+ */
+public class LnLogFunctionEnd2EndIT extends BaseHBaseManagedTimeIT {
+
+ private static final String KEY = "key";
+ private static final double ZERO = 1e-9;
+
+ private static boolean twoDoubleEquals(double a, double b) {
+ if (Double.isNaN(a) ^ Double.isNaN(b)) return false;
+ if (Double.isNaN(a)) return true;
+ if (Double.isInfinite(a) ^ Double.isInfinite(b)) return false;
+ if (Double.isInfinite(a)) {
+ if ((a > 0) ^ (b > 0)) return false;
+ else return true;
+ }
+ if (Math.abs(a - b) <= ZERO) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Before
+ public void initTable() throws Exception {
+ Connection conn = null;
+ PreparedStatement stmt = null;
+ try {
+ conn = DriverManager.getConnection(getUrl());
+ String ddl;
+ ddl =
+ "CREATE TABLE testSigned (k VARCHAR NOT NULL PRIMARY KEY, doub DOUBLE, fl FLOAT, inte INTEGER, lon BIGINT, smalli SMALLINT, tinyi TINYINT)";
+ conn.createStatement().execute(ddl);
+ ddl =
+ "CREATE TABLE testUnsigned (k VARCHAR NOT NULL PRIMARY KEY, doub UNSIGNED_DOUBLE, fl UNSIGNED_FLOAT, inte UNSIGNED_INT, lon UNSIGNED_LONG, smalli UNSIGNED_SMALLINT, tinyi UNSIGNED_TINYINT)";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ } finally {
+ closeStmtAndConn(stmt, conn);
+ }
+ }
+
+ private void updateTableSpec(Connection conn, double data, String tableName) throws Exception {
+ PreparedStatement stmt =
+ conn.prepareStatement("UPSERT INTO " + tableName + " VALUES (?, ?, ?, ?, ?, ?, ?)");
+ stmt.setString(1, KEY);
+ Double d = Double.valueOf(data);
+ stmt.setDouble(2, d.doubleValue());
+ stmt.setFloat(3, d.floatValue());
+ stmt.setInt(4, d.intValue());
+ stmt.setLong(5, d.longValue());
+ stmt.setShort(6, d.shortValue());
+ stmt.setByte(7, d.byteValue());
+ stmt.executeUpdate();
+ conn.commit();
+ }
+
+ private void testNumberSpec(Connection conn, double data, String tableName) throws Exception {
+ updateTableSpec(conn, data, tableName);
+ ResultSet rs =
+ conn.createStatement().executeQuery(
+ "SELECT LN(doub),LN(fl),LN(inte),LN(lon),LN(smalli),LN(tinyi) FROM "
+ + tableName);
+ assertTrue(rs.next());
+ Double d = Double.valueOf(data);
+ assertTrue(twoDoubleEquals(rs.getDouble(1), Math.log(d.doubleValue())));
+ assertTrue(twoDoubleEquals(rs.getDouble(2), Math.log(d.floatValue())));
+ assertTrue(twoDoubleEquals(rs.getDouble(3), Math.log(d.intValue())));
+ assertTrue(twoDoubleEquals(rs.getDouble(4), Math.log(d.longValue())));
+ assertTrue(twoDoubleEquals(rs.getDouble(5), Math.log(d.shortValue())));
+ assertTrue(twoDoubleEquals(rs.getDouble(6), Math.log(d.byteValue())));
+
+ assertTrue(!rs.next());
+ rs =
+ conn.createStatement().executeQuery(
+ "SELECT LOG(doub),LOG(fl),LOG(inte),LOG(lon),LOG(smalli),LOG(tinyi) FROM "
+ + tableName);
+ assertTrue(rs.next());
+ d = Double.valueOf(data);
+ assertTrue(twoDoubleEquals(rs.getDouble(1), Math.log10(d.doubleValue())));
+ assertTrue(twoDoubleEquals(rs.getDouble(2), Math.log10(d.floatValue())));
+ assertTrue(twoDoubleEquals(rs.getDouble(3), Math.log10(d.intValue())));
+ assertTrue(twoDoubleEquals(rs.getDouble(4), Math.log10(d.longValue())));
+ assertTrue(twoDoubleEquals(rs.getDouble(5), Math.log10(d.shortValue())));
+ assertTrue(twoDoubleEquals(rs.getDouble(6), Math.log10(d.byteValue())));
+ assertTrue(!rs.next());
+
+ rs =
+ conn.createStatement().executeQuery(
+ "SELECT LOG(doub,3),LOG(fl,3),LOG(inte,3),LOG(lon,3),LOG(smalli,3),LOG(tinyi,3) FROM "
+ + tableName);
+ assertTrue(rs.next());
+ d = Double.valueOf(data);
+ assertTrue(twoDoubleEquals(rs.getDouble(1), Math.log(d.doubleValue()) / Math.log(3)));
+ assertTrue(twoDoubleEquals(rs.getDouble(2), Math.log(d.floatValue()) / Math.log(3)));
+ assertTrue(twoDoubleEquals(rs.getDouble(3), Math.log(d.intValue()) / Math.log(3)));
+ assertTrue(twoDoubleEquals(rs.getDouble(4), Math.log(d.longValue()) / Math.log(3)));
+ assertTrue(twoDoubleEquals(rs.getDouble(5), Math.log(d.shortValue()) / Math.log(3)));
+ assertTrue(twoDoubleEquals(rs.getDouble(6), Math.log(d.byteValue()) / Math.log(3)));
+ assertTrue(!rs.next());
+ }
+
+ @Test
+ public void test() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ for (double d : new double[] { 0.0, 1.0, -1.0, 123.1234, -123.1234 }) {
+ testNumberSpec(conn, d, "testSigned");
+ if (d >= 0) testNumberSpec(conn, d, "testUnsigned");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/it/java/org/apache/phoenix/end2end/PowerFunctionEnd2EndIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/PowerFunctionEnd2EndIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/PowerFunctionEnd2EndIT.java
new file mode 100644
index 0000000..691fb61
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/PowerFunctionEnd2EndIT.java
@@ -0,0 +1,144 @@
+/*
+ * 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.phoenix.end2end;
+
+import static org.apache.phoenix.util.TestUtil.closeStmtAndConn;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+
+import org.apache.phoenix.expression.function.PowerFunction;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * End to end tests for {@link PowerFunction}
+ */
+public class PowerFunctionEnd2EndIT extends BaseHBaseManagedTimeIT {
+
+ private static final String KEY = "key";
+ private static final double ZERO = 1e-9;
+
+ private static boolean twoDoubleEquals(double a, double b) {
+ if (Double.isNaN(a) ^ Double.isNaN(b)) return false;
+ if (Double.isNaN(a)) return true;
+ if (Double.isInfinite(a) ^ Double.isInfinite(b)) return false;
+ if (Double.isInfinite(a)) {
+ if ((a > 0) ^ (b > 0)) return false;
+ else return true;
+ }
+ if (Math.abs(a - b) <= ZERO) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Before
+ public void initTable() throws Exception {
+ Connection conn = null;
+ PreparedStatement stmt = null;
+ try {
+ conn = DriverManager.getConnection(getUrl());
+ String ddl;
+ ddl =
+ "CREATE TABLE testSigned (k VARCHAR NOT NULL PRIMARY KEY, doub DOUBLE, fl FLOAT, inte INTEGER, lon BIGINT, smalli SMALLINT, tinyi TINYINT)";
+ conn.createStatement().execute(ddl);
+ ddl =
+ "CREATE TABLE testUnsigned (k VARCHAR NOT NULL PRIMARY KEY, doub UNSIGNED_DOUBLE, fl UNSIGNED_FLOAT, inte UNSIGNED_INT, lon UNSIGNED_LONG, smalli UNSIGNED_SMALLINT, tinyi UNSIGNED_TINYINT)";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ } finally {
+ closeStmtAndConn(stmt, conn);
+ }
+ }
+
+ private void updateTableSpec(Connection conn, double data, String tableName) throws Exception {
+ PreparedStatement stmt =
+ conn.prepareStatement("UPSERT INTO " + tableName + " VALUES (?, ?, ?, ?, ?, ?, ?)");
+ stmt.setString(1, KEY);
+ Double d = Double.valueOf(data);
+ stmt.setDouble(2, d.doubleValue());
+ stmt.setFloat(3, d.floatValue());
+ stmt.setInt(4, d.intValue());
+ stmt.setLong(5, d.longValue());
+ stmt.setShort(6, d.shortValue());
+ stmt.setByte(7, d.byteValue());
+ stmt.executeUpdate();
+ conn.commit();
+ }
+
+ private void testNumberSpec(Connection conn, double data, String tableName) throws Exception {
+ updateTableSpec(conn, data, tableName);
+ ResultSet rs =
+ conn.createStatement()
+ .executeQuery(
+ "SELECT POWER(doub, 1.5),POWER(fl, 1.5),POWER(inte, 1.5),POWER(lon, 1.5),POWER(smalli, 1.5),POWER(tinyi, 1.5) FROM "
+ + tableName);
+ assertTrue(rs.next());
+ Double d = Double.valueOf(data);
+ assertTrue(twoDoubleEquals(rs.getDouble(1), Math.pow(d.doubleValue(), 1.5)));
+ assertTrue(twoDoubleEquals(rs.getDouble(2), Math.pow(d.floatValue(), 1.5)));
+ assertTrue(twoDoubleEquals(rs.getDouble(3), Math.pow(d.intValue(), 1.5)));
+ assertTrue(twoDoubleEquals(rs.getDouble(4), Math.pow(d.longValue(), 1.5)));
+ assertTrue(twoDoubleEquals(rs.getDouble(5), Math.pow(d.shortValue(), 1.5)));
+ assertTrue(twoDoubleEquals(rs.getDouble(6), Math.pow(d.byteValue(), 1.5)));
+
+ assertTrue(!rs.next());
+ rs =
+ conn.createStatement()
+ .executeQuery(
+ "SELECT POWER(doub, 2),POWER(fl, 2),POWER(inte, 2),POWER(lon, 2),POWER(smalli, 2),POWER(tinyi, 2) FROM "
+ + tableName);
+ assertTrue(rs.next());
+ d = Double.valueOf(data);
+ assertTrue(twoDoubleEquals(rs.getDouble(1), Math.pow(d.doubleValue(), 2)));
+ assertTrue(twoDoubleEquals(rs.getDouble(2), Math.pow(d.floatValue(), 2)));
+ assertTrue(twoDoubleEquals(rs.getDouble(3), Math.pow(d.intValue(), 2)));
+ assertTrue(twoDoubleEquals(rs.getDouble(4), Math.pow(d.longValue(), 2)));
+ assertTrue(twoDoubleEquals(rs.getDouble(5), Math.pow(d.shortValue(), 2)));
+ assertTrue(twoDoubleEquals(rs.getDouble(6), Math.pow(d.byteValue(), 2)));
+ assertTrue(!rs.next());
+
+ rs =
+ conn.createStatement().executeQuery(
+ "SELECT POWER(doub,3),POWER(fl,3),POWER(inte,3),POWER(lon,3),POWER(smalli,3),POWER(tinyi,3) FROM "
+ + tableName);
+ assertTrue(rs.next());
+ d = Double.valueOf(data);
+ assertTrue(twoDoubleEquals(rs.getDouble(1), Math.pow(d.doubleValue(), 3)));
+ assertTrue(twoDoubleEquals(rs.getDouble(2), Math.pow(d.floatValue(), 3)));
+ assertTrue(twoDoubleEquals(rs.getDouble(3), Math.pow(d.intValue(), 3)));
+ assertTrue(twoDoubleEquals(rs.getDouble(4), Math.pow(d.longValue(), 3)));
+ assertTrue(twoDoubleEquals(rs.getDouble(5), Math.pow(d.shortValue(), 3)));
+ assertTrue(twoDoubleEquals(rs.getDouble(6), Math.pow(d.byteValue(), 3)));
+ assertTrue(!rs.next());
+ }
+
+ @Test
+ public void test() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ for (double d : new double[] { 0.0, 1.0, -1.0, 123.1234, -123.1234 }) {
+ testNumberSpec(conn, d, "testSigned");
+ if (d >= 0) testNumberSpec(conn, d, "testUnsigned");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
index 684e620..4f98cb8 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
@@ -19,6 +19,7 @@ package org.apache.phoenix.expression;
import java.util.Map;
+import org.apache.phoenix.expression.function.AbsFunction;
import org.apache.phoenix.expression.function.ArrayAllComparisonExpression;
import org.apache.phoenix.expression.function.ArrayAnyComparisonExpression;
import org.apache.phoenix.expression.function.ArrayAppendFunction;
@@ -29,6 +30,7 @@ import org.apache.phoenix.expression.function.ArrayPrependFunction;
import org.apache.phoenix.expression.function.ByteBasedRegexpReplaceFunction;
import org.apache.phoenix.expression.function.ByteBasedRegexpSplitFunction;
import org.apache.phoenix.expression.function.ByteBasedRegexpSubstrFunction;
+import org.apache.phoenix.expression.function.CbrtFunction;
import org.apache.phoenix.expression.function.CeilDateExpression;
import org.apache.phoenix.expression.function.CeilDecimalExpression;
import org.apache.phoenix.expression.function.CeilFunction;
@@ -41,6 +43,7 @@ import org.apache.phoenix.expression.function.DecodeFunction;
import org.apache.phoenix.expression.function.DistinctCountAggregateFunction;
import org.apache.phoenix.expression.function.DistinctValueAggregateFunction;
import org.apache.phoenix.expression.function.EncodeFunction;
+import org.apache.phoenix.expression.function.ExpFunction;
import org.apache.phoenix.expression.function.ExternalSqlTypeIdFunction;
import org.apache.phoenix.expression.function.FirstValueFunction;
import org.apache.phoenix.expression.function.FloorDateExpression;
@@ -53,6 +56,8 @@ import org.apache.phoenix.expression.function.InvertFunction;
import org.apache.phoenix.expression.function.LTrimFunction;
import org.apache.phoenix.expression.function.LastValueFunction;
import org.apache.phoenix.expression.function.LengthFunction;
+import org.apache.phoenix.expression.function.LnFunction;
+import org.apache.phoenix.expression.function.LogFunction;
import org.apache.phoenix.expression.function.LowerFunction;
import org.apache.phoenix.expression.function.LpadFunction;
import org.apache.phoenix.expression.function.MD5Function;
@@ -65,6 +70,7 @@ import org.apache.phoenix.expression.function.NthValueFunction;
import org.apache.phoenix.expression.function.PercentRankAggregateFunction;
import org.apache.phoenix.expression.function.PercentileContAggregateFunction;
import org.apache.phoenix.expression.function.PercentileDiscAggregateFunction;
+import org.apache.phoenix.expression.function.PowerFunction;
import org.apache.phoenix.expression.function.RTrimFunction;
import org.apache.phoenix.expression.function.RandomFunction;
import org.apache.phoenix.expression.function.RegexpReplaceFunction;
@@ -233,7 +239,13 @@ public enum ExpressionType {
ArrayAppendFunction(ArrayAppendFunction.class),
UDFExpression(UDFExpression.class),
ArrayPrependFunction(ArrayPrependFunction.class),
- SqrtFunction(SqrtFunction.class)
+ SqrtFunction(SqrtFunction.class),
+ AbsFunction(AbsFunction.class),
+ CbrtFunction(CbrtFunction.class),
+ LnFunction(LnFunction.class),
+ LogFunction(LogFunction.class),
+ ExpFunction(ExpFunction.class),
+ PowerFunction(PowerFunction.class)
;
ExpressionType(Class<? extends Expression> clazz) {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/main/java/org/apache/phoenix/expression/function/AbsFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/AbsFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/AbsFunction.java
new file mode 100644
index 0000000..6ef1b38
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/AbsFunction.java
@@ -0,0 +1,66 @@
+/*
+ * 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.phoenix.expression.function;
+
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.types.PDecimal;
+import org.apache.phoenix.schema.types.PNumericType;
+
+@BuiltInFunction(name = AbsFunction.NAME, args = { @Argument(allowedTypes = PDecimal.class) })
+public class AbsFunction extends ScalarFunction {
+
+ public static final String NAME = "ABS";
+
+ public AbsFunction() {
+ }
+
+ public AbsFunction(List<Expression> children) {
+ super(children);
+ }
+
+ @Override
+ public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+ Expression childExpr = children.get(0);
+ PDataType dataType = childExpr.getDataType();
+ if (childExpr.evaluate(tuple, ptr)) {
+ byte[] bytes = ptr.get();
+ int offset = ptr.getOffset(), length = ptr.getLength();
+ ptr.set(new byte[getDataType().getByteSize()]);
+ ((PNumericType) dataType).abs(bytes, offset, length, childExpr.getSortOrder(), ptr);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public PDataType getDataType() {
+ return children.get(0).getDataType();
+ }
+
+ @Override
+ public String getName() {
+ return AbsFunction.NAME;
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CbrtFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CbrtFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CbrtFunction.java
new file mode 100644
index 0000000..1c13924
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CbrtFunction.java
@@ -0,0 +1,55 @@
+/*
+ * 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.phoenix.expression.function;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.types.PDecimal;
+import org.apache.phoenix.schema.types.PDouble;
+
+@BuiltInFunction(name = CbrtFunction.NAME, args = { @Argument(allowedTypes = { PDouble.class, PDecimal.class }) })
+public class CbrtFunction extends JavaMathOneArgumentFunction {
+
+ public static final String NAME = "CBRT";
+
+ public CbrtFunction() {
+ }
+
+ public CbrtFunction(List<Expression> children) throws SQLException {
+ super(children);
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ protected double compute(double firstArg) {
+ return Math.cbrt(firstArg);
+ }
+
+ @Override
+ public OrderPreserving preservesOrder() {
+ return OrderPreserving.YES;
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ExpFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ExpFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ExpFunction.java
new file mode 100644
index 0000000..5c0ca72
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ExpFunction.java
@@ -0,0 +1,55 @@
+/*
+ * 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.phoenix.expression.function;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.types.PDecimal;
+import org.apache.phoenix.schema.types.PDouble;
+
+@BuiltInFunction(name = ExpFunction.NAME, args = { @Argument(allowedTypes = { PDouble.class, PDecimal.class }) })
+public class ExpFunction extends JavaMathOneArgumentFunction {
+
+ public static final String NAME = "EXP";
+
+ public ExpFunction() {
+ }
+
+ public ExpFunction(List<Expression> children) throws SQLException {
+ super(children);
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ protected double compute(double firstArg) {
+ return Math.exp(firstArg);
+ }
+
+ @Override
+ public OrderPreserving preservesOrder() {
+ return OrderPreserving.YES;
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/main/java/org/apache/phoenix/expression/function/JavaMathOneArgumentFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/JavaMathOneArgumentFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/JavaMathOneArgumentFunction.java
index 4ea5367..733f6fc 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/JavaMathOneArgumentFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/JavaMathOneArgumentFunction.java
@@ -39,39 +39,30 @@ public abstract class JavaMathOneArgumentFunction extends ScalarFunction {
protected abstract double compute(double firstArg);
- @Override
- public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
- Expression childExpr = children.get(0);
- PDataType returnType = getDataType();
- if (childExpr.evaluate(tuple, ptr)) {
- if (ptr.getLength() == 0) {
- return true;
- }
- double result;
- if (childExpr.getDataType() == PDecimal.INSTANCE) {
- result =
- ((BigDecimal) childExpr.getDataType().toObject(ptr,
- childExpr.getSortOrder())).doubleValue();
- } else {
- result =
- childExpr.getDataType().getCodec()
- .decodeDouble(ptr, childExpr.getSortOrder());
- }
- ptr.set(new byte[returnType.getByteSize()]);
- returnType.getCodec().encodeDouble(compute(result), ptr);
- return true;
+ static double getArg(Expression exp, ImmutableBytesWritable ptr) {
+ if (exp.getDataType() == PDecimal.INSTANCE) {
+ return ((BigDecimal) exp.getDataType().toObject(ptr, exp.getSortOrder())).doubleValue();
} else {
- return false;
+ return exp.getDataType().getCodec().decodeDouble(ptr, exp.getSortOrder());
}
}
@Override
- public PDataType getDataType() {
- return PDouble.INSTANCE;
+ public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+ PDataType returnType = getDataType();
+
+ Expression arg1Expr = children.get(0);
+ if (!arg1Expr.evaluate(tuple, ptr)) return false;
+ if (ptr.getLength() == 0) return true;
+ double arg1 = getArg(arg1Expr, ptr);
+
+ ptr.set(new byte[returnType.getByteSize()]);
+ returnType.getCodec().encodeDouble(compute(arg1), ptr);
+ return true;
}
@Override
- public OrderPreserving preservesOrder() {
- return OrderPreserving.YES;
+ public PDataType getDataType() {
+ return PDouble.INSTANCE;
}
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/main/java/org/apache/phoenix/expression/function/JavaMathTwoArgumentFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/JavaMathTwoArgumentFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/JavaMathTwoArgumentFunction.java
new file mode 100644
index 0000000..0d85797
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/JavaMathTwoArgumentFunction.java
@@ -0,0 +1,69 @@
+/*
+ * 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.phoenix.expression.function;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.types.PDouble;
+import org.apache.phoenix.util.ByteUtil;
+
+public abstract class JavaMathTwoArgumentFunction extends ScalarFunction {
+
+ public JavaMathTwoArgumentFunction() {
+ }
+
+ public JavaMathTwoArgumentFunction(List<Expression> children) throws SQLException {
+ super(children);
+ }
+
+ protected abstract double compute(double firstArg, double secondArg);
+
+ @Override
+ public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+ PDataType returnType = getDataType();
+
+ Expression arg1Expr = children.get(0);
+ if (!arg1Expr.evaluate(tuple, ptr)) return false;
+ if (ptr.getLength() == 0) return true;
+ double arg1 = JavaMathOneArgumentFunction.getArg(arg1Expr, ptr);
+
+ Expression arg2Expr = (children.size() <= 1) ? null : children.get(1);
+ double arg2;
+ if (arg2Expr != null && !arg2Expr.evaluate(tuple, ptr)) return false;
+ if (arg2Expr == null || ptr.getLength() == 0) {
+ ptr.set(ByteUtil.EMPTY_BYTE_ARRAY);
+ return true;
+ } else {
+ arg2 = JavaMathOneArgumentFunction.getArg(arg2Expr, ptr);
+ }
+
+ ptr.set(new byte[returnType.getByteSize()]);
+ returnType.getCodec().encodeDouble(compute(arg1, arg2), ptr);
+ return true;
+ }
+
+ @Override
+ public PDataType getDataType() {
+ return PDouble.INSTANCE;
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LnFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LnFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LnFunction.java
new file mode 100644
index 0000000..4275336
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LnFunction.java
@@ -0,0 +1,55 @@
+/*
+ * 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.phoenix.expression.function;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.types.PDecimal;
+import org.apache.phoenix.schema.types.PDouble;
+
+@BuiltInFunction(name = LnFunction.NAME, args = { @Argument(allowedTypes = { PDouble.class, PDecimal.class }) })
+public class LnFunction extends JavaMathOneArgumentFunction {
+
+ public static final String NAME = "LN";
+
+ public LnFunction() {
+ }
+
+ public LnFunction(List<Expression> children) throws SQLException {
+ super(children);
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ protected double compute(double firstArg) {
+ return Math.log(firstArg);
+ }
+
+ @Override
+ public OrderPreserving preservesOrder() {
+ return OrderPreserving.YES;
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LogFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LogFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LogFunction.java
new file mode 100644
index 0000000..87b9a79
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LogFunction.java
@@ -0,0 +1,56 @@
+/*
+ * 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.phoenix.expression.function;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.types.PDecimal;
+import org.apache.phoenix.schema.types.PDouble;
+
+@BuiltInFunction(name = LogFunction.NAME, args = { @Argument(allowedTypes = { PDouble.class, PDecimal.class }),
+ @Argument(allowedTypes = { PDouble.class, PDecimal.class }, defaultValue = "1e1") })
+public class LogFunction extends JavaMathTwoArgumentFunction {
+
+ public static final String NAME = "LOG";
+
+ public LogFunction() {
+ }
+
+ public LogFunction(List<Expression> children) throws SQLException {
+ super(children);
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ protected double compute(double firstArg, double secondArg) {
+ return Math.log(firstArg) / Math.log(secondArg);
+ }
+
+ @Override
+ public OrderPreserving preservesOrder() {
+ return OrderPreserving.YES;
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PowerFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PowerFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PowerFunction.java
new file mode 100644
index 0000000..1125ce1
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PowerFunction.java
@@ -0,0 +1,51 @@
+/*
+ * 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.phoenix.expression.function;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.types.PDecimal;
+import org.apache.phoenix.schema.types.PDouble;
+
+@BuiltInFunction(name = PowerFunction.NAME, args = { @Argument(allowedTypes = { PDouble.class, PDecimal.class }),
+ @Argument(allowedTypes = { PDouble.class, PDecimal.class }) })
+public class PowerFunction extends JavaMathTwoArgumentFunction {
+
+ public static final String NAME = "POWER";
+
+ public PowerFunction() {
+ }
+
+ public PowerFunction(List<Expression> children) throws SQLException {
+ super(children);
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ protected double compute(double firstArg, double secondArg) {
+ return Math.pow(firstArg, secondArg);
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ScalarFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ScalarFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ScalarFunction.java
index 014bda4..4f44cde 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ScalarFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ScalarFunction.java
@@ -65,13 +65,15 @@ public abstract class ScalarFunction extends FunctionExpression {
/**
* Determines whether or not a function may be used to form
* the start/stop key of a scan
+ * When OrderPreserving is YES, in order to make order-by optimization
+ * valid, it should return 0. (refer to {@link RoundDateExpression})
* @return the zero-based position of the argument to traverse
* into to look for a primary key column reference, or
* {@value #NO_TRAVERSAL} if the function cannot be used to
* form the scan key.
*/
public int getKeyFormationTraversalIndex() {
- return NO_TRAVERSAL;
+ return preservesOrder() == OrderPreserving.NO ? NO_TRAVERSAL : 0;
}
/**
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SqrtFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SqrtFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SqrtFunction.java
index bb5376e..260305a 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SqrtFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SqrtFunction.java
@@ -24,8 +24,9 @@ import org.apache.phoenix.expression.Expression;
import org.apache.phoenix.parse.FunctionParseNode.Argument;
import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
import org.apache.phoenix.schema.types.PDecimal;
+import org.apache.phoenix.schema.types.PDouble;
-@BuiltInFunction(name = SqrtFunction.NAME, args = { @Argument(allowedTypes = { PDecimal.class }) })
+@BuiltInFunction(name = SqrtFunction.NAME, args = { @Argument(allowedTypes = { PDouble.class, PDecimal.class }) })
public class SqrtFunction extends JavaMathOneArgumentFunction {
public static final String NAME = "SQRT";
@@ -46,4 +47,9 @@ public class SqrtFunction extends JavaMathOneArgumentFunction {
protected double compute(double firstArg) {
return Math.sqrt(firstArg);
}
+
+ @Override
+ public OrderPreserving preservesOrder() {
+ return OrderPreserving.YES;
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimal.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimal.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimal.java
index 199ed28..228aef1 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimal.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimal.java
@@ -421,4 +421,15 @@ public class PDecimal extends PRealNumber<BigDecimal> {
}
return ((signByte & 0x80) == 0) ? -1 : 1;
}
+
+ @Override
+ public void abs(byte[] bytes, int offset, int length, SortOrder sortOrder,
+ ImmutableBytesWritable outPtr) {
+ if (sortOrder == SortOrder.DESC) {
+ bytes = SortOrder.invert(bytes, offset, new byte[length], 0, length);
+ offset = 0;
+ }
+ BigDecimal bigDecimal = toBigDecimal(bytes, offset, length);
+ outPtr.set(toBytes(bigDecimal.abs()));
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PNumericType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PNumericType.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PNumericType.java
index 631ac8d..826d9ad 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PNumericType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PNumericType.java
@@ -41,4 +41,12 @@ public abstract class PNumericType<T> extends PDataType<T> {
abstract public int signum(byte[] bytes, int offset, int length, SortOrder sortOrder,
Integer maxLength, Integer scale);
+
+ abstract public void abs(byte[] bytes, int offset, int length, SortOrder sortOrder,
+ ImmutableBytesWritable outPtr);
+
+ public final void abs(ImmutableBytesWritable ptr, SortOrder sortOrder,
+ ImmutableBytesWritable outPtr) {
+ abs(ptr.get(), ptr.getOffset(), ptr.getLength(), sortOrder, outPtr);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PRealNumber.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PRealNumber.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PRealNumber.java
index d074511..4cab433 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PRealNumber.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PRealNumber.java
@@ -17,6 +17,7 @@
*/
package org.apache.phoenix.schema.types;
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.schema.IllegalDataException;
import org.apache.phoenix.schema.SortOrder;
@@ -36,4 +37,11 @@ public abstract class PRealNumber<T> extends PNumericType<T> {
}
return (d > 0) ? 1 : ((d < 0) ? -1 : 0);
}
+
+ @Override
+ public void abs(byte[] bytes, int offset, int length, SortOrder sortOrder,
+ ImmutableBytesWritable outPtr) {
+ double d = getCodec().decodeDouble(bytes, offset, sortOrder);
+ getCodec().encodeDouble(Math.abs(d), outPtr);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PWholeNumber.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PWholeNumber.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PWholeNumber.java
index f1c7d13..a3a1d13 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PWholeNumber.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PWholeNumber.java
@@ -17,6 +17,7 @@
*/
package org.apache.phoenix.schema.types;
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.phoenix.schema.SortOrder;
public abstract class PWholeNumber<T> extends PNumericType<T> {
@@ -32,4 +33,11 @@ public abstract class PWholeNumber<T> extends PNumericType<T> {
long l = getCodec().decodeLong(bytes, offset, sortOrder);
return Long.signum(l);
}
+
+ @Override
+ public void abs(byte[] bytes, int offset, int length, SortOrder sortOrder,
+ ImmutableBytesWritable outPtr) {
+ long l = getCodec().decodeLong(bytes, offset, sortOrder);
+ getCodec().encodeLong(Math.abs(l), outPtr);
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java
index 7be8eae..79721df 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java
@@ -34,6 +34,7 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
@@ -1634,7 +1635,72 @@ public class QueryCompilerTest extends BaseConnectionlessQueryTest {
assertLiteralEquals(oneMoreThanMaxLong, p, 11);
}
-
+ @Test
+ public void testMathFunctionOrderByOrderPreservingFwd() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ conn.createStatement().execute("CREATE TABLE t (k1 INTEGER not null, k2 double not null, k3 BIGINT not null, v varchar, constraint pk primary key(k1,k2,k3))");
+ /*
+ * "SELECT * FROM T ORDER BY k1, k2",
+ * "SELECT * FROM T ORDER BY k1, SIGN(k2)",
+ * "SELECT * FROM T ORDER BY SIGN(k1), k2",
+ */
+ List<String> queryList = new ArrayList<String>();
+ queryList.add("SELECT * FROM T ORDER BY k1, k2");
+ for (String sub : new String[] { "SIGN", "CBRT", "LN", "LOG", "EXP" }) {
+ queryList.add(String.format("SELECT * FROM T ORDER BY k1, %s(k2)", sub));
+ queryList.add(String.format("SELECT * FROM T ORDER BY %s(k1), k2", sub));
+ }
+ String[] queries = queryList.toArray(new String[queryList.size()]);
+ for (int i = 0; i < queries.length; i++) {
+ String query = queries[i];
+ QueryPlan plan = conn.createStatement().unwrap(PhoenixStatement.class).compileQuery(query);
+ assertTrue(plan.getOrderBy() == OrderBy.FWD_ROW_KEY_ORDER_BY);
+ }
+ // Negative test
+ queryList.clear();
+ for (String sub : new String[] { "SIGN", "CBRT", "LN", "LOG", "EXP" }) {
+ queryList.add(String.format("SELECT * FROM T WHERE %s(k2)=2.0", sub));
+ }
+ for (String query : queryList.toArray(new String[queryList.size()])) {
+ Scan scan = conn.createStatement().unwrap(PhoenixStatement.class).compileQuery(query).getContext().getScan();
+ assertNotNull(scan.getFilter());
+ assertTrue(scan.getStartRow().length == 0);
+ assertTrue(scan.getStopRow().length == 0);
+ }
+ }
+
+ @Test
+ public void testMathFunctionOrderByOrderPreservingRev() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ conn.createStatement().execute("CREATE TABLE t (k1 INTEGER not null, k2 double not null, k3 BIGINT not null, v varchar, constraint pk primary key(k1,k2 DESC,k3))");
+ List<String> queryList = new ArrayList<String>();
+ // "SELECT * FROM T ORDER BY k1 DESC, SIGN(k2) DESC, k3 DESC"
+ queryList.add("SELECT * FROM T ORDER BY k1 DESC");
+ queryList.add("SELECT * FROM T ORDER BY k1 DESC, k2");
+ queryList.add("SELECT * FROM T ORDER BY k1 DESC, k2, k3 DESC");
+ for (String sub : new String[] { "SIGN", "CBRT", "LN", "LOG", "EXP" }) {
+ queryList.add(String.format("SELECT * FROM T ORDER BY k1 DESC, %s(k2) DESC, k3 DESC", sub));
+ }
+ String[] queries = queryList.toArray(new String[queryList.size()]);
+ for (int i = 0; i < queries.length; i++) {
+ String query = queries[i];
+ QueryPlan plan =
+ conn.createStatement().unwrap(PhoenixStatement.class).compileQuery(query);
+ assertTrue(query, plan.getOrderBy() == OrderBy.REV_ROW_KEY_ORDER_BY);
+ }
+ // Negative test
+ queryList.clear();
+ for (String sub : new String[] { "SIGN", "CBRT", "LN", "LOG", "EXP" }) {
+ queryList.add(String.format("SELECT * FROM T WHERE %s(k2)=2.0", sub));
+ }
+ for (String query : queryList.toArray(new String[queryList.size()])) {
+ Scan scan = conn.createStatement().unwrap(PhoenixStatement.class).compileQuery(query).getContext().getScan();
+ assertNotNull(scan.getFilter());
+ assertTrue(scan.getStartRow().length == 0);
+ assertTrue(scan.getStopRow().length == 0);
+ }
+ }
+
@Test
public void testOrderByOrderPreservingFwd() throws Exception {
Connection conn = DriverManager.getConnection(getUrl());
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/test/java/org/apache/phoenix/expression/AbsFunctionTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/AbsFunctionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/AbsFunctionTest.java
new file mode 100644
index 0000000..46c0ed0
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/AbsFunctionTest.java
@@ -0,0 +1,180 @@
+/*
+ * 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.phoenix.expression;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.math.BigDecimal;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.expression.function.AbsFunction;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.types.PDecimal;
+import org.apache.phoenix.schema.types.PDouble;
+import org.apache.phoenix.schema.types.PFloat;
+import org.apache.phoenix.schema.types.PInteger;
+import org.apache.phoenix.schema.types.PLong;
+import org.apache.phoenix.schema.types.PNumericType;
+import org.apache.phoenix.schema.types.PSmallint;
+import org.apache.phoenix.schema.types.PTinyint;
+import org.apache.phoenix.schema.types.PUnsignedDouble;
+import org.apache.phoenix.schema.types.PUnsignedFloat;
+import org.apache.phoenix.schema.types.PUnsignedInt;
+import org.apache.phoenix.schema.types.PUnsignedLong;
+import org.apache.phoenix.schema.types.PUnsignedSmallint;
+import org.apache.phoenix.schema.types.PUnsignedTinyint;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Unit tests for {@link AbsFunction}
+ */
+public class AbsFunctionTest {
+
+ private static void testExpression(LiteralExpression literal, Number expected)
+ throws SQLException {
+ List<Expression> expressions = Lists.newArrayList((Expression) literal);
+ Expression absFunction = new AbsFunction(expressions);
+ ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+ absFunction.evaluate(null, ptr);
+ Number result =
+ (Number) absFunction.getDataType().toObject(ptr, absFunction.getSortOrder());
+ assertTrue(result.getClass().equals(expected.getClass()));
+ if (result instanceof BigDecimal) {
+ assertTrue(((BigDecimal) result).compareTo((BigDecimal) expected) == 0);
+ } else {
+ assertTrue(result.equals(expected));
+ }
+ }
+
+ private static void test(Number value, PNumericType dataType, Number expected)
+ throws SQLException {
+ LiteralExpression literal;
+ literal = LiteralExpression.newConstant(value, dataType, SortOrder.ASC);
+ testExpression(literal, expected);
+ literal = LiteralExpression.newConstant(value, dataType, SortOrder.DESC);
+ testExpression(literal, expected);
+ }
+
+ private static void
+ testBatch(Number[] value, PNumericType dataType, ArrayList<Number> expected)
+ throws SQLException {
+ assertEquals(value.length, expected.size());
+ for (int i = 0; i < value.length; ++i) {
+ test(value[i], dataType, expected.get(i));
+ }
+ }
+
+ @Test
+ public void testAbsFunction() throws Exception {
+ Random random = new Random();
+ Number[] value;
+ ArrayList<Number> expected = new ArrayList<Number>();
+ value = new BigDecimal[] { BigDecimal.valueOf(1.0), BigDecimal.valueOf(0.0),
+ BigDecimal.valueOf(-1.0), BigDecimal.valueOf(123.1234),
+ BigDecimal.valueOf(-123.1234) };
+ expected.clear();
+ for (int i = 0; i < value.length; ++i)
+ expected.add(((BigDecimal) value[i]).abs());
+ testBatch(value, PDecimal.INSTANCE, expected);
+
+ value = new Float[] { 1.0f, 0.0f, -1.0f, 123.1234f, -123.1234f, Float.MIN_VALUE,
+ Float.MAX_VALUE, -Float.MIN_VALUE, -Float.MAX_VALUE, random.nextFloat(),
+ random.nextFloat(), random.nextFloat() };
+ expected.clear();
+ for (int i = 0; i < value.length; ++i)
+ expected.add(Math.abs((Float) value[i]));
+ testBatch(value, PFloat.INSTANCE, expected);
+
+ value = new Float[] { 1.0f, 0.0f, 123.1234f, Float.MIN_VALUE, Float.MAX_VALUE, };
+ expected.clear();
+ for (int i = 0; i < value.length; ++i)
+ expected.add(Math.abs((Float) value[i]));
+ testBatch(value, PUnsignedFloat.INSTANCE, expected);
+
+ value = new Double[] { 1.0, 0.0, -1.0, 123.1234, -123.1234, Double.MIN_VALUE,
+ Double.MAX_VALUE, -Double.MIN_VALUE, -Double.MAX_VALUE,
+ random.nextDouble(), random.nextDouble(), random.nextDouble() };
+ expected.clear();
+ for (int i = 0; i < value.length; ++i)
+ expected.add(Math.abs((Double) value[i]));
+ testBatch(value, PDouble.INSTANCE, expected);
+
+ value = new Double[] { 1.0, 0.0, 123.1234, Double.MIN_VALUE, Double.MAX_VALUE, };
+ expected.clear();
+ for (int i = 0; i < value.length; ++i)
+ expected.add(Math.abs((Double) value[i]));
+ testBatch(value, PUnsignedDouble.INSTANCE, expected);
+
+ value = new Long[] { 1L, 0L, -1L, 123L, -123L, Long.MIN_VALUE + 1, Long.MAX_VALUE,
+ random.nextLong(), random.nextLong(), random.nextLong(), };
+ expected.clear();
+ for (int i = 0; i < value.length; ++i)
+ expected.add(Math.abs((Long) value[i]));
+ testBatch(value, PLong.INSTANCE, expected);
+
+ value = new Long[] { 1L, 0L, 123L, Long.MAX_VALUE };
+ expected.clear();
+ for (int i = 0; i < value.length; ++i)
+ expected.add(Math.abs((Long) value[i]));
+ testBatch(value, PUnsignedLong.INSTANCE, expected);
+
+ value = new Integer[] { 1, 0, -1, 123, -123, Integer.MIN_VALUE + 1, Integer.MAX_VALUE,
+ random.nextInt(), random.nextInt(), random.nextInt(), };
+ expected.clear();
+ for (int i = 0; i < value.length; ++i)
+ expected.add(Math.abs((Integer) value[i]));
+ testBatch(value, PInteger.INSTANCE, expected);
+
+ value = new Integer[] { 1, 0, 123, Integer.MAX_VALUE };
+ expected.clear();
+ for (int i = 0; i < value.length; ++i)
+ expected.add(Math.abs((Integer) value[i]));
+ testBatch(value, PUnsignedInt.INSTANCE, expected);
+
+ value = new Short[] { 1, 0, -1, 123, -123, Short.MIN_VALUE + 1, Short.MAX_VALUE };
+ expected.clear();
+ for (int i = 0; i < value.length; ++i)
+ expected.add((short) Math.abs((Short) value[i]));
+ testBatch(value, PSmallint.INSTANCE, expected);
+
+ value = new Short[] { 1, 0, 123, Short.MAX_VALUE };
+ expected.clear();
+ for (int i = 0; i < value.length; ++i)
+ expected.add((short) Math.abs((Short) value[i]));
+ testBatch(value, PUnsignedSmallint.INSTANCE, expected);
+
+ value = new Byte[] { 1, 0, -1, 123, -123, Byte.MIN_VALUE + 1, Byte.MAX_VALUE };
+ expected.clear();
+ for (int i = 0; i < value.length; ++i)
+ expected.add((byte) Math.abs((Byte) value[i]));
+ testBatch(value, PTinyint.INSTANCE, expected);
+
+ value = new Byte[] { 1, 0, 123, Byte.MAX_VALUE };
+ expected.clear();
+ for (int i = 0; i < value.length; ++i)
+ expected.add((byte) Math.abs((Byte) value[i]));
+ testBatch(value, PUnsignedTinyint.INSTANCE, expected);
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/c2927dde/phoenix-core/src/test/java/org/apache/phoenix/expression/CbrtFunctionTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/CbrtFunctionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/CbrtFunctionTest.java
new file mode 100644
index 0000000..2084896
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/CbrtFunctionTest.java
@@ -0,0 +1,127 @@
+/*
+ * 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.phoenix.expression;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.math.BigDecimal;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Random;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.expression.function.CbrtFunction;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.types.PDecimal;
+import org.apache.phoenix.schema.types.PDouble;
+import org.apache.phoenix.schema.types.PFloat;
+import org.apache.phoenix.schema.types.PInteger;
+import org.apache.phoenix.schema.types.PLong;
+import org.apache.phoenix.schema.types.PNumericType;
+import org.apache.phoenix.schema.types.PSmallint;
+import org.apache.phoenix.schema.types.PTinyint;
+import org.apache.phoenix.schema.types.PUnsignedDouble;
+import org.apache.phoenix.schema.types.PUnsignedFloat;
+import org.apache.phoenix.schema.types.PUnsignedInt;
+import org.apache.phoenix.schema.types.PUnsignedLong;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Unit tests for {@link CbrtFunction}
+ */
+public class CbrtFunctionTest {
+
+ private static void testExpression(LiteralExpression literal, double expected)
+ throws SQLException {
+ List<Expression> expressions = Lists.newArrayList((Expression) literal);
+ Expression cbrtFunction = new CbrtFunction(expressions);
+ ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+ cbrtFunction.evaluate(null, ptr);
+ Double result =
+ (Double) cbrtFunction.getDataType().toObject(ptr, cbrtFunction.getSortOrder());
+ assertTrue(Math.abs(result.doubleValue() - expected) <= 1e-9);
+ }
+
+ private static void test(Number value, PNumericType dataType, double expected)
+ throws SQLException {
+ LiteralExpression literal;
+ literal = LiteralExpression.newConstant(value, dataType, SortOrder.ASC);
+ testExpression(literal, expected);
+ literal = LiteralExpression.newConstant(value, dataType, SortOrder.DESC);
+ testExpression(literal, expected);
+ }
+
+ private static void testBatch(Number[] value, PNumericType dataType) throws SQLException {
+ double[] expected = new double[value.length];
+ for (int i = 0; i < expected.length; ++i) {
+ expected[i] = Math.cbrt(value[i].doubleValue());
+ }
+ assertEquals(value.length, expected.length);
+ for (int i = 0; i < value.length; ++i) {
+ test(value[i], dataType, expected[i]);
+ }
+ }
+
+ @Test
+ public void testCbrtFunction() throws Exception {
+ Random random = new Random();
+
+ testBatch(
+ new BigDecimal[] { BigDecimal.valueOf(1.0), BigDecimal.valueOf(0.0),
+ BigDecimal.valueOf(-1.0), BigDecimal.valueOf(123.1234),
+ BigDecimal.valueOf(-123.1234), BigDecimal.valueOf(random.nextDouble()),
+ BigDecimal.valueOf(random.nextDouble()) }, PDecimal.INSTANCE);
+
+ testBatch(new Float[] { 1.0f, 0.0f, -1.0f, 123.1234f, -123.1234f, random.nextFloat(),
+ random.nextFloat() }, PFloat.INSTANCE);
+
+ testBatch(new Float[] { 1.0f, 0.0f, 123.1234f, }, PUnsignedFloat.INSTANCE);
+
+ testBatch(
+ new Double[] { 1.0, 0.0, -1.0, 123.1234, -123.1234, random.nextDouble(),
+ random.nextDouble() }, PDouble.INSTANCE);
+
+ testBatch(new Double[] { 1.0, 0.0, 123.1234, }, PUnsignedDouble.INSTANCE);
+
+ testBatch(
+ new Long[] { 1L, 0L, -1L, Long.MAX_VALUE, Long.MIN_VALUE, 123L, -123L,
+ random.nextLong(), random.nextLong() }, PLong.INSTANCE);
+
+ testBatch(new Long[] { 1L, 0L, Long.MAX_VALUE, 123L }, PUnsignedLong.INSTANCE);
+
+ testBatch(
+ new Integer[] { 1, 0, -1, Integer.MAX_VALUE, Integer.MIN_VALUE, 123, -123,
+ random.nextInt(), random.nextInt() }, PInteger.INSTANCE);
+
+ testBatch(new Integer[] { 1, 0, Integer.MAX_VALUE, 123 }, PUnsignedInt.INSTANCE);
+
+ testBatch(new Short[] { (short) 1, (short) 0, (short) -1, Short.MAX_VALUE, Short.MIN_VALUE,
+ (short) 123, (short) -123 }, PSmallint.INSTANCE);
+
+ testBatch(new Short[] { (short) 1, (short) 0, Short.MAX_VALUE, (short) 123 },
+ PSmallint.INSTANCE);
+
+ testBatch(new Byte[] { (byte) 1, (byte) 0, (byte) -1, Byte.MAX_VALUE, Byte.MIN_VALUE,
+ (byte) 123, (byte) -123 }, PTinyint.INSTANCE);
+
+ testBatch(new Byte[] { (byte) 1, (byte) 0, Byte.MAX_VALUE, (byte) 123 }, PTinyint.INSTANCE);
+ }
+}