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

io.stargate.graphql.schema.cqlfirst.ddl.fetchers.DdlQueryFetcher Maven / Gradle / Ivy

There is a newer version: 2.0.31
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.graphql.schema.cqlfirst.ddl.fetchers;

import graphql.schema.DataFetchingEnvironment;
import io.stargate.auth.UnauthorizedException;
import io.stargate.db.query.Query;
import io.stargate.db.query.builder.QueryBuilder;
import io.stargate.db.schema.Column;
import io.stargate.db.schema.Column.ColumnType;
import io.stargate.db.schema.Column.Kind;
import io.stargate.db.schema.Column.Order;
import io.stargate.db.schema.Column.Type;
import io.stargate.db.schema.UserDefinedType;
import io.stargate.graphql.schema.CassandraFetcher;
import io.stargate.graphql.web.StargateGraphqlContext;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * Base class for fetchers that execute a single DDL query, such as a CREATE KEYSPACE or DROP TABLE.
 */
public abstract class DdlQueryFetcher extends CassandraFetcher {

  @Override
  protected Boolean get(DataFetchingEnvironment environment, StargateGraphqlContext context)
      throws Exception {
    context
        .getDataStore()
        .execute(buildQuery(environment, context.getDataStore().queryBuilder(), context).bind())
        .get();
    return true;
  }

  protected abstract Query buildQuery(
      DataFetchingEnvironment environment, QueryBuilder builder, StargateGraphqlContext context)
      throws UnauthorizedException;

  protected ColumnType decodeType(Object typeObject) {
    @SuppressWarnings("unchecked")
    Map type = (Map) typeObject;
    String basic = (String) type.get("basic");
    @SuppressWarnings("unchecked")
    Map info = (Map) type.get("info");
    String name = info == null ? null : (String) info.get("name");
    List subTypes = info == null ? null : (List) info.get("subTypes");
    boolean frozen = info != null && info.containsKey("frozen") && (Boolean) info.get("frozen");

    switch (basic) {
      case "INT":
        return Type.Int;
      case "INET":
        return Type.Inet;
      case "TIMEUUID":
        return Type.Timeuuid;
      case "TIMESTAMP":
        return Type.Timestamp;
      case "BIGINT":
        return Type.Bigint;
      case "TIME":
        return Type.Time;
      case "DURATION":
        return Type.Duration;
      case "VARINT":
        return Type.Varint;
      case "UUID":
        return Type.Uuid;
      case "BOOLEAN":
        return Type.Boolean;
      case "TINYINT":
        return Type.Tinyint;
      case "SMALLINT":
        return Type.Smallint;
      case "ASCII":
        return Type.Ascii;
      case "DECIMAL":
        return Type.Decimal;
      case "BLOB":
        return Type.Blob;
      case "VARCHAR":
      case "TEXT":
        return Type.Text;
      case "DOUBLE":
        return Type.Double;
      case "COUNTER":
        return Type.Counter;
      case "DATE":
        return Type.Date;
      case "FLOAT":
        return Type.Float;
      case "LIST":
        if (info == null) {
          throw new IllegalArgumentException(
              "List type should contain an 'info' field specifying the sub type");
        }
        if (subTypes == null || subTypes.size() != 1) {
          throw new IllegalArgumentException("List sub types should contain 1 item");
        }
        return Type.List.of(decodeType(subTypes.get(0))).frozen(frozen);
      case "SET":
        if (info == null) {
          throw new IllegalArgumentException(
              "Set type should contain an 'info' field specifying the sub type");
        }
        if (subTypes == null || subTypes.size() != 1) {
          throw new IllegalArgumentException("Set sub types should contain 1 item");
        }
        subTypes = (List) info.get("subTypes");
        return Type.Set.of(decodeType(subTypes.get(0))).frozen(frozen);
      case "MAP":
        if (info == null) {
          throw new IllegalArgumentException(
              "Map type should contain an 'info' field specifying the sub types");
        }
        if (subTypes == null || subTypes.size() != 2) {
          throw new IllegalArgumentException("Map sub types should contain 2 items");
        }
        return Type.Map.of(decodeType(subTypes.get(0)), decodeType(subTypes.get(1))).frozen(frozen);
      case "UDT":
        if (name == null) {
          throw new IllegalArgumentException(
              "UDT type should contain an 'info' field specifying the UDT name");
        }
        return UserDefinedType.reference(name).frozen(frozen);
      case "TUPLE":
        if (info == null) {
          throw new IllegalArgumentException(
              "TUPLE type should contain an 'info' field specifying the sub types");
        }
        if (subTypes.isEmpty()) {
          throw new IllegalArgumentException("TUPLE type should have at least one sub type");
        }
        ColumnType[] decodedSubTypes = new ColumnType[subTypes.size()];
        for (int i = 0; i < subTypes.size(); i++) {
          decodedSubTypes[i] = decodeType(subTypes.get(i));
        }
        return Type.Tuple.of(decodedSubTypes);
    }
    throw new RuntimeException(String.format("Data type %s is not supported", basic));
  }

  protected Column decodeColumn(Map key, Column.Kind kind) {
    return Column.create(
        (String) key.get("name"),
        kind,
        decodeType(key.get("type")),
        kind == Kind.Clustering ? decodeClusteringOrder((String) key.get("order")) : null);
  }

  private Order decodeClusteringOrder(String order) {
    if (order == null) {
      // Use the same default as CQL
      return Order.ASC;
    }
    return Order.valueOf(order.toUpperCase());
  }

  protected List decodeColumns(List> columnList, Column.Kind kind) {
    if (columnList == null) {
      return Collections.emptyList();
    }
    List columns = new ArrayList<>(columnList.size());
    for (Map entry : columnList) {
      columns.add(decodeColumn(entry, kind));
    }
    return columns;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy