com.taobao.tdhs.jdbc.TDHSStatement.java Source code

Java tutorial

Introduction

Here is the source code for com.taobao.tdhs.jdbc.TDHSStatement.java

Source

/*
 * Copyright(C) 2011-2012 Alibaba Group Holding Limited
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 *
 *  Authors:
 *    wentong <wentong@taobao.com>
 */

package com.taobao.tdhs.jdbc;

import com.taobao.tdhs.client.TDHSClient;
import com.taobao.tdhs.client.common.TDHSCommon;
import com.taobao.tdhs.client.easy.Insert;
import com.taobao.tdhs.client.easy.Query;
import com.taobao.tdhs.client.easy.Where;
import com.taobao.tdhs.client.exception.TDHSException;
import com.taobao.tdhs.client.response.TDHSMySQLResultSetWrap;
import com.taobao.tdhs.client.response.TDHSResponse;
import com.taobao.tdhs.client.response.TDHSResponseEnum;
import com.taobao.tdhs.client.response.TDHSResultSet;
import com.taobao.tdhs.client.statement.BatchStatement;
import com.taobao.tdhs.jdbc.exception.TDHSSQLException;
import com.taobao.tdhs.jdbc.sqlparser.*;
import com.taobao.tdhs.jdbc.util.ConvertUtil;
import com.taobao.tdhs.jdbc.util.StringUtil;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.*;
import java.util.*;

/**
 * @author <a href="mailto:wentong@taobao.com"></a>
 * @since 12-3-8 ?9:12
 */
public class TDHSStatement implements Statement {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private final Connection connection;

    private final TDHSClient client;

    private final String db;

    private boolean close = false;

    private ResultSet currentResultSet = null;

    private int updateCount = -1;

    private BatchStatement batchStatement = null;

    protected final Map<Integer, byte[]> byteParameters = new HashMap<Integer, byte[]>();

    protected final static String BYTE_PARAMETER_PREFIX = "___________________";

    public TDHSStatement(Connection connection, TDHSClient client, String db) {
        this.connection = connection;
        this.client = client;
        this.db = db;
    }

    public ResultSet executeQuery(String sql) throws SQLException {
        execute(sql);
        if (currentResultSet == null) {
            throw new TDHSSQLException("None ResultSet!", sql);
        }
        return currentResultSet;
    }

    private void doSelectOrCount(com.taobao.tdhs.client.statement.Statement s, ParseSQL parseSQL, String tableName,
            String dbName) throws SQLException {
        Query query = preprocessGet(s, parseSQL, tableName, dbName);
        List<Entry<String, String>> columns = parseSQL.getColumns();
        if (columns == null || columns.isEmpty()) {
            throw new TDHSSQLException("no columns to select!", parseSQL.getSql());
        }
        String[] field = new String[columns.size()];
        String[] alias = new String[columns.size()];
        int i = 0;
        for (Entry<String, String> e : columns) {
            String f = StringUtil.escapeField(e.getValue());
            if (f == null) {
                throw new TDHSSQLException("error in field[" + e.getValue() + "]", parseSQL.getSql());
            }
            field[i] = f;
            String a = StringUtil.escapeField(e.getKey());
            if (a == null) {
                throw new TDHSSQLException("error in alias[" + e.getKey() + "]", parseSQL.getSql());
            }
            alias[i++] = a;
        }
        if (field.length == 1 && field[0].equalsIgnoreCase("count(*)")
                && !columns.get(0).getValue().startsWith("`")) {
            TDHSResponse response = null;
            try {
                response = query.count();
            } catch (TDHSException e) {
                throw new SQLException(e);
            }
            processResponse(response, alias, false, false);

        } else {
            query.select(field);
            TDHSResponse response = null;
            try {
                response = query.get();
            } catch (TDHSException e) {
                throw new SQLException(e);
            }
            processResponse(response, alias, false, false);
        }
    }

