All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.stargate.it.http.graphql.cqlfirst.AggregationFunctionsTest Maven / Gradle / Ivy

There is a newer version: 2.1.0-BETA-19
Show newest version
/*
 * Copyright The Stargate Authors
 *
 * Licensed 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 io.stargate.it.http.graphql.cqlfirst;

import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;

import com.datastax.oss.driver.api.core.CqlIdentifier;
import com.datastax.oss.driver.api.core.CqlSession;
import com.jayway.jsonpath.JsonPath;
import io.stargate.it.driver.TestKeyspace;
import io.stargate.it.http.RestUtils;
import io.stargate.it.storage.StargateConnectionInfo;
import java.util.Map;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

public class AggregationFunctionsTest extends BetterbotzTestBase {
  private static CqlFirstClient CLIENT;
  private static CqlIdentifier KEYSPACE_ID;

  @BeforeAll
  public static void setup(StargateConnectionInfo cluster, @TestKeyspace CqlIdentifier keyspaceId) {
    String host = cluster.seedAddress();
    CLIENT = new CqlFirstClient(host, RestUtils.getAuthToken(host));
    KEYSPACE_ID = keyspaceId;
  }

  @AfterEach
  public void cleanup(CqlSession session) {
    session.execute("TRUNCATE TABLE \"Orders\"");
  }

  @Test
  @DisplayName("Should calculate number of orders using count aggregation")
  public void countUsingBigIntFunctionWithAlias() {
    insertOrder("p1", "c1", "3000", "d1");
    insertOrder("p1", "c2", "2500", "d1");

    Map result = getOrderWithCount("p1");
    assertThat(JsonPath.read(result, "$.Orders.values[0].count")).isEqualTo("2");
  }

  @Test
  @DisplayName("Should calculate average of orders' price using avg aggregation")
  public void avgUsingDecimalFunctionWithoutAlias() {
    insertOrder("p1", "c1", "4", "d1");
    insertOrder("p1", "c2", "10", "d1");

    Map result = getOrderWithAvg("p1");
    // avg price is (4 + 10) / 2 = 7
    assertThat(JsonPath.read(result, "$.Orders.values[0]._decimal_function"))
        .isEqualTo("7");
  }

  @Test
  @DisplayName("Should get the highest order using max aggregation")
  public void maxUsingDecimalFunctionWithAlias() {
    insertOrder("p1", "c1", "2500", "d1");
    insertOrder("p1", "c2", "3000", "d1");

    Map result = getOrderWithMax("p1");
    assertThat(JsonPath.read(result, "$.Orders.values[0].max")).isEqualTo("3000");
  }

  @Test
  @DisplayName("Should get the lowest order using min aggregation")
  public void minUsingDecimalFunctionWithAlias() {
    insertOrder("p1", "c1", "2500", "d1");
    insertOrder("p1", "c2", "3000", "d1");

    Map result = getOrderWithMin("p1");
    assertThat(JsonPath.read(result, "$.Orders.values[0].min")).isEqualTo("2500");
  }

  @Test
  @DisplayName("Should sum all orders' price using sum aggregation")
  public void sumUsingDecimalFunctionWithAlias() {
    insertOrder("p1", "c1", "2500", "d1");
    insertOrder("p1", "c2", "3000", "d1");

    Map result = getOrderWithSum("p1");
    assertThat(JsonPath.read(result, "$.Orders.values[0].sum")).isEqualTo("5500");
  }

  @Test
  @DisplayName("Should test all available function types")
  public void testAllGraphqlFunctionTypes() {
    Number value = 100;
    insertOrder("p1", "c1", "d1", value);

    Map result = getOrderWithAllFunctions("p1");
    assertThat(JsonPath.read(result, "$.Orders.values[0]._int_function"))
        .isEqualTo(value.intValue());
    assertThat(JsonPath.read(result, "$.Orders.values[0]._double_function"))
        .isEqualTo(value.doubleValue());
    assertThat(JsonPath.read(result, "$.Orders.values[0]._bigint_function"))
        .isEqualTo(value.toString());
    assertThat(JsonPath.read(result, "$.Orders.values[0]._decimal_function"))
        .isEqualTo(value.toString());
    assertThat(JsonPath.read(result, "$.Orders.values[0]._varint_function"))
        .isEqualTo(value.toString());
    assertThat(JsonPath.read(result, "$.Orders.values[0]._float_function"))
        .isEqualTo(value.doubleValue());
    assertThat(JsonPath.read(result, "$.Orders.values[0]._smallint_function"))
        .isEqualTo(value.shortValue());
    assertThat(JsonPath.read(result, "$.Orders.values[0]._tinyint_function"))
        .isEqualTo(value.byteValue());
  }

  @Test
  @DisplayName("Should error when trying to use an unknown aggregation function")
  public void shouldErrorWhenTryingToUseAnUnknownAggregationFunction() {
    insertOrder("p1", "c1", "2500", "d1");

    String result = getOrderWithUnknownFunction("p1");

    assertThat(result).contains("Column 'unknown_function' is not defined in the Row's metadata.");
  }

  @Test
  @DisplayName("Should error when trying to use an unknown graphql function return type")
  public void shouldErrorWhenTryingToUseAnUnknownGraphqlFunctionReturnType() {
    insertOrder("p1", "c1", "2500", "d1");

    String result = getOrderWithUnknownFunctionReturnType("p1");

    assertThat(result)
        .contains(
            "Validation error of type FieldUndefined: Field '_unknown_function' in type 'Orders' is undefined");
  }

  @Test
  @DisplayName("Should calculate the sum of orders sellPrices using sum on a case sensitive column")
  public void sumOnCaseSensitiveColumn() {
    insertOrder("p1", "c1", "3000", "d1");
    insertOrder("p1", "c2", "2500", "d1");

    Map result = getOrderWithSumCaseSensitive("p1");
    assertThat(JsonPath.read(result, "$.Orders.values[0].sum")).isEqualTo("5500");
  }

  private Map insertOrder(
      String prodName, String customerName, String description, Number value) {
    Map response =
        CLIENT.executeDmlQuery(
            KEYSPACE_ID,
            String.format(
                "mutation {\n"
                    + "  insertOrders(\n"
                    + "    value: {\n"
                    + "      prodName: \"%s\"\n"
                    + "      customerName: \"%s\"\n"
                    + "      price: \"%s\"\n"
                    + "      value_int: %s\n"
                    + "      value_double: %s\n"
                    + "      value_bigint: \"%s\"\n"
                    + "      value_varint: \"%s\"\n"
                    + "      value_float: %s\n"
                    + "      value_smallint: %s\n"
                    + "      value_tinyint: %s\n"
                    + "      description: \"%s\"\n"
                    + "    }\n,"
                    + "    ifNotExists: true"
                    + "  ) {\n"
                    + "    applied\n"
                    + "    value { id, prodId, prodName, customerName, address, description, price, sellPrice }"
                    + "  }\n"
                    + "}",
                prodName,
                customerName,
                value.toString(),
                value.intValue(),
                value.doubleValue(),
                value,
                value,
                value.doubleValue(),
                value.shortValue(),
                value.byteValue(),
                description));
    assertThat(JsonPath.read(response, "$.insertOrders.applied")).isTrue();
    return response;
  }

  private Map insertOrder(
      String prodName, String customerName, String price, String description) {
    Map response =
        CLIENT.executeDmlQuery(
            KEYSPACE_ID,
            String.format(
                "mutation {\n"
                    + "  insertOrders(\n"
                    + "    value: {\n"
                    + "      prodName: \"%s\"\n"
                    + "      customerName: \"%s\"\n"
                    + "      price: \"%s\"\n"
                    + "      sellPrice: \"%s\"\n"
                    + "      description: \"%s\"\n"
                    + "    }\n,"
                    + "    ifNotExists: true"
                    + "  ) {\n"
                    + "    applied\n"
                    + "    value { id, prodId, prodName, customerName, address, description, price, sellPrice }"
                    + "  }\n"
                    + "}",
                prodName, customerName, price, price, description));
    assertThat(JsonPath.read(response, "$.insertOrders.applied")).isTrue();
    return response;
  }

  private Map getOrderWithCount(String prodName) {
    return getOrderWithFunction(
        prodName, "count: _bigint_function(name: \"count\", args: [\"description\"])");
  }

  private Map getOrderWithMax(String prodName) {
    return getOrderWithFunction(
        prodName, "max: _decimal_function(name: \"max\", args: [\"price\"])");
  }

  private String getOrderWithUnknownFunction(String prodName) {
    return getOrderWithFunctionError(
        prodName,
        "unknown_function: _decimal_function(name: \"some_unknown_function\", args: [\"price\"])");
  }

  private String getOrderWithUnknownFunctionReturnType(String prodName) {
    return getOrderWithFunctionError(
        prodName,
        "unknown_function_return_type: _unknown_function(name: \"count\", args: [\"price\"])");
  }

  private Map getOrderWithMin(String prodName) {
    return getOrderWithFunction(
        prodName, "min: _decimal_function(name: \"min\", args: [\"price\"])");
  }

  private Map getOrderWithAvg(String prodName) {
    return getOrderWithFunction(prodName, "_decimal_function(name: \"avg\", args: [\"price\"])");
  }

  private Map getOrderWithSum(String prodName) {
    return getOrderWithFunction(
        prodName, "sum: _decimal_function(name: \"sum\", args: [\"price\"])");
  }

  private Map getOrderWithSumCaseSensitive(String prodName) {
    return getOrderWithFunction(
        prodName, "sum: _decimal_function(name: \"sum\", args: [\"sellPrice\"])");
  }

  private Map getOrderWithAllFunctions(String prodName) {
    return getOrderWithFunction(
        prodName,
        "_int_function(name: \"max\", args: [\"value_int\"])\n"
            + "            _double_function(name: \"max\", args: [\"value_double\"])\n"
            + "            _bigint_function(name: \"max\", args: [\"value_bigint\"])\n"
            + "            _decimal_function(name: \"max\", args: [\"price\"])\n"
            + "            _varint_function(name: \"max\", args: [\"value_varint\"])\n"
            + "            _float_function(name: \"max\", args: [\"value_float\"])\n"
            + "            _smallint_function(name: \"max\", args: [\"value_smallint\"])\n"
            + "            _tinyint_function(name: \"max\", args: [\"value_tinyint\"])");
  }

  private Map getOrderWithFunction(String prodName, String function) {
    return CLIENT.executeDmlQuery(KEYSPACE_ID, createQueryWithFunction(prodName, function));
  }

  private String getOrderWithFunctionError(String prodName, String function) {
    return CLIENT.getDmlQueryError(KEYSPACE_ID, createQueryWithFunction(prodName, function));
  }

  private String createQueryWithFunction(String prodName, String function) {
    return String.format(
        "{\n"
            + "  Orders(\n"
            + "    filter: {\n"
            + "      prodName: { eq: \"%s\" }\n"
            + "    }\n"
            + "  ) {\n"
            + "    values {\n"
            + "       %s\n"
            + "    }\n"
            + "  }\n"
            + "}",
        prodName, function);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy