Package com.github.youtube.vitess.jdbc.vtocc

Source Code of com.github.youtube.vitess.jdbc.vtocc.VtoccStatementHandler

package com.github.youtube.vitess.jdbc.vtocc;

import com.google.common.annotations.VisibleForTesting;
import com.google.protobuf.RpcController;
import com.google.protobuf.ServiceException;

import com.github.youtube.vitess.jdbc.vtocc.AcolyteRowList.Factory;
import com.github.youtube.vitess.jdbc.vtocc.QueryService.Query;
import com.github.youtube.vitess.jdbc.vtocc.QueryService.SqlQuery;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.regex.Pattern;

import javax.inject.Inject;

import acolyte.QueryResult;
import acolyte.StatementHandler;
import acolyte.UpdateResult;

/**
* Implementation of {@link StatementHandler} that glues Acolyte to {@link SqlQuery} calls.
*
* Instances are only called from within {@link acolyte.Driver}, contract is not well defined
* therefore there are no unit tests. This code is tested as a part of integration tests running SQL
* queries through JDBC.
*/
public class VtoccStatementHandler implements StatementHandler {

  private static final Pattern selectQueryPattern =
      Pattern.compile("^\\s*SELECT.*", Pattern.CASE_INSENSITIVE);
  private static final Pattern updateWhenNonSelectQueryPattern = Pattern.compile("^\\s*\\w.*");
  private final Logger LOGGER = LoggerFactory.getLogger(VtoccStatementHandler.class);
  private final VtoccQueryFactory vtoccQueryFactory;
  private final Factory acolyteRowListFactory;
  private final SqlQuery.BlockingInterface sqlQueryBlockingInterface;


  private final com.google.inject.Provider<RpcController> rpcControllerProvider;


  @Inject
  @VisibleForTesting
  VtoccStatementHandler(VtoccQueryFactory vtoccQueryFactory,
      Factory acolyteRowListFactory, SqlQuery.BlockingInterface sqlQueryBlockingInterface,
      com.google.inject.Provider<RpcController> rpcControllerProvider) {
    this.vtoccQueryFactory = vtoccQueryFactory;
    this.acolyteRowListFactory = acolyteRowListFactory;
    this.sqlQueryBlockingInterface = sqlQueryBlockingInterface;
    this.rpcControllerProvider = rpcControllerProvider;
  }

  /**
   * Called by Acolyte when it's time to do a query.
   */
  @Override
  public QueryResult whenSQLQuery(String sql, List<Parameter> parameters) throws SQLException {
    try {
      Query query = vtoccQueryFactory.create(sql, parameters);
      // TODO(timofeyb): provide rpc controller
      QueryService.QueryResult response = sqlQueryBlockingInterface
          .execute(rpcControllerProvider.get(), query);
      return acolyteRowListFactory.create(response).asResult();
    } catch (ServiceException e) {
      LOGGER.debug("SqlQuery failed: ", e);
      throw VtoccSqlExceptionFactory.getSqlException(e);
    }
  }

  /**
   * Called by Acolyte when it's time to do a DML query.
   */
  @Override
  public UpdateResult whenSQLUpdate(String sql, List<Parameter> parameters) throws SQLException {
    try {
      Query query = vtoccQueryFactory.create(sql, parameters);

      // TODO(timofeyb): provide rpc controller
      QueryService.QueryResult response = sqlQueryBlockingInterface
          .execute(rpcControllerProvider.get(), query);
      return new UpdateResult((int) response.getRowsAffected());
    } catch (ServiceException e) {
      LOGGER.debug("SqlUpdate failed: ", e);
      throw VtoccSqlExceptionFactory.getSqlException(e);
    }
  }

  /**
   * Due to internal structure of current implementation of Acolyte we're required to know in
   * advance if any specific query is a query or a DML operation.
   *
   * Return true for queries, false for DMLs and throws {@link IllegalArgumentException} in all
   * cases when we're not completely sure.
   */
  @Override
  public boolean isQuery(String sql) {
    // TODO(timofeyb): don't call from Acolyte this often, throw unsupported in all cases
    if (selectQueryPattern.matcher(sql).matches()) {
      // check if we have a select in the very beginning
      return true;
    }
    if (updateWhenNonSelectQueryPattern.matcher(sql).matches()) {
      // in case query start with a statement
      return false;
    }
    // in all cases when we're not sure what to do
    throw new IllegalArgumentException("SQL should start with SELECT, UPDATE, etc.");
  }

  @Override
  public ResultSet getGeneratedKeys() {
    throw new UnsupportedOperationException("Generated keys are not supported");
  }
}
TOP

Related Classes of com.github.youtube.vitess.jdbc.vtocc.VtoccStatementHandler

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.