    private Query preprocessGet(com.taobao.tdhs.client.statement.Statement s, ParseSQL parseSQL, String tableName,
            String dbName) throws TDHSSQLException {
        Query query = s.query().use(dbName).from(tableName);
        List<OperationStruct> operation = parseSQL.getListOperationStructs();
        if (StringUtils.isNotBlank(parseSQL.getErrmsg())) {
            throw new TDHSSQLException(parseSQL.getErrmsg(), parseSQL.getSql());
        }
        if (operation == null || operation.isEmpty()) {
            throw new TDHSSQLException("must have some where condition!", parseSQL.getSql());
        }
        List<OperationStruct> keys = new ArrayList<OperationStruct>(2);
        HintStruct hint = parseSQL.getHint();
        if (hint != null && StringUtils.isBlank(hint.getErrmsg()) && StringUtils.isNotBlank(hint.getIndexName())) {
            String index = hint.getIndexName();
            List<String> listIndexColumns = hint.getListIndexColumns();
            if (listIndexColumns == null || listIndexColumns.isEmpty()) {
                throw new TDHSSQLException("can't get columns from hint", parseSQL.getSql());
            }
            Map<String, List<OperationStruct>> mapOperationStructs = parseSQL.getMapOperationStructs();
            for (String hintKey : listIndexColumns) {
                List<OperationStruct> k = mapOperationStructs.get(hintKey);
                if ((k == null || k.isEmpty())) {
                    if (keys.isEmpty()) {
                        throw new TDHSSQLException("don't find key in Index!", parseSQL.getSql());
                    } else {
                        break;
                    }
                }
                if (keys.isEmpty()) {
                    keys.add(k.get(0));
                    if ("in".equalsIgnoreCase(k.get(0).getOper())) {
                        //in???
                        break;
                    }
                } else {
                    if (keys.get(0).getOper().equalsIgnoreCase(k.get(0).getOper())) {
                        keys.add(k.get(0));
                    } else {
                        break;
                    }
                }
            }

            List<String> orderByColumn = parseSQL.getOrderByColumn();
            if (!keys.get(0).getOper().equalsIgnoreCase("=")
                    && ((orderByColumn != null && !orderByColumn.isEmpty()) || parseSQL.getSortMethod() != null)) {
                throw new TDHSSQLException("can't support this orderBy!", parseSQL.getSql());
            }

            if (orderByColumn != null) {
                if (orderByColumn.size() > listIndexColumns.size()) {
                    throw new TDHSSQLException("too many orderBy columns for this index!", parseSQL.getSql());
                }
                int j = 0;
                for (String oc : orderByColumn) {
                    String indexField = listIndexColumns.get(listIndexColumns.size() - orderByColumn.size() + j);
                    if (!indexField.equalsIgnoreCase(oc)) {
                        throw new TDHSSQLException(
                                "can't support this orderBy columns which is not in index or error sort!",
                                parseSQL.getSql());
                    }

                }
            }
            Where where = query.where().index(index);
            processKey(parseSQL, keys, where);
        } else {
            if (hint != null && StringUtils.isNotBlank(hint.getErrmsg())) {
                logger.warn("TDHS: JDBC hint error:" + hint.getErrmsg() + " , SQL:" + parseSQL.getSql());
            }
            List<String> orderByColumn = parseSQL.getOrderByColumn();
            if ((orderByColumn != null && !orderByColumn.isEmpty()) || parseSQL.getSortMethod() != null) {
                throw new TDHSSQLException("can't support orderBy without hint!", parseSQL.getSql());
            }
            OperationStruct firstKey = operation.get(0);
            keys.add(firstKey);
            String firstField = StringUtil.escapeField(firstKey.getColumnName());
            if (firstField == null) {
                throw new TDHSSQLException("error field [" + firstKey.getColumnName() + "]", parseSQL.getSql());
            }
            Where where = query.where().fields(firstField);
            processKey(parseSQL, keys, where);

        }

        for (OperationStruct o : operation) {
            if (!keys.contains(o)) {
                String op = o.getOper();
                if ("=".equalsIgnoreCase(op)) {
                    PerprocessFilter perprocessFilter = new PerprocessFilter(parseSQL, o).invoke();
                    String f = perprocessFilter.getF();
                    String v = perprocessFilter.getV();
                    query.and().field(f).equal(v);
                } else if ("!=".equalsIgnoreCase(op)) {
                    PerprocessFilter perprocessFilter = new PerprocessFilter(parseSQL, o).invoke();
                    String f = perprocessFilter.getF();
                    String v = perprocessFilter.getV();
                    query.and().field(f).not(v);
                } else if (">".equalsIgnoreCase(op)) {
                    PerprocessFilter perprocessFilter = new PerprocessFilter(parseSQL, o).invoke();
                    String f = perprocessFilter.getF();
                    String v = perprocessFilter.getV();
                    query.and().field(f).greaterThan(v);
                } else if (">=".equalsIgnoreCase(op)) {
                    PerprocessFilter perprocessFilter = new PerprocessFilter(parseSQL, o).invoke();
                    String f = perprocessFilter.getF();
                    String v = perprocessFilter.getV();
                    query.and().field(f).greaterEqual(v);
                } else if ("<".equalsIgnoreCase(op)) {
                    PerprocessFilter perprocessFilter = new PerprocessFilter(parseSQL, o).invoke();
                    String f = perprocessFilter.getF();
                    String v = perprocessFilter.getV();
                    query.and().field(f).lessThan(v);
                } else if ("<=".equalsIgnoreCase(op)) {
                    PerprocessFilter perprocessFilter = new PerprocessFilter(parseSQL, o).invoke();
                    String f = perprocessFilter.getF();
                    String v = perprocessFilter.getV();
                    query.and().field(f).lessEqual(v);
                } else if ("in".equalsIgnoreCase(op)) {
                    throw new TDHSSQLException("can't support IN in this postion!", parseSQL.getSql());
                } else {
                    throw new TDHSSQLException("error operation!", parseSQL.getSql());
                }

            }
        }

        int limit = parseSQL.getLimit();
        int start = parseSQL.getLimitOffset();
        if (limit < 0 || start < 0) {
            throw new TDHSSQLException("limit can't be negative!", parseSQL.getSql());
        }
        query.limit(start, limit);
        return query;
    }

