Example #1
0
        void CreateSubQueries(QueryContextsEntry queryContextsEntry,
                              OqlExpression expressionTree,
                              bool hollow,
                              bool hasSubclassResultsets,
                              List <QueryOrder> orderings,
                              int skip,
                              int take)
        {
            Type t             = queryContextsEntry.Type;
            var  queryContexts = queryContextsEntry.QueryContexts;

            if (queryContexts.Count == 0)
            {
                this.subQueries.Add(new QueryInfo(t, ConstructQueryString(t, new Dictionary <Relation, Class>(), expressionTree, hollow, hasSubclassResultsets, orderings, skip, take)));
            }
            else
            {
                string queryString = string.Empty;
                int    added       = 0;
                foreach (var queryContext in queryContexts)
                {
                    if (!queryContext.Any(kvp => kvp.Value.SystemType == t))
                    {
                        if (added > 0)
                        {
                            queryString += " UNION \r\n";
                        }
                        queryString += ConstructQueryString(t, queryContext, expressionTree, hollow, hasSubclassResultsets, orderings, skip, take);
                        added++;
                    }
                }
                this.subQueries.Add(new QueryInfo(t, queryString));
            }
        }
Example #2
0
        void AddExpr(out OqlExpression expression)
        {
            OqlExpression child;
            OqlExpression result = new OqlExpression(la.line, la.col);
            string        newOp  = null;

            MulExpr(out child);
            result.Add(child);
            while (la.kind == 31 || la.kind == 32)
            {
                if (la.kind == 31)
                {
                    Get();
                    newOp = "+";
                }
                else
                {
                    Get();
                    newOp = "-";
                }
                MulExpr(out child);
                result.Add(child, newOp);
            }
            expression = result.Simplify();
        }
Example #3
0
        internal string GenerateFromExpression(OqlExpression expressionTree, List <Relation> prefetchRelations = null)
        {
            StringBuilder sb = new StringBuilder();

            AnnotateExpressionTree(expressionTree, prefetchRelations);
            if (expressionTree != null)
            {
                List <IdentifierExpression> identifiers = expressionTree.GetAll(e => e is IdentifierExpression && !String.Empty.Equals(e.GetAnnotation <string>(anKey))).Select(e => (IdentifierExpression)e).ToList();
                identifiers.Sort((i1, i2) => ((string)i1.Value).CompareTo((string)i2.Value));
                bool isFirst = true;
                foreach (IdentifierExpression exp in identifiers)
                {
                    if (!String.IsNullOrEmpty(exp.GetAnnotation <string>(anKey)))
                    {
                        if (isFirst)
                        {
                            sb.Append(' ');
                            isFirst = false;
                        }
                        sb.Append(exp.GetAnnotation <string>(anKey));
                        sb.Append(' ');
                    }
                }

                if (sb.Length > 0)
                {
                    sb.Length--;
                }
            }
            return("FROM " + cls.GetQualifiedTableName() + sb.ToString());
        }
Example #4
0
        void AndExpr(out OqlExpression expression)
        {
            OqlExpression child;
            OqlExpression result = new OqlExpression(la.line, la.col);

            EqlExpr(out child);
            result.Add(child);
            while (la.kind == 5)
            {
                Get();
                bool negated = false;
                if (la.kind == 7)
                {
                    Get();
                    negated = true;
                }
                EqlExpr(out child);
                if (negated)
                {
                    child.UnaryOp = "NOT";
                }
                result.Add(child, "AND");
            }
            expression = result.Simplify();
        }
Example #5
0
        void Unary(out OqlExpression expression)
        {
            OqlExpression child;
            OqlExpression result = new OqlExpression(la.line, la.col);
            string        newOp  = null;

            if (la.kind == 31 || la.kind == 32 || la.kind == 36)
            {
                if (la.kind == 31)
                {
                    Get();
                    newOp = "+";
                }
                else if (la.kind == 32)
                {
                    Get();
                    newOp = "-";
                }
                else
                {
                    Get();
                    newOp = "~";
                }
            }
            Primary(out child);
            result.Add(child); child.UnaryOp = newOp;
            expression = result.Simplify();
        }
