Package com.alibaba.wasp.plan.parser.druid

Source Code of com.alibaba.wasp.plan.parser.druid.FMetaEventOperation

/**
* Copyright 2010 The Apache Software Foundation
*
* 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 com.alibaba.wasp.plan.parser.druid;

import com.alibaba.wasp.DataType;
import com.alibaba.wasp.FieldKeyWord;
import com.alibaba.wasp.TableNotFoundException;
import com.alibaba.wasp.meta.FTable;
import com.alibaba.wasp.meta.Field;
import com.alibaba.wasp.meta.Index;
import com.alibaba.wasp.meta.RowBuilder;
import com.alibaba.wasp.meta.TableSchemaCacheReader;
import com.alibaba.wasp.plan.parser.Condition;
import com.alibaba.wasp.plan.parser.QueryInfo;
import com.alibaba.wasp.plan.parser.UnsupportedException;
import com.alibaba.wasp.util.ParserUtils;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Pair;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

/**
* Wasp meta operation.
*
*/
public class FMetaEventOperation implements MetaEventOperation {

  private TableSchemaCacheReader reader;

  public FMetaEventOperation(TableSchemaCacheReader reader) {
    this.reader = reader;
  }

  /**
   * Get the table as the specified name if exists, else throw exception
   *
   * @param tableName
   * @return the table
   * @throws java.io.IOException
   */
  @Override
  public FTable checkAndGetTable(String tableName, boolean fetch)
      throws IOException {
    FTable table = reader.getSchema(tableName);
    if (table == null) {
      if (fetch) {
        table = TableSchemaCacheReader.getService(reader.getConf()).getTable(
            tableName);
      }
    }
    if (table == null) {
      throw new TableNotFoundException(tableName + " not exists!");
    }
    return table;
  }

  @Override
  public boolean checkTableNotExists(String tableName, boolean fetch)
      throws IOException {
    FTable table = reader.getSchema(tableName);
    if (table == null) {
      if (fetch) {
        table = TableSchemaCacheReader.getService(reader.getConf()).getTable(
            tableName);
      }
    }
    return table == null;
  }

  /**
   * Get fields as the field names under the specified table, throw exception if
   * one does not exist
   *
   * @param table
   * @param fields
   * @return a list of fields
   * @throws java.io.IOException
   */
  @Override
  public LinkedHashMap<String, Field> checkAndGetFields(FTable table,
      Collection<String> fields) throws IOException {
    LinkedHashMap<String, Field> foundColumns = new LinkedHashMap<String, Field>(
        fields.size());
    for (String field : fields) {
      Field foundColumn = table.getColumn(field);
      if (foundColumn == null) {
        throw new UnsupportedException(table.getTableName() + " does not have column '"
            + field + "'!");
      }
      foundColumns.put(foundColumn.getName(), foundColumn);
    }
    return foundColumns;
  }

  /**
   * check whether the given field is primary key, throw exception if not
   *
   * @param table
   * @param field
   * @throws java.io.IOException
   */
  @Override
  public void checkIsPrimaryKey(FTable table, String field) throws IOException {
    LinkedHashMap<String, Field> primaryKeys = table.getPrimaryKeys();
    if (primaryKeys.size() == 1
        && primaryKeys.entrySet().iterator().next().getValue().getName()
            .equals(field)) {
    } else {
      throw new UnsupportedException(field + " is not Primary Key !");
    }
  }

  /**
   * check whether the given fields are primary key, throw exception if not
   *
   * @param table
   * @param fields
   * @throws java.io.IOException
   */
  @Override
  public void checkIsPrimaryKey(FTable table, Set<String> fields)
      throws IOException {
    LinkedHashMap<String, Field> primaryKeys = table.getPrimaryKeys();
    if (primaryKeys.size() != fields.size()) {
      throw new UnsupportedException(fields + " is not Primary Key !");
    }

    for (String fieldName : fields) {
      boolean exists = false;
      if (primaryKeys.containsKey(fieldName)) {
        exists = true;
      }

      if (!exists) {
        throw new UnsupportedException("Does not have primary key '" + fieldName + "'!");
      }
    }
  }

  /**
   * Check whether the given field is exist, throw exception if it is not exist
   *
   * @param table
   * @param field
   * @throws java.io.IOException
   */
  @Override
  public void checkFieldExists(FTable table, String field) throws IOException {
    LinkedHashMap<String, Field> columns = table.getColumns();
    if (!inSet(columns, field)) {
      throw new UnsupportedException("Field '" + field + "' not exists!");
    }
  }