    private void processKey(ParseSQL parseSQL, List<OperationStruct> keys, Where where) throws TDHSSQLException {
        String firstKeyOper = keys.get(0).getOper();
        if ("=".equalsIgnoreCase(firstKeyOper)) {
            if (OrderByType.DESC.equals(parseSQL.getSortMethod())) {
                where.descEqual(parseKeys(parseSQL, keys));
            } else {
                where.equal(parseKeys(parseSQL, keys));
            }
        } else if (">".equalsIgnoreCase(firstKeyOper)) {
            where.greaterThan(parseKeys(parseSQL, keys));
        } else if (">=".equalsIgnoreCase(firstKeyOper)) {
            where.greaterEqual(parseKeys(parseSQL, keys));
        } else if ("<".equalsIgnoreCase(firstKeyOper)) {
            where.lessThan(parseKeys(parseSQL, keys));
        } else if ("<=".equalsIgnoreCase(firstKeyOper)) {
            where.lessEqual(parseKeys(parseSQL, keys));
        } else if ("in".equalsIgnoreCase(firstKeyOper)) {
            String[] in = StringUtil.escapeIn(keys.get(0).getValue());
            if (in == null || in.length == 0) {
                throw new TDHSSQLException("don't have in values!", parseSQL.getSql());
            }
            String[][] inv = new String[in.length][1];
            int i = 0;
            for (String[] a : inv) {
                a[0] = in[i++];
            }
            where.in(inv);
        } else {
            throw new TDHSSQLException("error operation!", parseSQL.getSql());
        }
    }

    private String[] parseKeys(ParseSQL parseSQL, List<OperationStruct> keys) throws TDHSSQLException {
        String kk[] = new String[keys.size()];
        int i = 0;
        for (OperationStruct os : keys) {
            String s = StringUtil.escapeValue(os.getValue());
            if (s == null) {
                throw new TDHSSQLException("error value in index!", parseSQL.getSql());
            }
            kk[i++] = s;
        }
        return kk;
    }

    private void doDelete(com.taobao.tdhs.client.statement.Statement s, ParseSQL parseSQL, String tableName,
            String dbName) throws SQLException {
        Query query = preprocessGet(s, parseSQL, tableName, dbName);
        TDHSResponse response = null;
        try {
            response = query.delete();
        } catch (TDHSException e) {
            throw new SQLException(e);
        }
        processResponse(response, true);
    }

