public string ContinueFromManyToMany(string clazz, string[] joinColumns, QueryTranslator q)
        {
            Start(q);
            continuation = true;
            currentName  = q.CreateNameFor(clazz);
            q.AddType(currentName, clazz);
            IQueryable classPersister = q.GetPersister(clazz);

            AddJoin(currentName, TypeFactory.ManyToOne(clazz), joinColumns);
            currentPropertyMapping = classPersister;
            return(currentName);
        }
        public string ContinueFromManyToMany(System.Type clazz, string[] joinColumns, QueryTranslator q)
        {
            Start(q);
            continuation = true;
            currentName  = q.CreateNameFor(clazz);
            q.AddType(currentName, clazz);
            IQueryable classPersister = q.GetPersister(clazz);

            join.AddJoin(classPersister.TableName, currentName, joinColumns, classPersister.IdentifierColumnNames, joinType);
            currentPropertyMapping = classPersister;
            return(currentName);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="propertyName"></param>
        /// <param name="propertyType"></param>
        /// <param name="q"></param>
        /// <remarks>NOTE: we avoid joining to the next table if the named property is just the foreign key value</remarks>
        private void DereferenceEntity(string propertyName, EntityType propertyType, QueryTranslator q)
        {
            //if its "id"
            bool isIdShortcut = EntityID.Equals(propertyName) && !propertyType.IsUniqueKeyReference;

            //or its the id property name
            string idPropertyName;

            try
            {
                idPropertyName = propertyType.GetIdentifierOrUniqueKeyPropertyName(q.Factory);
            }
            catch (MappingException me)
            {
                throw new QueryException(me);
            }
            bool isNamedIdPropertyShortcut = idPropertyName != null && idPropertyName.Equals(propertyName);

            if (isIdShortcut || isNamedIdPropertyShortcut)
            {
                // special shortcut for id properties, skip the join!
                // this must only occur at the _end_ of a path expression
                DereferenceProperty(propertyName);
            }
            else
            {
                System.Type entityClass = propertyType.AssociatedClass;
                String      name        = q.CreateNameFor(entityClass);
                q.AddType(name, entityClass);
                IQueryable memberPersister = q.GetPersister(entityClass);
                //String[] keyColNames = memberPersister.getIdentifierColumnNames();
                string[] keyColNames;
                try
                {
                    keyColNames = propertyType.GetReferencedColumns(q.Factory);
                }
                catch (MappingException me)
                {
                    throw new QueryException(me);
                }
                AddJoin(memberPersister.TableName, name, keyColNames);
                if (propertyType.IsOneToOne)
                {
                    oneToOneOwnerName = currentName;
                }
                currentName     = name;
                currentProperty = propertyName;
                q.AddPathAliasAndJoin(path.Substring(0, path.LastIndexOf(StringHelper.Dot)), name, join);
                componentPath = null;
                //componentPath = new StringBuilder( );
                currentPropertyMapping = memberPersister;
            }
        }
        /// <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);
            }
        }
