/** * Prepares an explicitly defined select clause. * * @param fromClause The from clause linked to this select clause. * @throws SemanticException */ 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; IList <IType> constructorArgumentTypeList = _constructorNode.ConstructorArgumentTypeList; //sqlResultTypeList.addAll( constructorArgumentTypeList ); queryReturnTypeList.AddRange(constructorArgumentTypeList); _scalarSelect = true; for (int j = 1; j < _constructorNode.ChildCount; j++) { ISelectExpression se = _constructorNode.GetChild(j) as ISelectExpression; if (se != null && IsReturnableEntity(se)) { _fromElementsForLoad.Add(se.FromElement); } } } else { IType type = expr.DataType; if (type == null) { 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; } if (IsReturnableEntity(expr)) { _fromElementsForLoad.Add(expr.FromElement); } // 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 IList <IASTNode> fromElements = fromClause.GetProjectionList(); 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) { FromElement origin; if (fromElement.RealOrigin == null) { // work around that crazy issue where the tree contains // "empty" FromElements (no text); afaict, this is caused // by FromElementFactory.createCollectionJoin() if (fromElement.Origin == null) { throw new QueryException("Unable to determine origin of join fetch [" + fromElement.GetDisplayText() + "]"); } origin = fromElement.Origin; } else { origin = fromElement.RealOrigin; } if (!_fromElementsForLoad.Contains(origin)) { throw new QueryException(string.Format(JoinFetchWithoutOwnerExceptionMsg, fromElement.GetDisplayText())); } 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); }
/// <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; IList <IType> constructorArgumentTypeList = _constructorNode.ConstructorArgumentTypeList; //sqlResultTypeList.addAll( constructorArgumentTypeList ); queryReturnTypeList.AddRange(constructorArgumentTypeList); _scalarSelect = true; for (int j = 1; j < _constructorNode.ChildCount; j++) { ISelectExpression se = _constructorNode.GetChild(j) as ISelectExpression; if (se != null && IsReturnableEntity(se)) { _fromElementsForLoad.Add(se.FromElement); } } } else { IType type = expr.DataType; if (type == null && !(expr is ParameterNode)) { 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; } if (IsReturnableEntity(expr)) { _fromElementsForLoad.Add(expr.FromElement); } // 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 IList <IASTNode> fromElements = fromClause.GetProjectionList(); 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); }