    private void doUpdate(com.taobao.tdhs.client.statement.Statement s, ParseSQL parseSQL, String tableName,
            String dbName) throws SQLException {
        Query query = preprocessGet(s, parseSQL, tableName, dbName);
        List<Entry<String, String>> updateEntries = parseSQL.getUpdateEntries();
        if (updateEntries == null || updateEntries.isEmpty()) {
            throw new TDHSSQLException("no value to update!", parseSQL.getSql());
        }

        for (Entry<String, String> e : updateEntries) {
            if (StringUtils.isBlank(e.getKey()) || StringUtils.isBlank(e.getValue())) {
                throw new TDHSSQLException("insert column and values can't be empty!", parseSQL.getSql());
            }
            String field = StringUtil.escapeField(StringUtils.trim(e.getKey()));
            if (field == null) {
                throw new TDHSSQLException("insert column is error!", parseSQL.getSql());
            }
            String value = StringUtils.trim(e.getValue());
            if (StringUtils.equalsIgnoreCase("null", value)) {
                query.set().field(field).setNull();
            } else if (StringUtils.equalsIgnoreCase("now()", value)) {
                query.set().field(field).setNow();
            } else {
                if (StringUtils.startsWith(value, field)) {
                    value = value.substring(field.length());
                    value = StringUtils.trim(value);
                    if (StringUtils.startsWith(value, "+")) {
                        value = value.substring(1);
                        value = StringUtils.trim(value);
                        if (StringUtil.isLong(value)) {
                            query.set().field(field).add(Long.valueOf(value));
                        } else {
                            throw new TDHSSQLException("update value is error ,is not long", parseSQL.getSql());
                        }
                    } else if (StringUtils.startsWith(value, "-")) {
                        value = value.substring(1);
                        value = StringUtils.trim(value);
                        if (StringUtil.isLong(value)) {
                            query.set().field(field).sub(Long.valueOf(value));
                        } else {
                            throw new TDHSSQLException("update value is error ,is not long", parseSQL.getSql());
                        }

                    } else {
                        throw new TDHSSQLException("update value is error maybe can't support!", parseSQL.getSql());
                    }
                } else {
                    value = StringUtil.escapeValue(value);
                    if (value == null) {
                        throw new TDHSSQLException("update value is error!", parseSQL.getSql());
                    }

                    if (StringUtils.startsWith(value, BYTE_PARAMETER_PREFIX)) {
                        int pidx = ConvertUtil
                                .safeConvertInt(StringUtils.substring(value, BYTE_PARAMETER_PREFIX.length()), -1);
                        if (byteParameters.containsKey(pidx)) {
                            query.set().field(field).set(byteParameters.get(pidx));
                        } else {
                            query.set().field(field).set(value);
                        }
                    } else {
                        query.set().field(field).set(value);
                    }
                }
            }
        }
        TDHSResponse response = null;
        try {
            response = query.update();
        } catch (TDHSException e) {
            throw new SQLException(e);
        }
        processResponse(response, true);
    }

    private void doInsert(com.taobao.tdhs.client.statement.Statement s, ParseSQL parseSQL, String tableName,
            String dbName) throws SQLException {
        Insert insert = s.insert().use(dbName).from(tableName);
        List<Entry<String, String>> insertEntries = parseSQL.getInsertEntries();
        if (insertEntries == null || insertEntries.isEmpty()) {
            throw new TDHSSQLException("no value to insert!", parseSQL.getSql());
        }
        for (Entry<String, String> e : insertEntries) {
            if (StringUtils.isBlank(e.getKey()) || StringUtils.isBlank(e.getValue())) {
                throw new TDHSSQLException("insert column and values can't be empty!", parseSQL.getSql());
            }
            String field = StringUtil.escapeField(StringUtils.trim(e.getKey()));
            if (field == null) {
                throw new TDHSSQLException("insert column is error!", parseSQL.getSql());
            }
            String value = StringUtils.trim(e.getValue());
            if (StringUtils.equalsIgnoreCase("null", value)) {
                insert.valueSetNull(field);
            } else if (StringUtils.equalsIgnoreCase("now()", value)) {
                insert.valueSetNow(field);
            } else {
                value = StringUtil.escapeValue(value);
                if (value == null) {
                    throw new TDHSSQLException("insert value is error!", parseSQL.getSql());
                }
                if (StringUtils.startsWith(value, BYTE_PARAMETER_PREFIX)) {
                    int pidx = ConvertUtil
                            .safeConvertInt(StringUtils.substring(value, BYTE_PARAMETER_PREFIX.length()), -1);
                    if (byteParameters.containsKey(pidx)) {
                        insert.value(field, byteParameters.get(pidx));
                    } else {
                        insert.value(field, value);
                    }
                } else {
                    insert.value(field, value);
                }
            }
        }
        TDHSResponse response = null;
        try {
            response = insert.insert();
        } catch (TDHSException e) {
            throw new SQLException(e);
        }
        processResponse(response, null, true, true);
    }

