You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
235 lines
6.7 KiB
235 lines
6.7 KiB
/* |
|
* Hibernate, Relational Persistence for Idiomatic Java |
|
* |
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. |
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. |
|
*/ |
|
package com.fr.third.org.hibernate.loader.plan.exec.query.internal; |
|
|
|
import com.fr.third.org.hibernate.LockMode; |
|
import com.fr.third.org.hibernate.LockOptions; |
|
import com.fr.third.org.hibernate.dialect.Dialect; |
|
import com.fr.third.org.hibernate.internal.util.StringHelper; |
|
|
|
/** |
|
* Largely a copy of the {@link com.fr.third.org.hibernate.sql.Select} class, but changed up slightly to better meet needs |
|
* of building a SQL SELECT statement from a LoadPlan |
|
* |
|
* @author Steve Ebersole |
|
* @author Gavin King |
|
*/ |
|
public class SelectStatementBuilder { |
|
public final Dialect dialect; |
|
|
|
private StringBuilder selectClause = new StringBuilder(); |
|
private StringBuilder fromClause = new StringBuilder(); |
|
// private StringBuilder outerJoinsAfterFrom; |
|
private String outerJoinsAfterFrom; |
|
private StringBuilder whereClause; |
|
// private StringBuilder outerJoinsAfterWhere; |
|
private String outerJoinsAfterWhere; |
|
private StringBuilder orderByClause; |
|
private String comment; |
|
private LockOptions lockOptions = new LockOptions(); |
|
|
|
private int guesstimatedBufferSize = 20; |
|
|
|
/** |
|
* Constructs a select statement builder object. |
|
* |
|
* @param dialect The dialect. |
|
*/ |
|
public SelectStatementBuilder(Dialect dialect) { |
|
this.dialect = dialect; |
|
} |
|
|
|
/** |
|
* Appends a select clause fragment |
|
* |
|
* @param selection The selection fragment |
|
*/ |
|
public void appendSelectClauseFragment(String selection) { |
|
if ( this.selectClause.length() > 0 ) { |
|
this.selectClause.append( ", " ); |
|
this.guesstimatedBufferSize += 2; |
|
} |
|
this.selectClause.append( selection ); |
|
this.guesstimatedBufferSize += selection.length(); |
|
} |
|
|
|
/** |
|
* Appends the from clause fragment. |
|
* |
|
* @param fragment The from cause fragment. |
|
*/ |
|
public void appendFromClauseFragment(String fragment) { |
|
if ( this.fromClause.length() > 0 ) { |
|
this.fromClause.append( ", " ); |
|
this.guesstimatedBufferSize += 2; |
|
} |
|
this.fromClause.append( fragment ); |
|
this.guesstimatedBufferSize += fragment.length(); |
|
} |
|
|
|
/** |
|
* Appends the specified table name and alias as a from clause fragment. |
|
* |
|
* @param tableName The table name. |
|
* @param alias The table alias. |
|
*/ |
|
public void appendFromClauseFragment(String tableName, String alias) { |
|
appendFromClauseFragment( tableName + ' ' + alias ); |
|
} |
|
|
|
/** |
|
* Appends the specified restrictions after "cleaning" the specified value |
|
* (by trimming and removing 'and ' from beginning and ' and' from the end). |
|
* If the where clause already exists, this method ensure that ' and ' |
|
* prefixes the cleaned restrictions. |
|
* |
|
* @param restrictions The restrictions. |
|
*/ |
|
public void appendRestrictions(String restrictions) { |
|
final String cleaned = cleanRestrictions( restrictions ); |
|
if ( StringHelper.isEmpty( cleaned ) ) { |
|
return; |
|
} |
|
|
|
this.guesstimatedBufferSize += cleaned.length(); |
|
|
|
if ( whereClause == null ) { |
|
whereClause = new StringBuilder( cleaned ); |
|
} |
|
else { |
|
whereClause.append( " and " ).append( cleaned ); |
|
this.guesstimatedBufferSize += 5; |
|
} |
|
} |
|
|
|
private String cleanRestrictions(String restrictions) { |
|
restrictions = restrictions.trim(); |
|
if ( restrictions.startsWith( "and " ) ) { |
|
restrictions = restrictions.substring( 4 ); |
|
} |
|
if ( restrictions.endsWith( " and" ) ) { |
|
restrictions = restrictions.substring( 0, restrictions.length()-4 ); |
|
} |
|
|
|
return restrictions; |
|
} |
|
|
|
/** |
|
* Sets the outer join fragments to be added to the "from" and "where" clauses. |
|
* |
|
* @param outerJoinsAfterFrom The outer join fragment to be appended to the "from" clause. |
|
* @param outerJoinsAfterWhere The outer join fragment to be appended to the "where" clause. |
|
*/ |
|
public void setOuterJoins(String outerJoinsAfterFrom, String outerJoinsAfterWhere) { |
|
this.outerJoinsAfterFrom = outerJoinsAfterFrom; |
|
|
|
final String cleanRestrictions = cleanRestrictions( outerJoinsAfterWhere ); |
|
this.outerJoinsAfterWhere = cleanRestrictions; |
|
|
|
this.guesstimatedBufferSize += outerJoinsAfterFrom.length() + cleanRestrictions.length(); |
|
} |
|
|
|
/** |
|
* Appends the "order by" fragment, prefixed by a comma if the "order by" fragment already |
|
* exists. |
|
* |
|
* @param ordering The "order by" fragment to append. |
|
*/ |
|
public void appendOrderByFragment(String ordering) { |
|
if ( this.orderByClause == null ) { |
|
this.orderByClause = new StringBuilder(); |
|
} |
|
else { |
|
this.orderByClause.append( ", " ); |
|
this.guesstimatedBufferSize += 2; |
|
} |
|
this.orderByClause.append( ordering ); |
|
} |
|
|
|
/** |
|
* Sets the comment for the select statement. |
|
* |
|
* @param comment The comment. |
|
*/ |
|
public void setComment(String comment) { |
|
this.comment = comment; |
|
this.guesstimatedBufferSize += comment.length(); |
|
} |
|
|
|
/** |
|
* Sets the lock mode for the select statement. |
|
* |
|
* @param lockMode The lock mode. |
|
*/ |
|
public void setLockMode(LockMode lockMode) { |
|
this.lockOptions.setLockMode( lockMode ); |
|
} |
|
|
|
/** |
|
* Sets the lock options for the select statement. |
|
* |
|
* @param lockOptions The lock options. |
|
*/ |
|
public void setLockOptions(LockOptions lockOptions) { |
|
LockOptions.copy( lockOptions, this.lockOptions ); |
|
} |
|
|
|
/** |
|
* Construct an SQL <tt>SELECT</tt> statement from the given clauses. |
|
* |
|
* @return the SQL <tt>SELECT</tt> statement. |
|
*/ |
|
public String toStatementString() { |
|
StringBuilder buf = new StringBuilder( guesstimatedBufferSize ); |
|
|
|
if ( StringHelper.isNotEmpty( comment ) ) { |
|
buf.append( "/* " ).append( Dialect.escapeComment(comment) ).append( " */ " ); |
|
} |
|
|
|
buf.append( "select " ) |
|
.append( selectClause ) |
|
.append( " from " ) |
|
.append( fromClause ); |
|
|
|
if ( StringHelper.isNotEmpty( outerJoinsAfterFrom ) ) { |
|
buf.append( outerJoinsAfterFrom ); |
|
} |
|
|
|
if ( isNotEmpty( whereClause ) || isNotEmpty( outerJoinsAfterWhere ) ) { |
|
buf.append( " where " ); |
|
// the outerJoinsAfterWhere needs to come before where clause to properly |
|
// handle dynamic filters |
|
if ( StringHelper.isNotEmpty( outerJoinsAfterWhere ) ) { |
|
buf.append( outerJoinsAfterWhere ); |
|
if ( isNotEmpty( whereClause ) ) { |
|
buf.append( " and " ); |
|
} |
|
} |
|
if ( isNotEmpty( whereClause ) ) { |
|
buf.append( whereClause ); |
|
} |
|
} |
|
|
|
if ( orderByClause != null ) { |
|
buf.append( " order by " ).append( orderByClause ); |
|
} |
|
|
|
if ( lockOptions.getLockMode() != LockMode.NONE ) { |
|
buf = new StringBuilder(dialect.applyLocksToSql( buf.toString(), lockOptions, null ) ); |
|
} |
|
|
|
return dialect.transformSelectString( buf.toString() ); |
|
} |
|
|
|
private boolean isNotEmpty(String string) { |
|
return StringHelper.isNotEmpty( string ); |
|
} |
|
|
|
private boolean isNotEmpty(StringBuilder builder) { |
|
return builder != null && builder.length() > 0; |
|
} |
|
}
|
|
|