From hibernate-commits at lists.jboss.org Mon Feb 2 19:47:58 2009 Content-Type: multipart/mixed; boundary="===============2333757217077316013==" MIME-Version: 1.0 From: hibernate-commits at lists.jboss.org To: hibernate-commits at lists.jboss.org Subject: [hibernate-commits] Hibernate SVN: r15861 - in core/branches/Branch_3_2: test/org/hibernate/test/dialect and 1 other directories. Date: Mon, 02 Feb 2009 19:47:57 -0500 Message-ID: --===============2333757217077316013== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Author: steve.ebersole(a)jboss.com Date: 2009-02-02 19:47:57 -0500 (Mon, 02 Feb 2009) New Revision: 15861 Added: core/branches/Branch_3_2/src/org/hibernate/dialect/function/AbstractAnsi= TrimEmulationFunction.java core/branches/Branch_3_2/test/org/hibernate/test/dialect/function/ core/branches/Branch_3_2/test/org/hibernate/test/dialect/function/AnsiTr= imEmulationFunctionTest.java Modified: core/branches/Branch_3_2/src/org/hibernate/dialect/function/AnsiTrimEmul= ationFunction.java Log: HHH-3701 : trim function emulation for sybase Copied: core/branches/Branch_3_2/src/org/hibernate/dialect/function/Abstrac= tAnsiTrimEmulationFunction.java (from rev 15840, core/branches/Branch_3_2/s= rc/org/hibernate/dialect/function/AnsiTrimEmulationFunction.java) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- core/branches/Branch_3_2/src/org/hibernate/dialect/function/AbstractAns= iTrimEmulationFunction.java (rev 0) +++ core/branches/Branch_3_2/src/org/hibernate/dialect/function/AbstractAns= iTrimEmulationFunction.java 2009-02-03 00:47:57 UTC (rev 15861) @@ -0,0 +1,227 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2009, Red Hat Middleware LLC 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 Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, m= odify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Founda= tion. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT= ABILITY + * 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.Hibernate; +import org.hibernate.QueryException; +import org.hibernate.engine.Mapping; +import org.hibernate.engine.SessionFactoryImplementor; +import org.hibernate.type.Type; + +import java.util.List; +import java.util.ArrayList; + +/** + * A {@link org.hibernate.dialect.function.SQLFunction} providing support = for implementing TRIM functionality + * (as defined by both the ANSI SQL and JPA specs) in cases where the dial= ect may not support the full trim + * function itself. + *

+ * Follows the template pattern in order to implement + * the {@link #render} method. + * + * @author Steve Ebersole + */ +public abstract class AbstractAnsiTrimEmulationFunction implements SQLFunc= tion { + /** + * {@inheritDoc} = + */ + public final Type getReturnType(Type columnType, Mapping mapping) throws = QueryException { + return Hibernate.STRING; + } + + /** + * {@inheritDoc} + */ + public final boolean hasArguments() { + return true; + } + + /** + * {@inheritDoc} + */ + public final boolean hasParenthesesIfNoArguments() { + return false; + } + + /** + * {@inheritDoc} + */ + public final String render(List args, SessionFactoryImplementor factory) = throws QueryException { + // According to both the ANSI-SQL and JPA specs, trim takes a variable n= umber of parameters between 1 and 4. + // at least one paramer (trimSource) is required. From the SQL spec: + // + // ::=3D + // TRIM + // + // ::=3D + // [ [ ] [ ] FROM ] + // + // ::=3D + // LEADING + // | TRAILING + // | BOTH + // + // If is omitted, BOTH is assumed. + // If is omitted, space is assumed + if ( args.size() =3D=3D 1 ) { + // we have the form: trim(trimSource) + // so we trim leading and trailing spaces + return resolveBothSpaceTrimFunction().render( args, factory ); // EAR= LY EXIT!!!! + } + else if ( "from".equalsIgnoreCase( ( String ) args.get( 0 ) ) ) { + // we have the form: trim(from trimSource). + // This is functionally equivalent to trim(trimSource) + return resolveBothSpaceTrimFromFunction().render( args, factory ); /= / EARLY EXIT!!!! + } + else { + // otherwise, a trim-specification and/or a trim-character + // have been specified; we need to decide which options + // are present and "do the right thing" + boolean leading =3D true; // should leading trim-characters be = trimmed? + boolean trailing =3D true; // should trailing trim-characters be= trimmed? + String trimCharacter; // the trim-character (what is to be trimmed= off?) + String trimSource; // the trim-source (from where should it be = trimmed?) + + // potentialTrimCharacterArgIndex =3D 1 assumes that a + // trim-specification has been specified. we handle the + // exception to that explicitly + int potentialTrimCharacterArgIndex =3D 1; + String firstArg =3D ( String ) args.get( 0 ); + if ( "leading".equalsIgnoreCase( firstArg ) ) { + trailing =3D false; + } + else if ( "trailing".equalsIgnoreCase( firstArg ) ) { + leading =3D false; + } + else if ( "both".equalsIgnoreCase( firstArg ) ) { + } + else { + potentialTrimCharacterArgIndex =3D 0; + } + + String potentialTrimCharacter =3D ( String ) args.get( potentialTrimCha= racterArgIndex ); + if ( "from".equalsIgnoreCase( potentialTrimCharacter ) ) { = + trimCharacter =3D "' '"; + trimSource =3D ( String ) args.get( potentialTrimCharacterArgIndex + 1= ); + } + else if ( potentialTrimCharacterArgIndex + 1 >=3D args.size() ) { + trimCharacter =3D "' '"; + trimSource =3D potentialTrimCharacter; + } + else { + trimCharacter =3D potentialTrimCharacter; + if ( "from".equalsIgnoreCase( ( String ) args.get( potentialTrimCharac= terArgIndex + 1 ) ) ) { + trimSource =3D ( String ) args.get( potentialTrimCharacterArgIndex + = 2 ); + } + else { + trimSource =3D ( String ) args.get( potentialTrimCharacterArgIndex + = 1 ); + } + } + + List argsToUse =3D new ArrayList(); + argsToUse.add( trimSource ); + argsToUse.add( trimCharacter ); + + if ( trimCharacter.equals( "' '" ) ) { + if ( leading && trailing ) { + return resolveBothSpaceTrimFunction().render( argsToUse, factory ); + } + else if ( leading ) { + return resolveLeadingSpaceTrimFunction().render( argsToUse, factory ); + } + else { + return resolveTrailingSpaceTrimFunction().render( argsToUse, factory = ); + } + } + else { + if ( leading && trailing ) { + return resolveBothTrimFunction().render( argsToUse, factory ); + } + else if ( leading ) { + return resolveLeadingTrimFunction().render( argsToUse, factory ); + } + else { + return resolveTrailingTrimFunction().render( argsToUse, factory ); + } + } + } + } + + /** + * Resolve the function definition which should be used to trim both lead= ing and trailing spaces. + *

+ * In this form, the imput arguments is missing the FROM keyword. + * + * @return The sql function + */ + protected abstract SQLFunction resolveBothSpaceTrimFunction(); + + /** + * Resolve the function definition which should be used to trim both lead= ing and trailing spaces. + *

+ * The same as {#link resolveBothSpaceTrimFunction} except that here the<= tt>FROM is included and + * will need to be accounted for during {@link SQLFunction#render} proces= sing. + * = + * @return The sql function + */ + protected abstract SQLFunction resolveBothSpaceTrimFromFunction(); + + /** + * Resolve the function definition which should be used to trim leading s= paces. + * + * @return The sql function + */ + protected abstract SQLFunction resolveLeadingSpaceTrimFunction(); + + /** + * Resolve the function definition which should be used to trim trailing = spaces. + * + * @return The sql function + */ + protected abstract SQLFunction resolveTrailingSpaceTrimFunction(); + + /** + * Resolve the function definition which should be used to trim the speci= fied character from both the + * beginning (leading) and end (trailing) of the trim source. + * + * @return The sql function + */ + protected abstract SQLFunction resolveBothTrimFunction(); + + /** + * Resolve the function definition which should be used to trim the speci= fied character from the + * beginning (leading) of the trim source. + * + * @return The sql function + */ + protected abstract SQLFunction resolveLeadingTrimFunction(); + + /** + * Resolve the function definition which should be used to trim the speci= fied character from the + * end (trailing) of the trim source. + * + * @return The sql function + */ + protected abstract SQLFunction resolveTrailingTrimFunction(); +} \ No newline at end of file Modified: core/branches/Branch_3_2/src/org/hibernate/dialect/function/AnsiT= rimEmulationFunction.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- core/branches/Branch_3_2/src/org/hibernate/dialect/function/AnsiTrimEmu= lationFunction.java 2009-02-03 00:47:23 UTC (rev 15860) +++ core/branches/Branch_3_2/src/org/hibernate/dialect/function/AnsiTrimEmu= lationFunction.java 2009-02-03 00:47:57 UTC (rev 15861) @@ -1,14 +1,7 @@ package org.hibernate.dialect.function; = import org.hibernate.Hibernate; -import org.hibernate.QueryException; -import org.hibernate.engine.Mapping; -import org.hibernate.engine.SessionFactoryImplementor; -import org.hibernate.type.Type; = -import java.util.List; -import java.util.ArrayList; - /** * A {@link SQLFunction} implementation that emulates the ANSI SQL trim fu= nction * on dialects which do not support the full definition. However, this fu= nction @@ -18,129 +11,222 @@ * * @author Steve Ebersole */ -public class AnsiTrimEmulationFunction implements SQLFunction { +public class AnsiTrimEmulationFunction extends AbstractAnsiTrimEmulationFu= nction { + public static final String LTRIM =3D "ltrim"; + public static final String RTRIM =3D "rtrim"; + public static final String REPLACE =3D "replace"; + public static final String SPACE_PLACEHOLDER =3D "${space}$"; = - private static final SQLFunction LEADING_SPACE_TRIM =3D new SQLFunctionTe= mplate( Hibernate.STRING, "ltrim( ?1 )"); - private static final SQLFunction TRAILING_SPACE_TRIM =3D new SQLFunctionT= emplate( Hibernate.STRING, "rtrim( ?1 )"); - private static final SQLFunction BOTH_SPACE_TRIM =3D new SQLFunctionTempl= ate( Hibernate.STRING, "ltrim( rtrim( ?1 ) )"); - private static final SQLFunction BOTH_SPACE_TRIM_FROM =3D new SQLFunction= Template( Hibernate.STRING, "ltrim( rtrim( ?2 ) )"); + public static final String LEADING_SPACE_TRIM_TEMPLATE =3D LTRIM + "(?1)"; + public static final String TRAILING_SPACE_TRIM_TEMPLATE =3D RTRIM + "(?1)= "; + public static final String BOTH_SPACE_TRIM_TEMPLATE =3D LTRIM + "(" + RTR= IM + "(?1))"; + public static final String BOTH_SPACE_TRIM_FROM_TEMPLATE =3D LTRIM + "(" = + RTRIM + "(?2))"; //skip the FROM keyword in params = - private static final SQLFunction LEADING_TRIM =3D new SQLFunctionTemplate= ( Hibernate.STRING, "replace( replace( rtrim( replace( replace( ?1, ' ', '$= {space}$' ), ?2, ' ' ) ), ' ', ?2 ), '${space}$', ' ' )" ); - private static final SQLFunction TRAILING_TRIM =3D new SQLFunctionTemplat= e( Hibernate.STRING, "replace( replace( ltrim( replace( replace( ?1, ' ', '= ${space}$' ), ?2, ' ' ) ), ' ', ?2 ), '${space}$', ' ' )" ); - private static final SQLFunction BOTH_TRIM =3D new SQLFunctionTemplate( H= ibernate.STRING, "replace( replace( ltrim( rtrim( replace( replace( ?1, ' '= , '${space}$' ), ?2, ' ' ) ) ), ' ', ?2 ), '${space}$', ' ' )" ); + /** + * A template for the series of calls required to trim non-space chars fr= om the beginning of text. + *

+ * NOTE : essentially we: + *

  • replace all space chars with the text '${space}$'
  • + *
  • replace all the actual replacement chars with space chars
  • + *
  • perform left-trimming (that removes any of the space chars we just= added which occur at the beginning of the text)
  • + *
  • replace all space chars with the replacement char
  • + *
  • replace all the '${space}$' text with space chars
  • + * + */ + public static final String LEADING_TRIM_TEMPLATE =3D + REPLACE + "(" + + REPLACE + "(" + + LTRIM + "(" + + REPLACE + "(" + + REPLACE + "(" + + "?1," + + "' '," + + "'" + SPACE_PLACEHOLDER + "'" + + ")," + + "?2," + + "' '" + + ")" + + ")," + + "' '," + + "?2" + + ")," + + "'" + SPACE_PLACEHOLDER + "'," + + "' '" + + ")"; = - public Type getReturnType(Type columnType, Mapping mapping) throws QueryE= xception { - return Hibernate.STRING; + /** + * A template for the series of calls required to trim non-space chars fr= om the end of text. + *

    + * NOTE: essentially the same series of calls as outlined in {@link #LEAD= ING_TRIM_TEMPLATE} except that here, + * instead of left-trimming the added spaces, we right-trim them to remov= e them from the end of the text. + */ + public static final String TRAILING_TRIM_TEMPLATE =3D + 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 fr= om both the beginning and the end of text. + *

    + * 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) t= rimming. + */ + public static final String BOTH_TRIM_TEMPLATE =3D + 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}, {@lin= k #RTRIM}, and {@link #REPLACE} + * respectively. + * + * @see #AnsiTrimEmulationFunction(String,String,String) + */ + public AnsiTrimEmulationFunction() { + this( LTRIM, RTRIM, REPLACE ); } = - public boolean hasArguments() { - return true; + /** + * Constructs a trim() emulation function definition using the s= pecified function calls. + * + * @param ltrimFunctionName The left trim function to use. + * @param rtrimFunctionName The right trim function to use. + * @param replaceFunctionName The replace function to use. + */ + public AnsiTrimEmulationFunction(String ltrimFunctionName, String rtrimFu= nctionName, String replaceFunctionName) { + leadingSpaceTrim =3D new SQLFunctionTemplate( + Hibernate.STRING, + LEADING_SPACE_TRIM_TEMPLATE.replaceAll( LTRIM, ltrimFunctionName ) + ); + + trailingSpaceTrim =3D new SQLFunctionTemplate( + Hibernate.STRING, + TRAILING_SPACE_TRIM_TEMPLATE.replaceAll( RTRIM, rtrimFunctionName ) + ); + + bothSpaceTrim =3D new SQLFunctionTemplate( + Hibernate.STRING, + BOTH_SPACE_TRIM_TEMPLATE.replaceAll( LTRIM, ltrimFunctionName ) + .replaceAll( RTRIM, rtrimFunctionName ) + ); + + bothSpaceTrimFrom =3D new SQLFunctionTemplate( + Hibernate.STRING, + BOTH_SPACE_TRIM_FROM_TEMPLATE.replaceAll( LTRIM, ltrimFunctionName ) + .replaceAll( RTRIM, rtrimFunctionName ) + ); + + leadingTrim =3D new SQLFunctionTemplate( + Hibernate.STRING, + LEADING_TRIM_TEMPLATE.replaceAll( LTRIM, ltrimFunctionName ) + .replaceAll( RTRIM, rtrimFunctionName ) + .replaceAll( REPLACE,replaceFunctionName ) + ); + + trailingTrim =3D new SQLFunctionTemplate( + Hibernate.STRING, + TRAILING_TRIM_TEMPLATE.replaceAll( LTRIM, ltrimFunctionName ) + .replaceAll( RTRIM, rtrimFunctionName ) + .replaceAll( REPLACE,replaceFunctionName ) + ); + + bothTrim =3D new SQLFunctionTemplate( + Hibernate.STRING, + BOTH_TRIM_TEMPLATE.replaceAll( LTRIM, ltrimFunctionName ) + .replaceAll( RTRIM, rtrimFunctionName ) + .replaceAll( REPLACE,replaceFunctionName ) + ); } = - public boolean hasParenthesesIfNoArguments() { - return false; + /** + * {@inheritDoc} + */ + protected SQLFunction resolveBothSpaceTrimFunction() { + return bothSpaceTrim; } = - public String render(List args, SessionFactoryImplementor factory) throws= QueryException { - // according to both the ANSI-SQL and EJB3 specs, trim can either take - // exactly one parameter or a variable number of parameters between 1 an= d 4. - // from the SQL spec: - // - // ::=3D - // TRIM - // - // ::=3D - // [ [ ] [ ] FROM ] - // - // ::=3D - // LEADING - // | TRAILING - // | BOTH - // - // If only is omitted, BOTH is assumed; - // if is omitted, space is assumed - if ( args.size() =3D=3D 1 ) { - // we have the form: trim(trimSource) - // so we trim leading and trailing spaces - return BOTH_SPACE_TRIM.render( args, factory ); - } - else if ( "from".equalsIgnoreCase( ( String ) args.get( 0 ) ) ) { - // we have the form: trim(from trimSource). - // This is functionally equivalent to trim(trimSource) - return BOTH_SPACE_TRIM_FROM.render( args, factory ); - } - else { - // otherwise, a trim-specification and/or a trim-character - // have been specified; we need to decide which options - // are present and "do the right thing" - boolean leading =3D true; // should leading trim-characters be = trimmed? - boolean trailing =3D true; // should trailing trim-characters be= trimmed? - String trimCharacter =3D null; // the trim-character - String trimSource =3D null; // the trim-source + /** + * {@inheritDoc} + */ + protected SQLFunction resolveBothSpaceTrimFromFunction() { + return bothSpaceTrimFrom; + } = - // potentialTrimCharacterArgIndex =3D 1 assumes that a - // trim-specification has been specified. we handle the - // exception to that explicitly - int potentialTrimCharacterArgIndex =3D 1; - String firstArg =3D ( String ) args.get( 0 ); - if ( "leading".equalsIgnoreCase( firstArg ) ) { - trailing =3D false; - } - else if ( "trailing".equalsIgnoreCase( firstArg ) ) { - leading =3D false; - } - else if ( "both".equalsIgnoreCase( firstArg ) ) { - } - else { - potentialTrimCharacterArgIndex =3D 0; - } + /** + * {@inheritDoc} + */ + protected SQLFunction resolveLeadingSpaceTrimFunction() { + return leadingSpaceTrim; + } = - String potentialTrimCharacter =3D ( String ) args.get( potentialTrimCha= racterArgIndex ); - if ( "from".equalsIgnoreCase( potentialTrimCharacter ) ) { - trimCharacter =3D "' '"; - trimSource =3D ( String ) args.get( potentialTrimCharacterArgIndex + 1= ); - } - else if ( potentialTrimCharacterArgIndex + 1 >=3D args.size() ) { - trimCharacter =3D "' '"; - trimSource =3D potentialTrimCharacter; - } - else { - trimCharacter =3D potentialTrimCharacter; - if ( "from".equalsIgnoreCase( ( String ) args.get( potentialTrimCharac= terArgIndex + 1 ) ) ) { - trimSource =3D ( String ) args.get( potentialTrimCharacterArgIndex + = 2 ); - } - else { - trimSource =3D ( String ) args.get( potentialTrimCharacterArgIndex + = 1 ); - } - } + /** + * {@inheritDoc} + */ + protected SQLFunction resolveTrailingSpaceTrimFunction() { + return trailingSpaceTrim; + } = - List argsToUse =3D null; - argsToUse =3D new ArrayList(); - argsToUse.add( trimSource ); - argsToUse.add( trimCharacter ); + /** + * {@inheritDoc} + */ + protected SQLFunction resolveBothTrimFunction() { + return bothTrim; + } = - if ( trimCharacter.equals( "' '" ) ) { - if ( leading && trailing ) { - return BOTH_SPACE_TRIM.render( argsToUse, factory ); - } - else if ( leading ) { - return LEADING_SPACE_TRIM.render( argsToUse, factory ); - } - else { - return TRAILING_SPACE_TRIM.render( argsToUse, factory ); - } - } - else { - if ( leading && trailing ) { - return BOTH_TRIM.render( argsToUse, factory ); - } - else if ( leading ) { - return LEADING_TRIM.render( argsToUse, factory ); - } - else { - return TRAILING_TRIM.render( argsToUse, factory ); - } - } - } + /** + * {@inheritDoc} + */ + protected SQLFunction resolveLeadingTrimFunction() { + return leadingTrim; } + + /** + * {@inheritDoc} + */ + protected SQLFunction resolveTrailingTrimFunction() { + return trailingTrim; + } } Added: core/branches/Branch_3_2/test/org/hibernate/test/dialect/function/An= siTrimEmulationFunctionTest.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- core/branches/Branch_3_2/test/org/hibernate/test/dialect/function/AnsiT= rimEmulationFunctionTest.java (rev 0) +++ core/branches/Branch_3_2/test/org/hibernate/test/dialect/function/AnsiT= rimEmulationFunctionTest.java 2009-02-03 00:47:57 UTC (rev 15861) @@ -0,0 +1,169 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2009, Red Hat Middleware LLC 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 Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, m= odify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Founda= tion. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT= ABILITY + * 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.test.dialect.function; + +import java.util.List; +import java.util.ArrayList; + +import junit.framework.TestCase; + +import org.hibernate.dialect.function.AnsiTrimEmulationFunction; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public class AnsiTrimEmulationFunctionTest extends TestCase { + private static final String trimSource =3D "a.column"; + + public void testBasicSqlServerProcessing() { + AnsiTrimEmulationFunction function =3D new AnsiTrimEmulationFunction(); + + performBasicSpaceTrimmingTests( function ); + + final String expectedTrimPrep =3D "replace(replace(a.column,' ','${space= }$'),'-',' ')"; + final String expectedPostTrimPrefix =3D "replace(replace("; + final String expectedPostTrimSuffix =3D ",' ','-'),'${space}$',' ')"; + + // -> trim(LEADING '-' FROM a.column) + String rendered =3D function.render( argList( "LEADING", "'-'", "FROM", = trimSource ), null ); + String expected =3D expectedPostTrimPrefix + "ltrim(" + expectedTrimPrep= + ")" + expectedPostTrimSuffix; + assertEquals( expected, rendered ); + + // -> trim(TRAILING '-' FROM a.column) + rendered =3D function.render( argList( "TRAILING", "'-'", "FROM", trimSo= urce ), null ); + expected =3D expectedPostTrimPrefix + "rtrim(" + expectedTrimPrep + ")" = + expectedPostTrimSuffix; + assertEquals( expected, rendered ); + + // -> trim(BOTH '-' FROM a.column) + rendered =3D function.render( argList( "BOTH", "'-'", "FROM", trimSource= ), null ); + expected =3D expectedPostTrimPrefix + "ltrim(rtrim(" + expectedTrimPrep = + "))" + expectedPostTrimSuffix; + assertEquals( expected, rendered ); + + // -> trim('-' FROM a.column) + rendered =3D function.render( argList( "'-'", "FROM", trimSource ), null= ); + expected =3D expectedPostTrimPrefix + "ltrim(rtrim(" + expectedTrimPrep = + "))" + expectedPostTrimSuffix; + assertEquals( expected, rendered ); + } + + public void testBasicSybaseProcessing() { + AnsiTrimEmulationFunction function =3D new AnsiTrimEmulationFunction( + AnsiTrimEmulationFunction.LTRIM, + AnsiTrimEmulationFunction.RTRIM, + "str_replace" + ); + + performBasicSpaceTrimmingTests( function ); + + final String expectedTrimPrep =3D "str_replace(str_replace(a.column,' ',= '${space}$'),'-',' ')"; + final String expectedPostTrimPrefix =3D "str_replace(str_replace("; + final String expectedPostTrimSuffix =3D ",' ','-'),'${space}$',' ')"; + + // -> trim(LEADING '-' FROM a.column) + String rendered =3D function.render( argList( "LEADING", "'-'", "FROM", = trimSource ), null ); + String expected =3D expectedPostTrimPrefix + "ltrim(" + expectedTrimPrep= + ")" + expectedPostTrimSuffix; + assertEquals( expected, rendered ); + + // -> trim(TRAILING '-' FROM a.column) + rendered =3D function.render( argList( "TRAILING", "'-'", "FROM", trimSo= urce ), null ); + expected =3D expectedPostTrimPrefix + "rtrim(" + expectedTrimPrep + ")" = + expectedPostTrimSuffix; + assertEquals( expected, rendered ); + + // -> trim(BOTH '-' FROM a.column) + rendered =3D function.render( argList( "BOTH", "'-'", "FROM", trimSource= ), null ); + expected =3D expectedPostTrimPrefix + "ltrim(rtrim(" + expectedTrimPrep = + "))" + expectedPostTrimSuffix; + assertEquals( expected, rendered ); + + // -> trim('-' FROM a.column) + rendered =3D function.render( argList( "'-'", "FROM", trimSource ), null= ); + expected =3D expectedPostTrimPrefix + "ltrim(rtrim(" + expectedTrimPrep = + "))" + expectedPostTrimSuffix; + assertEquals( expected, rendered ); + } + + private void performBasicSpaceTrimmingTests(AnsiTrimEmulationFunction fun= ction) { + // -> trim(a.column) + String rendered =3D function.render( argList( trimSource ), null ); + assertEquals( "ltrim(rtrim(a.column))", rendered ); + + // -> trim(FROM a.column) + rendered =3D function.render( argList( "FROM", trimSource ), null ); + assertEquals( "ltrim(rtrim(a.column))", rendered ); + + // -> trim(BOTH FROM a.column) + rendered =3D function.render( argList( "BOTH", "FROM", trimSource ), nul= l ); + assertEquals( "ltrim(rtrim(a.column))", rendered ); + + // -> trim(BOTH ' ' FROM a.column) + rendered =3D function.render( argList( "BOTH", "' '", "FROM", trimSource= ), null ); + assertEquals( "ltrim(rtrim(a.column))", rendered ); + + // -> trim(LEADING FROM a.column) + rendered =3D function.render( argList( "LEADING", "FROM", trimSource ), = null ); + assertEquals( "ltrim(a.column)", rendered ); + + // -> trim(LEADING ' ' FROM a.column) + rendered =3D function.render( argList( "LEADING", "' '", "FROM", trimSou= rce ), null ); + assertEquals( "ltrim(a.column)", rendered ); + + // -> trim(TRAILING FROM a.column) + rendered =3D function.render( argList( "TRAILING", "FROM", trimSource ),= null ); + assertEquals( "rtrim(a.column)", rendered ); + + // -> trim(TRAILING ' ' FROM a.column) + rendered =3D function.render( argList( "TRAILING", "' '", "FROM", trimSo= urce ), null ); + assertEquals( "rtrim(a.column)", rendered ); + } + + private List argList(String arg) { + ArrayList args =3D new ArrayList(); + args.add( arg ); + return args; + } + + private List argList(String arg1, String arg2) { + ArrayList args =3D new ArrayList(); + args.add( arg1 ); + args.add( arg2 ); + return args; + } + + private List argList(String arg1, String arg2, String arg3) { + ArrayList args =3D new ArrayList(); + args.add( arg1 ); + args.add( arg2 ); + args.add( arg3 ); + return args; + } + + private List argList(String arg1, String arg2, String arg3, String arg4) { + ArrayList args =3D new ArrayList(); + args.add( arg1 ); + args.add( arg2 ); + args.add( arg3 ); + args.add( arg4 ); + return args; + } + +} --===============2333757217077316013==--