    protected void processResponse(TDHSResponse response, boolean isModify) throws SQLException {
        processResponse(response, null, isModify, false);
    }

    protected void processResponse(TDHSResponse response, @Nullable String[] alias, boolean isModify,
            boolean isInsert) throws SQLException {
        if (batchStatement != null) {
            return;
        }
        if (response == null) {
            throw new SQLException("None response!");
        }
        try {
            if (!TDHSResponseEnum.ClientStatus.OK.equals(response.getStatus())) {
                if (TDHSResponseEnum.ClientStatus.DB_ERROR.equals(response.getStatus())) {
                    throw new SQLException(
                            "DB Handler return error code [" + response.getMySQLHandlerErrorCode() + "]");
                } else {
                    throw new SQLException("return error [" + response.getErrorCode() + "]");
                }
            } else {
                TDHSResultSet resultSet;
                if (alias != null) {
                    resultSet = (TDHSResultSet) response.getResultSet(Arrays.asList(alias));
                } else {
                    resultSet = (TDHSResultSet) response.getResultSet();
                }
                currentResultSet = resultSet != null ? new TDHSMySQLResultSetWrap(resultSet) : null;
                if (isModify) {
                    updateCount = isInsert ? 1
                            : ConvertUtil.safeConvertInt(response.getFieldData().get(0).get(0), -1);
                } else {
                    updateCount = -1;
                }
            }
        } catch (Exception e) {
            throw new SQLException(e);
        }
    }

    public int executeUpdate(String sql) throws SQLException {
        execute(sql);
        return updateCount;
    }

    protected void checkclose() throws SQLException {
        if (isClosed() || getConnection().isClosed()) {
            throw new SQLException("This statement is closed!");
        }
    }

    protected void reset() throws SQLException {
        currentResultSet = null;
        updateCount = -1;
        clearBatch();
    }

    public void close() throws SQLException {
        close = true;
        reset();
    }

    public int getMaxFieldSize() throws SQLException {
        return TDHSCommon.REQUEST_MAX_FIELD_NUM;
    }

    public void setMaxFieldSize(int max) throws SQLException {
        throw new SQLFeatureNotSupportedException();
    }

    public int getMaxRows() throws SQLException {
        return 0;
    }

    public void setMaxRows(int max) throws SQLException {
        throw new SQLFeatureNotSupportedException();
    }

    public void setEscapeProcessing(boolean enable) throws SQLException {
    }

    public int getQueryTimeout() throws SQLException {
        return Integer.parseInt(connection.getClientInfo(NonRegisteringDriver.TIME_OUT_PROPERTY_KEY));
    }

    public void setQueryTimeout(int seconds) throws SQLException {
        logger.info("setQueryTimeout will be ignore!");
        //        throw new SQLFeatureNotSupportedException();
    }

    public void cancel() throws SQLException {
        throw new SQLFeatureNotSupportedException();
    }

    public SQLWarning getWarnings() throws SQLException {
        return null;
    }

    public void clearWarnings() throws SQLException {
    }

    public void setCursorName(String name) throws SQLException {
        throw new SQLFeatureNotSupportedException();
    }

    public boolean execute(String sql) throws SQLException {
        checkclose();
        reset();
        if (StringUtils.isBlank(sql)) {
            throw new SQLException("sql can't be null!");
        }
        PreproccessSQL preproccessSQL = new PreproccessSQL(sql).invoke();
        ParseSQL parseSQL = preproccessSQL.getParseSQL();
        String tableName = preproccessSQL.getTableName();
        String dbName = preproccessSQL.getDbName();
        if (getConnection().isReadOnly() && !SQLType.SELECT.equals(parseSQL.getSqlType())) {
            throw new TDHSSQLException(
                    "It is readonly, can't executeSelect " + parseSQL.getSqlType().toString() + " !", sql);
        }
        com.taobao.tdhs.client.statement.Statement s;
        HintStruct hint = parseSQL.getHint();
        if (hint != null && StringUtils.isBlank(hint.getErrmsg())) {
            s = client.createStatement(hint.getHash());
        } else {
            s = client;
        }

        switch (parseSQL.getSqlType()) {
        case INSERT:
            doInsert(s, parseSQL, tableName, dbName);
            return false;
        case UPDATE:
            doUpdate(s, parseSQL, tableName, dbName);
            return false;
        case DELETE:
            doDelete(s, parseSQL, tableName, dbName);
            return false;
        case SELECT:
            doSelectOrCount(s, parseSQL, tableName, dbName);
            return true;
        default:
            throw new TDHSSQLException("can't parse this SQL!", sql);
        }
    }

