private static void RenderNonScalarProperties(ASTAppender appender, FromElement fromElement, int nonscalarSize, int k) { string text = fromElement.RenderPropertySelect(nonscalarSize, k); appender.Append(HqlSqlWalker.SQL_TOKEN, text, false); if (fromElement.QueryableCollection != null && fromElement.IsFetch) { text = fromElement.RenderCollectionSelectFragment(nonscalarSize, k); appender.Append(HqlSqlWalker.SQL_TOKEN, text, false); } // Look through the FromElement's children to find any collections of values that should be fetched... ASTIterator iter = new ASTIterator(fromElement); foreach (FromElement child in iter) { if (child.IsCollectionOfValuesOrComponents && child.IsFetch) { // Need a better way to define the suffixes here... text = child.RenderValueCollectionSelectFragment(nonscalarSize, nonscalarSize + k); appender.Append(HqlSqlWalker.SQL_TOKEN, text, false); } } }
private void RenderNonScalarIdentifiers(FromElement fromElement, int nonscalarSize, int j, ISelectExpression expr, ASTAppender appender) { string text = fromElement.RenderIdentifierSelect(nonscalarSize, j); if (!fromElement.FromClause.IsSubQuery) { if (!_scalarSelect && !Walker.IsShallowQuery) { //TODO: is this a bit ugly? expr.Text = text; } else { appender.Append(HqlSqlWalker.SQL_TOKEN, text, false); } } }
/// <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" ); // } IList<IASTNode> fromElements = fromClause.GetProjectionList(); ASTAppender appender = new ASTAppender(ASTFactory, this); // Get ready to start adding nodes. int size = fromElements.Count; List<IType> sqlResultTypeList = new List<IType>(size); 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); 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++; } // 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); }
private void RenderNonScalarSelects(ISelectExpression[] selectExpressions, FromClause currentFromClause) { ASTAppender appender = new ASTAppender(ASTFactory, this); int size = selectExpressions.Length; int nonscalarSize = 0; for (int i = 0; i < size; i++) { if (!selectExpressions[i].IsScalar) { nonscalarSize++; } } int j = 0; for (int i = 0; i < size; i++) { if (!selectExpressions[i].IsScalar) { ISelectExpression expr = selectExpressions[i]; FromElement fromElement = expr.FromElement; if (fromElement != null) { RenderNonScalarIdentifiers(fromElement, nonscalarSize, j, expr, appender); j++; } } } if (!currentFromClause.IsSubQuery) { // Generate the property select tokens. int k = 0; for (int i = 0; i < size; i++) { if (!selectExpressions[i].IsScalar) { FromElement fromElement = selectExpressions[i].FromElement; if (fromElement != null) { RenderNonScalarProperties(appender, fromElement, nonscalarSize, k); k++; } } } } }
/// <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) { 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; } // 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); }
private void RenderNonScalarSelects(ISelectExpression[] selectExpressions, FromClause currentFromClause) { var appender = new ASTAppender(ASTFactory, this); var nonscalarSize = selectExpressions.Count(e => !e.IsScalar); int j = 0; foreach (var e in selectExpressions) { if (!e.IsScalar) { FromElement fromElement = e.FromElement; if (fromElement != null) { RenderNonScalarIdentifiers(fromElement, nonscalarSize, j, e, appender); j++; } } } if (!currentFromClause.IsSubQuery) { // Generate the property select tokens. int k = 0; foreach (var e in selectExpressions) { if (!e.IsScalar) { FromElement fromElement = e.FromElement; if (fromElement != null) { RenderNonScalarProperties(appender, fromElement, nonscalarSize, k); k++; } } } } }