예제 #1
0
        public Dictionary <IASTNode, IASTNode[]> Process(IASTNode tree)
        {
            foreach (var querySource in new QuerySourceDetector(tree).LocateQuerySources())
            {
                var className = GetClassName(querySource);
                var classType = _sessionFactoryHelper.GetImportedClass(className);

                AddImplementorsToMap(querySource, classType == null ? className : classType.FullName);
            }

            return(_map);
        }
예제 #2
0
        /// <summary>
        /// Handle Hibernate "implicit" polymorphism, by translating the query string into
        /// several "concrete" queries against mapped classes.
        /// </summary>
        /// <param name="query"></param>
        /// <param name="factory"></param>
        /// <returns></returns>
        /// <exception cref="NHibernate.MappingException"/>
        public static string[] ConcreteQueries(string query, ISessionFactoryImplementor factory)
        {
            //scan the query string for class names appearing in the from clause and replace
            //with all persistent implementors of the class/interface, returning multiple
            //query strings (make sure we don't pick up a class in the select clause!)

            //TODO: this is one of the ugliest and most fragile pieces of code in Hibernate....

            SessionFactoryHelper helper = new SessionFactoryHelper(factory);

            string[] tokens = StringHelper.Split(StringHelper.WhiteSpace + "(),", query, true);
            if (tokens.Length == 0)
            {
                return(new String[] { query });              // just especially for the trivial collection filter
            }
            ArrayList     placeholders  = new ArrayList();
            ArrayList     replacements  = new ArrayList();
            StringBuilder templateQuery = new StringBuilder(40);
            int           count         = 0;
            string        last          = null;
            int           nextIndex     = 0;
            string        next          = null;

            templateQuery.Append(tokens[0]);
            bool isSelectClause = StringHelper.EqualsCaseInsensitive("select", tokens[0]);

            for (int i = 1; i < tokens.Length; i++)
            {
                //update last non-whitespace token, if necessary
                if (!ParserHelper.IsWhitespace(tokens[i - 1]))
                {
                    last = tokens[i - 1].ToLowerInvariant();
                }

                // select-range is terminated by declaration of "from"
                isSelectClause = !StringHelper.EqualsCaseInsensitive("from", tokens[i]);

                string token = tokens[i];
                if (!ParserHelper.IsWhitespace(token) || last == null)
                {
                    //scan for next non-whitespace token
                    if (nextIndex <= i)
                    {
                        for (nextIndex = i + 1; nextIndex < tokens.Length; nextIndex++)
                        {
                            next = tokens[nextIndex].ToLowerInvariant();
                            if (!ParserHelper.IsWhitespace(next))
                            {
                                break;
                            }
                        }
                    }

                    // TODO H3.2 Different behavior
                    // NHb: This block is not an exactly port from H3.2 but a port from previous implementation of QueryTranslator
                    if (((last != null && beforeClassTokens.Contains(last)) &&
                         (next == null || !notAfterClassTokens.Contains(next))) ||
                        PathExpressionParser.EntityClass.Equals(last))
                    {
                        System.Type clazz = helper.GetImportedClass(token);
                        if (clazz != null)
                        {
                            string[] implementors = factory.GetImplementors(clazz.FullName);
                            string   placeholder  = "$clazz" + count++ + "$";

                            if (implementors != null)
                            {
                                placeholders.Add(placeholder);
                                replacements.Add(implementors);
                            }
                            token = placeholder;                             //Note this!!
                        }
                    }
                }
                templateQuery.Append(token);
            }
            string[] results =
                StringHelper.Multiply(templateQuery.ToString(), placeholders.GetEnumerator(), replacements.GetEnumerator());
            if (results.Length == 0)
            {
                log.Warn("no persistent classes found for query class: " + query);
            }
            return(results);
        }
예제 #3
0
        private void DoToken(string token, QueryTranslator q)
        {
            SessionFactoryHelper helper = new SessionFactoryHelper(q.Factory);

            if (q.IsName(StringHelper.Root(token)))             //path expression
            {
                DoPathExpression(q.Unalias(token), q);
            }
            else if (token.StartsWith(ParserHelper.HqlVariablePrefix))             //named query parameter
            {
                var name = token.Substring(1);
                // this is only a temporary parameter to help with the parsing of hql -
                // when the type becomes known then this will be converted to its real
                // parameter type.
                AppendToken(q, q.GetNamedParameter(name));
            }
            else if (token.Equals(StringHelper.SqlParameter))
            {
                //if the token is a "?" then we have a Parameter so convert it to a SqlCommand.Parameter
                // instead of appending a "?" to the WhereTokens
                AppendToken(q, q.GetPositionalParameter());
            }
            else
            {
                IQueryable persister = q.GetPersisterUsingImports(token);
                if (persister != null)                 // the name of a class
                {
                    string discrim = persister.DiscriminatorSQLValue;
                    if (InFragment.Null == discrim || InFragment.NotNull == discrim)
                    {
                        throw new QueryException("subclass test not allowed for null or not null discriminator");
                    }
                    AppendToken(q, discrim);
                }
                else
                {
                    object      constant;
                    string      fieldName    = null;
                    System.Type importedType = null;

                    int indexOfDot = token.IndexOf(StringHelper.Dot);
                    // don't even bother to do the lookups if the indexOfDot is not
                    // greater than -1.  This will save all the string modifications.

                    // This allows us to resolve to the full type before obtaining the value e.g. FooStatus.OFF -> NHibernate.Model.FooStatus.OFF
                    if (indexOfDot > -1)
                    {
                        fieldName = StringHelper.Unqualify(token);
                        string typeName = StringHelper.Qualifier(token);
                        importedType = helper.GetImportedClass(typeName);
                    }

                    if (indexOfDot > -1 && importedType != null &&
                        (constant = ReflectHelper.GetConstantValue(importedType, fieldName)) != null)
                    {
                        // need to get the NHibernate Type so we can convert the Enum or field from
                        // a class into it's string representation for hql.
                        IType type;
                        try
                        {
                            type = TypeFactory.HeuristicType(constant.GetType().AssemblyQualifiedName);
                        }
                        catch (MappingException me)
                        {
                            throw new QueryException(me);
                        }

                        if (type == null)
                        {
                            throw new QueryException(string.Format("Could not determin the type of: {0}", token));
                        }

                        try
                        {
                            AppendToken(q, ((ILiteralType)type).ObjectToSQLString(constant, q.Factory.Dialect));
                        }
                        catch (Exception e)
                        {
                            throw new QueryException("Could not format constant value to SQL literal: " + token, e);
                        }
                    }
                    else
                    {
                        //anything else
                        string negatedToken = null;
                        if (negated)
                        {
                            negations.TryGetValue(token.ToLowerInvariant(), out negatedToken);
                        }
                        if (negatedToken != null && (!betweenSpecialCase || !"or".Equals(negatedToken)))
                        {
                            AppendToken(q, negatedToken);
                        }
                        else
                        {
                            AppendToken(q, token);
                        }
                    }
                }
            }
        }
예제 #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;
            }
        }