/** * Coordinates the efforts to perform an execution across all the included query translators. * * @param queryParameters The query parameters * @param session The session * * @return The aggregated "affected row" count * * @throws HibernateException Indicates a problem performing the execution */ public int performExecuteUpdate(QueryParameters queryParameters, SessionImplementor session) throws HibernateException { if ( TRACE_ENABLED ) { LOG.tracev( "Execute update: {0}", getSourceQuery() ); queryParameters.traceParameters( session.getFactory() ); } if ( translators.length != 1 ) { LOG.splitQueries( getSourceQuery(), translators.length ); } int result = 0; for ( QueryTranslator translator : translators ) { result += translator.executeUpdate( queryParameters, session ); } return result; }
@Override @SuppressWarnings("unchecked") public String getRenderText(SessionFactoryImplementor sessionFactory) { final Type type = expectedType == null ? heuristicType : Number.class.isAssignableFrom( heuristicType.getReturnedClass() ) ? heuristicType : expectedType; try { final LiteralType literalType = (LiteralType) type; final Dialect dialect = factory.getDialect(); return literalType.objectToSQLString( constantValue, dialect ); } catch (Exception t) { throw new QueryException( QueryTranslator.ERROR_CANNOT_FORMAT_LITERAL + constantExpression, t ); } }
/** * Returns the locations of all occurrences of the named parameter. */ public int[] getNamedParameterLocations(String name) throws QueryException { Object o = namedParameters.get( name ); if ( o == null ) { throw new QueryException( QueryTranslator.ERROR_NAMED_PARAMETER_DOES_NOT_APPEAR + name, queryTranslatorImpl.getQueryString() ); } if ( o instanceof Integer ) { return new int[] {(Integer) o}; } else { return ArrayHelper.toIntArray( (ArrayList) o ); } }
private QueryPlanWork specificationToWork(Specification<T> spec, Pageable pageable) { // Unwrap to Hibernate final QueryImpl query = getQuery(spec, pageable).unwrap(QueryImpl.class); final String hql = query.getQueryString(); // Create translator final QueryTranslator queryTranslator = new ASTQueryTranslatorFactory().createQueryTranslator("", hql, Collections.emptyMap(), em.unwrap(SessionImplementor.class).getFactory(), null); queryTranslator.compile(Collections.emptyMap(), false); // Get translated query and parameters final String sql = queryTranslator.getSQLString(); final Object[] parameters = translateParameters(query, queryTranslator); // Done return new QueryPlanWork(sql, parameters); }
/** * Do not use in production code! Only for testing purposes only. Used for example during query engine upgrade. * Method provides translation from hibernate HQL query to plain SQL string query. * * @param sessionFactory * @param hqlQueryText * @return SQL string, null if hqlQueryText parameter is empty. */ public static String toSql(SessionFactory sessionFactory, String hqlQueryText) { Validate.notNull(sessionFactory, "Session factory must not be null."); if (StringUtils.isEmpty(hqlQueryText)) { return null; } final QueryTranslatorFactory translatorFactory = new ASTQueryTranslatorFactory(); final SessionFactoryImplementor factory = (SessionFactoryImplementor) sessionFactory; final QueryTranslator translator = translatorFactory. createQueryTranslator( hqlQueryText, hqlQueryText, Collections.EMPTY_MAP, factory, null ); translator.compile(Collections.EMPTY_MAP, false); return translator.getSQLString(); }
@Override public QueryTranslator createQueryTranslator( String queryIdentifier, String queryString, Map filters, SessionFactoryImplementor factory, EntityGraphQueryHint entityGraphQueryHint) { return new QueryTranslatorImpl( queryIdentifier, queryString, filters, factory, entityGraphQueryHint ); }
public void setFetch(boolean fetch) { this.fetch = fetch; // Fetch can't be used with scroll() or iterate(). if ( fetch && getWalker().isShallowQuery() ) { throw new QueryException( QueryTranslator.ERROR_CANNOT_FETCH_WITH_ITERATE ); } }
/** * @see QueryTranslatorFactory#createQueryTranslator */ public QueryTranslator createQueryTranslator( String queryIdentifier, String queryString, Map filters, SessionFactoryImplementor factory, EntityGraphQueryHint entityGraphQueryHint) { if (entityGraphQueryHint != null) { throw new QueryException( "EntityGraphs cannot be applied queries using the classic QueryTranslator!" ); } return new QueryTranslatorImpl( queryIdentifier, queryString, filters, factory ); }
private Map<Integer, Object> getPositionParametersMap(QueryTranslator translator, Map<String, Object> parametersMap) { Map<Integer, Object> positionParametersMap = new HashMap<Integer, Object>(); ParameterTranslations parameterTranslations = translator.getParameterTranslations(); for (Entry<String, Object> parameter : parametersMap.entrySet()) { String name = parameter.getKey(); for (int position : parameterTranslations.getNamedParameterSqlLocations(name)) { positionParametersMap.put(position + 1, parameter.getValue()); // Note that the +1 on the position is needed because of a mismatch between 0-based and 1-based indexing of both APIs. } } return positionParametersMap; }
@SuppressWarnings("unchecked") protected HQLQueryPlan( String hql, String collectionRole, boolean shallow, Map<String,Filter> enabledFilters, SessionFactoryImplementor factory, EntityGraphQueryHint entityGraphQueryHint) { this.sourceQuery = hql; this.shallow = shallow; final Set<String> copy = new HashSet<String>(); copy.addAll( enabledFilters.keySet() ); this.enabledFilterNames = java.util.Collections.unmodifiableSet( copy ); final String[] concreteQueryStrings = QuerySplitter.concreteQueries( hql, factory ); final int length = concreteQueryStrings.length; this.translators = new QueryTranslator[length]; final List<String> sqlStringList = new ArrayList<String>(); final Set<Serializable> combinedQuerySpaces = new HashSet<Serializable>(); final boolean hasCollectionRole = (collectionRole == null); final Map querySubstitutions = factory.getSettings().getQuerySubstitutions(); final QueryTranslatorFactory queryTranslatorFactory = factory.getSettings().getQueryTranslatorFactory(); for ( int i=0; i<length; i++ ) { if ( hasCollectionRole ) { translators[i] = queryTranslatorFactory .createQueryTranslator( hql, concreteQueryStrings[i], enabledFilters, factory, entityGraphQueryHint ); translators[i].compile( querySubstitutions, shallow ); } else { translators[i] = queryTranslatorFactory .createFilterTranslator( hql, concreteQueryStrings[i], enabledFilters, factory ); ( (FilterTranslator) translators[i] ).compile( collectionRole, querySubstitutions, shallow ); } combinedQuerySpaces.addAll( translators[i].getQuerySpaces() ); sqlStringList.addAll( translators[i].collectSqlStrings() ); } this.sqlStrings = ArrayHelper.toStringArray( sqlStringList ); this.querySpaces = combinedQuerySpaces; if ( length == 0 ) { parameterMetadata = new ParameterMetadata( null, null ); returnMetadata = null; } else { this.parameterMetadata = buildParameterMetadata( translators[0].getParameterTranslations(), hql ); if ( translators[0].isManipulationStatement() ) { returnMetadata = null; } else { final Type[] types = ( length > 1 ) ? new Type[translators[0].getReturnTypes().length] : translators[0].getReturnTypes(); returnMetadata = new ReturnMetadata( translators[0].getReturnAliases(), types ); } } }
/** * Coordinates the efforts to perform a list across all the included query translators. * * @param queryParameters The query parameters * @param session The session * * @return The query result list * * @throws HibernateException Indicates a problem performing the query */ @SuppressWarnings("unchecked") public List performList( QueryParameters queryParameters, SessionImplementor session) throws HibernateException { if ( TRACE_ENABLED ) { LOG.tracev( "Find: {0}", getSourceQuery() ); queryParameters.traceParameters( session.getFactory() ); } final RowSelection rowSelection = queryParameters.getRowSelection(); final boolean hasLimit = rowSelection != null && rowSelection.definesLimits(); final boolean needsLimit = hasLimit && translators.length > 1; final QueryParameters queryParametersToUse; if ( needsLimit ) { LOG.needsLimit(); final RowSelection selection = new RowSelection(); selection.setFetchSize( queryParameters.getRowSelection().getFetchSize() ); selection.setTimeout( queryParameters.getRowSelection().getTimeout() ); queryParametersToUse = queryParameters.createCopyUsing( selection ); } else { queryParametersToUse = queryParameters; } final int guessedResultSize = guessResultSize( rowSelection ); final List combinedResults = new ArrayList( guessedResultSize ); final IdentitySet distinction = new IdentitySet( guessedResultSize ); int includedCount = -1; translator_loop: for ( QueryTranslator translator : translators ) { final List tmp = translator.list( session, queryParametersToUse ); if ( needsLimit ) { // NOTE : firstRow is zero-based final int first = queryParameters.getRowSelection().getFirstRow() == null ? 0 : queryParameters.getRowSelection().getFirstRow(); final int max = queryParameters.getRowSelection().getMaxRows() == null ? -1 : queryParameters.getRowSelection().getMaxRows(); for ( final Object result : tmp ) { if ( !distinction.add( result ) ) { continue; } includedCount++; if ( includedCount < first ) { continue; } combinedResults.add( result ); if ( max >= 0 && includedCount > max ) { // break the outer loop !!! break translator_loop; } } } else { combinedResults.addAll( tmp ); } } return combinedResults; }
/** * Access to the underlying translators associated with this query * * @return The translators */ public QueryTranslator[] getTranslators() { final QueryTranslator[] copy = new QueryTranslator[translators.length]; System.arraycopy( translators, 0, copy, 0, copy.length ); return copy; }
private void setConstantValue(DotNode node, String text, Object value) { if ( LOG.isDebugEnabled() ) { LOG.debugf( "setConstantValue() %s -> %s %s", text, value, value.getClass().getName() ); } // Chop off the rest of the tree. node.setFirstChild( null ); if ( value instanceof String ) { node.setType( SqlTokenTypes.QUOTED_STRING ); } else if ( value instanceof Character ) { node.setType( SqlTokenTypes.QUOTED_STRING ); } else if ( value instanceof Byte ) { node.setType( SqlTokenTypes.NUM_INT ); } else if ( value instanceof Short ) { node.setType( SqlTokenTypes.NUM_INT ); } else if ( value instanceof Integer ) { node.setType( SqlTokenTypes.NUM_INT ); } else if ( value instanceof Long ) { node.setType( SqlTokenTypes.NUM_LONG ); } else if ( value instanceof Double ) { node.setType( SqlTokenTypes.NUM_DOUBLE ); } else if ( value instanceof Float ) { node.setType( SqlTokenTypes.NUM_FLOAT ); } else { node.setType( SqlTokenTypes.CONSTANT ); } Type type; try { type = walker.getSessionFactoryHelper().getFactory().getTypeResolver().heuristicType( value.getClass().getName() ); } catch (MappingException me) { throw new QueryException( me ); } if ( type == null ) { throw new QueryException( QueryTranslator.ERROR_CANNOT_DETERMINE_TYPE + node.getText() ); } try { LiteralType literalType = (LiteralType) type; Dialect dialect = walker.getSessionFactoryHelper().getFactory().getDialect(); //noinspection unchecked node.setText( literalType.objectToSQLString( value, dialect ) ); } catch (Exception e) { throw new QueryException( QueryTranslator.ERROR_CANNOT_FORMAT_LITERAL + node.getText(), e ); } node.setDataType( type ); node.setResolvedConstant( text ); }
private void doToken(String token, QueryTranslatorImpl q) throws QueryException { if ( q.isName( StringHelper.root( token ) ) ) { //path expression doPathExpression( q.unalias( token ), q ); } else if ( token.startsWith( ParserHelper.HQL_VARIABLE_PREFIX ) ) { //named query parameter q.addNamedParameter( token.substring( 1 ) ); appendToken( q, "?" ); } else { Queryable persister = q.getEntityPersisterUsingImports( token ); if ( persister != null ) { // the name of a class final String discrim = persister.getDiscriminatorSQLValue(); if ( InFragment.NULL.equals(discrim) || InFragment.NOT_NULL.equals(discrim) ) { throw new QueryException( "subclass test not allowed for null or not null discriminator" ); } else { appendToken( q, discrim ); } } else { Object constant; if ( token.indexOf( '.' ) > -1 && ( constant = ReflectHelper.getConstantValue( token ) ) != null ) { Type type; try { type = q.getFactory().getTypeResolver().heuristicType( constant.getClass().getName() ); } catch ( MappingException me ) { throw new QueryException( me ); } if ( type == null ) throw new QueryException( QueryTranslator.ERROR_CANNOT_DETERMINE_TYPE + token ); try { appendToken( q, ( ( LiteralType ) type ).objectToSQLString( constant, q.getFactory().getDialect() ) ); } catch ( Exception e ) { throw new QueryException( QueryTranslator.ERROR_CANNOT_FORMAT_LITERAL + token, e ); } } else { //anything else String negatedToken = negated ? ( String ) NEGATIONS.get( token.toLowerCase() ) : null; if ( negatedToken != null && ( !betweenSpecialCase || !"or".equals( negatedToken ) ) ) { appendToken( q, negatedToken ); } else { appendToken( q, token ); } } } } }
@Override protected TypedQuery<Long> getCountQuery(final Specification<T> spec) { final CriteriaBuilder builder = em.getCriteriaBuilder(); final CriteriaQuery<T> criteria = builder.createQuery(getDomainClass()); final Root<T> root = applySpecificationToQueryCriteria(spec, criteria); criteria.select(root); final TypedQuery<T> query = em.createQuery(criteria); final AbstractQueryImpl hibernateQuery = query.unwrap(AbstractQueryImpl.class); @SuppressWarnings("unchecked") final Map<String, TypedValue> pNamedParameters = (Map<String, TypedValue>) getField(hibernateQuery, AbstractQueryImpl.class, "namedParameters"); final String hql = hibernateQuery.getQueryString(); final ASTQueryTranslatorFactory queryTranslatorFactory = new ASTQueryTranslatorFactory(); final SessionImplementor hibernateSession = em.unwrap(SessionImplementor.class); final QueryTranslator queryTranslator = queryTranslatorFactory.createQueryTranslator("", hql, Collections.emptyMap(), hibernateSession.getFactory(), null); queryTranslator.compile(Collections.emptyMap(), false); final String sql = queryTranslator.getSQLString(); final ParameterTranslations paramTranslations = queryTranslator.getParameterTranslations(); final String countSql = String.format("select count(*) from (%s limit %d) as sqry", sql, maximumRecords + 1); final Query nativeQuery = em.createNativeQuery(countSql); final AbstractQueryImpl resultQuery = nativeQuery.unwrap(AbstractQueryImpl.class); if (pNamedParameters != null) { for (final Entry<String, TypedValue> entry : pNamedParameters.entrySet()) { for (final int index : paramTranslations.getNamedParameterSqlLocations(entry.getKey())) { resultQuery.setParameter(index, entry.getValue().getValue(), entry.getValue().getType()); } } } return new CustomCountQueryWrapper(nativeQuery); }
private <X> TypedQuery<X> createQuery(EntityManager entityManager, Class<X> clazz, boolean pagedCount) { StrQLBuilder oThis = this; while (oThis.unionParent != null) { log.warn("Warning: you are trying to execute a query over an auxiliar instance -used to build union union queries-. Use .endUnion() to remove this message."); oThis = oThis.unionParent; } String sql = oThis.build(pagedCount); Map<String, Object> parametersMap = oThis.getParametersMap(); AbstractEntityManagerImpl abstractEntityManager = entityManager.unwrap(AbstractEntityManagerImpl.class); try { QueryTranslator translator = null; boolean fixJpqlCountQuery = !isNative && pagedCount; if (fixJpqlCountQuery) { translator = translator(sql, entityManager); sql = "select count(*) from (" + translator.getSQLString() + ") x"; } Query q = createQuery(sql, abstractEntityManager, fixJpqlCountQuery); TypedQueryImpl<X> typedQuery = new TypedQueryImpl<X>(q, abstractEntityManager); if (fixJpqlCountQuery) { typedQuery.setPositionParameters(getPositionParametersMap(translator, parametersMap)); } else { typedQuery.setParameters(parametersMap); } typedQuery.setAlias(oThis.select.getAliases()); typedQuery.setTargetClass(clazz); return typedQuery; } catch (HibernateException he) { throw abstractEntityManager.convert(he); } }
private Long getTotal(TypedQuery<T> query) { String hqlQuery = query.unwrap(org.hibernate.Query.class).getQueryString(); QueryTranslator translator = translatorFactory.createQueryTranslator(hqlQuery, hqlQuery, EMPTY, sessionFactory, null); translator.compile(EMPTY, false); String sqlQuery = new StringBuilder("SELECT COUNT(*) FROM (").append(translator.getSQLString()) .append(") x").toString(); Query countQuery = entityManager.createNativeQuery(sqlQuery); ParameterTranslations parameterTranslations = translator.getParameterTranslations(); query.getParameters().stream().forEach( parameter -> { String name = parameter.getName(); for(int position : parameterTranslations.getNamedParameterSqlLocations(name)) { countQuery.setParameter(position+1, query.getParameterValue(name)); }; }); return ((Number) countQuery.getSingleResult()).longValue(); }