Example #6
0
        private void GenerateQueryContexts()
        {
            //if ((int) this.queryLanguage == OldQuery.LoadRelations)
            //	LoadRelatedTables();
            //else if (this.queryLanguage == Language.NDOql)
            if (this.queryLanguage == QueryLanguage.Sql)
            {
                var selectList = new SqlColumnListGenerator(pm.NDOMapping.FindClass(typeof(T))).SelectList;
                var sql        = Regex.Replace(this.queryExpression, @"SELECT\s+\*", "SELECT " + selectList);
                this.expressionTree = new RawIdentifierExpression(sql, 0, 0);
            }
            else
            {
                NDOql.OqlParser parser     = new NDOql.OqlParser();
                var             parsedTree = parser.Parse(this.queryExpression);
                if (parsedTree != null)
                {
                    // The root expression tree might get exchanged.
                    // To make this possible we make it the child of a dummy expression.
                    this.expressionTree = new OqlExpression(0, 0);
                    this.expressionTree.Add(parsedTree);
                    ((IManageExpression)parsedTree).SetParent(this.expressionTree);
                }
            }

            CreateQueryContextsForTypes();
        }
Example #7
0
        /// <summary>
        /// Parses a given Oql string
        /// </summary>
        /// <param name="oql"></param>
        /// <returns></returns>
        public OqlExpression Parse(string oql)
        {
            if (String.IsNullOrEmpty(oql))
            {
                return(null);
            }
            MemoryStream stream = new MemoryStream();
            StreamWriter sw     = new StreamWriter(stream, Encoding.UTF8);

            sw.Write(oql);
            sw.Flush();
            stream.Position = 0;
            Parser       parser = new Parser(new Scanner(stream));
            MemoryStream ms     = new MemoryStream();
            StreamWriter errSw  = new StreamWriter(ms);

            parser.errors.errorStream = errSw;
            parser.Parse();
            if (parser.errors.count > 0)
            {
                errSw.Flush();
                ms.Seek(0L, SeekOrigin.Begin);
                string errString = string.Empty;
                using (StreamReader sr = new StreamReader(ms))
                    errString = sr.ReadToEnd();
                throw new OqlExpressionException("Parser Errors: " + errString);
            }
            OqlExpression result = parser.RootExpression;

            AddParents(result);
            return(result);
        }
Example #8
0
        /// <summary>
        /// Get the where clause of the SQL string
        /// </summary>
        /// <returns>Where clause string</returns>
        public QueryContexts GetContexts(Class resultClass, OqlExpression expressionTree)
        {
            var result = new QueryContexts();

            if (expressionTree == null)
            {
                return(result);
            }

            this.names        = (from oex in expressionTree.GetAll(e => e is IdentifierExpression) select(string) oex.Value).ToList();
            this.allRelations = new HashSet <Relation>();

            if (names.Count == 0)
            {
                return(result);
            }

            foreach (string name in names)
            {
                CreateContextForName(resultClass, name, allRelations);
            }
            if (allRelations.Count > 0)
            {
                this.relations = new List <Relation>();
                foreach (var de in allRelations)
                {
                    relations.Add(de);
                }
                BuildMutations(0, result, new Stack <Class>());
            }
            return(result);
        }
Example #9
0
        void MulExpr(out OqlExpression expression)
        {
            OqlExpression child;
            OqlExpression result = new OqlExpression(la.line, la.col);
            string        newOp  = null;

            Unary(out child);
            result.Add(child);
            while (StartOf(4))
            {
                if (la.kind == 33)
                {
                    Get();
                    newOp = "*";
                }
                else if (la.kind == 34)
                {
                    Get();
                    newOp = "/";
                }
                else if (la.kind == 35)
                {
                    Get();
                    newOp = "%";
                }
                else
                {
                    Get();
                    newOp = "MOD";
                }
                Unary(out child);
                result.Add(child, newOp);
            }
            expression = result.Simplify();
        }