  /**
   * Check whether the given field is not a primary key, throw exception if it
   * is
   *
   * @param table
   * @param field
   * @throws java.io.IOException
   */
  @Override
  public void checkFieldNotInPrimaryKeys(FTable table, String field)
      throws IOException {
    LinkedHashMap<String, Field> primaryKeys = table.getPrimaryKeys();
    if (inSet(primaryKeys, field)) {
      throw new UnsupportedException(field + " is primary key!");
    }
  }

  /**
   * Check whether the given fields are primary keys under the specified table
   *
   * @param table
   * @param fields
   * @return true if they are primary keys
   * @throws java.io.IOException
   */
  @Override
  public boolean arePrimaryKeys(FTable table, List<String> fields) {
    LinkedHashMap<String, Field> primaryKeys = table.getPrimaryKeys();
    if (primaryKeys.size() == fields.size()) {
      for (int i = 0; i < fields.size(); i++) {
        if (!inSet(primaryKeys, fields.get(i))) {
          return false;
        }
      }
      return true;
    } else {
      return false;
    }
  }

  public boolean inSet(LinkedHashMap<String, Field> columns, String field) {
    return columns.containsKey(field);
  }

  public boolean inSet(List<String> fields, String field) {
    return fields.contains(field);
  }

  @Override
  public boolean containPrimaryKeys(FTable table, List<String> fields) {
    LinkedHashMap<String, Field> primaryKeys = table.getPrimaryKeys();
    if (primaryKeys.size() <= fields.size()) {
      Iterator<Entry<String, Field>> iter = primaryKeys.entrySet().iterator();
      while (iter.hasNext()) {
        if (!inSet(fields, iter.next().getKey())) {
          return false;
        }
      }
      return true;
    } else {
      return false;
    }
  }

  /**
   * Check whether the given column not belong to a index, if it is, throw
   * Exception, for example alter table change column, the changed column should
   * not be in a index.
   *
   * @param table
   * @param field
   * @throws java.io.IOException
   */
  @Override
  public void checkColumnNotInIndex(FTable table, String field)
      throws IOException {
    LinkedHashMap<String, Index> allIndexs = table.getIndex();
    if (allIndexs != null && allIndexs.size() > 0) {
      for (Index index : allIndexs.values()) {
        if (index.getIndexKeys().containsKey(field)) {
          throw new UnsupportedException("Column " + field + " in Index "
              + index.getIndexName());
        }
      }
    }
  }

  /**
   * Get the index, throw exception if not exist
   *
   * @param table
   * @param fields
   * @return the index if exists
   * @throws java.io.IOException
   */
  @Override
  public Index checkAndGetIndex(FTable table, List<String> fields)
      throws IOException {
    StringBuilder egkb = new StringBuilder();
    StringBuilder negkb = new StringBuilder();
    for (String field : fields) {
      egkb.append(field);
      if (!field.equalsIgnoreCase(table.getEntityGroupKey().getName())) {
        negkb.append(field);
      }
    }

    List<Index> indexs = reader.getIndexsByComposite(table.getTableName(),
        egkb.toString());

    if (indexs == null) {
      indexs = reader.getIndexsByComposite(table.getTableName(),
          negkb.toString());
    }

//    if(indexs == null) {
//      boolean isIndexLeftMatch = true;//TODO add config
//      if(isIndexLeftMatch) {
//        indexs = reader.leftMatchIndexsByComposite(table.getTableName(), negkb.toString());
//      }
//    }
    if(indexs == null) {
      boolean isEnableNotOnlyIndex = true;//TODO add config
      if(isEnableNotOnlyIndex) {
        for(int i = 1; i < fields.size() && indexs == null ; i++) {
          List<String> newField = fields.subList(0, fields.size() - i);
          indexs = reader.getIndexsByComposite(table.getTableName(),
              getCompositeName(newField));
        }
      }
    }

    // Not supported no-index query!
    if (indexs == null) {
      throw new UnsupportedException("Don't get a Index!");
    } else if (indexs.size() > 1) {
      return optimizationIndex(indexs, fields);
    } else if (indexs.size() == 1) {
      return indexs.get(0);
    } else {
      return null;
    }
  }

  private String getCompositeName(List<String> newFields) {
    StringBuilder egkb = new StringBuilder();
    for (String filed : newFields) {
      egkb.append(filed);
    }
    return egkb.toString();
  }

  private Index optimizationIndex(List<Index> indexs, List<String> fields) {
    // TODO optimization index.
    for (Index index : indexs) {
      if (index.getIndexKeys().size() == fields.size()) {
        return index;
      }
    }
    return indexs.get(0);
  }

  /**
   * Get the start key and end key of the given query
   *
   * @param index
   * @param queryInfo
   * @return a pair of start key and end key
   * @throws java.io.IOException
   */
  @Override
  public Pair<byte[], byte[]> getStartkeyAndEndkey(Index index,
      QueryInfo queryInfo) throws IOException {
    return RowBuilder.build().buildStartkeyAndEndkey(index, queryInfo);
  }