    public ResultSet getResultSet() throws SQLException {
        checkclose();
        return currentResultSet;
    }

    public int getUpdateCount() throws SQLException {
        checkclose();
        return updateCount;
    }

    public boolean getMoreResults() throws SQLException {
        return false;
    }

    public void setFetchDirection(int direction) throws SQLException {
        throw new SQLFeatureNotSupportedException();
    }

    public int getFetchDirection() throws SQLException {
        return ResultSet.FETCH_FORWARD;
    }

    public void setFetchSize(int rows) throws SQLException {
        throw new SQLFeatureNotSupportedException();
    }

    public int getFetchSize() throws SQLException {
        throw new SQLFeatureNotSupportedException();
    }

    public int getResultSetConcurrency() throws SQLException {
        return ResultSet.CONCUR_READ_ONLY;
    }

    public int getResultSetType() throws SQLException {
        return ResultSet.TYPE_FORWARD_ONLY;
    }

    public void addBatch(String sql) throws SQLException {
        checkclose();
        if (StringUtils.isBlank(sql)) {
            throw new SQLException("sql can't be null!");
        }
        if (batchStatement == null) {
            batchStatement = client.createBatchStatement();
        }
        PreproccessSQL preproccessSQL = new PreproccessSQL(sql).invoke();
        ParseSQL parseSQL = preproccessSQL.getParseSQL();
        String tableName = preproccessSQL.getTableName();
        String dbName = preproccessSQL.getDbName();
        switch (parseSQL.getSqlType()) {
        case INSERT:
            doInsert(batchStatement, parseSQL, tableName, dbName);
            break;
        case UPDATE:
            doUpdate(batchStatement, parseSQL, tableName, dbName);
            break;
        case DELETE:
            doDelete(batchStatement, parseSQL, tableName, dbName);
            break;
        case SELECT:
            throw new TDHSSQLException("add batch not support select!", sql);
        default:
            throw new TDHSSQLException("can't parse this SQL!", sql);
        }
    }

    public void clearBatch() throws SQLException {
        batchStatement = null;
    }

    public int[] executeBatch() throws SQLException {
        checkclose();
        BatchStatement b = batchStatement;
        reset();

        TDHSResponse[] responses = null;
        try {
            responses = b.commit();
        } catch (TDHSException e) {
            throw new SQLException(e);
        }
        int[] result = new int[responses.length];
        StringBuilder expString = new StringBuilder();
        boolean success = true;
        int i = 0;
        try {
            for (TDHSResponse r : responses) {
                if (!r.getStatus().equals(TDHSResponseEnum.ClientStatus.OK)) {
                    success = false;
                    expString.append(r).append("|");
                } else {
                    result[i++] = ConvertUtil.safeConvertInt(r.getFieldData().get(0).get(0), -1);
                }
            }
        } catch (TDHSException e) {
            throw new SQLException(e);
        }
        if (!success) {
            throw new SQLException(expString.toString());
        }
        return result;
    }

    public Connection getConnection() throws SQLException {
        return connection;
    }

    public boolean getMoreResults(int current) throws SQLException {
        checkclose();
        return false;
    }

    public ResultSet getGeneratedKeys() throws SQLException {
        throw new SQLFeatureNotSupportedException();
    }