Example #10
0
        void Identifier(out OqlExpression expression)
        {
            OqlExpression result = null;

            Expect(1);
            result     = new IdentifierExpression(t.val, t.line, t.col);
            expression = result.Simplify();
        }
Example #11
0
 /// <summary>
 /// Sets the Parent property for each element in the tree
 /// </summary>
 /// <param name="exp"></param>
 private void AddParents(OqlExpression exp)
 {
     foreach (OqlExpression child in exp.Children)
     {
         ((IManageExpression)child).SetParent(exp);
         AddParents(child);
     }
 }
Example #12
0
        void Primary(out OqlExpression expression)
        {
            OqlExpression result = null;
            OqlExpression child;

            if (la.kind == 1)
            {
                Get();
                result = new IdentifierExpression(t.val, t.line, t.col);
                if (la.kind == 20)
                {
                    if (IsOidIdentifier(result))
                    {
                        Expect(20);
                        Expect(3);
                        result.UnaryOp = "";
                        result.Add(new IndexExpression(int.Parse(t.val), t.line, t.col));

                        Expect(21);
                    }
                    else
                    {
                        Get();
                        ParameterList(out child);
                        result         = new FunctionExpression(result.Value, t.line, t.col);
                        result.UnaryOp = "";
                        result.Add(child);

                        Expect(21);
                    }
                }
            }
            else if (StartOf(5))
            {
                Literal(out result);
            }
            else if (la.kind == 16)
            {
                Get();
                result = new ParameterExpression(t.val, t.line, t.col);
            }
            else if (la.kind == 20)
            {
                Get();
                RootExpr(out result);
                result.HasBrackets = true;
                Expect(21);
            }
            else
            {
                SynErr(44);
            }
            expression = result.Simplify();
        }
Example #13
0
        internal string GenerateWhereClause(OqlExpression expressionTree)
        {
            if (expressionTree == null)
            {
                return(string.Empty);
            }

            AnnotateExpressionTree(expressionTree);

            // We remove the dummy expression here.
            return("WHERE " + WhereString(expressionTree));
        }
Example #14
0
 void CreateSubQueriesForAllTypes(
     List <QueryContextsEntry> queryContextsList,
     OqlExpression expressionTree,
     bool hollow,
     List <QueryOrder> orderings,
     int skip,
     int take,
     string prefetch = null)
 {
     foreach (var item in queryContextsList)
     {
         CreateSubQueries(item, expressionTree, hollow, queryContextsList.Count > 1, orderings, skip, take);
     }
 }
Example #15
0
        void StringList(out OqlExpression expression)
        {
            OqlExpression result = new OqlExpression(la.line, la.col);

            Expect(4);
            result.Add(new StringLiteralExpression(t.val, t.line, t.col));
            while (la.kind == 37)
            {
                Get();
                Expect(4);
                result.Add(new StringLiteralExpression(t.val, t.line, t.col), ",");
            }
            expression = result;
        }
Example #16
0
        /// <summary>
        /// Creates a SQL query string, which can be passed to the IPersistenceHandler to fetch the results for a given concrete type.
        /// </summary>
        /// <param name="queryContextsEntry">All contexts which define possible mutations of concrete classes in results and relations.</param>
        /// <param name="expressionTree">The syntax tree of the NDOql query expression.</param>
        /// <param name="hollow">Determines, if the query results should be hollow objects.</param>
        /// <param name="hasSubclassResultsets">Determines, if this query is part of a composed query which spans over several tables.</param>
        /// <param name="orderings">List of orderings for the resultset.</param>
        /// <param name="skip">Determines how many records of the resultset should be skipped. The resultset must be ordered.</param>
        /// <param name="take">Determines how many records of the resultset should be returned by the query. The resultset must be ordered.</param>
        /// <param name="prefetch">Query for the given prefetch relation.</param>
        /// <returns>A Query string.</returns>
        public string GenerateQueryString(
            QueryContextsEntry queryContextsEntry,
            OqlExpression expressionTree,
            bool hollow,
            bool hasSubclassResultsets,
            List <QueryOrder> orderings,
            int skip,
            int take,
            string prefetch)
        {
            this.selectPartCreator = CreateQuerySelectPart;

            return(InnerGenerateQueryString(queryContextsEntry, expressionTree, hollow, hasSubclassResultsets, orderings, skip, take, prefetch));
        }
