Package cn.paxos.rabbitsnail

Source Code of cn.paxos.rabbitsnail.QueryImpl

package cn.paxos.rabbitsnail;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.persistence.FlushModeType;
import javax.persistence.LockModeType;
import javax.persistence.Parameter;
import javax.persistence.Query;
import javax.persistence.TemporalType;

import org.apache.hadoop.hbase.client.HTableInterface;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.filter.PageFilter;
import org.apache.hadoop.hbase.util.Bytes;

import cn.paxos.rabbitsnail.util.ByteArrayUtils;

public class QueryImpl implements Query {

  private static final Pattern QUERY_PATTERN_FINDING = Pattern.compile("^from[\\s]+([^\\s]+)(?:[\\s]+where[\\s]+(.+))?$");
  private static final Pattern QUERY_PATTERN_UPDATING = Pattern.compile("^update[\\s]+([^\\s]+)[\\s]+set[\\s]+(.+)[\\s]+where[\\s]+(.+)$");
  private static final Pattern SETTING_PATTERN = Pattern.compile("^(.+)=.+$");
  private static final Pattern CONDITION_PATTERN = Pattern.compile("^(.+)([=<>]).+$");

  private static final Map<String, byte[]> INDEX_TO_ROW = new HashMap<String, byte[]>();
 
  private final EntityManagerImpl entityManagerImpl;
  private final String qlString;
  private final Map<Integer, Object> parameters;
 
  private int maxResult;
  private int startPosition;

  public QueryImpl(EntityManagerImpl entityManagerImpl, String qlString) {
    this.entityManagerImpl = entityManagerImpl;
    this.qlString = qlString;
    this.parameters = new HashMap<Integer, Object>();
    this.maxResult = -1;
    this.startPosition = -1;
  }

  @SuppressWarnings({ "rawtypes", "unchecked" })
  @Override
  public List getResultList() {
    Matcher queryMatcher = QUERY_PATTERN_FINDING.matcher(qlString);
    if (!queryMatcher.find()) {
      throw new RuntimeException("Invalid query: " + qlString);
    }
    String entityTypeName = queryMatcher.group(1);
    String whereClause = queryMatcher.group(2);
   
    String startRowHex = null;
    int parameterIndex = 1;
    Entity entityDefinition = entityManagerImpl.getEntities().byName(entityTypeName);
    Scan scan = new Scan();
    if (whereClause != null) {
      String[] conditions = whereClause.split(" and ");
      for (String condition : conditions) {
        Matcher conditionMatcher = CONDITION_PATTERN.matcher(condition.trim());
        conditionMatcher.find();
        String operator = conditionMatcher.group(2);
        if (operator.equals(">")) {
          byte[] startRow = (byte[]) parameters.get(parameterIndex++);
          startRowHex = Bytes.toHex(startRow);
          scan.setStartRow(startRow);
        } else if (operator.equals("<")) {
          scan.setStopRow((byte[]) parameters.get(parameterIndex++));
        } else {
          throw new RuntimeException("Unsupported operator: " + operator);
        }
      }
    }
    boolean toCut = false;
    if (startPosition > -1) {
      String indexedRowKey = entityTypeName + "-" + startRowHex + "-" + (startPosition - 1);
      final byte[] indexedRow;
      synchronized (QueryImpl.class) {
        indexedRow = INDEX_TO_ROW.get(indexedRowKey);
      }
      if (indexedRow == null) {
        scan.setFilter(new PageFilter(startPosition + maxResult));
        toCut = true;
      } else {
        scan.setStartRow(ByteArrayUtils.increaseOne(indexedRow));
        scan.setFilter(new PageFilter(maxResult));
      }
    }
    List results = new LinkedList();
    HTableInterface hTable = null;
    try {
      hTable = entityManagerImpl.getTable(entityDefinition.getTableName());
      ResultScanner rs = hTable.getScanner(scan);
      int rowIndex = -1;
      Result lastResult = null;
      for(Result r : rs) {
        rowIndex++;
        lastResult = r;
        if (toCut && rowIndex < startPosition) {
          continue;
        }
        final Object entity = entityManagerImpl.readEntityFromResult(entityDefinition, r);
        results.add(entity);
      }
      if (startPosition > -1 && lastResult != null) {
        String indexedRowKey = entityTypeName + "-" + startRowHex + "-" + (startPosition + rowIndex);
        synchronized (QueryImpl.class) {
          INDEX_TO_ROW.put(indexedRowKey, lastResult.getRow());
        }
      }
    } catch (Exception e) {
      throw new RuntimeException("Error on querying: " + qlString, e);
    } finally {
      if (hTable != null)
        try {
          hTable.close();
        } catch (Exception e) {}
    }
    return results;
  }

  @Override
  public Object getSingleResult() {
    throw new UnsupportedOperationException();
  }

