private void AutoDetectCollections(SchemaInfo si)
        {
            int counter = 0;
            foreach (ClassInfo ci in si.Classes)
            {
                foreach (FieldInfo fi in ci.LocalTables[0].Fields)
                {
                    if (fi.ReferencedClass != null)
                    {
                        ArrayList al = new ArrayList();
                        if (fi.ReferencedClass.Collections1toN != null)
                        {
                            al.AddRange(fi.ReferencedClass.Collections1toN);
                        }
                        CollectionOnetoManyInfo coll = new CollectionOnetoManyInfo();
                        coll.Name = "CollectionOf" + ci.Name + "" + counter++;
                        coll.ClassName = ci.Name;
                        coll.ForeignFieldName = fi.Name;
                        al.Add(coll);

                        fi.ReferencedClass.Collections1toN = (CollectionOnetoManyInfo[])al.ToArray(typeof(CollectionOnetoManyInfo));
                        // ci.Collections1toN
                    }
                }
            }
            foreach (RelationInfo ri in si.Relations)
            {
                CollectionManyToManyInfo mm;
                ArrayList al;

                al = new ArrayList();
                if (ri.Table.Fields[0].ReferencedClass.CollectionsNtoN != null)
                    al.AddRange(ri.Table.Fields[0].ReferencedClass.CollectionsNtoN);

                mm = new CollectionManyToManyInfo();
                mm.Name = "CollectionOf" + ri.Table.Fields[1].ReferencedClass.Name + "" + counter++;
                mm.Relation = ri.Name;
                mm.ForeignField = ri.Table.Fields[0].Name;
                al.Add(mm);

                ri.Table.Fields[0].ReferencedClass.CollectionsNtoN = (CollectionManyToManyInfo[])al.ToArray(typeof(CollectionManyToManyInfo));

                al = new ArrayList();
                if (ri.Table.Fields[1].ReferencedClass.CollectionsNtoN != null)
                    al.AddRange(ri.Table.Fields[1].ReferencedClass.CollectionsNtoN);

                mm = new CollectionManyToManyInfo();
                mm.Name = "CollectionOf" + ri.Table.Fields[0].ReferencedClass.Name + "" + al.Count;
                mm.Relation = ri.Name;
                mm.ForeignField = ri.Table.Fields[1].Name;
                al.Add(mm);

                ri.Table.Fields[1].ReferencedClass.CollectionsNtoN = (CollectionManyToManyInfo[])al.ToArray(typeof(CollectionManyToManyInfo));

            }
        }
        SoqlQueryExpression CreateCollectionQuery(ClassInfo currentClass, string p, CollectionOnetoManyInfo col1n, SoqlExpression selectExpression, SoqlExpression needle)
        {
            SoqlBooleanExpression where = new SoqlBooleanRelationalExpression(
                new SoqlPathExpression(col1n.ForeignField2.Name),
                new SoqlPathExpression(new SoqlPathExpression(p.Split('.')), currentClass.GetFirstPrimaryKeyField().Name),
                SoqlRelationalOperator.Equal);

            if (col1n.Where != null && col1n.Where.Length > 0)
                where &= SoqlParser.ParseWhereClause(col1n.Where);

            string fromAlias = string.Empty;
            if (needle != null)
            {
                SoqlQueryExpression nq = needle as SoqlQueryExpression;
                if (nq != null
                    && nq.StartIdx == 0 && nq.PageCount == -1 && nq.SelectExpressions.Count == 0
                    && nq.From.Count == 1 && nq.From[0] == col1n.ClassName
                    && nq.Having == null && nq.GroupByExpressions.Count == 0)
                {
                    fromAlias = nq.FromAliases[0];
                    if (nq.WhereClause != null)
                        where &= nq.WhereClause;
                }
                else
                {
                    if (col1n.Class.GetPrimaryKeyFields().Length >= 2)
                        throw new NotSupportedException("Contains() with composite primary key");
                    SoqlExpressionCollection collection = new SoqlExpressionCollection();
                    collection.Add(needle);
                    where &= new SoqlBooleanInExpression(
                        new SoqlPathExpression(col1n.Class.GetFirstPrimaryKeyField().Name),
                        collection);
                }
            }

            SoqlQueryExpression query = new SoqlQueryExpression();
            query.SelectExpressions.Add(selectExpression);
            query.SelectAliases.Add("");
            query.From.Add(col1n.ClassName);
            query.FromAliases.Add(fromAlias);
            query.WhereClause = where;
            return query;
        }