private void PrepareForIndex(QueryTranslator q)
        {
            IQueryableCollection collPersister = q.GetCollectionPersister(collectionRole);

            if (!collPersister.HasIndex)
            {
                throw new QueryException("unindexed collection before []");
            }
            string[] indexCols = collPersister.IndexColumnNames;
            if (indexCols.Length != 1)
            {
                throw new QueryException("composite-index appears in []: " + path);
            }
            string[] keyCols = collPersister.KeyColumnNames;

            JoinFragment ojf = q.CreateJoinFragment(useThetaStyleJoin);

            ojf.AddCrossJoin(collPersister.TableName, collectionName);
            ojf.AddFromFragmentString(join.ToFromFragmentString);
            if (collPersister.IsOneToMany)
            {
                IQueryable persister = (IQueryable)collPersister.ElementPersister;
                ojf.AddJoins(
                    ((IJoinable)persister).FromJoinFragment(collectionName, true, false),
                    ((IJoinable)persister).WhereJoinFragment(collectionName, true, false)
                    );
            }

            if (!continuation)
            {
                AddJoin(collPersister.TableName, collectionName, keyCols);
            }
            join.AddCondition(collectionName, indexCols, " = ");

            string[] eltCols = collPersister.ElementColumnNames;

            CollectionElement elem = new CollectionElement();

            elem.ElementColumns = StringHelper.Qualify(collectionName, eltCols);
            elem.Type           = collPersister.ElementType;
            elem.IsOneToMany    = collPersister.IsOneToMany;
            elem.Alias          = collectionName;
            elem.Join           = join;
            collectionElements.Add(elem);               //addlast
            SetExpectingCollectionIndex();

            q.AddCollection(collectionName, collectionRole);
            q.AddJoin(collectionName, ojf);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="q"></param>
        /// <returns></returns>
        public string AddFromCollection(QueryTranslator q)
        {
            IType collectionElementType = PropertyType;

            if (collectionElementType == null)
            {
                throw new QueryException(string.Format("must specify 'elements' for collection valued property in from clause: {0}", path));
            }
            if (collectionElementType.IsEntityType)
            {
                // an association
                IQueryableCollection collectionPersister = q.GetCollectionPersister(collectionRole);
                IQueryable           entityPersister     = (IQueryable)collectionPersister.ElementPersister;
                System.Type          clazz = entityPersister.MappedClass;

                string[] collectionElementColumns = CurrentColumns();

                string elementName;
                if (collectionPersister.IsOneToMany)
                {
                    elementName = collectionName;
                    // allow index() function
                    q.DecoratePropertyMapping(elementName, collectionPersister);
                }
                else
                {
                    // many to many
                    q.AddCollection(collectionName, collectionRole);
                    elementName = q.CreateNameFor(clazz);
                    string[] keyColumnNames = entityPersister.IdentifierColumnNames;
                    join.AddJoin(entityPersister.TableName, elementName, collectionElementColumns, keyColumnNames, joinType);
                }
                q.AddFrom(elementName, clazz, join);
                currentPropertyMapping = new CollectionPropertyMapping(collectionPersister);
                return(elementName);
            }
            else
            {
                // collection of values
                q.AddFromCollection(collectionName, collectionRole, join);
                return(collectionName);
            }
        }
        private void PrepareForIndex(QueryTranslator q)
        {
            IQueryableCollection collPersister = q.GetCollectionPersister(collectionRole);

            if (!collPersister.HasIndex)
            {
                throw new QueryException("unindexed collection before []");
            }
            string[] indexCols = collPersister.IndexColumnNames;
            if (indexCols.Length != 1)
            {
                throw new QueryException("composite-index appears in []: " + path);
            }

            JoinSequence fromJoins = new JoinSequence(q.Factory)
                                     .SetUseThetaStyle(useThetaStyleJoin)
                                     .SetRoot(collPersister, collectionName)
                                     .SetNext(joinSequence.Copy());

            if (!continuation)
            {
                AddJoin(collectionName, collPersister.CollectionType);
            }
            joinSequence.AddCondition(new SqlString(collectionName + '.' + indexCols[0] + " = "));

            CollectionElement elem = new CollectionElement();

            elem.ElementColumns = collPersister.GetElementColumnNames(collectionName);
            elem.Type           = collPersister.ElementType;
            elem.IsOneToMany    = collPersister.IsOneToMany;
            elem.Alias          = collectionName;
            elem.JoinSequence   = joinSequence;
            collectionElements.Add(elem);             //addlast
            SetExpectingCollectionIndex();

            q.AddCollection(collectionName, collectionRole);
            q.AddJoin(collectionName, fromJoins);
        }
Example #4
0
        public void Token(string token, QueryTranslator q)
        {
            SessionFactoryHelper helper = new SessionFactoryHelper(q.Factory);
            string lctoken = token.ToLowerInvariant();

            if (first)
            {
                first = false;
                if ("distinct".Equals(lctoken))
                {
                    q.Distinct = true;
                    return;
                }
                else if ("all".Equals(lctoken))
                {
                    q.Distinct = false;
                    return;
                }
            }

            if (afterNew)
            {
                afterNew    = false;
                holderClass = helper.GetImportedClass(token);
                if (holderClass == null)
                {
                    throw new QueryException("class not found: " + token);
                }
                q.HolderClass = holderClass;
                insideNew     = true;
            }
            else if (token.Equals(StringHelper.Comma))
            {
                if (readyForAliasOrExpression)
                {
                    throw new QueryException("alias or expression expected in SELECT");
                }
                q.AppendScalarSelectToken(StringHelper.CommaSpace);
                readyForAliasOrExpression = true;
            }
            else if ("new".Equals(lctoken))
            {
                afterNew = true;
                readyForAliasOrExpression = false;
            }
            else if (StringHelper.OpenParen.Equals(token))
            {
                parenCount++;
                if (!funcStack.HasFunctions && holderClass != null && !readyForAliasOrExpression)
                {
                    //opening paren in new Foo ( ... )
                    readyForAliasOrExpression = true;
                }
                else if (funcStack.HasFunctions)
                {
                    q.AppendScalarSelectToken(token);
                }
                else
                {
                    throw new QueryException("HQL function expected before '(' in SELECT clause.");
                }
                readyForAliasOrExpression = true;
            }
            else if (StringHelper.ClosedParen.Equals(token))
            {
                parenCount--;
                if (parenCount < 0)
                {
                    throw new QueryException("'(' expected before ')' in SELECT clause.");
                }

                if (insideNew && !funcStack.HasFunctions && !readyForAliasOrExpression)
                {
                    //if we are inside a new Result(), but not inside a nested function
                    insideNew = false;
                }
                else if (funcStack.HasFunctions)
                {
                    q.AppendScalarSelectToken(token);
                    IType scalarType = funcStack.GetReturnType();
                    funcStack.Pop();

                    // Can't have an alias or expression right after the closing parenthesis of a function call.
                    readyForAliasOrExpression = false;

                    // if all functions were parsed add the type of the first function in stack
                    if (!funcStack.HasFunctions)
                    {
                        q.AddSelectScalar(scalarType);
                    }
                }
            }
            else if (IsHQLFunction(lctoken, q) && token == q.Unalias(token))
            {
                if (!readyForAliasOrExpression && !funcStack.HasFunctions)
                {
                    // The syntax control inside a functions is delegated to the render
                    throw new QueryException("',' expected before function in SELECT: " + token);
                }
                if (funcStack.HasFunctions && funcStack.FunctionGrammar.IsKnownArgument(lctoken))
                {
                    // Some function, like extract, may have KnownArgument with the same name of another function
                    q.AppendScalarSelectToken(token);
                }
                else
                {
                    // Is a nested function
                    funcStack.Push(GetFunction(lctoken, q));
                    q.AppendScalarSelectToken(token);
                    if (!funcStack.SqlFunction.HasArguments && !funcStack.SqlFunction.HasParenthesesIfNoArguments)
                    {
                        q.AddSelectScalar(funcStack.GetReturnType());
                        funcStack.Pop();
                        readyForAliasOrExpression = funcStack.HasFunctions;
                    }
                }
            }
            else if (funcStack.HasFunctions)
            {
                bool constantToken = false;
                var  expectedParen = parenCount + ((insideNew) ? -1 : 0);
                if (!readyForAliasOrExpression && expectedParen != funcStack.NestedFunctionCount)
                {
                    throw new QueryException("'(' expected after HQL function in SELECT");
                }
                try
                {
                    ParserHelper.Parse(funcStack.PathExpressionParser, q.Unalias(token), ParserHelper.PathSeparators, q);
                }
                catch (QueryException)
                {
                    if (IsPathExpression(token))
                    {
                        throw;
                    }
                    // If isn't a path the token is added like part of function arguments
                    constantToken = true;
                }

                if (token.StartsWith(ParserHelper.HqlVariablePrefix))
                {
                    string name = token.Substring(1);
                    q.AppendScalarSelectParameter(name);
                }
                else if (token.Equals(StringHelper.SqlParameter))
                {
                    q.AppendScalarSelectParameter();
                }
                else if (constantToken)
                {
                    q.AppendScalarSelectToken(token);
                }
                else
                {
                    if (funcStack.PathExpressionParser.IsCollectionValued)
                    {
                        q.AddCollection(
                            funcStack.PathExpressionParser.CollectionName,
                            funcStack.PathExpressionParser.CollectionRole);
                    }
                    q.AppendScalarSelectToken(funcStack.PathExpressionParser.WhereColumn);
                    funcStack.PathExpressionParser.AddAssociation(q);
                }
                // after a function argument
                readyForAliasOrExpression = false;
            }
            else
            {
                if (!readyForAliasOrExpression)
                {
                    throw new QueryException("',' expected in SELECT before:" + token);
                }

                try
                {
                    //High probablly to find a valid pathExpression
                    ParserHelper.Parse(pathExpressionParser, q.Unalias(token), ParserHelper.PathSeparators, q);
                    if (pathExpressionParser.IsCollectionValued)
                    {
                        q.AddCollection(
                            pathExpressionParser.CollectionName,
                            pathExpressionParser.CollectionRole);
                    }
                    else if (pathExpressionParser.WhereColumnType.IsEntityType)
                    {
                        q.AddSelectClass(pathExpressionParser.SelectName);
                    }
                    q.AppendScalarSelectTokens(pathExpressionParser.WhereColumns);
                    q.AddSelectScalar(pathExpressionParser.WhereColumnType);
                    pathExpressionParser.AddAssociation(q);
                }
                catch (QueryException)
                {
                    // Accept costants in SELECT: NH-280
                    // TODO: Parse a costant expression like 5+3+8 (now is not supported in SELECT)
                    if (IsStringCostant(token))
                    {
                        q.AppendScalarSelectToken(token);
                        q.AddSelectScalar(NHibernateUtil.String);
                    }
                    else if (IsIntegerConstant(token))
                    {
                        q.AppendScalarSelectToken(token);
                        q.AddSelectScalar(GetIntegerConstantType(token));
                    }
                    else if (IsFloatingPointConstant(token))
                    {
                        q.AppendScalarSelectToken(token);
                        q.AddSelectScalar(GetFloatingPointConstantType());
                    }
                    else if (token.StartsWith(ParserHelper.HqlVariablePrefix))
                    {
                        string name = token.Substring(1);
                        q.AppendScalarSelectParameter(name);
                    }
                    else if (token.Equals(StringHelper.SqlParameter))
                    {
                        q.AppendScalarSelectParameter();
                    }
                    else
                    {
                        throw;
                    }
                }
                readyForAliasOrExpression = false;
            }
        }
Example #5
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="token"></param>
        /// <param name="q"></param>
        public void Token(string token, QueryTranslator q)
        {
            string lctoken = token.ToLower(System.Globalization.CultureInfo.InvariantCulture);

            if (first)
            {
                first = false;
                if (lctoken.Equals("distinct"))
                {
                    q.Distinct = true;
                    return;
                }
                else if (lctoken.Equals("all"))
                {
                    q.Distinct = false;
                    return;
                }
            }

            if (afterNew)
            {
                afterNew    = false;
                holderClass = q.GetImportedClass(token);
                if (holderClass == null)
                {
                    throw new QueryException("class not found: " + token);
                }
                q.HolderClass = holderClass;
                insideNew     = true;
            }
            else if (token.Equals(StringHelper.Comma))
            {
                if (ready)
                {
                    throw new QueryException("alias or expression expected in SELECT");
                }
                q.AppendScalarSelectToken(StringHelper.CommaSpace);
                ready = true;
            }
            else if ("new".Equals(lctoken))
            {
                afterNew = true;
                ready    = false;
            }
            else if (StringHelper.OpenParen.Equals(token))
            {
                if (!aggregate && holderClass != null && !ready)
                {
                    //opening paren in new Foo ( ... )
                    ready = true;
                }
                else if (aggregate)
                {
                    q.AppendScalarSelectToken(token);
                }
                else
                {
                    throw new QueryException("aggregate function expected before ( in SELECT");
                }
                ready = true;
            }
            else if (StringHelper.ClosedParen.Equals(token))
            {
                if (insideNew && !aggregate && !ready)
                {
                    //if we are inside a new Result(), but not inside a nested function
                    insideNew = false;
                }
                else if (aggregate && ready)
                {
                    q.AppendScalarSelectToken(token);
                    aggregateFuncTokenList.RemoveAt(0);
                    if (aggregateFuncTokenList.Count < 1)
                    {
                        aggregate = false;
                        ready     = false;
                    }
                }
                else
                {
                    throw new QueryException("( expected before ) in select");
                }
            }
            else if (countArguments.Contains(lctoken))
            {
                if (!ready || !aggregate)
                {
                    throw new QueryException(token + " only allowed inside aggregate function in SELECT");
                }
                q.AppendScalarSelectToken(token);
                if ("*".Equals(token))
                {
                    q.AddSelectScalar(NHibernateUtil.Int32);
                }                 //special case
            }
            else if (GetFunction(lctoken, q) != null && token == q.Unalias(token))
            {
                // the name of an SQL function
                if (!ready)
                {
                    throw new QueryException(", expected before aggregate function in SELECT: " + token);
                }
                aggregate = true;
                aggregateAddSelectScalar = true;
                aggregateFuncTokenList.Insert(0, lctoken);
                ready = false;
                q.AppendScalarSelectToken(token);
                if (!AggregateHasArgs(lctoken, q))
                {
                    q.AddSelectScalar(AggregateType(aggregateFuncTokenList, null, q));
                    if (!AggregateFuncNoArgsHasParenthesis(lctoken, q))
                    {
                        aggregateFuncTokenList.RemoveAt(0);
                        if (aggregateFuncTokenList.Count < 1)
                        {
                            aggregate = false;
                            ready     = false;
                        }
                        else
                        {
                            ready = true;
                        }
                    }
                }
            }
            else if (aggregate)
            {
                bool constantToken = false;
                if (!ready)
                {
                    throw new QueryException("( expected after aggregate function in SELECT");
                }
                try
                {
                    ParserHelper.Parse(aggregatePathExpressionParser, q.Unalias(token), ParserHelper.PathSeparators, q);
                }
                catch (QueryException)
                {
                    constantToken = true;
                }

                if (constantToken)
                {
                    q.AppendScalarSelectToken(token);
                }
                else
                {
                    if (aggregatePathExpressionParser.IsCollectionValued)
                    {
                        q.AddCollection(
                            aggregatePathExpressionParser.CollectionName,
                            aggregatePathExpressionParser.CollectionRole);
                    }
                    q.AppendScalarSelectToken(aggregatePathExpressionParser.WhereColumn);
                    if (aggregateAddSelectScalar)
                    {
                        q.AddSelectScalar(AggregateType(aggregateFuncTokenList, aggregatePathExpressionParser.WhereColumnType, q));
                        aggregateAddSelectScalar = false;
                    }
                    aggregatePathExpressionParser.AddAssociation(q);
                }
            }
            else
            {
                if (!ready)
                {
                    throw new QueryException(", expected in SELECT");
                }

                ParserHelper.Parse(pathExpressionParser, q.Unalias(token), ParserHelper.PathSeparators, q);
                if (pathExpressionParser.IsCollectionValued)
                {
                    q.AddCollection(
                        pathExpressionParser.CollectionName,
                        pathExpressionParser.CollectionRole);
                }
                else if (pathExpressionParser.WhereColumnType.IsEntityType)
                {
                    q.AddSelectClass(pathExpressionParser.SelectName);
                }
                q.AppendScalarSelectTokens(pathExpressionParser.WhereColumns);
                q.AddSelectScalar(pathExpressionParser.WhereColumnType);
                pathExpressionParser.AddAssociation(q);

                ready = false;
            }
        }