/* * Copyright (C) 2014 Jörg Prante * * 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 org.xbib.elasticsearch.common.util; import org.elasticsearch.common.io.Streams; import org.elasticsearch.common.xcontent.support.XContentMapValues; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.regex.Pattern; /** * The SQL command */ public class SQLCommand { private String sql; private static final Pattern STATEMENT_PATTERN = Pattern.compile("^\\s*(update|insert)", Pattern.CASE_INSENSITIVE); private List<Object> params = new LinkedList<>(); private boolean write; private Map<String, Object> register = new HashMap<>(); private boolean callable; public SQLCommand setSQL(String sql) throws IOException { if (sql.endsWith(".sql")) { Reader r = new InputStreamReader(new FileInputStream(sql), "UTF-8"); sql = Streams.copyToString(r); r.close(); } this.sql = sql; return this; } public String getSQL() { return sql; } public SQLCommand setParameters(List<Object> params) { this.params = params; return this; } public List<Object> getParameters() { return params; } public SQLCommand setCallable(boolean callable) { this.callable = callable; return this; } public boolean isCallable() { return callable; } public SQLCommand setWrite(boolean write) { this.write = write; return this; } public boolean isWrite() { return write; } public boolean isQuery() { if (sql == null) { throw new IllegalArgumentException("no SQL found"); } if (write) { return false; } if (STATEMENT_PATTERN.matcher(sql).find()) { return false; } int p1 = sql.toLowerCase().indexOf("select"); if (p1 < 0) { return false; } int p2 = sql.toLowerCase().indexOf("update"); if (p2 < 0) { return true; } int p3 = sql.toLowerCase().indexOf("insert"); return p3 < 0 || p1 < p2 && p1 < p3; } /** * A register is for parameters of a callable statement. * * @param register a map for registering parameters */ public void setRegister(Map<String, Object> register) { this.register = register; } /** * Get the parameters of a callable statement * * @return the register map */ public Map<String, Object> getRegister() { return register; } @SuppressWarnings({"unchecked"}) public static List<SQLCommand> parse(Map<String, Object> settings) { List<SQLCommand> sql = new LinkedList<SQLCommand>(); if (!XContentMapValues.isArray(settings.get("sql"))) { settings.put("sql", Arrays.asList(settings.get("sql"))); } List<Object> list = (List<Object>) settings.get("sql"); for (Object entry : list) { SQLCommand command = new SQLCommand(); try { if (entry instanceof Map) { Map<String, Object> m = (Map<String, Object>) entry; if (m.containsKey("statement")) { command.setSQL((String) m.get("statement")); } if (m.containsKey("parameter")) { command.setParameters(XContentMapValues.extractRawValues("parameter", m)); } if (m.containsKey("write")) { command.setWrite(XContentMapValues.nodeBooleanValue(m.get("write"))); } if (m.containsKey("callable")) { command.setCallable(XContentMapValues.nodeBooleanValue(m.get("callable"))); } if (m.containsKey("register")) { command.setRegister(XContentMapValues.nodeMapValue(m.get("register"), null)); } } else if (entry instanceof String) { command.setSQL((String) entry); } sql.add(command); } catch (IOException e) { throw new IllegalArgumentException("SQL command not found", e); } } return sql; } public String toString() { return "statement=" + sql + " parameter=" + params + " write=" + write + " callable=" + callable; } }