Datei: NDODLL/SqlPersistenceHandling/WhereGenerator.cs
Last Commit (28c8c45)
1 | using System; |
2 | using System.Collections.Generic; |
3 | using System.Linq; |
4 | using System.Text; |
5 | using NDOql.Expressions; |
6 | using NDO.Mapping; |
7 | using System.Globalization; |
8 | using NDO.Query; |
9 | |
10 | namespace NDO.SqlPersistenceHandling |
11 | { |
12 | ····/// <summary> |
13 | ····/// Helper class to generate Column names of the select statement |
14 | ····/// </summary> |
15 | ····internal class WhereGenerator |
16 | ····{ |
17 | ········Class cls; |
18 | ········Dictionary<Relation, Class> queryContext; |
19 | ········static readonly string anKey = "where"; |
20 | |
21 | ········internal WhereGenerator(Class cls, Dictionary<Relation, Class> queryContext) |
22 | ········{ |
23 | ············this.cls = cls; |
24 | ············this.queryContext = queryContext; |
25 | ········} |
26 | |
27 | ········internal string GenerateWhereClause(OqlExpression expressionTree) |
28 | ········{ |
29 | ············if (expressionTree == null) |
30 | ················return string.Empty; |
31 | |
32 | ············AnnotateExpressionTree( expressionTree ); |
33 | |
34 | ············// We remove the dummy expression here. |
35 | ············return "WHERE " + WhereString( expressionTree ); |
36 | ········} |
37 | |
38 | ········private void MoveParameterExpression(OqlExpression expressionTree, int fromOrdinal, int additionalSpace) |
39 | ········{ |
40 | ············if (additionalSpace == 0) |
41 | ················return; |
42 | |
43 | ············// Moves the ordinal numbers of ParameterExpressions above the current expression to leave parameters for |
44 | ············// the additional columns. |
45 | ············foreach (ParameterExpression parExp in expressionTree.GetAll( e => |
46 | ················{ |
47 | ····················ParameterExpression pe = e as ParameterExpression; |
48 | ····················if (pe == null) |
49 | ························return false; |
50 | ····················return pe.Ordinal > fromOrdinal; |
51 | ················} )) |
52 | ············{ |
53 | ················parExp.Ordinal += additionalSpace; |
54 | ············} |
55 | ········} |
56 | |
57 | ········private void AnnotateExpressionTree( OqlExpression expressionTree ) |
58 | ········{ |
59 | ············foreach (ParameterExpression parExp in expressionTree.GetAll(e=>e is ParameterExpression).ToList()) |
60 | ············{ |
61 | ················if (Guid.Empty.Equals( parExp.ParameterValue ) || DateTime.MinValue.Equals( parExp.ParameterValue )) |
62 | ················{ |
63 | ····················var parent = parExp.Parent; |
64 | ····················if (parent.Operator == "=") |
65 | ····················{ |
66 | ························var i = parent.Children.IndexOf(parExp); |
67 | ························var nullExp = new NamedConstantExpression( "NULL", false, 0, 0 ); |
68 | ························parent.Children[i] = nullExp; |
69 | ························( (IManageExpression) nullExp ).SetParent( parent ); |
70 | ························parent.Operator = "IS"; |
71 | ····················} |
72 | ····················if (parent.Operator == "<>") |
73 | ····················{ |
74 | ························var i = parent.Children.IndexOf(parExp); |
75 | ························var nullExp = new NamedConstantExpression( "NULL", true, 0, 0 ); |
76 | ························parent.Children[i] = nullExp; |
77 | ························( (IManageExpression) nullExp ).SetParent( parent ); |
78 | ························parent.Operator = "IS"; |
79 | ····················} |
80 | ················} |
81 | ············} |
82 | |
83 | ············foreach (IdentifierExpression exp in expressionTree.GetAll( e => e is IdentifierExpression ).ToList()) |
84 | ············{ |
85 | ················string[] arr = ((string)exp.Value).Split( '.' ); |
86 | ················string fieldName = arr[arr.Length - 1]; // In case of embedded or value types this will be overwritten |
87 | ················Relation relation; |
88 | ················Class parentClass = GetParentClass( exp, arr, out fieldName, out relation ); |
89 | |
90 | ················if (fieldName == "oid") |
91 | ················{ |
92 | ····················string[] oidColumns = (from c in parentClass.Oid.OidColumns select QualifiedColumnName.Get( c )).ToArray(); |
93 | ····················if (relation != null) |
94 | ····················{ |
95 | ························// In these cases we don't need the join to the table of the class owning the oid. |
96 | ························// It's sufficient to compare against the foreign keys stored in the owner class' table |
97 | ························// or in the mapping table |
98 | ························if (relation.MappingTable != null) |
99 | ························{ |
100 | ····························oidColumns = (from c in relation.MappingTable.ChildForeignKeyColumns select QualifiedColumnName.Get( relation.MappingTable, c )).ToArray(); |
101 | ························} |
102 | ························else if (relation.Multiplicity == RelationMultiplicity.Element) |
103 | ························{ |
104 | ····························oidColumns = (from c in relation.ForeignKeyColumns select QualifiedColumnName.Get( c )).ToArray(); |
105 | ························} |
106 | ····················} |
107 | |
108 | ····················ParameterExpression parExp = exp.Siblings[0] as ParameterExpression; |
109 | ····················var isDirectSingleExpression = exp.Parent.Operator != "=" || oidColumns.Length == 1 && exp.Siblings[0] is ConstantExpression; // like "oid = 123" |
110 | ····················if (parExp == null && !isDirectSingleExpression) |
111 | ························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]}" ); |
112 | |
113 | ····················object[] oidKeys = null; |
114 | |
115 | ····················if (!isDirectSingleExpression) |
116 | ····················{ |
117 | ························// split the ObjectId or an array into individual parameters |
118 | ························oidKeys = ExtractOidKeys( parExp ); |
119 | |
120 | ························// Now set the parameter value of the first column |
121 | ························if (oidKeys != null) |
122 | ····························parExp.ParameterValue = oidKeys[0]; |
123 | ····················} |
124 | |
125 | ····················if (oidColumns.Length > 1 && exp.Children.Count == 0) |
126 | ····················{ |
127 | ························OqlExpression equalsExpression = exp.Parent;··// Must be a = expression like 'xxx.oid = {0}'. |
128 | ························// We need some additional parameters for the additional columns. |
129 | ························MoveParameterExpression( expressionTree, parExp.Ordinal, oidColumns.Length - 1 ); |
130 | |
131 | ························// Replace the parent expression with a new AND expression |
132 | ························OqlExpression andExpression = new OqlExpression( 0, 0 ); |
133 | ························((IManageExpression)andExpression).SetParent( equalsExpression.Parent ); |
134 | ························equalsExpression.Parent.Children.Remove( equalsExpression ); |
135 | ························equalsExpression.Parent.Add( andExpression ); |
136 | ························// We need to set Parent and Child explicitly. |
137 | ························// See comment in IManageExpression.SetParent. |
138 | ························// Reuse the original equality expression as first child of the AND expression |
139 | ························((IManageExpression)equalsExpression).SetParent( andExpression ); |
140 | ························andExpression.Add( equalsExpression ); |
141 | ························exp.SetAnnotation( anKey, oidColumns[0] ); |
142 | ························int currentOrdinal = parExp.Ordinal; |
143 | ························// Now add the additional children of the AND expression |
144 | ························for (int i = 1; i < oidColumns.Length; i++) |
145 | ························{ |
146 | ····························OqlExpression newParent = equalsExpression.DeepClone; // equality expression and it's both children |
147 | ····························andExpression.Add( newParent, "AND" ); |
148 | ····························((IManageExpression)newParent).SetParent( andExpression ); |
149 | ····························// Now patch the Annotation and a new parameter to the children |
150 | ····························IdentifierExpression newIdentExp = (IdentifierExpression)newParent.Children.Where( e => e is IdentifierExpression ).First(); |
151 | ····························newIdentExp.SetAnnotation( anKey, oidColumns[i]); |
152 | ····························ParameterExpression newParExp = (ParameterExpression)newParent.Children.Where( e => e is ParameterExpression ).First(); |
153 | ····························if (oidKeys != null) |
154 | ································newParExp.ParameterValue = oidKeys[i]; |
155 | ····························newParExp.Ordinal = ++currentOrdinal; |
156 | ························} |
157 | ····················} |
158 | ····················else |
159 | ····················{ |
160 | ························int index = 0; |
161 | ························if (exp.Children.Count > 0 && exp.Children[0] is IndexExpression) |
162 | ····························index = (int)exp.Children[0].Value; |
163 | ························if (index >= oidColumns.Length) |
164 | ····························throw new IndexOutOfRangeException("oid index exceeds oid column count"); |
165 | ························exp.SetAnnotation( anKey, oidColumns[index]);····················} |
166 | ················} |
167 | ················else |
168 | ················{ |
169 | ····················Field field = parentClass.FindField( fieldName ); |
170 | ····················if (field != null) |
171 | ····················{ |
172 | ························exp.SetAnnotation( anKey, QualifiedColumnName.Get( field.Column ) ); |
173 | ····················} |
174 | ····················else |
175 | ····················{ |
176 | |
177 | ························Relation oneTooneRelation = parentClass.Relations.FirstOrDefault( r => r.Multiplicity == RelationMultiplicity.Element && (r.FieldName == fieldName || r.AccessorName == fieldName) ); |
178 | ························if (oneTooneRelation != null) |
179 | ····························exp.SetAnnotation( anKey, QualifiedColumnName.Get( oneTooneRelation.ForeignKeyColumns.First() ) ); |
180 | |
181 | ························else |
182 | ····························throw new Exception( "Can't find Field mapping for " + fieldName + " in " + exp.Value ); |
183 | ····················} |
184 | ················} |
185 | ············} |
186 | ········} |
187 | |
188 | ········private static object[] ExtractOidKeys( ParameterExpression parExp ) |
189 | ········{ |
190 | ············object[] oidKeys = null; |
191 | ············if (parExp.ParameterValue != null) |
192 | ············{ |
193 | ················oidKeys = ((parExp.ParameterValue as ObjectId)?.Id); |
194 | ················if (oidKeys == null) |
195 | ····················oidKeys = (parExp.ParameterValue as object[]); |
196 | ················if (oidKeys == null) |
197 | ····················oidKeys = new object[] { parExp.ParameterValue }; |
198 | ············} |
199 | |
200 | ············return oidKeys; |
201 | ········} |
202 | |
203 | ········private Class GetParentClass( OqlExpression exp, string[] arr, out string fieldName, out Relation relation ) |
204 | ········{ |
205 | ············Class relClass = this.cls; |
206 | ············NDOMapping mappings = relClass.Parent; |
207 | ············int i; |
208 | ············relation = null; |
209 | |
210 | ············for (i = 0; i < arr.Length - 1; i++) |
211 | ············{ |
212 | ················relation = relClass.FindRelation( arr[i] ); |
213 | ················if (relation == null)··// must be a value type or embedded type |
214 | ················{ |
215 | ····················break; |
216 | ················} |
217 | |
218 | ················if (this.queryContext.ContainsKey(relation)) |
219 | ····················relClass = this.queryContext[relation]; |
220 | ················else |
221 | ····················relClass = mappings.FindClass( relation.ReferencedType ); |
222 | ············} |
223 | |
224 | ············fieldName = String.Join( ".", arr, i, arr.Length - i ); |
225 | ············if (relClass.FindField(fieldName) == null &&··fieldName.IndexOf('.') > -1) |
226 | ············{ |
227 | ················// We might have a value type or embedded type here. |
228 | ················// These don't have accessor names. |
229 | ················// So we try to find the field via the standard column name. |
230 | ················// Note, that this doesn't work, if the column name was remapped. |
231 | ················// But we don't see another solution for this situation. |
232 | ················string tempName = fieldName.Replace( '.', '_' ); |
233 | ················var field = relClass.Fields.FirstOrDefault( f => f.Column.Name == tempName ); |
234 | ················if (field != null) |
235 | ····················fieldName = field.Name; |
236 | ············} |
237 | |
238 | ············return relClass; |
239 | ········} |
240 | |
241 | ········string WhereString(OqlExpression thisExpression) |
242 | ········{ |
243 | ············StringBuilder sb = new StringBuilder(); |
244 | |
245 | ············if (thisExpression.IsTerminating || thisExpression is IdentifierExpression) |
246 | ············{ |
247 | ················if (thisExpression.UnaryOp != null) |
248 | ················{ |
249 | ····················sb.Append(thisExpression.UnaryOp); |
250 | ····················sb.Append(' '); |
251 | ················} |
252 | ················if (thisExpression.Value.GetType().IsPrimitive) |
253 | ················{ |
254 | ····················sb.Append( Convert.ToString( thisExpression.Value, CultureInfo.InvariantCulture ) ); |
255 | ················} |
256 | ················else |
257 | ················{ |
258 | ····················IdentifierExpression iexp = thisExpression as IdentifierExpression; |
259 | ····················if (iexp != null) |
260 | ····················{ |
261 | ························sb.Append( iexp.GetAnnotation<string>( anKey ) ); |
262 | ····················} |
263 | ····················else |
264 | ····················{ |
265 | ························sb.Append( thisExpression.Value.ToString() ); |
266 | ····················} |
267 | ················} |
268 | ············} |
269 | ············else |
270 | ············{ |
271 | ················if (thisExpression.UnaryOp != null) |
272 | ················{ |
273 | ····················sb.Append( thisExpression.UnaryOp ); |
274 | ····················sb.Append( ' ' ); |
275 | ················} |
276 | ················if (thisExpression.HasBrackets) |
277 | ····················sb.Append('('); |
278 | ················string op1 = thisExpression.Operator; |
279 | |
280 | ················int childExpEndIndex = thisExpression.Children.Count - 1; |
281 | ················for (int i = 0; i <= childExpEndIndex; i++) |
282 | ················{ |
283 | ····················OqlExpression child = thisExpression.Children[i]; |
284 | ····················sb.Append(WhereString(child)); |
285 | ····················if (i < childExpEndIndex) |
286 | ····················{ |
287 | ························if (op1 != ",") |
288 | ····························sb.Append(' '); |
289 | ························sb.Append(op1); |
290 | ························if (op1 == "BETWEEN") |
291 | ························{ |
292 | ····························op1 = "AND"; |
293 | ························} |
294 | ························sb.Append(' '); |
295 | ····················} |
296 | ················} |
297 | ················ |
298 | ················if (thisExpression.HasBrackets) |
299 | ····················sb.Append(')'); |
300 | ············} |
301 | ············return sb.ToString(); |
302 | ········} |
303 | ····} |
304 | } |
305 |
New Commit (b47b95e)
1 | using System; |
2 | using System.Collections.Generic; |
3 | using System.Linq; |
4 | using System.Text; |
5 | using NDOql.Expressions; |
6 | using NDO.Mapping; |
7 | using System.Globalization; |
8 | using NDO.Query; |
9 | |
10 | namespace NDO.SqlPersistenceHandling |
11 | { |
12 | ····/// <summary> |
13 | ····/// Helper class to generate Column names of the select statement |
14 | ····/// </summary> |
15 | ····internal class WhereGenerator |
16 | ····{ |
17 | ········Class cls; |
18 | ········Dictionary<Relation, Class> queryContext; |
19 | ········static readonly string anKey = "where"; |
20 | |
21 | ········internal WhereGenerator(Class cls, Dictionary<Relation, Class> queryContext) |
22 | ········{ |
23 | ············this.cls = cls; |
24 | ············this.queryContext = queryContext; |
25 | ········} |
26 | |
27 | ········internal string GenerateWhereClause(OqlExpression expressionTree) |
28 | ········{ |
29 | ············if (expressionTree == null) |
30 | ················return string.Empty; |
31 | |
32 | ············AnnotateExpressionTree( expressionTree ); |
33 | |
34 | ············// We remove the dummy expression here. |
35 | ············return "WHERE " + WhereString( expressionTree ); |
36 | ········} |
37 | |
38 | ········private void MoveParameterExpression(OqlExpression expressionTree, int fromOrdinal, int additionalSpace) |
39 | ········{ |
40 | ············if (additionalSpace == 0) |
41 | ················return; |
42 | |
43 | ············// Moves the ordinal numbers of ParameterExpressions above the current expression to leave parameters for |
44 | ············// the additional columns. |
45 | ············foreach (ParameterExpression parExp in expressionTree.GetAll( e => |
46 | ················{ |
47 | ····················ParameterExpression pe = e as ParameterExpression; |
48 | ····················if (pe == null) |
49 | ························return false; |
50 | ····················return pe.Ordinal > fromOrdinal; |
51 | ················} )) |
52 | ············{ |
53 | ················parExp.Ordinal += additionalSpace; |
54 | ············} |
55 | ········} |
56 | |
57 | ········private void AnnotateExpressionTree( OqlExpression expressionTree ) |
58 | ········{ |
59 | ············foreach (ParameterExpression parExp in expressionTree.GetAll(e=>e is ParameterExpression).ToList()) |
60 | ············{ |
61 | ················if (Guid.Empty.Equals( parExp.ParameterValue ) || DateTime.MinValue.Equals( parExp.ParameterValue )) |
62 | ················{ |
63 | ····················var parent = parExp.Parent; |
64 | ····················if (parent.Operator == "=") |
65 | ····················{ |
66 | ························var i = parent.Children.IndexOf(parExp); |
67 | ························var nullExp = new NamedConstantExpression( "NULL", false, 0, 0 ); |
68 | ························parent.Children[i] = nullExp; |
69 | ························( (IManageExpression) nullExp ).SetParent( parent ); |
70 | ························parent.Operator = "IS"; |
71 | ····················} |
72 | ····················if (parent.Operator == "<>") |
73 | ····················{ |
74 | ························var i = parent.Children.IndexOf(parExp); |
75 | ························var nullExp = new NamedConstantExpression( "NULL", true, 0, 0 ); |
76 | ························parent.Children[i] = nullExp; |
77 | ························( (IManageExpression) nullExp ).SetParent( parent ); |
78 | ························parent.Operator = "IS"; |
79 | ····················} |
80 | ················} |
81 | ············} |
82 | |
83 | ············foreach (IdentifierExpression exp in expressionTree.GetAll( e => e is IdentifierExpression ).ToList()) |
84 | ············{ |
85 | ················string[] arr = ((string)exp.Value).Split( '.' ); |
86 | ················string fieldName = arr[arr.Length - 1]; // In case of embedded or value types this will be overwritten |
87 | ················Relation relation; |
88 | ················Class parentClass = GetParentClass( exp, arr, out fieldName, out relation ); |
89 | |
90 | ················if (fieldName == "oid") |
91 | ················{ |
92 | ····················string[] oidColumns = (from c in parentClass.Oid.OidColumns select QualifiedColumnName.Get( c )).ToArray(); |
93 | ····················if (relation != null) |
94 | ····················{ |
95 | ························// In these cases we don't need the join to the table of the class owning the oid. |
96 | ························// It's sufficient to compare against the foreign keys stored in the owner class' table |
97 | ························// or in the mapping table |
98 | ························if (relation.MappingTable != null) |
99 | ························{ |
100 | ····························oidColumns = (from c in relation.MappingTable.ChildForeignKeyColumns select QualifiedColumnName.Get( relation.MappingTable, c )).ToArray(); |
101 | ························} |
102 | ························else if (relation.Multiplicity == RelationMultiplicity.Element) |
103 | ························{ |
104 | ····························oidColumns = (from c in relation.ForeignKeyColumns select QualifiedColumnName.Get( c )).ToArray(); |
105 | ························} |
106 | ····················} |
107 | |
108 | ····················ParameterExpression parExp = exp.Siblings[0] as ParameterExpression; |
109 | ····················var isDirectSingleExpression = exp.Parent.Operator != "=" || oidColumns.Length == 1 && exp.Siblings[0] is ConstantExpression; // like "oid = 123" |
110 | ····················if (parExp == null && !isDirectSingleExpression) |
111 | ························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]}" ); |
112 | |
113 | ····················object[] oidKeys = null; |
114 | |
115 | ····················if (!isDirectSingleExpression) |
116 | ····················{ |
117 | ························// split the ObjectId or an array into individual parameters |
118 | ························oidKeys = ExtractOidKeys( parExp ); |
119 | |
120 | ························// Now set the parameter value of the first column |
121 | ························if (oidKeys != null) |
122 | ····························parExp.ParameterValue = oidKeys[0]; |
123 | ····················} |
124 | |
125 | ····················if (oidColumns.Length > 1 && exp.Children.Count == 0) |
126 | ····················{ |
127 | ························OqlExpression equalsExpression = exp.Parent;··// Must be a = expression like 'xxx.oid = {0}'. |
128 | ························// We need some additional parameters for the additional columns. |
129 | ························MoveParameterExpression( expressionTree, parExp.Ordinal, oidColumns.Length - 1 ); |
130 | |
131 | ························// Replace the parent expression with a new AND expression |
132 | ························OqlExpression andExpression = new OqlExpression( 0, 0 ); |
133 | ························((IManageExpression)andExpression).SetParent( equalsExpression.Parent ); |
134 | ························equalsExpression.Parent.Children.Remove( equalsExpression ); |
135 | ························equalsExpression.Parent.Add( andExpression ); |
136 | ························// We need to set Parent and Child explicitly. |
137 | ························// See comment in IManageExpression.SetParent. |
138 | ························// Reuse the original equality expression as first child of the AND expression |
139 | ························((IManageExpression)equalsExpression).SetParent( andExpression ); |
140 | ························andExpression.Add( equalsExpression ); |
141 | ························exp.SetAnnotation( anKey, oidColumns[0] ); |
142 | ························int currentOrdinal = parExp.Ordinal; |
143 | ························// Now add the additional children of the AND expression |
144 | ························for (int i = 1; i < oidColumns.Length; i++) |
145 | ························{ |
146 | ····························OqlExpression newParent = equalsExpression.DeepClone; // equality expression and it's both children |
147 | ····························andExpression.Add( newParent, "AND" ); |
148 | ····························((IManageExpression)newParent).SetParent( andExpression ); |
149 | ····························// Now patch the Annotation and a new parameter to the children |
150 | ····························IdentifierExpression newIdentExp = (IdentifierExpression)newParent.Children.Where( e => e is IdentifierExpression ).First(); |
151 | ····························newIdentExp.SetAnnotation( anKey, oidColumns[i]); |
152 | ····························ParameterExpression newParExp = (ParameterExpression)newParent.Children.Where( e => e is ParameterExpression ).First(); |
153 | ····························if (oidKeys != null) |
154 | ································newParExp.ParameterValue = oidKeys[i]; |
155 | ····························newParExp.Ordinal = ++currentOrdinal; |
156 | ························} |
157 | ····················} |
158 | ····················else |
159 | ····················{ |
160 | ························int index = 0; |
161 | ························if (exp.Children.Count > 0 && exp.Children[0] is IndexExpression) |
162 | ····························index = (int)exp.Children[0].Value; |
163 | ························if (index >= oidColumns.Length) |
164 | ····························throw new IndexOutOfRangeException("oid index exceeds oid column count"); |
165 | ························exp.SetAnnotation( anKey, oidColumns[index]);····················} |
166 | ················} |
167 | ················else |
168 | ················{ |
169 | ····················Field field = parentClass.FindField( fieldName ); |
170 | ····················if (field != null) |
171 | ····················{ |
172 | ························exp.SetAnnotation( anKey, QualifiedColumnName.Get( field.Column ) ); |
173 | ····················} |
174 | ····················else |
175 | ····················{ |
176 | |
177 | ························Relation oneTooneRelation = parentClass.Relations.FirstOrDefault( r => r.Multiplicity == RelationMultiplicity.Element && (r.FieldName == fieldName || r.AccessorName == fieldName) ); |
178 | ························if (oneTooneRelation != null) |
179 | ····························exp.SetAnnotation( anKey, QualifiedColumnName.Get( oneTooneRelation.ForeignKeyColumns.First() ) ); |
180 | |
181 | ························else |
182 | ····························throw new Exception( "Can't find Field mapping for " + fieldName + " in " + exp.Value ); |
183 | ····················} |
184 | ················} |
185 | ············} |
186 | ········} |
187 | |
188 | ········private static object[] ExtractOidKeys( ParameterExpression parExp ) |
189 | ········{ |
190 | ············object[] oidKeys = null; |
191 | ············if (parExp.ParameterValue != null) |
192 | ············{ |
193 | ················oidKeys = ((parExp.ParameterValue as ObjectId)?.Id); |
194 | ················if (oidKeys == null) |
195 | ····················oidKeys = (parExp.ParameterValue as object[]); |
196 | ················if (oidKeys == null) |
197 | ····················oidKeys = new object[] { parExp.ParameterValue }; |
198 | ············} |
199 | |
200 | ············return oidKeys; |
201 | ········} |
202 | |
203 | ········private Class GetParentClass( OqlExpression exp, string[] arr, out string fieldName, out Relation relation ) |
204 | ········{ |
205 | ············Class relClass = this.cls; |
206 | ············NDOMapping mappings = relClass.Parent; |
207 | ············int i; |
208 | ············relation = null; |
209 | |
210 | ············for (i = 0; i < arr.Length - 1; i++) |
211 | ············{ |
212 | ················relation = relClass.FindRelation( arr[i] ); |
213 | ················if (relation == null)··// must be a value type or embedded type |
214 | ················{ |
215 | ····················break; |
216 | ················} |
217 | |
218 | ················if (this.queryContext.ContainsKey(relation)) |
219 | ····················relClass = this.queryContext[relation]; |
220 | ················else |
221 | ····················relClass = mappings.FindClass( relation.ReferencedType ); |
222 | ············} |
223 | |
224 | ············fieldName = String.Join( ".", arr, i, arr.Length - i ); |
225 | ············if (relClass.FindField(fieldName) == null &&··fieldName.IndexOf('.') > -1) |
226 | ············{ |
227 | ················// We might have a value type or embedded type here. |
228 | ················// These don't have accessor names. |
229 | ················// So we try to find the field via the standard column name. |
230 | ················// Note, that this doesn't work, if the column name was remapped. |
231 | ················// But we don't see another solution for this situation. |
232 | ················string tempName = fieldName.Replace( '.', '_' ); |
233 | ················var field = relClass.Fields.FirstOrDefault( f => f.Column.Name == tempName ); |
234 | ················if (field != null) |
235 | ····················fieldName = field.Name; |
236 | ············} |
237 | |
238 | ············return relClass; |
239 | ········} |
240 | |
241 | ········string WhereString(OqlExpression thisExpression) |
242 | ········{ |
243 | ············StringBuilder sb = new StringBuilder(); |
244 | |
245 | ············if (thisExpression.IsTerminating || thisExpression is IdentifierExpression) |
246 | ············{ |
247 | ················if (thisExpression.UnaryOp != null) |
248 | ················{ |
249 | ····················sb.Append(thisExpression.UnaryOp); |
250 | ····················sb.Append(' '); |
251 | ················} |
252 | ················if (thisExpression.Value.GetType().IsPrimitive) |
253 | ················{ |
254 | ····················sb.Append( Convert.ToString( thisExpression.Value, CultureInfo.InvariantCulture ) ); |
255 | ················} |
256 | ················else |
257 | ················{ |
258 | ····················IdentifierExpression iexp = thisExpression as IdentifierExpression; |
259 | ····················if (iexp != null) |
260 | ····················{ |
261 | ························sb.Append( iexp.GetAnnotation<string>( anKey ) ); |
262 | ····················} |
263 | ····················else |
264 | ····················{ |
265 | ························sb.Append( thisExpression.Value.ToString() ); |
266 | ····················} |
267 | ················} |
268 | ············} |
269 | ············else |
270 | ············{ |
271 | ················if (thisExpression.UnaryOp != null) |
272 | ················{ |
273 | ····················sb.Append( thisExpression.UnaryOp ); |
274 | ····················sb.Append( ' ' ); |
275 | ················} |
276 | ················if (thisExpression is FunctionExpression) |
277 | ················{ |
278 | ····················sb.Append( thisExpression.Value ); |
279 | ················} |
280 | ················if (thisExpression.HasBrackets) |
281 | ····················sb.Append('('); |
282 | ················string op1 = thisExpression.Operator; |
283 | |
284 | ················int childExpEndIndex = thisExpression.Children.Count - 1; |
285 | ················for (int i = 0; i <= childExpEndIndex; i++) |
286 | ················{ |
287 | ····················OqlExpression child = thisExpression.Children[i]; |
288 | ····················sb.Append(WhereString(child)); |
289 | ····················if (i < childExpEndIndex) |
290 | ····················{ |
291 | ························if (op1 != ",") |
292 | ····························sb.Append(' '); |
293 | ························sb.Append(op1); |
294 | ························if (op1 == "BETWEEN") |
295 | ························{ |
296 | ····························op1 = "AND"; |
297 | ························} |
298 | ························sb.Append(' '); |
299 | ····················} |
300 | ················} |
301 | ················ |
302 | ················if (thisExpression.HasBrackets) |
303 | ····················sb.Append(')'); |
304 | ············} |
305 | ············return sb.ToString(); |
306 | ········} |
307 | ····} |
308 | } |
309 |