Beispiel #5
0
        public void Token(string token, QueryTranslator q)
        {
            // start by looking for HQL keywords....
            string lcToken = token.ToLower(System.Globalization.CultureInfo.InvariantCulture);

            if (lcToken.Equals(StringHelper.Comma))
            {
                if (!(expectingJoin | expectingAs))
                {
                    throw new QueryException("unexpected token: ,");
                }
                expectingJoin = false;
                expectingAs   = false;
            }
            else if (lcToken.Equals("join"))
            {
                if (!afterJoinType)
                {
                    if (!(expectingJoin | expectingAs))
                    {
                        throw new QueryException("unexpected token: join");
                    }
                    // inner joins can be abbreviated to 'join'
                    joinType      = JoinType.InnerJoin;
                    expectingJoin = false;
                    expectingAs   = false;
                }
                else
                {
                    afterJoinType = false;
                }
            }
            else if (lcToken.Equals("fetch"))
            {
                if (q.IsShallowQuery)
                {
                    throw new QueryException("fetch may not be used with scroll() or iterate()");
                }
                if (joinType == JoinType.None)
                {
                    throw new QueryException("unexpected token: fetch");
                }
                if (joinType == JoinType.FullJoin || joinType == JoinType.RightOuterJoin)
                {
                    throw new QueryException("fetch may only be used with inner join or left outer join");
                }
                afterFetch = true;
            }
            else if (lcToken.Equals("outer"))
            {
                // 'outer' is optional and is ignored)
                if (!afterJoinType || (joinType != JoinType.LeftOuterJoin && joinType != JoinType.RightOuterJoin))
                {
                    throw new QueryException("unexpected token: outer");
                }
            }
            else if (joinTypes.Contains(lcToken))
            {
                if (!(expectingJoin | expectingAs))
                {
                    throw new QueryException("unexpected token: " + token);
                }
                joinType      = ( JoinType )joinTypes[lcToken];
                afterJoinType = true;
                expectingJoin = false;
                expectingAs   = false;
            }
            else if (lcToken.Equals("class"))
            {
                if (!afterIn)
                {
                    throw new QueryException("unexpected token: class");
                }
                if (joinType != JoinType.None)
                {
                    throw new QueryException("outer or full join must be followed by path expression");
                }
                afterClass = true;
            }
            else if (lcToken.Equals("in"))
            {
                if (!expectingIn)
                {
                    throw new QueryException("unexpected token: in");
                }
                afterIn     = true;
                expectingIn = false;
            }
            else if (lcToken.Equals("as"))
            {
                if (!expectingAs)
                {
                    throw new QueryException("unexpected token: as");
                }
                afterAs     = true;
                expectingAs = false;
            }
            else
            {
                if (afterJoinType)
                {
                    throw new QueryException("join expected: " + token);
                }
                if (expectingJoin)
                {
                    throw new QueryException("unexpected token: " + token);
                }
                if (expectingIn)
                {
                    throw new QueryException("in expected: " + token);
                }

                // now anything that is not a HQL keyword

                if (afterAs || expectingAs)
                {
                    // (AS is always optional, for consistentcy with SQL/OQL

                    // process the "new" HQL stype where aliases are assigned
                    // _after_ the class name or path expression ie using the
                    // AS construction

                    if (entityName != null)
                    {
                        q.SetAliasName(token, entityName);
                    }
                    else
                    {
                        throw new QueryException("unexpected: as " + token);
                    }
                    afterAs       = false;
                    expectingJoin = true;
                    expectingAs   = false;
                    entityName    = null;
                }
                else if (afterIn)
                {
                    // process the "old" HQL style where aliases appear _first
                    // ie using the IN or IN CLASS constructions

                    if (alias == null)
                    {
                        throw new QueryException("alias not specified for: " + token);
                    }

                    if (joinType != JoinType.None)
                    {
                        throw new QueryException("outer or full join must be followed by path expressions");
                    }

                    if (afterClass)
                    {
                        // treat it as a classname
                        IQueryable p = q.GetPersisterUsingImports(token);
                        if (p == null)
                        {
                            throw new QueryException("persister not found: " + token);
                        }
                        q.AddFromClass(alias, p);
                    }
                    else
                    {
                        // treat it as a path expression
                        peParser.JoinType          = JoinType.InnerJoin;
                        peParser.UseThetaStyleJoin = true;
                        ParserHelper.Parse(peParser, q.Unalias(token), ParserHelper.PathSeparators, q);
                        if (!peParser.IsCollectionValued)
                        {
                            throw new QueryException("pathe expression did not resolve to collection: " + token);
                        }
                        string nm = peParser.AddFromCollection(q);
                        q.SetAliasName(alias, nm);
                    }

                    alias         = null;
                    afterIn       = false;
                    afterClass    = false;
                    expectingJoin = true;
                }
                else
                {
                    // handle a path expression or class name that appears
                    // at the start, in the "new" HQL style or an alias that
                    // appears at the start in the "old HQL stype
                    IQueryable p = q.GetPersisterUsingImports(token);
                    if (p != null)
                    {
                        // starts with the name of a mapped class (new style)
                        if (joinType != JoinType.None)
                        {
                            throw new QueryException("outer or full join must be followed by path expression");
                        }
                        entityName = q.CreateNameFor(p.MappedClass);
                        q.AddFromClass(entityName, p);
                        expectingAs = true;
                    }
                    else if (token.IndexOf('.') < 0)
                    {
                        // starts with an alias (old style)
                        // semi-bad thing about this: can't re-alias another alias...
                        alias       = token;
                        expectingIn = true;
                    }
                    else
                    {
                        // starts with a path expression (new style)

                        // force HQL style: from Person p inner join p.cars c
                        //if (joinType==JoinType.None) throw new QueryException("path expression must be preceded by full, left, right or inner join");

                        //allow ODMG OQL style: from Person p, p.cars c
                        if (joinType != JoinType.None)
                        {
                            peParser.JoinType = joinType;
                        }
                        else
                        {
                            peParser.JoinType = JoinType.InnerJoin;
                        }
                        peParser.UseThetaStyleJoin = q.IsSubquery;

                        ParserHelper.Parse(peParser, q.Unalias(token), ParserHelper.PathSeparators, q);
                        entityName = peParser.AddFromAssociation(q);

                        joinType          = JoinType.None;
                        peParser.JoinType = JoinType.InnerJoin;

                        if (afterFetch)
                        {
                            peParser.Fetch(q, entityName);
                            afterFetch = false;
                        }

                        expectingAs = true;
                    }
                }
            }
        }