/* * Hibernate, Relational Persistence for Idiomatic Java * * Copyright (c) 2010, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution; if not, write to: * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ package org.hibernate.dialect.function; import org.hibernate.type.StandardBasicTypes; /** * A {@link SQLFunction} implementation that emulates the ANSI SQL trim function * on dialects which do not support the full definition. However, this function * definition does assume the availability of ltrim, rtrim, and replace functions * which it uses in various combinations to emulate the desired ANSI trim() * functionality. * * @author Steve Ebersole */ public class AnsiTrimEmulationFunction extends AbstractAnsiTrimEmulationFunction { public static final String LTRIM = "ltrim"; public static final String RTRIM = "rtrim"; public static final String REPLACE = "replace"; public static final String SPACE_PLACEHOLDER = "${space}$"; public static final String LEADING_SPACE_TRIM_TEMPLATE = LTRIM + "(?1)"; public static final String TRAILING_SPACE_TRIM_TEMPLATE = RTRIM + "(?1)"; public static final String BOTH_SPACE_TRIM_TEMPLATE = LTRIM + "(" + RTRIM + "(?1))"; public static final String BOTH_SPACE_TRIM_FROM_TEMPLATE = LTRIM + "(" + RTRIM + "(?2))"; //skip the FROM keyword in params /** * A template for the series of calls required to trim non-space chars from the beginning of text. * <p/> * NOTE : essentially we:</ol> * <li>replace all space chars with the text '${space}$'</li> * <li>replace all the actual replacement chars with space chars</li> * <li>perform left-trimming (that removes any of the space chars we just added which occur at the beginning of the text)</li> * <li>replace all space chars with the replacement char</li> * <li>replace all the '${space}$' text with space chars</li> * </ol> */ public static final String LEADING_TRIM_TEMPLATE = REPLACE + "(" + REPLACE + "(" + LTRIM + "(" + REPLACE + "(" + REPLACE + "(" + "?1," + "' '," + "'" + SPACE_PLACEHOLDER + "'" + ")," + "?2," + "' '" + ")" + ")," + "' '," + "?2" + ")," + "'" + SPACE_PLACEHOLDER + "'," + "' '" + ")"; /** * A template for the series of calls required to trim non-space chars from the end of text. * <p/> * NOTE: essentially the same series of calls as outlined in {@link #LEADING_TRIM_TEMPLATE} except that here, * instead of left-trimming the added spaces, we right-trim them to remove them from the end of the text. */ public static final String TRAILING_TRIM_TEMPLATE = REPLACE + "(" + REPLACE + "(" + RTRIM + "(" + REPLACE + "(" + REPLACE + "(" + "?1," + "' '," + "'" + SPACE_PLACEHOLDER + "'" + ")," + "?2," + "' '" + ")" + ")," + "' '," + "?2" + ")," + "'" + SPACE_PLACEHOLDER + "'," + "' '" + ")"; /** * A template for the series of calls required to trim non-space chars from both the beginning and the end of text. * <p/> * NOTE: again, we have a series of calls that is essentially the same as outlined in {@link #LEADING_TRIM_TEMPLATE} * except that here we perform both left (leading) and right (trailing) trimming. */ public static final String BOTH_TRIM_TEMPLATE = REPLACE + "(" + REPLACE + "(" + LTRIM + "(" + RTRIM + "(" + REPLACE + "(" + REPLACE + "(" + "?1," + "' '," + "'" + SPACE_PLACEHOLDER + "'" + ")," + "?2," + "' '" + ")" + ")" + ")," + "' '," + "?2" + ")," + "'" + SPACE_PLACEHOLDER + "'," + "' '" + ")"; private final SQLFunction leadingSpaceTrim; private final SQLFunction trailingSpaceTrim; private final SQLFunction bothSpaceTrim; private final SQLFunction bothSpaceTrimFrom; private final SQLFunction leadingTrim; private final SQLFunction trailingTrim; private final SQLFunction bothTrim; /** * Constructs a new AnsiTrimEmulationFunction using {@link #LTRIM}, {@link #RTRIM}, and {@link #REPLACE} * respectively. * * @see #AnsiTrimEmulationFunction(String,String,String) */ public AnsiTrimEmulationFunction() { this( LTRIM, RTRIM, REPLACE ); } /** * Constructs a <tt>trim()</tt> emulation function definition using the specified function calls. * * @param ltrimFunctionName The <tt>left trim</tt> function to use. * @param rtrimFunctionName The <tt>right trim</tt> function to use. * @param replaceFunctionName The <tt>replace</tt> function to use. */ public AnsiTrimEmulationFunction(String ltrimFunctionName, String rtrimFunctionName, String replaceFunctionName) { leadingSpaceTrim = new SQLFunctionTemplate( StandardBasicTypes.STRING, LEADING_SPACE_TRIM_TEMPLATE.replaceAll( LTRIM, ltrimFunctionName ) ); trailingSpaceTrim = new SQLFunctionTemplate( StandardBasicTypes.STRING, TRAILING_SPACE_TRIM_TEMPLATE.replaceAll( RTRIM, rtrimFunctionName ) ); bothSpaceTrim = new SQLFunctionTemplate( StandardBasicTypes.STRING, BOTH_SPACE_TRIM_TEMPLATE.replaceAll( LTRIM, ltrimFunctionName ) .replaceAll( RTRIM, rtrimFunctionName ) ); bothSpaceTrimFrom = new SQLFunctionTemplate( StandardBasicTypes.STRING, BOTH_SPACE_TRIM_FROM_TEMPLATE.replaceAll( LTRIM, ltrimFunctionName ) .replaceAll( RTRIM, rtrimFunctionName ) ); leadingTrim = new SQLFunctionTemplate( StandardBasicTypes.STRING, LEADING_TRIM_TEMPLATE.replaceAll( LTRIM, ltrimFunctionName ) .replaceAll( RTRIM, rtrimFunctionName ) .replaceAll( REPLACE,replaceFunctionName ) ); trailingTrim = new SQLFunctionTemplate( StandardBasicTypes.STRING, TRAILING_TRIM_TEMPLATE.replaceAll( LTRIM, ltrimFunctionName ) .replaceAll( RTRIM, rtrimFunctionName ) .replaceAll( REPLACE,replaceFunctionName ) ); bothTrim = new SQLFunctionTemplate( StandardBasicTypes.STRING, BOTH_TRIM_TEMPLATE.replaceAll( LTRIM, ltrimFunctionName ) .replaceAll( RTRIM, rtrimFunctionName ) .replaceAll( REPLACE,replaceFunctionName ) ); } /** * {@inheritDoc} */ protected SQLFunction resolveBothSpaceTrimFunction() { return bothSpaceTrim; } /** * {@inheritDoc} */ protected SQLFunction resolveBothSpaceTrimFromFunction() { return bothSpaceTrimFrom; } /** * {@inheritDoc} */ protected SQLFunction resolveLeadingSpaceTrimFunction() { return leadingSpaceTrim; } /** * {@inheritDoc} */ protected SQLFunction resolveTrailingSpaceTrimFunction() { return trailingSpaceTrim; } /** * {@inheritDoc} */ protected SQLFunction resolveBothTrimFunction() { return bothTrim; } /** * {@inheritDoc} */ protected SQLFunction resolveLeadingTrimFunction() { return leadingTrim; } /** * {@inheritDoc} */ protected SQLFunction resolveTrailingTrimFunction() { return trailingTrim; } }