/* * Copyright 2012 - 2014 Anton Tananaev (anton.tananaev@gmail.com) * * 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.traccar.database; import java.sql.*; import java.util.*; import java.util.Date; public class NamedParameterStatement { private final Map> indexMap; private final String parsedQuery; public NamedParameterStatement(String query) { indexMap = new HashMap>(); parsedQuery = parse(query, indexMap); } static String parse(String query, Map> paramMap) { int length = query.length(); StringBuilder parsedQuery = new StringBuilder(length); boolean inSingleQuote = false; boolean inDoubleQuote = false; int index = 1; for(int i = 0; i < length; i++) { char c = query.charAt(i); // String end if (inSingleQuote) { if (c == '\'') inSingleQuote = false; } else if (inDoubleQuote) { if (c == '"') inDoubleQuote = false; } else { // String begin if (c == '\'') { inSingleQuote = true; } else if (c == '"') { inDoubleQuote = true; } else if (c == ':' && i + 1 < length && Character.isJavaIdentifierStart(query.charAt(i + 1))) { // Identifier name int j = i + 2; while (j < length && Character.isJavaIdentifierPart(query.charAt(j))) j++; String name = query.substring(i + 1, j); c = '?'; i += name.length(); // Add to list List indexList = paramMap.get(name); if (indexList == null) { indexList = new LinkedList(); paramMap.put(name, indexList); } indexList.add(index); index++; } } parsedQuery.append(c); } return parsedQuery.toString(); } public PreparedStatement prepare(Connection connection, int autoGeneratedKeys) throws SQLException { return connection.prepareStatement(parsedQuery, autoGeneratedKeys); } public PreparedStatement prepare(Connection connection) throws SQLException { return prepare(connection, Statement.NO_GENERATED_KEYS); } public void setInt(PreparedStatement statement, String name, Integer value) throws SQLException { List indexList = indexMap.get(name); if (indexList != null) for (Integer index: indexList) { if (value != null) { statement.setInt(index, value); } else { statement.setNull(index, Types.INTEGER); } } } public void setLong(PreparedStatement statement, String name, Long value) throws SQLException { List indexList = indexMap.get(name); if (indexList != null) for (Integer index: indexList) { if (value != null) { statement.setLong(index, value); } else { statement.setNull(index, Types.INTEGER); } } } public void setBoolean(PreparedStatement statement, String name, Boolean value) throws SQLException { List indexList = indexMap.get(name); if (indexList != null) for (Integer index: indexList) { if (value != null) { statement.setBoolean(index, value); } else { statement.setNull(index, Types.BOOLEAN); } } } public void setDouble(PreparedStatement statement, String name, Double value) throws SQLException { List indexList = indexMap.get(name); if (indexList != null) for (Integer index: indexList) { if (value != null) { statement.setDouble(index, value); } else { statement.setNull(index, Types.DOUBLE); } } } public void setTimestamp(PreparedStatement statement, String name, Date value) throws SQLException { List indexList = indexMap.get(name); if (indexList != null) for (Integer index: indexList) { if (value != null) { statement.setTimestamp(index, new Timestamp(value.getTime())); } else { statement.setNull(index, Types.TIMESTAMP); } } } public void setString(PreparedStatement statement, String name, String value) throws SQLException { List indexList = indexMap.get(name); if (indexList != null) for (Integer index: indexList) { if (value != null) { statement.setString(index, value); } else { statement.setNull(index, Types.VARCHAR); } } } }