blob: 828051f9d5e11c01aa66cfccec7b17865173c45b [file] [log] [blame]
/*
* 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.ROW6;
import static org.apache.phoenix.util.TestUtil.ROW7;
import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import org.apache.phoenix.exception.SQLExceptionCode;
import org.apache.phoenix.util.PropertiesUtil;
import org.junit.Assert;
import org.junit.Test;
public class CoalesceFunctionIT extends ParallelStatsDisabledIT {
@Test
public void testCoalesce() throws Exception {
String tenantId = getOrganizationId();
String tableName = initATableValues(tenantId, getDefaultSplits(tenantId), getUrl());
Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
Connection conn = DriverManager.getConnection(getUrl(), props);
String query = "SELECT entity_id, a_integer + COALESCE(x_integer,1) FROM " + tableName + " WHERE organization_id = ? AND a_integer >= 6 AND a_integer <= 7";
PreparedStatement statement = conn.prepareStatement(query);
statement.setString(1, tenantId);
ResultSet rs = statement.executeQuery();
assertTrue(rs.next());
assertEquals(ROW6, rs.getString(1));
assertEquals(7, rs.getInt(2));
assertTrue(rs.next());
assertEquals(ROW7, rs.getString(1));
assertEquals(12, rs.getInt(2));
assertFalse(rs.next());
conn.close();
}
@Test
public void coalesceWithSumExplicitLong() throws Exception {
Connection conn = DriverManager.getConnection(getUrl());
String tableName = generateUniqueName();
String ddl = "CREATE TABLE " + tableName + "("
+ " ID BIGINT NOT NULL, "
+ " \"COUNT\" BIGINT "
+ " CONSTRAINT pk PRIMARY KEY(ID))";
conn.createStatement().execute(ddl);
conn.createStatement().execute("UPSERT INTO " + tableName + "(ID, \"COUNT\") VALUES(2, null)");
conn.commit();
ResultSet rs = conn.createStatement().executeQuery(
"SELECT "
+ "COALESCE(SUM(\"COUNT\"), CAST(0 AS BIGINT)) " //explicitly def long
+ "FROM " + tableName
+ " GROUP BY ID");
assertTrue(rs.next());
assertEquals(0, rs.getLong(1));
assertFalse(rs.wasNull());
}
@Test
public void coalesceWithSumImplicitLong() throws Exception {
Connection conn = DriverManager.getConnection(getUrl());
String tableName = generateUniqueName();
String ddl = "CREATE TABLE " + tableName + "("
+ " ID BIGINT NOT NULL, "
+ " \"COUNT\" BIGINT "
+ " CONSTRAINT pk PRIMARY KEY(ID))";
conn.createStatement().execute(ddl);
conn.createStatement().execute("UPSERT INTO " + tableName + "(ID, \"COUNT\") VALUES(2, null)");
conn.commit();
ResultSet rs = conn.createStatement().executeQuery(
"SELECT "
+ "COALESCE(SUM(\"COUNT\"), 0) " // no long def
+ "FROM " + tableName
+ " GROUP BY ID");
assertTrue(rs.next());
assertEquals(0, rs.getLong(1));
assertFalse(rs.wasNull());
}
@Test
public void coalesceWithSecondParamAsExpression() throws Exception {
Connection conn = DriverManager.getConnection(getUrl());
String tableName = generateUniqueName();
String ddl = "CREATE TABLE " + tableName + "("
+ " ID BIGINT NOT NULL, "
+ " \"COUNT\" BIGINT "
+ " CONSTRAINT pk PRIMARY KEY(ID))";
conn.createStatement().execute(ddl);
conn.createStatement().execute("UPSERT INTO " + tableName + "(ID, \"COUNT\") VALUES(2, null)");
conn.commit();
ResultSet rs = conn.createStatement().executeQuery(
"SELECT "
+ "COALESCE(SUM(\"COUNT\"), SUM(ID)) " // second param as expression
+ "FROM " + tableName
+ " GROUP BY ID");
assertTrue(rs.next());
assertEquals(2, rs.getLong(1));
assertFalse(rs.wasNull());
}
@Test
public void nonTypedSecondParameterLong() throws Exception {
Connection conn = DriverManager.getConnection(getUrl());
String tableName = generateUniqueName();
String ddl = "CREATE TABLE " + tableName + "("
+ " ID BIGINT NOT NULL, "
+ " \"COUNT\" BIGINT " //first parameter to coalesce
+ " CONSTRAINT pk PRIMARY KEY(ID))";
conn.createStatement().execute(ddl);
conn.createStatement().execute("UPSERT INTO " + tableName + "(ID, \"COUNT\") VALUES(2, null)");
conn.commit();
ResultSet rs = conn.createStatement().executeQuery(
"SELECT "
+ "COALESCE(NTH_VALUE(\"COUNT\", 100) WITHIN GROUP (ORDER BY \"COUNT\" DESC), 0) " //second param is int
+ "FROM " + tableName
+ " GROUP BY ID");
assertTrue(rs.next());
assertEquals(0, rs.getLong(1));
assertFalse(rs.wasNull());
}
@Test
public void nonTypedSecondParameterUnsignedDataTypes() throws Exception {
Connection conn = DriverManager.getConnection(getUrl());
String tableName = generateUniqueName();
String ddl = "CREATE TABLE " + tableName + "("
+ " ID BIGINT NOT NULL, "
+ " \"COUNT\" UNSIGNED_INT " //first parameter to coalesce
+ " CONSTRAINT pk PRIMARY KEY(ID))";
conn.createStatement().execute(ddl);
conn.createStatement().execute("UPSERT INTO " + tableName + " (ID, \"COUNT\") VALUES(2, null)");
conn.commit();
//second param to coalesce is signed int
ResultSet rs = conn.createStatement().executeQuery(
"SELECT "
+ " COALESCE(NTH_VALUE(\"COUNT\", 100) WITHIN GROUP (ORDER BY COUNT DESC), 1) "
+ " FROM " + tableName
+ " GROUP BY ID");
assertTrue(rs.next());
assertEquals(1, rs.getInt(1));
assertFalse(rs.wasNull());
}
@Test
public void testWithNthValueAggregationFunction() throws Exception {
Connection conn = DriverManager.getConnection(getUrl());
String tableName = generateUniqueName();
String ddl = "CREATE TABLE " + tableName + "("
+ " ID BIGINT NOT NULL, "
+ " DATE TIMESTAMP NOT NULL, "
+ " \"COUNT\" BIGINT "
+ " CONSTRAINT pk PRIMARY KEY(ID, DATE))";
conn.createStatement().execute(ddl);
conn.createStatement().execute("UPSERT INTO " + tableName + "(ID, DATE, \"COUNT\") VALUES(1, CURRENT_TIME(), 1)");
conn.createStatement().execute("UPSERT INTO " + tableName + "(ID, DATE, \"COUNT\") VALUES(1, CURRENT_TIME(), 2)");
conn.createStatement().execute("UPSERT INTO " + tableName + "(ID, DATE, \"COUNT\") VALUES(2, CURRENT_TIME(), 1)");
conn.commit();
//second param to coalesce is signed int
ResultSet rs = conn.createStatement().executeQuery(
"SELECT "
+ " COALESCE("
+ " NTH_VALUE(\"COUNT\", 2000)" // should evaluate null
+ " WITHIN GROUP (ORDER BY \"COUNT\" DESC),"
+ " 0)"
+ "FROM " + tableName
+ " GROUP BY ID");
assertTrue(rs.next());
assertEquals(0, rs.getLong(1));
assertFalse(rs.wasNull());
}
@Test
public void wrongDataTypeOfSecondParameter() throws Exception {
Connection conn = DriverManager.getConnection(getUrl());
String tableName = generateUniqueName();
String ddl = "CREATE TABLE " + tableName + "("
+ " ID UNSIGNED_INT NOT NULL, "
+ " \"COUNT\" UNSIGNED_INT "
+ " CONSTRAINT pk PRIMARY KEY(ID))";
conn.createStatement().execute(ddl);
conn.createStatement().execute("UPSERT INTO " + tableName + "(ID, \"COUNT\") VALUES(2, null)");
conn.commit();
try {
conn.createStatement().executeQuery(
"SELECT "
+ "COALESCE(MIN(\"COUNT\"), -1) " // invalid value for UNSIGNED_INT
+ "FROM " + tableName
+ " GROUP BY ID");
Assert.fail("CANNOT CONVERT TYPE exception expected");
} catch (SQLException e) {
}
}
@Test
public void testImplicitSecondArgCastingException() throws Exception {
Connection conn = DriverManager.getConnection(getUrl());
String tableName = generateUniqueName();
String ddl = "CREATE TABLE " + tableName + "("
+ " ID INTEGER NOT NULL, "
+ " \"COUNT\" UNSIGNED_INT " //first parameter to coalesce
+ " CONSTRAINT pk PRIMARY KEY(ID))";
conn.createStatement().execute(ddl);
conn.createStatement().execute("UPSERT INTO " + tableName + "(ID, \"COUNT\") VALUES(-2, null)");
conn.commit();
try {
ResultSet rs = conn.createStatement().executeQuery(
"SELECT "
+ "COALESCE(MIN(\"COUNT\"), ID) "
+ "FROM " + tableName
+ " GROUP BY ID");
assertTrue(rs.next());
assertEquals(0, rs.getLong(1));
fail("Should not cast -2 to UNSIGNED_INT");
} catch (SQLException e) {
assertEquals(SQLExceptionCode.ILLEGAL_DATA.getErrorCode(), e.getErrorCode());
}
}
@Test
public void testImplicitSecondArgCasting() throws Exception {
Connection conn = DriverManager.getConnection(getUrl());
String tableName = generateUniqueName();
String ddl = "CREATE TABLE " + tableName + "("
+ " ID DOUBLE NOT NULL, "
+ " \"COUNT\" INTEGER " //first parameter to coalesce
+ " CONSTRAINT pk PRIMARY KEY(ID))";
conn.createStatement().execute(ddl);
conn.createStatement().execute("UPSERT INTO " + tableName + "(ID, \"COUNT\") VALUES(2.0, null)");
conn.commit();
ResultSet rs = conn.createStatement().executeQuery(
"SELECT "
+ "COALESCE(MIN(\"COUNT\"), ID) "
+ "FROM " + tableName
+ " GROUP BY ID");
assertTrue(rs.next());
assertEquals(2, rs.getLong(1));
assertFalse(rs.wasNull());
}
@Test
public void testCoalesceInRowKeyColumn() throws Exception {
Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
Connection conn = DriverManager.getConnection(getUrl(), props);
String tableName = generateUniqueName();
conn.createStatement().execute("CREATE TABLE " + tableName + "(k1 decimal, k2 decimal, constraint pk primary key (k1,k2))");
conn.createStatement().execute("UPSERT INTO " + tableName + "(k2) VALUES (1)");
conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES (2,2)");
conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES (3,3)");
conn.commit();
ResultSet rs = conn.createStatement().executeQuery("SELECT coalesce(k1, 1) ,k2 FROM " + tableName);
assertTrue(rs.next());
assertEquals(1, rs.getInt(1));
assertEquals(1, rs.getInt(2));
assertTrue(rs.next());
assertEquals(2, rs.getInt(1));
assertEquals(2, rs.getInt(2));
assertTrue(rs.next());
assertEquals(3, rs.getInt(1));
assertEquals(3, rs.getInt(2));
assertFalse(rs.next());
}
}