  /**
   * check whether all required fields(include primary keys) have shown up
   *
   * @param table
   * @param fields
   * @throws java.io.IOException
   */
  @Override
  public void checkRequiredFields(FTable table, LinkedHashSet<String> fields)
      throws IOException {
    LinkedHashMap<String, Field> primaryKeys = table.getPrimaryKeys();

    int count = 0;
    for (String fieldName : fields) {
      if (primaryKeys.containsKey(fieldName)) {
        count++;
      }
    }

    if (count != primaryKeys.size()) {
      throw new UnsupportedException("PrimaryKeys have " + primaryKeys.size()
          + " Fields, but only find " + count + " Fields");
    }

    LinkedHashMap<String, Field> columns = table.getColumns();
    for (Field field : columns.values()) {
      if (field.getKeyWord() == FieldKeyWord.REQUIRED) {
        if (!inSet(fields, field)) {
          throw new UnsupportedException("Field " + field.getName()
              + " is REQUIRED, but don't show up ");
        }
      }
    }
  }

  public boolean inSet(LinkedHashSet<String> columns, Field field) {
    return columns.contains(field.getName());
  }

  /**
   * Get the column's familyName in FTable
   *
   * @param fTableName
   * @param columnName
   * @return column family name
   * @throws java.io.IOException
   */
  @Override
  public String getColumnFamily(String fTableName, String columnName)
      throws IOException {
    FTable table = reader.getSchema(fTableName);
    if (table == null) {
      throw new UnsupportedException(fTableName + " is not exists!");
    }
    Field column = table.getColumn(columnName);
    if (column != null) {
      return column.getFamily();
    }
    throw new UnsupportedException(fTableName + " don't have column '" + columnName
        + "'");
  }

  /**
   * Get the column's Field in FTable
   *
   * @param fTable
   * @param columnName
   * @return Field
   * @throws java.io.IOException
   */
  @Override
  public Field getColumnInfo(FTable fTable, String columnName)
      throws IOException {
    if (fTable == null) {
      throw new UnsupportedException(" Table is not exists!");
    }
    Field column = fTable.getColumn(columnName);
    if (column != null) {
      return column;
    }
    throw new UnsupportedException(fTable.getTableName() + " don't have column '"
        + columnName + "'");
  }

  /**
   * Check whether the index exists, throw exception if not exist
   *
   * @param table
   * @param indexName
   * @throws java.io.IOException
   */
  @Override
  public void checkIndexExists(FTable table, String indexName)
      throws IOException {
    LinkedHashMap<String, Index> allIndexs = table.getIndex();
    if (allIndexs != null && allIndexs.size() > 0) {
      if (!isIndexExists(table, indexName)) {
        throw new UnsupportedException("Table " + table.getTableName()
            + " doesn't have this index '" + indexName + "'");
      }
    } else {
      throw new UnsupportedException("Table " + table.getTableName()
          + " doesn't have any index.");
    }
  }

  /**
   * Check whether the index not exist, throw exception if exist
   *
   * @param table
   * @param indexName
   * @throws java.io.IOException
   */
  @Override
  public void checkIndexNotExists(FTable table, String indexName)
      throws IOException {
    if (isIndexExists(table, indexName)) {
      throw new UnsupportedException("Table " + table.getTableName()
          + " has already a same name index.");
    }
  }

  /**
   * Check whether two indexs have same fields
   *
   * @param table
   * @param index
   * @throws java.io.IOException
   */
  @Override
  public void checkTwoIndexWithSameColumn(FTable table, Index index)
      throws IOException {
    LinkedHashMap<String, Index> allIndexs = table.getIndex();
    if (allIndexs != null && allIndexs.size() > 0) {
      for (Index exist : allIndexs.values()) {
        LinkedHashMap<String, Field> indexKeys = exist.getIndexKeys();
        LinkedHashMap<String, Field> toCheck = index.getIndexKeys();
        if (indexKeys.size() == toCheck.size()) {
          boolean allSame = true;
          Iterator<Entry<String, Field>> iterIndexKeys = indexKeys.entrySet()
              .iterator();
          Iterator<Entry<String, Field>> iterToCheck = toCheck.entrySet()
              .iterator();
          while (iterIndexKeys.hasNext()) {
            if (!iterIndexKeys.next().getValue().getName()
                .equals(iterToCheck.next().getValue().getName())) {
              allSame = false;
            }
          }
          if (allSame) {
            throw new UnsupportedException("Two index: " + index.getIndexName()
                + " and " + exist.getIndexName() + " have the same columns.");
          }
        }
      }
    }
  }