Example #17
0
        void BitAndExpr(out OqlExpression expression)
        {
            OqlExpression child;
            OqlExpression result = new OqlExpression(la.line, la.col);

            AddExpr(out child);
            result.Add(child);
            while (la.kind == 30)
            {
                Get();
                AddExpr(out child);
                result.Add(child, "&");
            }
            expression = result.Simplify();
        }
Example #18
0
        void BitOrExpr(out OqlExpression expression)
        {
            OqlExpression child;
            OqlExpression result = new OqlExpression(la.line, la.col);

            BitXorExpr(out child);
            result.Add(child);
            while (la.kind == 28)
            {
                Get();
                BitXorExpr(out child);
                result.Add(child, "|");
            }
            expression = result.Simplify();
        }
Example #19
0
        string ConstructQueryString(
            Type resultType,
            Dictionary <Relation, Class> relationContext,
            OqlExpression expressionTree,
            bool hollow,
            bool hasSubclassResultsets,
            List <QueryOrder> orderings,
            int skip,
            int take)
        {
            Class cls = this.mappings.FindClass(resultType);

            StringBuilder sb = new StringBuilder("SELECT ");

            var from = new FromGenerator(cls, relationContext).GenerateFromExpression(expressionTree);
            var qualifyWithTableName = from.IndexOf("INNER JOIN") > -1;

            string columnList = this.selectPartCreator(relationContext, hollow, cls, qualifyWithTableName, this.additionalSelectPartData);

            sb.Append(columnList);

            // If we need to sort a set of hollow results for different subclasses
            // we need to fetch the ordering columns together with the oid columns
            if (hollow && orderings.Count > 0 && hasSubclassResultsets)
            {
                var orderCols = (from o in orderings select cls.FindField(o.FieldName).Column.GetQualifiedName()).ToArray();
                columnList += ", " + String.Join(", ", orderCols);
            }

            sb.Append(' ');
            sb.Append(from);
            string where = new WhereGenerator(cls, relationContext).GenerateWhereClause(expressionTree);
            if (where != string.Empty)
            {
                sb.Append(' ');
                sb.Append(where);
            }

            if (orderings.Count > 0)
            {
                sb.Append(' ');
                sb.Append(new OrderGenerator(cls).GenerateOrderClause(orderings, skip, take));
            }

            return(sb.ToString());
        }
Example #20
0
        void Literal(out OqlExpression expression)
        {
            OqlExpression result = null;

            switch (la.kind)
            {
            case 2: {
                Get();
                result = new NumberExpression(double.Parse(t.val, CultureInfo.InvariantCulture), t.line, t.col);
                break;
            }

            case 3: {
                Get();
                result = new NumberExpression(int.Parse(t.val), t.line, t.col);
                break;
            }

            case 4: {
                Get();
                result = new StringLiteralExpression(t.val, t.line, t.col);
                break;
            }

            case 13: {
                Get();
                result = new NamedConstantExpression("TRUE", t.line, t.col);
                break;
            }

            case 38: {
                Get();
                result = new NamedConstantExpression("FALSE", t.line, t.col);
                break;
            }

            case 12: {
                Get();
                result = new NamedConstantExpression("NULL", t.line, t.col);
                break;
            }

            default: SynErr(45); break;
            }
            expression = result.Simplify();
        }
Example #21
0
        void ParameterList(out OqlExpression expression)
        {
            OqlExpression result = new ParameterListExpression(la.line, la.col);
            OqlExpression child;

            if (StartOf(6))
            {
                Primary(out child);
                result.Add(child);
                while (la.kind == 37)
                {
                    Get();
                    Primary(out child);
                    result.Add(child, ",");
                }
            }
            expression = result;     /* Do not simplify here, because otherwise the brackets are missing */
        }
