示例#1
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);
        }
示例#2
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());
        }
示例#3
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;
            }
        }
示例#4
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);
                        }
                    }
                }
            }
        }
示例#5
0
        private void AnnotateExpressionTree(OqlExpression expressionTree, List <Relation> prefetchRelations)
        {
            HashSet <Relation> allJoins = new HashSet <Relation>();

            if (prefetchRelations != null)
            {
                // if a prefetch relation is bidirectional,
                // this will prevent adding the relation into the joins twice
                foreach (var rel in prefetchRelations)
                {
                    allJoins.Add(rel);
                }
                // We know, that this must be a prefetch, so the direction
                // of the relation is reversed.
#warning Hier muss noch die Annotation rein
            }

            if (expressionTree == null)
            {
                return;
            }

            foreach (IdentifierExpression exp in expressionTree.GetAll(e => e is IdentifierExpression))
            {
                string fullName = (string)exp.Value;
                if (fullName.IndexOf('.') < 0)
                {
                    continue;
                }

                StringBuilder sb         = new StringBuilder();
                string[]      arr        = ((string)exp.Value).Split('.');
                Class         startClass = this.cls;
                bool          isFirst    = true;

                for (int i = 0; i < arr.Length - 1; i++)                  // at least the last element is the field name
                {
                    string relationName = arr[i];

                    if (relationName == "oid")
                    {
                        break;
                    }

                    Relation relation = startClass.FindRelation(relationName);

                    if (relation == null)
                    {
                        break;
                    }

                    if (allJoins.Contains(relation))
                    {
                        continue;
                    }

                    allJoins.Add(relation);

                    Class childClass = this.relationContext.ContainsKey(relation)
                                                ? this.relationContext[relation]
                                                : this.mappings.FindClass(relation.ReferencedType);

                    if (!isFirst)
                    {
                        sb.Append(' ');
                    }

                    // In the cases where the following condition doesn't apply, 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.
                    if ((relation.Multiplicity == RelationMultiplicity.List || relation.MappingTable != null) || arr[i + 1] != "oid")
                    {
                        sb.Append(new InnerJoinExpression(relation, this.relationContext, arr[i + 1] == "oid").ToString());
                    }

                    startClass = childClass;
                    isFirst    = false;
                }
                string join = sb.ToString();
                exp.SetAnnotation(anKey, join);
            }
        }