  @Override
  public int executeUpdate() {
    Matcher queryMatcher = QUERY_PATTERN_UPDATING.matcher(qlString);
    if (!queryMatcher.find()) {
      throw new RuntimeException("Invalid query: " + qlString);
    }
    String entityTypeName = queryMatcher.group(1);
    String setClause = queryMatcher.group(2);
    String whereClause = queryMatcher.group(3);
   
    int parameterIndex = 1;
    Entity entityDefinition = entityManagerImpl.getEntities().byName(entityTypeName);

    List<String> setFields = new LinkedList<String>();
    String[] sets = setClause.split("\\,");
    for (String set : sets) {
      Matcher setMatcher = SETTING_PATTERN.matcher(set.trim());
      setMatcher.find();
      setFields.add(setMatcher.group(1).trim());
      parameterIndex++;
    }
    byte[] id = null;
    String checkingFieldName = null;
    byte[] checkingFieldValue = null;
    String[] conditions = whereClause.split(" and ");
    for (String condition : conditions) {
      Matcher conditionMatcher = CONDITION_PATTERN.matcher(condition.trim());
      conditionMatcher.find();
      String field = conditionMatcher.group(1).trim();
      if (field.equals(entityDefinition.getIdColumn().getName())) {
        id = (byte[]) parameters.get(parameterIndex);
      } else {
        checkingFieldName = field;
        checkingFieldValue = ByteArrayUtils.toBytes(parameters.get(parameterIndex));
      }
      parameterIndex++;
    }

    parameterIndex = 1;
    final Put put = new Put(id);
    for (String setField : setFields) {
      Column column = entityDefinition.getColumn(setField);
      final byte[] columnValueAsBytes = ByteArrayUtils.toBytes(parameters.get(parameterIndex));
      put.add(Bytes.toBytes(column.getColumnFamily()), Bytes.toBytes(column.getColumn()), columnValueAsBytes);
      parameterIndex++;
    }
    HTableInterface hTable = null;
    try {
      hTable = entityManagerImpl.getTable(entityDefinition.getTableName());
      if (checkingFieldName == null) {
        hTable.put(put);
        return 1;
      } else {
        Column checkingColumn = entityDefinition.getColumn(checkingFieldName);
        return hTable.checkAndPut(
            id,
            Bytes.toBytes(checkingColumn.getColumnFamily()),
            Bytes.toBytes(checkingColumn.getColumn()),
            checkingFieldValue,
            put) ? 1 : 0;
      }
    } catch (Exception e) {
      throw new RuntimeException("Error on querying: " + qlString, e);
    } finally {
      if (hTable != null)
        try {
          hTable.close();
        } catch (Exception e) {}
    }
  }

  @Override
  public Query setMaxResults(int maxResult) {
    this.maxResult = maxResult;
    return this;
  }

  @Override
  public Query setFirstResult(int startPosition) {
    this.startPosition = startPosition;
    return this;
  }

  @Override
  public Query setHint(String hintName, Object value) {
    throw new UnsupportedOperationException();
  }

  @Override
  public Query setParameter(String name, Object value) {
    throw new UnsupportedOperationException();
  }

  @Override
  public Query setParameter(String name, Date value, TemporalType temporalType) {
    throw new UnsupportedOperationException();
  }

  @Override
  public Query setParameter(String name, Calendar value,
      TemporalType temporalType) {
    throw new UnsupportedOperationException();
  }

  @Override
  public Query setParameter(int position, Object value) {
    parameters.put(position, value);
    return this;
  }

  @Override
  public Query setParameter(int position, Date value,
      TemporalType temporalType) {
    throw new UnsupportedOperationException();
  }

  @Override
  public Query setParameter(int position, Calendar value,
      TemporalType temporalType) {
    throw new UnsupportedOperationException();
  }

  @Override
  public Query setFlushMode(FlushModeType flushMode) {
    throw new UnsupportedOperationException();
  }
 
  public static void main(String[] args) {
    Matcher matcher = QUERY_PATTERN_FINDING.matcher("from User");
    while (matcher.find()) {
      for (int i = 0; i <= matcher.groupCount(); i++) {
        System.out.println(i + " " + matcher.group(i));
      }
    }
    matcher = QUERY_PATTERN_UPDATING.matcher("update User set name = ?, code = ? where id = ? and name = ?");
    while (matcher.find()) {
      for (int i = 0; i <= matcher.groupCount(); i++) {
        System.out.println(i + " " + matcher.group(i));
      }
    }
  }

  @Override
  public int getMaxResults() {
    throw new UnsupportedOperationException();
  }

  @Override
  public int getFirstResult() {
    throw new UnsupportedOperationException();
  }

  @Override
  public Map<String, Object> getHints() {
    throw new UnsupportedOperationException();
  }

  @Override
  public <T> Query setParameter(Parameter<T> param, T value) {
    throw new UnsupportedOperationException();
  }

  @Override
  public Query setParameter(Parameter<Calendar> param, Calendar value,
      TemporalType temporalType) {
    throw new UnsupportedOperationException();
  }

  @Override
  public Query setParameter(Parameter<Date> param, Date value,
      TemporalType temporalType) {
    throw new UnsupportedOperationException();
  }

  @Override
  public Set<Parameter<?>> getParameters() {
    throw new UnsupportedOperationException();
  }

  @Override
  public Parameter<?> getParameter(String name) {
    throw new UnsupportedOperationException();
  }

  @Override
  public <T> Parameter<T> getParameter(String name, Class<T> type) {
    throw new UnsupportedOperationException();
  }

  @Override
  public Parameter<?> getParameter(int position) {
    throw new UnsupportedOperationException();
  }

  @Override
  public <T> Parameter<T> getParameter(int position, Class<T> type) {
    throw new UnsupportedOperationException();
  }

  @Override
  public boolean isBound(Parameter<?> param) {
    throw new UnsupportedOperationException();
  }

  @Override
  public <T> T getParameterValue(Parameter<T> param) {
    throw new UnsupportedOperationException();
  }

  @Override
  public Object getParameterValue(String name) {
    throw new UnsupportedOperationException();
  }

  @Override
  public Object getParameterValue(int position) {
    throw new UnsupportedOperationException();
  }

  @Override
  public FlushModeType getFlushMode() {
    throw new UnsupportedOperationException();
  }

  @Override
  public Query setLockMode(LockModeType lockMode) {
    throw new UnsupportedOperationException();
  }

  @Override
  public LockModeType getLockMode() {
    throw new UnsupportedOperationException();
  }

  @Override
  public <T> T unwrap(Class<T> cls) {
    throw new UnsupportedOperationException();
  }

}
TOP

Related Classes of cn.paxos.rabbitsnail.QueryImpl

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.