/// <summary> /// Generate compares for type codes /// </summary> /// <param name="mappingNode"></param> /// <param name="columnName"></param> /// <param name="value"></param> public OnCompareExpression(MappingNode mappingNode, string columnName, int value) : base(null, 0, 0) { Class fkParentClass = mappingNode as Class; if (fkParentClass != null) { Add(new RawIdentifierExpression(QualifiedColumnName.Get(fkParentClass, columnName), 0, 0)); Add(new NumberExpression(value, 0, 0), "="); return; } MappingTable mappingTable = mappingNode as MappingTable; if (mappingTable != null) { Add(new RawIdentifierExpression(QualifiedColumnName.Get(mappingTable, columnName), 0, 0)); Add(new NumberExpression(value, 0, 0), "="); return; } else { throw new ArgumentException("OnCompareExpression: Unexpected mapping node type", "mappingNode"); } }
public OnCompareExpression(MappingNode mappingNode, OidColumn oidColumn, ForeignKeyColumn fkColumn) : base(null, 0, 0) { Class fkParentClass = mappingNode as Class; if (fkParentClass != null) { Add(new RawIdentifierExpression(QualifiedColumnName.Get(oidColumn), 0, 0)); Add(new RawIdentifierExpression(QualifiedColumnName.Get(fkParentClass, fkColumn), 0, 0), "="); return; } MappingTable mappingTable = mappingNode as MappingTable; if (mappingTable != null) { Add(new RawIdentifierExpression(QualifiedColumnName.Get(oidColumn), 0, 0)); Add(new RawIdentifierExpression(QualifiedColumnName.Get(mappingTable, fkColumn), 0, 0), "="); return; } else { throw new ArgumentException("OnCompareExpression: Unexpected mapping node type", "mappingNode"); } }
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); } } } } }