/* * Copyright (C) 2016-2020 ActionTech. * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher. */ package com.actiontech.dble.manager.handler; import com.actiontech.dble.DbleServer; import com.actiontech.dble.backend.datasource.PhysicalDataHost; import com.actiontech.dble.backend.datasource.PhysicalDataSource; import com.actiontech.dble.config.ErrorCode; import com.actiontech.dble.manager.ManagerConnection; import com.actiontech.dble.manager.response.SelectMaxAllowedPacket; import com.actiontech.dble.manager.response.SelectSessionTxReadOnly; import com.actiontech.dble.manager.response.ShowSingleString; import com.actiontech.dble.route.parser.ManagerParseSelect; import com.actiontech.dble.server.response.SelectVersionComment; import com.actiontech.dble.sqlengine.TransformSQLJob; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.druid.sql.ast.statement.SQLSelectItem; import com.alibaba.druid.sql.ast.statement.SQLSelectQuery; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.ast.statement.SQLTableSource; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; import com.alibaba.druid.sql.parser.SQLStatementParser; import java.util.Iterator; import static com.actiontech.dble.route.parser.ManagerParseSelect.*; public final class SelectHandler { private SelectHandler() { } public static void handle(String stmt, ManagerConnection c, int offset) { int rs = ManagerParseSelect.parse(stmt, offset); switch (rs & 0xff) { case VERSION_COMMENT: SelectVersionComment.response(c); break; case SESSION_TX_READ_ONLY: SelectSessionTxReadOnly.execute(c, stmt.substring(offset).trim()); break; case SESSION_TRANSACTION_READ_ONLY: SelectSessionTxReadOnly.execute(c, stmt.substring(offset).trim()); break; case MAX_ALLOWED_PACKET: SelectMaxAllowedPacket.execute(c); break; case TIMEDIFF: ShowSingleString.execute(c, stmt.substring(rs >>> 8), "00:00:00"); break; default: if (isSupportSelect(stmt)) { Iterator<PhysicalDataHost> iterator = DbleServer.getInstance().getConfig().getDataHosts().values().iterator(); if (iterator.hasNext()) { PhysicalDataHost pool = iterator.next(); final PhysicalDataSource source = pool.getWriteSource(); TransformSQLJob sqlJob = new TransformSQLJob(stmt, null, source, c); sqlJob.run(); } else { c.writeErrMessage(ErrorCode.ER_YES, "no valid data host"); } } else { c.writeErrMessage(ErrorCode.ER_YES, "Unsupported statement"); } } } private static boolean isSupportSelect(String stmt) { SQLStatementParser parser = new MySqlStatementParser(stmt); SQLStatement statement = parser.parseStatement(); if (!(statement instanceof SQLSelectStatement)) { return false; } SQLSelectQuery sqlSelectQuery = ((SQLSelectStatement) statement).getSelect().getQuery(); if (!(sqlSelectQuery instanceof MySqlSelectQueryBlock)) { return false; } MySqlSelectQueryBlock selectQueryBlock = (MySqlSelectQueryBlock) sqlSelectQuery; SQLTableSource mysqlFrom = selectQueryBlock.getFrom(); if (mysqlFrom != null) { return false; } for (SQLSelectItem item : selectQueryBlock.getSelectList()) { SQLExpr selectItem = item.getExpr(); if (!isVariantRef(selectItem)) { return false; } } return true; } private static boolean isVariantRef(SQLExpr expr) { if (expr instanceof SQLVariantRefExpr) { return true; } else if (expr instanceof SQLPropertyExpr) { return isVariantRef(((SQLPropertyExpr) expr).getOwner()); } else { return false; } } }