Example #22
0
        private Class GetParentClass(OqlExpression exp, string[] arr, out string fieldName, out Relation relation)
        {
            Class      relClass = this.cls;
            NDOMapping mappings = relClass.Parent;
            int        i;

            relation = null;

            for (i = 0; i < arr.Length - 1; i++)
            {
                relation = relClass.FindRelation(arr[i]);
                if (relation == null)                  // must be a value type or embedded type
                {
                    break;
                }

                if (this.queryContext.ContainsKey(relation))
                {
                    relClass = this.queryContext[relation];
                }
                else
                {
                    relClass = mappings.FindClass(relation.ReferencedType);
                }
            }

            fieldName = String.Join(".", arr, i, arr.Length - i);
            if (relClass.FindField(fieldName) == null && fieldName.IndexOf('.') > -1)
            {
                // We might have a value type or embedded type here.
                // These don't have accessor names.
                // So we try to find the field via the standard column name.
                // Note, that this doesn't work, if the column name was remapped.
                // But we don't see another solution for this situation.
                string tempName = fieldName.Replace('.', '_');
                var    field    = relClass.Fields.FirstOrDefault(f => f.Column.Name == tempName);
                if (field != null)
                {
                    fieldName = field.Name;
                }
            }

            return(relClass);
        }
Example #23
0
        void RootExpr(out OqlExpression expression)
        {
            OqlExpression child;
            OqlExpression result  = new OqlExpression(la.line, la.col);
            bool          negated = false;

            if (la.kind == 7)
            {
                Get();
                negated = true;
            }
            OrExpr(out child);
            if (negated)
            {
                result.UnaryOp = "NOT";
            }
            result.Add(child);
            expression = result.Simplify();
        }
Example #24
0
        void Initialize(MappingNode mappingNode, IEnumerable <OidColumn> oidColumns, IEnumerable <ForeignKeyColumn> fkColumns, KeyValuePair <string, int>?typeCodeInfo)
        {
            IEnumerator <OidColumn> oidEnumerator = oidColumns.GetEnumerator();

            oidEnumerator.MoveNext();
            List <OqlExpression> compareExpressions = new List <OqlExpression>();

            foreach (ForeignKeyColumn fkColumn in fkColumns)
            {
                OidColumn oidColumn = oidEnumerator.Current;
                compareExpressions.Add(new OnCompareExpression(mappingNode, oidColumn, fkColumn));
                oidEnumerator.MoveNext();
            }

            if (typeCodeInfo.HasValue)
            {
                compareExpressions.Add(new OnCompareExpression(mappingNode, typeCodeInfo.Value.Key, typeCodeInfo.Value.Value));
            }

            if (compareExpressions.Count == 1)
            {
                Add(compareExpressions[0]);
            }
            else
            {
                OqlExpression andExpression = new OqlExpression(0, 0);
                int           i             = 0;
                foreach (var compareExpression in compareExpressions)
                {
                    if (i++ == 0)
                    {
                        andExpression.Add(compareExpression);
                    }
                    else
                    {
                        andExpression.Add(compareExpression, "AND");
                    }
                }

                Add(andExpression);
            }
        }
Example #25
0
        private void MoveParameterExpression(OqlExpression expressionTree, int fromOrdinal, int additionalSpace)
        {
            if (additionalSpace == 0)
            {
                return;
            }

            // Moves the ordinal numbers of ParameterExpressions above the current expression to leave parameters for
            // the additional columns.
            foreach (ParameterExpression parExp in expressionTree.GetAll(e =>
            {
                ParameterExpression pe = e as ParameterExpression;
                if (pe == null)
                {
                    return(false);
                }
                return(pe.Ordinal > fromOrdinal);
            }))
            {
                parExp.Ordinal += additionalSpace;
            }
        }
