/* * Copyright 1999-2012 Alibaba Group. * * Licensed 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 fm.liu.timo.server.handler; import java.io.UnsupportedEncodingException; import java.sql.SQLSyntaxErrorException; import java.util.ArrayList; import java.util.Collections; import fm.liu.timo.config.ErrorCode; import fm.liu.timo.manager.response.ResponseUtil; import fm.liu.timo.manager.response.ResponseUtil.Head; import fm.liu.timo.mysql.ByteUtil; import fm.liu.timo.mysql.PreparedStatement; import fm.liu.timo.mysql.packet.ExecutePacket; import fm.liu.timo.mysql.packet.OkPacket; import fm.liu.timo.parser.ast.expression.Expression; import fm.liu.timo.parser.ast.expression.primary.UsrDefVarPrimary; import fm.liu.timo.parser.ast.stmt.extension.DropPrepareStatement; import fm.liu.timo.parser.ast.stmt.extension.ExecutePrepareStatement; import fm.liu.timo.parser.ast.stmt.extension.PrepareStatement; import fm.liu.timo.parser.recognizer.SQLParserDelegate; import fm.liu.timo.server.ServerConnection; /** * @author liuhuanting */ public class ServerPrepareHandler { private static final ArrayList<Head> fields = new ArrayList<Head>(); static { fields.add(new Head("n")); } private ServerConnection source; public ServerPrepareHandler(ServerConnection source) { this.source = source; } public void prepare(String sql) { prepare(sql, source); } public void execute(byte[] data) { long pstmtId = ByteUtil.readUB4(data, 5); PreparedStatement pstmt = null; if ((pstmt = source.getPreparedStatement(pstmtId + "")) == null) { source.writeErrMessage(ErrorCode.ER_ERROR_WHEN_EXECUTING_COMMAND, "Unknown pstmtId when executing."); } else { ExecutePacket packet = new ExecutePacket(pstmt); try { packet.read(data, source.getCharset()); } catch (UnsupportedEncodingException e) { source.writeErrMessage(ErrorCode.ER_ERROR_WHEN_EXECUTING_COMMAND, e.getMessage()); return; } execute(packet.getSQL(), source); } } public void close(byte[] data) { long pstmtId = ByteUtil.readUB4(data, 5); source.dropPreparedStatement(pstmtId + ""); source.write(OkPacket.OK); } public static void prepare(String sql, ServerConnection c) { try { PrepareStatement stmt = (PrepareStatement) SQLParserDelegate.parse(sql); c.prepare(stmt); c.write(OkPacket.OK); } catch (SQLSyntaxErrorException e) { c.writeErrMessage(ErrorCode.ER_PARSE_ERROR, e.getMessage()); } } public static void execute(String sql, ServerConnection c) { try { ExecutePrepareStatement stmt = (ExecutePrepareStatement) SQLParserDelegate.parse(sql); PreparedStatement prepare = c.getPreparedStatement(stmt.getName()); if (prepare == null) { c.writeErrMessage(ErrorCode.ER_UNKNOWN_STMT_HANDLER, "unknown prepared statement handler (" + stmt.getName() + ") given to EXECUTE"); } else { StringBuilder sb = new StringBuilder(); String[] stmts = prepare.getStatements(); int length = stmts.length; ArrayList<Object> values = new ArrayList<>(); for (Expression var : stmt.getVars()) { Expression exp = c.getUserVariable(((UsrDefVarPrimary) var).getVarText().toLowerCase()); if (exp != null) { values.add(exp.evaluation(Collections.emptyMap())); } else { ResponseUtil.write(c, fields, null); return; } } if (prepare.isEndsWithQuestionMark()) { if (length != values.size()) { c.writeErrMessage(ErrorCode.ER_WRONG_ARGUMENTS, "Incorrect arguments to EXECUTE"); return; } else { for (int i = 0; i < length; i++) { sb.append(stmts[i]).append(values.get(i).toString()); } } } else { if (length != values.size() + 1) { c.writeErrMessage(ErrorCode.ER_WRONG_ARGUMENTS, "Incorrect arguments to EXECUTE"); return; } else { for (int i = 0; i < length - 1; i++) { sb.append(stmts[i]).append(values.get(i).toString()); } sb.append(stmts[length - 1]); } } c.query(sb.toString()); } } catch (SQLSyntaxErrorException e) { c.writeErrMessage(ErrorCode.ER_PARSE_ERROR, e.getMessage()); } } public static void close(String sql, ServerConnection c) { try { DropPrepareStatement stmt = (DropPrepareStatement) SQLParserDelegate.parse(sql); c.dropPreparedStatement(stmt.getName()); c.write(OkPacket.OK); } catch (SQLSyntaxErrorException e) { c.writeErrMessage(ErrorCode.ER_PARSE_ERROR, e.getMessage()); } } }