/// <summary> /// Prepares a derived (i.e., not explicitly defined in the query) select clause. /// </summary> /// <param name="fromClause">The from clause to which this select clause is linked.</param> public void InitializeDerivedSelectClause(FromClause fromClause) { if (_prepared) { throw new InvalidOperationException("SelectClause was already prepared!"); } //Used to be tested by the TCK but the test is no longer here // if ( getSessionFactoryHelper().isStrictJPAQLComplianceEnabled() && !getWalker().isSubQuery() ) { // // NOTE : the isSubQuery() bit is a temporary hack... // throw new QuerySyntaxException( "JPA-QL compliance requires select clause" ); // } var fromElements = fromClause.GetProjectionListTyped(); ASTAppender appender = new ASTAppender(ASTFactory, this); // Get ready to start adding nodes. int size = fromElements.Count; List <IType> queryReturnTypeList = new List <IType>(size); int k = 0; foreach (FromElement fromElement in fromElements) { IType type = fromElement.SelectType; AddCollectionFromElement(fromElement); if (type != null) { bool collectionOfElements = fromElement.IsCollectionOfValuesOrComponents; if (!collectionOfElements) { if (!fromElement.IsFetch) { // Add the type to the list of returned sqlResultTypes. queryReturnTypeList.Add(type); } _fromElementsForLoad.Add(fromElement); // Generate the select expression. string text = fromElement.RenderIdentifierSelect(size, k); SelectExpressionImpl generatedExpr = (SelectExpressionImpl)appender.Append(HqlSqlWalker.SELECT_EXPR, text, false); if (generatedExpr != null) { generatedExpr.FromElement = fromElement; } } } k++; } // Get all the select expressions (that we just generated) and render the select. ISelectExpression[] selectExpressions = CollectSelectExpressions(); if (Walker.IsShallowQuery) { RenderScalarSelects(selectExpressions, fromClause); } else { RenderNonScalarSelects(selectExpressions, fromClause); } FinishInitialization(/*sqlResultTypeList,*/ queryReturnTypeList); }
/// <summary> /// Prepares an explicitly defined select clause. /// </summary> /// <param name="fromClause">The from clause linked to this select clause.</param> /// <exception cref="SemanticException"></exception> public void InitializeExplicitSelectClause(FromClause fromClause) { if (_prepared) { throw new InvalidOperationException("SelectClause was already prepared!"); } //explicit = true; // This is an explict Select. //ArrayList sqlResultTypeList = new ArrayList(); List <IType> queryReturnTypeList = new List <IType>(); // First, collect all of the select expressions. // NOTE: This must be done *before* invoking setScalarColumnText() because setScalarColumnText() // changes the AST!!! ISelectExpression[] selectExpressions = CollectSelectExpressions(); for (int i = 0; i < selectExpressions.Length; i++) { ISelectExpression expr = selectExpressions[i]; if (expr.IsConstructor) { _constructorNode = (ConstructorNode)expr; //sqlResultTypeList.addAll( constructorArgumentTypeList ); _scalarSelect = true; var ctorSelectExpressions = _constructorNode.CollectSelectExpressions(); for (int j = 0; j < ctorSelectExpressions.Length; j++) { ISelectExpression se = ctorSelectExpressions[j]; if (IsReturnableEntity(se)) { AddEntityToProjection(queryReturnTypeList.Count, se); } queryReturnTypeList.Add(se.DataType); } } else { IType type = expr.DataType; if (type == null) { if (expr is ParameterNode param) { type = param.GuessedType; } else { throw new QueryException("No data type for node: " + expr.GetType().Name + " " + new ASTPrinter().ShowAsString((IASTNode)expr, "")); } } //sqlResultTypeList.add( type ); // If the data type is not an association type, it could not have been in the FROM clause. if (expr.IsScalar) { _scalarSelect = true; } else if (IsReturnableEntity(expr)) { AddEntityToProjection(queryReturnTypeList.Count, expr); } // Always add the type to the return type list. queryReturnTypeList.Add(type); } } //init the aliases, after initing the constructornode InitAliases(selectExpressions); if (!Walker.IsShallowQuery) { // add the fetched entities var fromElements = fromClause.GetProjectionListTyped(); ASTAppender appender = new ASTAppender(ASTFactory, this); // Get ready to start adding nodes. int size = fromElements.Count; int k = 0; foreach (FromElement fromElement in fromElements) { if (fromElement.IsFetch) { var origin = GetOrigin(fromElement); // Only perform the fetch if its owner is included in the select if (!_fromElementsForLoad.Contains(origin)) { // NH-2846: Before 2012-01-18, we threw this exception. However, some // components using LINQ (e.g. paging) like to automatically append e.g. Count(). It // can then be difficult to avoid having a bogus fetch statement, so just ignore those. // An alternative solution may be to have the linq provider filter out the fetch instead. // throw new QueryException(string.Format(JoinFetchWithoutOwnerExceptionMsg, fromElement.GetDisplayText())); //throw away the fromElement. It's clearly redundant. fromElement.Parent.RemoveChild(fromElement); } else { IType type = fromElement.SelectType; AddCollectionFromElement(fromElement); if (type != null) { bool collectionOfElements = fromElement.IsCollectionOfValuesOrComponents; if (!collectionOfElements) { // Add the type to the list of returned sqlResultTypes. fromElement.IncludeSubclasses = true; _fromElementsForLoad.Add(fromElement); //sqlResultTypeList.add( type ); // Generate the select expression. String text = fromElement.RenderIdentifierSelect(size, k); SelectExpressionImpl generatedExpr = (SelectExpressionImpl)appender.Append(HqlSqlWalker.SELECT_EXPR, text, false); if (generatedExpr != null) { generatedExpr.FromElement = fromElement; } } } } } k++; } // generate id select fragment and then property select fragment for // each expression, just like generateSelectFragments(). RenderNonScalarSelects(CollectSelectExpressions(true), fromClause); } if (_scalarSelect || Walker.IsShallowQuery) { // If there are any scalars (non-entities) selected, render the select column aliases. RenderScalarSelects(selectExpressions, fromClause); } FinishInitialization(/*sqlResultTypeList,*/ queryReturnTypeList); }