Example #26
0
        void NumList(out OqlExpression expression)
        {
            OqlExpression result = new OqlExpression(la.line, la.col);

            if (la.kind == 2)
            {
                Get();
                result.Add(new NumberExpression(double.Parse(t.val, CultureInfo.InvariantCulture), t.line, t.col));
            }
            else if (la.kind == 3)
            {
                Get();
                result.Add(new NumberExpression(int.Parse(t.val), t.line, t.col));
            }
            else
            {
                SynErr(42);
            }
            while (la.kind == 37)
            {
                Get();
                if (la.kind == 2)
                {
                    Get();
                    result.Add(new NumberExpression(double.Parse(t.val, CultureInfo.InvariantCulture), t.line, t.col), ",");
                }
                else if (la.kind == 3)
                {
                    Get();
                    result.Add(new NumberExpression(int.Parse(t.val), t.line, t.col), ",");
                }
                else
                {
                    SynErr(43);
                }
            }
            expression = result;
        }
Example #27
0
        /// <summary>
        /// Creates a Sql query string for the complete query over all types.
        /// </summary>
        /// <param name="queryContextsList">List of all contexts which define possible mutations of concrete classes in results and relations.</param>
        /// <param name="expressionTree">The syntax tree of the NDOql query expression.</param>
        /// <param name="hollow">Determines, if the query results should be hollow objects.</param>
        /// <param name="orderings">List of orderings for the resultset.</param>
        /// <param name="skip">Determines how many records of the resultset should be skipped. The resultset must be ordered.</param>
        /// <param name="take">Determines how many records of the resultset should be returned by the query. The resultset must be ordered.</param>
        /// <param name="prefetch">Query for the given prefetch relation.</param>
        /// <returns>A query string.</returns>
        /// <remarks>The result can be used for debugging and display purposes or with handlers, which don't support distributed databases.</remarks>
        public string GenerateQueryStringForAllTypes(
            List <QueryContextsEntry> queryContextsList,
            OqlExpression expressionTree,
            bool hollow,
            List <QueryOrder> orderings,
            int skip,
            int take, string prefetch = null)
        {
            this.selectPartCreator = CreateQuerySelectPart;

            CreateSubQueriesForAllTypes(queryContextsList, expressionTree, hollow, orderings, skip, take);
            StringBuilder generatedQuery = new StringBuilder();

            foreach (QueryInfo qi in subQueries)
            {
                generatedQuery.Append(qi.QueryString);
                generatedQuery.Append(";\r\n");
            }

            generatedQuery.Length -= 3; // the trailing ;\r\n

            return(generatedQuery.ToString());
        }
Example #28
0
        void RelExpr(out OqlExpression expression)
        {
            OqlExpression child;
            OqlExpression result  = new OqlExpression(la.line, la.col);
            string        newOp   = null;
            bool          negated = false;

            BitOrExpr(out child);
            result.Add(child);
            if (StartOf(2))
            {
                if (StartOf(3))
                {
                    switch (la.kind)
                    {
                    case 22: {
                        Get();
                        newOp = "<";
                        break;
                    }

                    case 23: {
                        Get();
                        newOp = ">";
                        break;
                    }

                    case 24: {
                        Get();
                        newOp = "<=";
                        break;
                    }

                    case 25: {
                        Get();
                        newOp = ">=";
                        break;
                    }

                    case 26: {
                        Get();
                        newOp = ">=";
                        break;
                    }

                    case 27: {
                        Get();
                        newOp = "<=";
                        break;
                    }
                    }
                    BitOrExpr(out child);
                    result.Add(child, newOp);
                }
                else if (la.kind == 11)
                {
                    Get();
                    if (la.kind == 7)
                    {
                        Get();
                        negated = true;
                    }
                    Expect(12);
                    result.Add(new NamedConstantExpression("NULL", negated, t.line, t.col), "IS");
                }
                else
                {
                    if (la.kind == 7)
                    {
                        Get();
                        negated = true;
                    }
                    Expect(10);
                    BitOrExpr(out child);
                    result.Add(child, "BETWEEN");
                    Expect(5);
                    BitOrExpr(out child);
                    result.Add(child, "BETWEEN");
                }
            }
            expression = result.Simplify();
        }
