001/* 002 * Copyright (C) 2014 Jörg Prante 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.xbib.elasticsearch.plugin.jdbc.util; 017 018import org.elasticsearch.common.io.Streams; 019import org.elasticsearch.common.xcontent.support.XContentMapValues; 020 021import java.io.FileInputStream; 022import java.io.IOException; 023import java.io.InputStreamReader; 024import java.io.Reader; 025import java.util.Arrays; 026import java.util.LinkedList; 027import java.util.List; 028import java.util.Map; 029import java.util.regex.Pattern; 030 031import static org.elasticsearch.common.collect.Lists.newLinkedList; 032import static org.elasticsearch.common.collect.Maps.newHashMap; 033 034/** 035 * The SQL command 036 */ 037public class SQLCommand { 038 039 private String sql; 040 041 private static final Pattern STATEMENT_PATTERN = Pattern.compile("^\\s*(update|insert)", Pattern.CASE_INSENSITIVE); 042 043 private List<Object> params = newLinkedList(); 044 045 private Map<String, Object> register = newHashMap(); 046 047 private boolean callable; 048 049 public SQLCommand setSQL(String sql) throws IOException { 050 if (sql.endsWith(".sql")) { 051 Reader r = new InputStreamReader(new FileInputStream(sql), "UTF-8"); 052 sql = Streams.copyToString(r); 053 r.close(); 054 } 055 this.sql = sql; 056 return this; 057 } 058 059 public String getSQL() { 060 return sql; 061 } 062 063 public SQLCommand setParameters(List<Object> params) { 064 this.params = params; 065 return this; 066 } 067 068 public List<Object> getParameters() { 069 return params; 070 } 071 072 public SQLCommand setCallable(boolean callable) { 073 this.callable = callable; 074 return this; 075 } 076 077 public boolean isCallable() { 078 return callable; 079 } 080 081 public boolean isQuery() { 082 if (sql == null) { 083 throw new IllegalArgumentException("no SQL found"); 084 } 085 if (STATEMENT_PATTERN.matcher(sql).find()) { 086 return false; 087 } 088 int p1 = sql.toLowerCase().indexOf("select"); 089 if (p1 < 0) { 090 return false; 091 } 092 int p2 = sql.toLowerCase().indexOf("update"); 093 if (p2 < 0) { 094 return true; 095 } 096 int p3 = sql.toLowerCase().indexOf("insert"); 097 return p3 < 0 || p1 < p2 && p1 < p3; 098 } 099 100 /** 101 * A register is for parameters of a callable statement. 102 * 103 * @param register a map for registering parameters 104 */ 105 public void setRegister(Map<String, Object> register) { 106 this.register = register; 107 } 108 109 /** 110 * Get the parameters of a callable statement 111 * 112 * @return the register map 113 */ 114 public Map<String, Object> getRegister() { 115 return register; 116 } 117 118 @SuppressWarnings({"unchecked"}) 119 public static List<SQLCommand> parse(Map<String, Object> settings) { 120 List<SQLCommand> sql = new LinkedList<SQLCommand>(); 121 if (!XContentMapValues.isArray(settings.get("sql"))) { 122 settings.put("sql", Arrays.asList(settings.get("sql"))); 123 } 124 List<Object> list = (List<Object>) settings.get("sql"); 125 for (Object entry : list) { 126 SQLCommand command = new SQLCommand(); 127 try { 128 if (entry instanceof Map) { 129 Map<String, Object> m = (Map<String, Object>) entry; 130 if (m.containsKey("statement")) { 131 command.setSQL((String) m.get("statement")); 132 } 133 if (m.containsKey("parameter")) { 134 command.setParameters(XContentMapValues.extractRawValues("parameter", m)); 135 } 136 if (m.containsKey("callable")) { 137 command.setCallable(XContentMapValues.nodeBooleanValue(m.get("callable"))); 138 } 139 if (m.containsKey("register")) { 140 command.setRegister(XContentMapValues.nodeMapValue(m.get("register"), null)); 141 } 142 } else if (entry instanceof String) { 143 command.setSQL((String) entry); 144 } 145 sql.add(command); 146 } catch (IOException e) { 147 throw new IllegalArgumentException("SQL command not found", e); 148 } 149 } 150 return sql; 151 } 152 153 public String toString() { 154 return "statement=" + sql + " parameter=" + params + " callable=" + callable; 155 } 156 157}