  private boolean isIndexExists(FTable table, String indexName) {
    return table.getIndex().containsKey(indexName);
  }

  /**
   * Check whether the given columns are primary keys
   *
   * @param table
   * @param columns
   * @throws java.io.IOException
   */
  @Override
  public void checkIsPrimaryKeyOrIndex(FTable table, List<String> columns)
      throws IOException {
    if (arePrimaryKeys(table, columns)) {
      return;
    } else {
      Index index = checkAndGetIndex(table, columns);
      if (index == null) {
        throw new UnsupportedException("Not a PrimaryKey or a Index");
      }
    }
  }

  /**
   * Get primary keys
   *
   * @param table
   * @param conditions
   * @return a list of pair of pk and its value
   * @throws java.io.IOException
   */
  @Override
  public List<Pair<String, byte[]>> getPrimaryKeyPairList(FTable table,
      LinkedHashMap<String, Condition> conditions,  LinkedHashMap<String, Condition> rangeConditions)
      throws IOException {
    List<Pair<String, byte[]>> primaryKeys = new ArrayList<Pair<String, byte[]>>();
    for (Field primaryKey : table.getPrimaryKeys().values()) {
      Condition condition = ParserUtils.getCondition(primaryKey.getName(),
          conditions);
      if (condition != null) {
        primaryKeys.add(new Pair<String, byte[]>(condition.getFieldName(),
            DruidParser.convert(table.getColumn(condition.getFieldName()),
                condition.getValue())));
      } else {
        primaryKeys = null;
        break;
      }
    }
    return primaryKeys;
  }

  /**
   * Check whether the given table name is legal, throw exception if not legal
   *
   * @param tableName
   * @throws java.io.IOException
   */
  @Override
  public void isLegalTableName(String tableName) throws IOException {
    try {
      FTable.isLegalTableName(tableName);
    } catch (Exception e) {
      throw new UnsupportedException("Unsupported TableName " + tableName, e);
    }
  }

  /**
   * Check whether the given index name is legal, throw exception if not
   *
   * @param indexName
   * @throws java.io.IOException
   */
  @Override
  public void isLegalIndexName(String indexName) throws IOException {
    isLegalTableName(indexName);
  }

  /**
   * Check whether the table has duplicate column name after adding the new
   * columns
   *
   * @param existedColumns
   * @param newColumns
   * @throws java.io.IOException
   */
  @Override
  public void areLegalTableColumns(Collection<Field> existedColumns,
      Collection<Field> newColumns) throws IOException {
    HashSet<String> existedColumnNames = new HashSet<String>();
    if (existedColumns != null && !existedColumns.isEmpty()) {
      for (Field existedColumn : existedColumns) {
        existedColumnNames.add(existedColumn.getName());
      }
    }
    for (Field newColumn : newColumns) {
      if (existedColumnNames.contains(newColumn.getName())) {
        throw new UnsupportedException("Duplicate column name "
            + newColumn.getName() + " in the table definition.");
      }
      existedColumnNames.add(newColumn.getName());
    }
  }

  @Override
  public void checkColumnFamilyName(Collection<Field> existedColumns, Collection<Field> newColumns)
      throws IOException {
    HashSet<String> existedColumnFamilys = new HashSet<String>();
    if (existedColumns != null && !existedColumns.isEmpty()) {
      for (Field existedColumn : existedColumns) {
        existedColumnFamilys.add(existedColumn.getFamily());
      }
    }
    for (Field newColumn : newColumns) {
      if (!existedColumnFamilys.contains(newColumn.getFamily())) {
        throw new UnsupportedException("ColumnFamily '" + newColumn.getFamily()
            + "' not exists and do not support add columnfamily dynamic now.");
      }
    }
  }

  /**
   * check whether the column family name is legal, throw exception if not
   *
   * @param columnFamily
   * @throws java.io.IOException
   */
  @Override
  public void isLegalFamilyName(String columnFamily) throws IOException {
    try {
      HColumnDescriptor.isLegalFamilyName(Bytes.toBytes(columnFamily));
    } catch (Exception e) {
      throw new UnsupportedException("Unsupported ColumnFamily name "
          + columnFamily, e);
    }
  }

  /**
   * Check whether the columns are legal under the given table
   *
   * @param table
   * @param columns
   * @return true if legal
   */
  @Override
  public boolean isLegalDescFields(FTable table, List<String> columns) {
    for (String columnName : columns) {
      if (table.getColumn(columnName).getType() != DataType.DATETIME) {
        return false;
      }
    }
    return true;
  }
}
TOP

Related Classes of com.alibaba.wasp.plan.parser.druid.FMetaEventOperation

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.