Example #29
0
        private void AnnotateExpressionTree(OqlExpression expressionTree)
        {
            foreach (ParameterExpression parExp in expressionTree.GetAll(e => e is ParameterExpression).ToList())
            {
                if (Guid.Empty.Equals(parExp.ParameterValue) || DateTime.MinValue.Equals(parExp.ParameterValue))
                {
                    var parent = parExp.Parent;
                    if (parent.Operator == "=")
                    {
                        var i       = parent.Children.IndexOf(parExp);
                        var nullExp = new NamedConstantExpression("NULL", false, 0, 0);
                        parent.Children[i] = nullExp;
                        ((IManageExpression)nullExp).SetParent(parent);
                        parent.Operator = "IS";
                    }
                    if (parent.Operator == "<>")
                    {
                        var i       = parent.Children.IndexOf(parExp);
                        var nullExp = new NamedConstantExpression("NULL", true, 0, 0);
                        parent.Children[i] = nullExp;
                        ((IManageExpression)nullExp).SetParent(parent);
                        parent.Operator = "IS";
                    }
                }
            }

            foreach (IdentifierExpression exp in expressionTree.GetAll(e => e is IdentifierExpression).ToList())
            {
                string[] arr       = ((string)exp.Value).Split('.');
                string   fieldName = arr[arr.Length - 1];               // In case of embedded or value types this will be overwritten
                Relation relation;
                Class    parentClass = GetParentClass(exp, arr, out fieldName, out relation);

                if (fieldName == "oid")
                {
                    string[] oidColumns = (from c in parentClass.Oid.OidColumns select QualifiedColumnName.Get(c)).ToArray();
                    if (relation != null)
                    {
                        // In these cases we don't need the join to the table of the class owning the oid.
                        // It's sufficient to compare against the foreign keys stored in the owner class' table
                        // or in the mapping table
                        if (relation.MappingTable != null)
                        {
                            oidColumns = (from c in relation.MappingTable.ChildForeignKeyColumns select QualifiedColumnName.Get(relation.MappingTable, c)).ToArray();
                        }
                        else if (relation.Multiplicity == RelationMultiplicity.Element)
                        {
                            oidColumns = (from c in relation.ForeignKeyColumns select QualifiedColumnName.Get(c)).ToArray();
                        }
                    }

                    ParameterExpression parExp   = exp.Siblings[0] as ParameterExpression;
                    var isDirectSingleExpression = exp.Parent.Operator != "=" || oidColumns.Length == 1 && exp.Siblings[0] is ConstantExpression;                     // like "oid = 123"
                    if (parExp == null && !isDirectSingleExpression)
                    {
                        throw new QueryException(10010, $"Expression '{exp.ToString()}' resolves to an oid. It's sibling expression must be a ParameterExpression. But the sibling is {exp.Siblings[0]}");
                    }

                    object[] oidKeys = null;

                    if (!isDirectSingleExpression)
                    {
                        // split the ObjectId or an array into individual parameters
                        oidKeys = ExtractOidKeys(parExp);

                        // Now set the parameter value of the first column
                        if (oidKeys != null)
                        {
                            parExp.ParameterValue = oidKeys[0];
                        }
                    }

                    if (oidColumns.Length > 1 && exp.Children.Count == 0)
                    {
                        OqlExpression equalsExpression = exp.Parent;                          // Must be a = expression like 'xxx.oid = {0}'.
                        // We need some additional parameters for the additional columns.
                        MoveParameterExpression(expressionTree, parExp.Ordinal, oidColumns.Length - 1);

                        // Replace the parent expression with a new AND expression
                        OqlExpression andExpression = new OqlExpression(0, 0);
                        ((IManageExpression)andExpression).SetParent(equalsExpression.Parent);
                        equalsExpression.Parent.Children.Remove(equalsExpression);
                        equalsExpression.Parent.Add(andExpression);
                        // We need to set Parent and Child explicitly.
                        // See comment in IManageExpression.SetParent.
                        // Reuse the original equality expression as first child of the AND expression
                        ((IManageExpression)equalsExpression).SetParent(andExpression);
                        andExpression.Add(equalsExpression);
                        exp.SetAnnotation(anKey, oidColumns[0]);
                        int currentOrdinal = parExp.Ordinal;
                        // Now add the additional children of the AND expression
                        for (int i = 1; i < oidColumns.Length; i++)
                        {
                            OqlExpression newParent = equalsExpression.DeepClone;                             // equality expression and it's both children
                            andExpression.Add(newParent, "AND");
                            ((IManageExpression)newParent).SetParent(andExpression);
                            // Now patch the Annotation and a new parameter to the children
                            IdentifierExpression newIdentExp = (IdentifierExpression)newParent.Children.Where(e => e is IdentifierExpression).First();
                            newIdentExp.SetAnnotation(anKey, oidColumns[i]);
                            ParameterExpression newParExp = (ParameterExpression)newParent.Children.Where(e => e is ParameterExpression).First();
                            if (oidKeys != null)
                            {
                                newParExp.ParameterValue = oidKeys[i];
                            }
                            newParExp.Ordinal = ++currentOrdinal;
                        }
                    }
                    else
                    {
                        int index = 0;
                        if (exp.Children.Count > 0 && exp.Children[0] is IndexExpression)
                        {
                            index = (int)exp.Children[0].Value;
                        }
                        if (index >= oidColumns.Length)
                        {
                            throw new IndexOutOfRangeException("oid index exceeds oid column count");
                        }
                        exp.SetAnnotation(anKey, oidColumns[index]);
                    }
                }
                else
                {
                    Field field = parentClass.FindField(fieldName);
                    if (field != null)
                    {
                        exp.SetAnnotation(anKey, QualifiedColumnName.Get(field.Column));
                    }
                    else
                    {
                        Relation oneTooneRelation = parentClass.Relations.FirstOrDefault(r => r.Multiplicity == RelationMultiplicity.Element && (r.FieldName == fieldName || r.AccessorName == fieldName));
                        if (oneTooneRelation != null)
                        {
                            exp.SetAnnotation(anKey, QualifiedColumnName.Get(oneTooneRelation.ForeignKeyColumns.First()));
                        }

                        else
                        {
                            throw new Exception("Can't find Field mapping for " + fieldName + " in " + exp.Value);
                        }
                    }
                }
            }
        }