    public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
        if (autoGeneratedKeys == Statement.RETURN_GENERATED_KEYS) {
            throw new SQLFeatureNotSupportedException();
        }
        return executeUpdate(sql);
    }

    public int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
        if (columnIndexes != null && columnIndexes.length > 0) {
            throw new SQLFeatureNotSupportedException();
        }
        return executeUpdate(sql);
    }

    public int executeUpdate(String sql, String[] columnNames) throws SQLException {
        if (columnNames != null && columnNames.length > 0) {
            throw new SQLFeatureNotSupportedException();
        }
        return executeUpdate(sql);
    }

    public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
        if (autoGeneratedKeys == Statement.RETURN_GENERATED_KEYS) {
            throw new SQLFeatureNotSupportedException();
        }
        return execute(sql);
    }

    public boolean execute(String sql, int[] columnIndexes) throws SQLException {
        if (columnIndexes != null && columnIndexes.length > 0) {
            throw new SQLFeatureNotSupportedException();
        }
        return execute(sql);
    }

    public boolean execute(String sql, String[] columnNames) throws SQLException {
        if (columnNames != null && columnNames.length > 0) {
            throw new SQLFeatureNotSupportedException();
        }
        return execute(sql);
    }

    public int getResultSetHoldability() throws SQLException {
        return ResultSet.CLOSE_CURSORS_AT_COMMIT;
    }

    public boolean isClosed() throws SQLException {
        return this.close || getConnection().isClosed();
    }

    public void setPoolable(boolean poolable) throws SQLException {
        throw new SQLFeatureNotSupportedException();
    }

    public boolean isPoolable() throws SQLException {
        throw new SQLFeatureNotSupportedException();
    }

    public void closeOnCompletion() throws SQLException {
        throw new SQLFeatureNotSupportedException();
    }

    public boolean isCloseOnCompletion() throws SQLException {
        throw new SQLFeatureNotSupportedException();
    }

    public <T> T unwrap(Class<T> iface) throws SQLException {
        try {
            // This works for classes that aren't actually wrapping
            // anything
            return iface.cast(this);
        } catch (ClassCastException cce) {
            throw new SQLException(cce);
        }
    }

    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return iface.isInstance(this);
    }

    protected class PreproccessSQL {
        private String sql;
        private ParseSQL parseSQL;
        private String tableName;
        private String dbName;

        public PreproccessSQL(@NotNull String sql) {
            this.sql = sql;
        }

        public ParseSQL getParseSQL() {
            return parseSQL;
        }

        public String getTableName() {
            return tableName;
        }

        public String getDbName() {
            return dbName;
        }

        public PreproccessSQL invoke() throws SQLException {
            parseSQL = parseSQL(sql);
            tableName = StringUtil.escapeField(parseSQL.getTableName());
            if (tableName == null) {
                throw new TDHSSQLException("can't parse table name!", sql);
            }
            dbName = db;
            if (StringUtils.contains(tableName, ".")) {
                String[] strings = StringUtils.split(tableName, ".");
                if (strings.length == 2) {
                    dbName = strings[0];
                    tableName = strings[1];
                } else if (strings.length == 1) {
                    tableName = strings[0];
                } else {
                    throw new TDHSSQLException("can't parse table!", sql);
                }
            }
            if (StringUtils.isBlank(dbName) || StringUtils.isBlank(tableName)) {
                throw new TDHSSQLException("can't parse table!", sql);
            }
            return this;
        }

        private ParseSQL parseSQL(@NotNull String sql) throws SQLException {
            ParseSQL parseSQL = new ParseSQL(sql);
            parseSQL.sqlDispatch();
            if (StringUtils.isNotBlank(parseSQL.getErrmsg())) {
                throw new TDHSSQLException("message:" + parseSQL.getErrmsg(), sql);
            }
            if (StringUtils.isBlank(parseSQL.getTableName())) {
                throw new TDHSSQLException("don't have table!", sql);
            }
            return parseSQL;
        }
    }

    private class PerprocessFilter {
        private ParseSQL parseSQL;
        private OperationStruct o;
        private String f;
        private String v;

        public PerprocessFilter(ParseSQL parseSQL, OperationStruct o) {
            this.parseSQL = parseSQL;
            this.o = o;
        }

        public String getF() {
            return f;
        }

        public String getV() {
            return v;
        }

        public PerprocessFilter invoke() throws TDHSSQLException {
            f = StringUtil.escapeField(o.getColumnName());
            if (f == null) {
                throw new TDHSSQLException("error column [" + o.getColumnName() + "]", parseSQL.getSql());
            }
            v = StringUtil.escapeValue(o.getValue());
            if (v == null) {
                throw new TDHSSQLException("error value [" + o.getValue() + "]", parseSQL.getSql());
            }
            return this;
        }
    }
}