package com.nurkiewicz.jdbcrepository.sql; import com.nurkiewicz.jdbcrepository.TableDescription; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; /** * @author Tomasz Nurkiewicz * @since 12/18/12, 9:18 PM */ public class SqlGenerator { public static final String WHERE = " WHERE "; public static final String AND = " AND "; public static final String OR = " OR "; public static final String SELECT = "SELECT "; public static final String FROM = "FROM "; public static final String DELETE = "DELETE "; public static final String COMMA = ", "; public static final String PARAM = " = ?"; private String allColumnsClause; public SqlGenerator(String allColumnsClause) { this.allColumnsClause = allColumnsClause; } public SqlGenerator() { this("*"); } public String count(TableDescription table) { return SELECT + "COUNT(*) " + FROM + table.getFromClause(); } public String deleteById(TableDescription table) { return DELETE + FROM + table.getName() + whereByIdClause(table); } private String whereByIdClause(TableDescription table) { final StringBuilder whereClause = new StringBuilder(WHERE); for (Iterator<String> idColIterator = table.getIdColumns().iterator(); idColIterator.hasNext(); ) { whereClause.append(idColIterator.next()).append(PARAM); if (idColIterator.hasNext()) { whereClause.append(AND); } } return whereClause.toString(); } private String whereByIdsClause(TableDescription table, int idsCount) { final List<String> idColumnNames = table.getIdColumns(); if (idColumnNames.size() > 1) { return whereByIdsWithMultipleIdColumns(idsCount, idColumnNames); } else { return whereByIdsWithSingleIdColumn(idsCount, idColumnNames.get(0)); } } private String whereByIdsWithMultipleIdColumns(int idsCount, List<String> idColumnNames) { int idColumnsCount = idColumnNames.size(); final StringBuilder whereClause = new StringBuilder(WHERE); final int totalParams = idsCount * idColumnsCount; for (int idColumnIdx = 0; idColumnIdx < totalParams; idColumnIdx += idColumnsCount) { if (idColumnIdx > 0) { whereClause.append(OR); } whereClause.append("("); for (int i = 0; i < idColumnsCount; ++i) { if (i > 0) { whereClause.append(AND); } whereClause.append(idColumnNames.get(i)).append(" = ?"); } whereClause.append(")"); } return whereClause.toString(); } private String whereByIdsWithSingleIdColumn(int idsCount, String idColumn) { final StringBuilder whereClause = new StringBuilder(WHERE); return whereClause. append(idColumn). append(" IN ("). append(repeat("?", COMMA, idsCount)). append(")"). toString(); } public String selectAll(TableDescription table) { return SELECT + allColumnsClause + " " + FROM + table.getFromClause(); } public String selectAll(TableDescription table, Pageable page) { return selectAll(table, page.getSort()) + limitClause(page); } public String selectAll(TableDescription table, Sort sort) { return selectAll(table) + sortingClauseIfRequired(sort); } protected String limitClause(Pageable page) { final int offset = page.getPageNumber() * page.getPageSize(); return " LIMIT " + offset + COMMA + page.getPageSize(); } public String selectById(TableDescription table) { return selectAll(table) + whereByIdClause(table); } public String selectByIds(TableDescription table, int idsCount) { switch (idsCount) { case 0: return selectAll(table); case 1: return selectById(table); default: return selectAll(table) + whereByIdsClause(table, idsCount); } } protected String sortingClauseIfRequired(Sort sort) { if (sort == null) { return ""; } StringBuilder orderByClause = new StringBuilder(); orderByClause.append(" ORDER BY "); for(Iterator<Sort.Order> iterator = sort.iterator(); iterator.hasNext();) { final Sort.Order order = iterator.next(); orderByClause. append(order.getProperty()). append(" "). append(order.getDirection().toString()); if (iterator.hasNext()) { orderByClause.append(COMMA); } } return orderByClause.toString(); } public String update(TableDescription table, Map<String, Object> columns) { final StringBuilder updateQuery = new StringBuilder("UPDATE " + table.getName() + " SET "); for(Iterator<Map.Entry<String,Object>> iterator = columns.entrySet().iterator(); iterator.hasNext();) { Map.Entry<String, Object> column = iterator.next(); updateQuery.append(column.getKey()).append(" = ?"); if (iterator.hasNext()) { updateQuery.append(COMMA); } } updateQuery.append(whereByIdClause(table)); return updateQuery.toString(); } public String create(TableDescription table, Map<String, Object> columns) { final StringBuilder createQuery = new StringBuilder("INSERT INTO " + table.getName() + " ("); appendColumnNames(createQuery, columns.keySet()); createQuery.append(")").append(" VALUES ("); createQuery.append(repeat("?", COMMA, columns.size())); return createQuery.append(")").toString(); } private void appendColumnNames(StringBuilder createQuery, Set<String> columnNames) { for(Iterator<String> iterator = columnNames.iterator(); iterator.hasNext();) { final String column = iterator.next(); createQuery.append(column); if (iterator.hasNext()) { createQuery.append(COMMA); } } } // Unfortunately {@link org.apache.commons.lang3.StringUtils} not available private static String repeat(String s, String separator, int count) { StringBuilder string = new StringBuilder((s.length() + separator.length()) * count); while (--count > 0) { string.append(s).append(separator); } return string.append(s).toString(); } public String deleteAll(TableDescription table) { return DELETE + FROM + table.getName(); } public String countById(TableDescription table) { return count(table) + whereByIdClause(table); } public String getAllColumnsClause() { return allColumnsClause; } }