All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.avaje.ebeaninternal.server.util.BindParamsParser Maven / Gradle / Ivy

There is a newer version: 8.1.1
Show newest version
package com.avaje.ebeaninternal.server.util;

import java.util.Collection;

import javax.persistence.PersistenceException;

import com.avaje.ebean.config.EncryptKey;
import com.avaje.ebeaninternal.api.BindParams;
import com.avaje.ebeaninternal.api.BindParams.OrderedList;
import com.avaje.ebeaninternal.api.BindParams.Param;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;

/**
 * Parses the BindParams if they are using named parameters.
 * 

* This is a thread safe implementation. *

*/ public class BindParamsParser { public static final String ENCRYPTKEY_PREFIX = "encryptkey_"; public static final String ENCRYPTKEY_GAP = "___"; private static final int ENCRYPTKEY_PREFIX_LEN = ENCRYPTKEY_PREFIX.length(); private static final int ENCRYPTKEY_GAP_LEN = ENCRYPTKEY_GAP.length(); /** * Used to parse sql looking for named parameters. */ private static final String quote = "'"; /** * Used to parse sql looking for named parameters. */ private static final String colon = ":"; private final BindParams params; private final String sql; private final BeanDescriptor beanDescriptor; public static String parse(BindParams params, String sql) { return parse(params, sql, null); } public static String parse(BindParams params, String sql, BeanDescriptor beanDescriptor) { return new BindParamsParser(params, sql, beanDescriptor).parseSql(); } public static OrderedList parseNamedParams(BindParams params, String sql) { return new BindParamsParser(params, sql, null).parseSqlNamedParams(); } private BindParamsParser(BindParams params, String sql, BeanDescriptor beanDescriptor) { this.params = params; this.sql = sql; this.beanDescriptor = beanDescriptor; } /** * Used for parsing having clauses with named parameters. *

* The issue here is that BindParams contains named parameters for * both where and having clauses. BindParams.positionedParameters is * used for the where and the OrderedList for the having. *

*/ private OrderedList parseSqlNamedParams() { OrderedList orderedList = new OrderedList(); parseNamedParams(orderedList); return orderedList; } /** * Parse the sql changed named parameters to positioned parameters if required. *

* The sql is used when named parameters are used. *

*

* This is used in most cases of named parameters. The case it is NOT used for is * named parameters in a having clause. In this case some of the named parameters * could be for a where clause and some for the having clause. *

*/ private String parseSql() { if (params.isSameBindHash()) { String preparedSql = params.getPreparedSql(); if (preparedSql != null && preparedSql.length() > 0) { // the sql has already been parsed and positionedParameters are set in order return preparedSql; } } String preparedSql; if (params.requiresNamedParamsPrepare()) { // convert named parameters into ordered list OrderedList orderedList = params.createOrderedList(); parseNamedParams(orderedList); preparedSql = orderedList.getPreparedSql(); } else { preparedSql = sql; } params.setPreparedSql(preparedSql); return preparedSql; } /** * Named parameters need to be parsed and replaced with ?. */ private void parseNamedParams(OrderedList orderedList) { parseNamedParams(0, orderedList); } private void parseNamedParams(int startPos, OrderedList orderedList) { if (sql == null) { throw new PersistenceException("query does not contain any named bind parameters?"); } if (startPos > sql.length()) { return; } // search for quotes and named params... in order... int beginQuotePos = sql.indexOf(quote, startPos); int nameParamStart = sql.indexOf(colon, startPos); if (beginQuotePos > 0 && beginQuotePos < nameParamStart) { // the quote precedes the named parameter... // find and add up to the end quote int endQuotePos = sql.indexOf(quote, beginQuotePos + 1); String sub = sql.substring(startPos, endQuotePos + 1); orderedList.appendSql(sub); // start again after the end quote parseNamedParams(endQuotePos + 1, orderedList); } else { if (nameParamStart < 0) { // no more params, add the rest String sub = sql.substring(startPos, sql.length()); orderedList.appendSql(sub); } else { // find the end of the parameter name int endOfParam = nameParamStart + 1; do { char c = sql.charAt(endOfParam); if (c != '_' && !Character.isLetterOrDigit(c)) { break; } endOfParam++; } while (endOfParam < sql.length()); // add the named parameter value to bindList String paramName = sql.substring(nameParamStart + 1, endOfParam); Param param; if (paramName.startsWith(ENCRYPTKEY_PREFIX)) { param = addEncryptKeyParam(paramName); } else { param = params.getParameter(paramName); } if (param == null) { String msg = "Bind value is not set or null for [" + paramName + "] in [" + sql + "]"; throw new PersistenceException(msg); } String sub = sql.substring(startPos, nameParamStart); orderedList.appendSql(sub); // check if inValue is a Collection type... Object inValue = param.getInValue(); if (inValue != null && inValue instanceof Collection) { // Chop up Collection parameter into a number // of individual parameters and add each one individually Collection collection = (Collection) inValue; int c = 0; for (Object elVal : collection) { if (++c > 1) { orderedList.appendSql(","); } orderedList.appendSql("?"); BindParams.Param elParam = new BindParams.Param(); elParam.setInValue(elVal); orderedList.add(elParam); } } else { // its a normal scalar value parameter... orderedList.add(param); orderedList.appendSql("?"); } // continue on after the end of the parameter parseNamedParams(endOfParam, orderedList); } } } /** * Add an encryption key bind parameter. */ private Param addEncryptKeyParam(String keyNamedParam) { int pos = keyNamedParam.indexOf(ENCRYPTKEY_GAP, ENCRYPTKEY_PREFIX_LEN); String tableName = keyNamedParam.substring(ENCRYPTKEY_PREFIX_LEN, pos); String columnName = keyNamedParam.substring(pos + ENCRYPTKEY_GAP_LEN); EncryptKey key = beanDescriptor.getEncryptKey(tableName, columnName); String strKey = key.getStringValue(); return params.setEncryptionKey(keyNamedParam, strKey); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy