SQLQueryParserpublic class SQLQueryParser extends Object
Fields Summary |
---|
private final String | originalQueryString | private final ParserContext | context | private final Map | namedParameters | private long | aliasesFound |
Constructors Summary |
---|
public SQLQueryParser(String queryString, ParserContext context)
this.originalQueryString = queryString;
this.context = context;
|
Methods Summary |
---|
public java.util.Map | getNamedParameters()
return namedParameters;
| public java.lang.String | process()
return substituteParams( substituteBrackets( originalQueryString ) );
| public boolean | queryHasAliases()
return aliasesFound>0;
| private java.lang.String | resolveCollectionProperties(java.lang.String aliasName, java.lang.String propertyName)
Map fieldResults = context.getPropertyResultsMapByAlias( aliasName );
SQLLoadableCollection collectionPersister = context.getCollectionPersisterByAlias( aliasName );
String collectionSuffix = context.getCollectionSuffixByAlias( aliasName );
if ( "*".equals( propertyName ) ) {
if( !fieldResults.isEmpty() ) {
throw new QueryException("Using return-propertys together with * syntax is not supported.");
}
String selectFragment = collectionPersister.selectFragment( aliasName, collectionSuffix );
aliasesFound++;
return selectFragment
+ ", "
+ resolveProperties( aliasName, propertyName );
}
else if ( "element.*".equals( propertyName ) ) {
return resolveProperties( aliasName, "*" );
}
else {
String[] columnAliases;
// Let return-propertys override whatever the persister has for aliases.
columnAliases = ( String[] ) fieldResults.get(propertyName);
if ( columnAliases==null ) {
columnAliases = collectionPersister.getCollectionPropertyColumnAliases( propertyName, collectionSuffix );
}
if ( columnAliases == null || columnAliases.length == 0 ) {
throw new QueryException(
"No column name found for property [" + propertyName + "] for alias [" + aliasName + "]",
originalQueryString
);
}
if ( columnAliases.length != 1 ) {
// TODO: better error message since we actually support composites if names are explicitly listed.
throw new QueryException(
"SQL queries only support properties mapped to a single column - property [" +
propertyName + "] is mapped to " + columnAliases.length + " columns.",
originalQueryString
);
}
aliasesFound++;
return columnAliases[0];
}
| private java.lang.String | resolveProperties(java.lang.String aliasName, java.lang.String propertyName)
Map fieldResults = context.getPropertyResultsMapByAlias( aliasName );
SQLLoadable persister = context.getEntityPersisterByAlias( aliasName );
String suffix = context.getEntitySuffixByAlias( aliasName );
if ( "*".equals( propertyName ) ) {
if( !fieldResults.isEmpty() ) {
throw new QueryException("Using return-propertys together with * syntax is not supported.");
}
aliasesFound++;
return persister.selectFragment( aliasName, suffix ) ;
}
else {
String[] columnAliases;
// Let return-propertys override whatever the persister has for aliases.
columnAliases = (String[]) fieldResults.get( propertyName );
if ( columnAliases == null ) {
columnAliases = persister.getSubclassPropertyColumnAliases( propertyName, suffix );
}
if ( columnAliases == null || columnAliases.length == 0 ) {
throw new QueryException(
"No column name found for property [" + propertyName + "] for alias [" + aliasName + "]",
originalQueryString
);
}
if ( columnAliases.length != 1 ) {
// TODO: better error message since we actually support composites if names are explicitly listed.
throw new QueryException(
"SQL queries only support properties mapped to a single column - property [" + propertyName + "] is mapped to " + columnAliases.length + " columns.",
originalQueryString
);
}
aliasesFound++;
return columnAliases[0];
}
| private java.lang.String | substituteBrackets(java.lang.String sqlQuery)
StringBuffer result = new StringBuffer( sqlQuery.length() + 20 );
int left, right;
// replace {....} with corresponding column aliases
for ( int curr = 0; curr < sqlQuery.length(); curr = right + 1 ) {
if ( ( left = sqlQuery.indexOf( '{", curr ) ) < 0 ) {
// No additional open braces found in the string, append the
// rest of the string in its entirty and quit this loop
result.append( sqlQuery.substring( curr ) );
break;
}
// apend everything up until the next encountered open brace
result.append( sqlQuery.substring( curr, left ) );
if ( ( right = sqlQuery.indexOf( '}", left + 1 ) ) < 0 ) {
throw new QueryException( "Unmatched braces for alias path", sqlQuery );
}
String aliasPath = sqlQuery.substring( left + 1, right );
int firstDot = aliasPath.indexOf( '." );
if ( firstDot == -1 ) {
if ( context.isEntityAlias( aliasPath ) ) {
// it is a simple table alias {foo}
result.append( aliasPath );
aliasesFound++;
}
else {
// passing through anything we do not know : to support jdbc escape sequences HB-898
result.append( '{" ).append(aliasPath).append( '}" );
}
}
else {
String aliasName = aliasPath.substring(0, firstDot);
boolean isCollection = context.isCollectionAlias( aliasName );
boolean isEntity = context.isEntityAlias( aliasName );
if ( isCollection ) {
// The current alias is referencing the collection to be eagerly fetched
String propertyName = aliasPath.substring( firstDot + 1 );
result.append( resolveCollectionProperties( aliasName, propertyName ) );
aliasesFound++;
}
else if ( isEntity ) {
// it is a property reference {foo.bar}
String propertyName = aliasPath.substring( firstDot + 1 );
result.append( resolveProperties( aliasName, propertyName ) );
aliasesFound++;
}
else {
// passing through anything we do not know : to support jdbc escape sequences HB-898
result.append( '{" ).append(aliasPath).append( '}" );
}
}
}
// Possibly handle :something parameters for the query ?
return result.toString();
| private java.lang.String | substituteParams(java.lang.String sqlString)Substitues JDBC parameter placeholders (?) for all encountered
parameter specifications. It also tracks the positions of these
parameter specifications within the query string. This accounts for
ordinal-params, named-params, and ejb3-positional-params.
ParameterSubstitutionRecognizer recognizer = new ParameterSubstitutionRecognizer();
ParameterParser.parse( sqlString, recognizer );
namedParameters.clear();
namedParameters.putAll( recognizer.namedParameterBindPoints );
return recognizer.result.toString();
|
|