Example #30
0
        string WhereString(OqlExpression thisExpression)
        {
            StringBuilder sb = new StringBuilder();

            if (thisExpression.IsTerminating || thisExpression is IdentifierExpression)
            {
                if (thisExpression.UnaryOp != null)
                {
                    sb.Append(thisExpression.UnaryOp);
                    sb.Append(' ');
                }
                if (thisExpression.Value.GetType().IsPrimitive)
                {
                    sb.Append(Convert.ToString(thisExpression.Value, CultureInfo.InvariantCulture));
                }
                else
                {
                    IdentifierExpression iexp = thisExpression as IdentifierExpression;
                    if (iexp != null)
                    {
                        sb.Append(iexp.GetAnnotation <string>(anKey));
                    }
                    else
                    {
                        sb.Append(thisExpression.Value.ToString());
                    }
                }
            }
            else
            {
                if (thisExpression.UnaryOp != null)
                {
                    sb.Append(thisExpression.UnaryOp);
                    sb.Append(' ');
                }
                if (thisExpression is FunctionExpression)
                {
                    sb.Append(thisExpression.Value);
                }
                if (thisExpression.HasBrackets)
                {
                    sb.Append('(');
                }
                string op1 = thisExpression.Operator;

                int childExpEndIndex = thisExpression.Children.Count - 1;
                for (int i = 0; i <= childExpEndIndex; i++)
                {
                    OqlExpression child = thisExpression.Children[i];
                    sb.Append(WhereString(child));
                    if (i < childExpEndIndex)
                    {
                        if (op1 != ",")
                        {
                            sb.Append(' ');
                        }
                        sb.Append(op1);
                        if (op1 == "BETWEEN")
                        {
                            op1 = "AND";
                        }
                        sb.Append(' ');
                    }
                }

                if (thisExpression.HasBrackets)
                {
                    sb.Append(')');
                }
            }
            return(sb.ToString());
        }