private static String adaptForNamedParams(String sql, List<Tuple> indexPropList) { StringBuilder newSql = new StringBuilder(); int txtIndex = 0; Matcher matcher = NAMED_QUERY_PATTERN.matcher(sql); while (matcher.find()) { newSql.append(sql.substring(txtIndex, matcher.start())).append('?'); String indexStr = matcher.group(1); if (indexStr == null) indexStr = matcher.group(3); int index = (indexStr == null || indexStr.length() == 0 || ":".equals(indexStr)) ? 0 : Integer.parseInt(indexStr) - 1; String prop = matcher.group(2); if (prop == null) prop = matcher.group(4); indexPropList.add(new Tuple(new Object[]{index, prop == null || prop.length() == 0 ? "<this>" : prop})); txtIndex = matcher.end(); } newSql.append(sql.substring(txtIndex)); // append ending SQL after last param. return newSql.toString(); }
@Override public Tuple maybeMakeImmutable(final String propertyPath, Object propertyValue) { if (!isImmutableProperty(propertyPath)) { getLogger().debug("Mutable property '{}'", propertyPath); return null; } if (semiMutablePropertyPaths.contains(propertyPath)) { getLogger().debug("Semi-mutable property '{}'", propertyPath); return new Tuple(new Object[]{makeSemiMutable(propertyValue)}); } getLogger().debug("Immutable property '{}'", propertyPath); return new Tuple(new Object[]{makeImmutable(propertyValue)}); }
public SqlWithParams checkForNamedParams(String sql, List<Object> params) { SqlWithParams preCheck = buildSqlWithIndexedProps(sql); if (preCheck == null) { return new SqlWithParams(sql, params); } List<Tuple> indexPropList = new ArrayList<Tuple>(); for (Object next : preCheck.getParams()) { indexPropList.add((Tuple) next); } return new SqlWithParams(preCheck.getSql(), getUpdatedParams(params, indexPropList)); }
/** * Hook to allow derived classes to override behavior associated with the * parsing and indexing of parameters from a given sql statement. * * @param sql the sql statement to process * @return a {@link SqlWithParams} instance containing the parsed sql * and parameters containing the indexed location and property * name of parameters or {@code null} if no parsing of * the sql was performed. */ protected SqlWithParams buildSqlWithIndexedProps(String sql) { // look for quick exit if (!enableNamedQueries || !ExtractIndexAndSql.hasNamedParameters(sql)) { return null; } String newSql; List<Tuple> propList; if (cacheNamedQueries && namedParamSqlCache.containsKey(sql)) { newSql = namedParamSqlCache.get(sql); propList = namedParamIndexPropCache.get(sql); } else { ExtractIndexAndSql extractIndexAndSql = ExtractIndexAndSql.from(sql); newSql = extractIndexAndSql.getNewSql(); propList = extractIndexAndSql.getIndexPropList(); namedParamSqlCache.put(sql, newSql); namedParamIndexPropCache.put(sql, propList); } if (sql.equals(newSql)) { return null; } List<Object> indexPropList = new ArrayList<Object>(propList); return new SqlWithParams(newSql, indexPropList); }
public List<Object> getUpdatedParams(List<Object> params, List<Tuple> indexPropList) { List<Object> updatedParams = new ArrayList<Object>(); for (Tuple tuple : indexPropList) { int index = (Integer) tuple.get(0); String prop = (String) tuple.get(1); if (index < 0 || index >= params.size()) throw new IllegalArgumentException("Invalid index " + index + " should be in range 1.." + params.size()); try { updatedParams.add(prop.equals("<this>") ? params.get(index) : InvokerHelper.getProperty(params.get(index), prop)); } catch(MissingPropertyException mpe) { throw new IllegalArgumentException("Property '" + prop + "' not found for parameter " + index); } } return updatedParams; }
private ExtractIndexAndSql invoke() { indexPropList = new ArrayList<Tuple>(); StringBuilder sb = new StringBuilder(); StringBuilder currentChunk = new StringBuilder(); while (index < sql.length()) { switch (sql.charAt(index)) { case QUOTE: sb.append(adaptForNamedParams(currentChunk.toString(), indexPropList)); currentChunk = new StringBuilder(); appendToEndOfString(sb); break; case '-': if (next() == '-') { sb.append(adaptForNamedParams(currentChunk.toString(), indexPropList)); currentChunk = new StringBuilder(); appendToEndOfLine(sb); } else { currentChunk.append(sql.charAt(index)); } break; case '/': if (next() == '*') { sb.append(adaptForNamedParams(currentChunk.toString(), indexPropList)); currentChunk = new StringBuilder(); appendToEndOfComment(sb); } else { currentChunk.append(sql.charAt(index)); } break; default: currentChunk.append(sql.charAt(index)); } index++; } sb.append(adaptForNamedParams(currentChunk.toString(), indexPropList)); newSql = sb.toString(); return this; }
@Override public Tuple maybeMakeImmutable(String propertyPath, Object propertyValue) { return configurableImmutabilityStrategy.maybeMakeImmutable(propertyPath, propertyValue); }
List<Tuple> getIndexPropList() { return indexPropList; }
public BatchingPreparedStatementWrapper(PreparedStatement delegate, List<Tuple> indexPropList, int batchSize, Logger log, Sql sql) { super(delegate, batchSize, log); this.delegate = delegate; this.indexPropList = indexPropList; this.sql = sql; }
public static Tuple createTuple(Object[] array) { return new Tuple(array); }
Tuple maybeMakeImmutable(String propertyPath, Object propertyValue);