void setConfiguredQueries(Map<String, String> replacements, JsonValue queriesConfig) { configured.clear(); for (String queryName : queriesConfig.keys()) { String rawQuery = queriesConfig.get(queryName).required().asString(); TokenHandler tokenHandler = new TokenHandler(); // Replace the table name tokens. String tempQueryString = tokenHandler.replaceSomeTokens(rawQuery, replacements); // Convert to ? for prepared statement, populate token replacement info List<String> tokenNames = tokenHandler.extractTokens(tempQueryString); String queryString = tokenHandler.replaceTokens(tempQueryString, "?", PREFIX_LIST); QueryInfo queryInfo = new QueryInfo(queryString, tokenNames); configured.put(queryName, queryInfo); logger.info( "Configured query converted to JDBC query {} and tokens {}", queryString, tokenNames); } }
/** * Resolves a query filter. * * @param con The db connection * @param filter the query filter to parse * @return A resolved statement */ PreparedStatement parseQueryFilter(Connection con, QueryFilter filter, Map<String, Object> params) throws SQLException, ResourceException { Map<String, Object> replacementTokens = new LinkedHashMap<String, Object>(); String rawQuery = tableHandler.renderQueryFilter(filter, replacementTokens, params); Map<String, String> replacements = new LinkedHashMap<String, String>(); replacements.put("_mainTable", mainTableName); replacements.put("_propTable", propTableName); replacements.put("_dbSchema", dbSchemaName); TokenHandler tokenHandler = new TokenHandler(); // Replace the table name tokens. String tempQueryString = tokenHandler.replaceSomeTokens(rawQuery, replacements); logger.debug("Tokenized statement: {} with replacementTokens: {}", rawQuery, replacementTokens); // Convert to ? for prepared statement, populate token replacement info List<String> tokenNames = tokenHandler.extractTokens(tempQueryString); String queryString = tokenHandler.replaceTokens(tempQueryString, "?", PREFIX_LIST); QueryInfo queryInfo = new QueryInfo(queryString, tokenNames); return resolveQuery(queryInfo, con, replacementTokens); }
/** * Resolves a query, given a QueryInfo * * @param info The info encapsulating the query information * @param con the db connection * @param params the parameters passed to query * @return the resolved query * @throws SQLException if resolving the query failed */ PreparedStatement resolveQuery(QueryInfo info, Connection con, Map<String, Object> params) throws SQLException, ResourceException { String queryStr = info.getQueryString(); List<String> tokenNames = info.getTokenNames(); // replace ${list:variable} tokens with the correct number of bind variables Map<String, Integer> listReplacements = new HashMap<String, Integer>(); for (String tokenName : tokenNames) { String[] tokenParts = tokenName.split(":", 2); if (PREFIX_LIST.equals(tokenParts[0]) && params.containsKey(tokenParts[1])) { listReplacements.put(tokenName, ((String) params.get(tokenParts[1])).split(",").length); } } if (listReplacements.size() > 0) { TokenHandler tokenHandler = new TokenHandler(); queryStr = tokenHandler.replaceListTokens(queryStr, listReplacements, "?"); } // now prepare the statement using the correct number of bind variables PreparedStatement statement = getPreparedStatement(con, queryStr); int count = 1; // DB column count starts at 1 for (String tokenName : tokenNames) { String[] tokenParts = tokenName.split(":", 2); if (tokenParts.length == 1) { // handle single value - assume String Object objValue = params.get(tokenName); String value = null; if (objValue != null) { value = trimValue(objValue); } else { // fail with an exception if token not found throw new BadRequestException( "Missing entry in params passed to query for token " + tokenName); } statement.setString(count, value); count++; } else { Object objValue = params.get(tokenParts[1]); if (objValue == null) { // fail with an exception if token not found throw new BadRequestException( "Missing entry in params passed to query for token " + tokenName); } if (PREFIX_INT.equals(tokenParts[0])) { // handle single integer value Integer int_value = null; if (objValue != null) { int_value = Integer.parseInt(objValue.toString()); } statement.setInt(count, int_value); count++; } else if (PREFIX_LIST.equals(tokenParts[0])) { // handle list of values - presently assumes Strings, TODO support integer lists if (objValue != null) { for (String list_value : objValue.toString().split(",")) { // if list value is surrounded by single quotes remove them if (list_value != null && list_value.startsWith("'") && list_value.endsWith("'")) { list_value = list_value.substring(1, list_value.length() - 1); } statement.setString(count, trimValue(list_value)); count++; } } else { statement.setString(count, null); count++; } } } } logger.debug("Prepared statement: {}", statement); return statement; }