Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
FunctionNode.cs
Go to the documentation of this file.
6
7namespace System.Data;
8
9internal sealed class FunctionNode : ExpressionNode
10{
11 internal readonly string _name;
12
13 internal readonly int _info = -1;
14
15 internal int _argumentCount;
16
18
19 private readonly TypeLimiter _capturedLimiter;
20
21 private static readonly Function[] s_funcs = new Function[16]
22 {
23 new Function("Abs", FunctionId.Abs, typeof(object), IsValidateArguments: true, IsVariantArgumentList: false, 1, typeof(object), null, null),
24 new Function("IIf", FunctionId.Iif, typeof(object), IsValidateArguments: false, IsVariantArgumentList: false, 3, typeof(object), typeof(object), typeof(object)),
25 new Function("In", FunctionId.In, typeof(bool), IsValidateArguments: false, IsVariantArgumentList: true, 1, null, null, null),
26 new Function("IsNull", FunctionId.IsNull, typeof(object), IsValidateArguments: false, IsVariantArgumentList: false, 2, typeof(object), typeof(object), null),
27 new Function("Len", FunctionId.Len, typeof(int), IsValidateArguments: true, IsVariantArgumentList: false, 1, typeof(string), null, null),
28 new Function("Substring", FunctionId.Substring, typeof(string), IsValidateArguments: true, IsVariantArgumentList: false, 3, typeof(string), typeof(int), typeof(int)),
29 new Function("Trim", FunctionId.Trim, typeof(string), IsValidateArguments: true, IsVariantArgumentList: false, 1, typeof(string), null, null),
30 new Function("Convert", FunctionId.Convert, typeof(object), IsValidateArguments: false, IsVariantArgumentList: true, 1, typeof(object), null, null),
31 new Function("DateTimeOffset", FunctionId.DateTimeOffset, typeof(DateTimeOffset), IsValidateArguments: false, IsVariantArgumentList: true, 3, typeof(DateTime), typeof(int), typeof(int)),
32 new Function("Max", FunctionId.Max, typeof(object), IsValidateArguments: false, IsVariantArgumentList: false, 1, null, null, null),
33 new Function("Min", FunctionId.Min, typeof(object), IsValidateArguments: false, IsVariantArgumentList: false, 1, null, null, null),
34 new Function("Sum", FunctionId.Sum, typeof(object), IsValidateArguments: false, IsVariantArgumentList: false, 1, null, null, null),
35 new Function("Count", FunctionId.Count, typeof(object), IsValidateArguments: false, IsVariantArgumentList: false, 1, null, null, null),
36 new Function("Var", FunctionId.Var, typeof(object), IsValidateArguments: false, IsVariantArgumentList: false, 1, null, null, null),
37 new Function("StDev", FunctionId.StDev, typeof(object), IsValidateArguments: false, IsVariantArgumentList: false, 1, null, null, null),
38 new Function("Avg", FunctionId.Avg, typeof(object), IsValidateArguments: false, IsVariantArgumentList: false, 1, null, null, null)
39 };
40
42 {
43 get
44 {
45 if (IsAggregate)
46 {
47 return s_funcs[_info]._id;
48 }
49 return FunctionId.none;
50 }
51 }
52
54
55 internal FunctionNode(DataTable table, string name)
56 : base(table)
57 {
59 _name = name;
60 for (int i = 0; i < s_funcs.Length; i++)
61 {
62 if (string.Equals(s_funcs[i]._name, name, StringComparison.OrdinalIgnoreCase))
63 {
64 _info = i;
65 break;
66 }
67 }
68 if (_info < 0)
69 {
71 }
72 }
73
75 {
76 if (!s_funcs[_info]._isVariantArgumentList && _argumentCount >= s_funcs[_info]._argumentCount)
77 {
79 }
80 if (_arguments == null)
81 {
83 }
84 else if (_argumentCount == _arguments.Length)
85 {
89 }
91 }
92
93 internal override void Bind(DataTable table, List<DataColumn> list)
94 {
96 Check();
97 if (s_funcs[_info]._id == FunctionId.Convert)
98 {
99 if (_argumentCount != 2)
100 {
102 }
104 if (_arguments[1].GetType() == typeof(NameNode))
105 {
107 _arguments[1] = new ConstNode(table, ValueType.Str, nameNode._name);
108 }
110 }
111 else
112 {
113 for (int i = 0; i < _argumentCount; i++)
114 {
116 }
117 }
118 }
119
120 [RequiresUnreferencedCode("Members from serialized types may be trimmed if not referenced directly.")]
121 internal override object Eval()
122 {
123 return Eval(null, DataRowVersion.Default);
124 }
125
126 [RequiresUnreferencedCode("Members from serialized types may be trimmed if not referenced directly.")]
127 internal override object Eval(DataRow row, DataRowVersion version)
128 {
129 object[] array = new object[_argumentCount];
130 if (s_funcs[_info]._id == FunctionId.Convert)
131 {
132 if (_argumentCount != 2)
133 {
135 }
136 array[0] = _arguments[0].Eval(row, version);
138 }
139 else if (s_funcs[_info]._id != FunctionId.Iif)
140 {
141 for (int i = 0; i < _argumentCount; i++)
142 {
143 array[i] = _arguments[i].Eval(row, version);
144 if (!s_funcs[_info]._isValidateArguments)
145 {
146 continue;
147 }
148 if (array[i] == DBNull.Value || typeof(object) == s_funcs[_info]._parameters[i])
149 {
150 return DBNull.Value;
151 }
152 if (!(array[i].GetType() != s_funcs[_info]._parameters[i]))
153 {
154 continue;
155 }
156 if (s_funcs[_info]._parameters[i] == typeof(int) && ExpressionNode.IsInteger(DataStorage.GetStorageType(array[i].GetType())))
157 {
158 array[i] = Convert.ToInt32(array[i], base.FormatProvider);
159 continue;
160 }
161 if (s_funcs[_info]._id == FunctionId.Trim || s_funcs[_info]._id == FunctionId.Substring || s_funcs[_info]._id == FunctionId.Len)
162 {
163 if (typeof(string) != array[i].GetType() && typeof(SqlString) != array[i].GetType())
164 {
165 throw ExprException.ArgumentType(s_funcs[_info]._name, i + 1, s_funcs[_info]._parameters[i]);
166 }
167 continue;
168 }
169 throw ExprException.ArgumentType(s_funcs[_info]._name, i + 1, s_funcs[_info]._parameters[i]);
170 }
171 }
172 return EvalFunction(s_funcs[_info]._id, array, row, version);
173 }
174
175 [RequiresUnreferencedCode("Members from serialized types may be trimmed if not referenced directly.")]
176 internal override object Eval(int[] recordNos)
177 {
179 }
180
181 internal override bool IsConstant()
182 {
183 bool flag = true;
184 for (int i = 0; i < _argumentCount; i++)
185 {
186 flag = flag && _arguments[i].IsConstant();
187 }
188 return flag;
189 }
190
191 internal override bool IsTableConstant()
192 {
193 for (int i = 0; i < _argumentCount; i++)
194 {
195 if (!_arguments[i].IsTableConstant())
196 {
197 return false;
198 }
199 }
200 return true;
201 }
202
203 internal override bool HasLocalAggregate()
204 {
205 for (int i = 0; i < _argumentCount; i++)
206 {
208 {
209 return true;
210 }
211 }
212 return false;
213 }
214
215 internal override bool HasRemoteAggregate()
216 {
217 for (int i = 0; i < _argumentCount; i++)
218 {
220 {
221 return true;
222 }
223 }
224 return false;
225 }
226
227 internal override bool DependsOn(DataColumn column)
228 {
229 for (int i = 0; i < _argumentCount; i++)
230 {
232 {
233 return true;
234 }
235 }
236 return false;
237 }
238
239 [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Constant expressions are safe to be evaluated.")]
240 internal override ExpressionNode Optimize()
241 {
242 for (int i = 0; i < _argumentCount; i++)
243 {
245 }
246 if (s_funcs[_info]._id == FunctionId.In)
247 {
248 if (!IsConstant())
249 {
251 }
252 }
253 else if (IsConstant())
254 {
255 return new ConstNode(base.table, ValueType.Object, Eval(), fParseQuotes: false);
256 }
257 return this;
258 }
259
260 [RequiresUnreferencedCode("Members from serialized types may be trimmed if not referenced directly.")]
262 {
263 Type type = node.GetType();
264 string text = null;
265 if (type == typeof(NameNode))
266 {
267 text = ((NameNode)node)._name;
268 }
269 if (type == typeof(ConstNode))
270 {
271 text = ((ConstNode)node)._val.ToString();
272 }
273 if (text == null)
274 {
276 }
278 if (type2 == null)
279 {
281 }
283 return type2;
284 }
285
286 [RequiresUnreferencedCode("Members from serialized types may be trimmed if not referenced directly.")]
287 private object EvalFunction(FunctionId id, object[] argumentValues, DataRow row, DataRowVersion version)
288 {
289 switch (id)
290 {
291 case FunctionId.Abs:
292 {
295 {
296 return Math.Abs((long)argumentValues[0]);
297 }
299 {
300 return Math.Abs((double)argumentValues[0]);
301 }
303 }
304 case FunctionId.cBool:
305 return DataStorage.GetStorageType(argumentValues[0].GetType()) switch
306 {
308 StorageType.Int32 => (int)argumentValues[0] != 0,
309 StorageType.Double => (double)argumentValues[0] != 0.0,
310 StorageType.String => bool.Parse((string)argumentValues[0]),
311 _ => throw ExprException.DatatypeConvertion(argumentValues[0].GetType(), typeof(bool)),
312 };
313 case FunctionId.cInt:
314 return Convert.ToInt32(argumentValues[0], base.FormatProvider);
315 case FunctionId.cDate:
316 return Convert.ToDateTime(argumentValues[0], base.FormatProvider);
317 case FunctionId.cDbl:
318 return Convert.ToDouble(argumentValues[0], base.FormatProvider);
319 case FunctionId.cStr:
320 return Convert.ToString(argumentValues[0], base.FormatProvider);
321 case FunctionId.Charindex:
323 {
324 return DBNull.Value;
325 }
327 {
328 argumentValues[0] = ((SqlString)argumentValues[0]).Value;
329 }
331 {
332 argumentValues[1] = ((SqlString)argumentValues[1]).Value;
333 }
334 return ((string)argumentValues[1]).IndexOf((string)argumentValues[0], StringComparison.Ordinal);
335 case FunctionId.Iif:
336 {
337 object value = _arguments[0].Eval(row, version);
339 {
340 return _arguments[1].Eval(row, version);
341 }
342 return _arguments[2].Eval(row, version);
343 }
344 case FunctionId.In:
346 case FunctionId.IsNull:
348 {
349 return argumentValues[1];
350 }
351 return argumentValues[0];
352 case FunctionId.Len:
354 {
356 {
357 return DBNull.Value;
358 }
359 argumentValues[0] = ((SqlString)argumentValues[0]).Value;
360 }
361 return ((string)argumentValues[0]).Length;
362 case FunctionId.Substring:
363 {
364 int num = (int)argumentValues[1] - 1;
365 int num2 = (int)argumentValues[2];
366 if (num < 0)
367 {
368 throw ExprException.FunctionArgumentOutOfRange("index", "Substring");
369 }
370 if (num2 < 0)
371 {
372 throw ExprException.FunctionArgumentOutOfRange("length", "Substring");
373 }
374 if (num2 == 0)
375 {
376 return string.Empty;
377 }
379 {
380 argumentValues[0] = ((SqlString)argumentValues[0]).Value;
381 }
382 int length = ((string)argumentValues[0]).Length;
383 if (num > length)
384 {
385 return DBNull.Value;
386 }
387 if (num + num2 > length)
388 {
389 num2 = length - num;
390 }
391 return ((string)argumentValues[0]).Substring(num, num2);
392 }
393 case FunctionId.Trim:
395 {
396 return DBNull.Value;
397 }
399 {
400 argumentValues[0] = ((SqlString)argumentValues[0]).Value;
401 }
402 return ((string)argumentValues[0]).Trim();
403 case FunctionId.Convert:
404 {
405 if (_argumentCount != 2)
406 {
408 }
409 if (argumentValues[0] == DBNull.Value)
410 {
411 return DBNull.Value;
412 }
416 if (storageType == StorageType.DateTimeOffset && storageType2 == StorageType.String)
417 {
418 return SqlConvert.ConvertStringToDateTimeOffset((string)argumentValues[0], base.FormatProvider);
419 }
420 if (StorageType.Object != storageType)
421 {
422 if (storageType == StorageType.Guid && storageType2 == StorageType.String)
423 {
424 return new Guid((string)argumentValues[0]);
425 }
427 {
428 if (StorageType.Single == storageType2)
429 {
430 return SqlConvert.ChangeType2((float)SqlConvert.ChangeType2(argumentValues[0], StorageType.Single, typeof(float), base.FormatProvider), storageType, type, base.FormatProvider);
431 }
432 if (StorageType.Double == storageType2)
433 {
434 return SqlConvert.ChangeType2((double)SqlConvert.ChangeType2(argumentValues[0], StorageType.Double, typeof(double), base.FormatProvider), storageType, type, base.FormatProvider);
435 }
436 if (StorageType.Decimal == storageType2)
437 {
438 return SqlConvert.ChangeType2((decimal)SqlConvert.ChangeType2(argumentValues[0], StorageType.Decimal, typeof(decimal), base.FormatProvider), storageType, type, base.FormatProvider);
439 }
440 }
443 {
444 return SqlConvert.ChangeType2(argumentValues[0], storageType, type, base.FormatProvider);
445 }
446 }
447 return argumentValues[0];
448 }
449 case FunctionId.DateTimeOffset:
451 {
452 return DBNull.Value;
453 }
454 switch (((DateTime)argumentValues[0]).Kind)
455 {
456 case DateTimeKind.Utc:
457 if ((int)argumentValues[1] != 0 && (int)argumentValues[2] != 0)
458 {
460 }
461 break;
462 case DateTimeKind.Local:
463 if (DateTimeOffset.Now.Offset.Hours != (int)argumentValues[1] && DateTimeOffset.Now.Offset.Minutes != (int)argumentValues[2])
464 {
466 }
467 break;
468 }
469 if ((int)argumentValues[1] < -14 || (int)argumentValues[1] > 14)
470 {
472 }
473 if ((int)argumentValues[2] < -59 || (int)argumentValues[2] > 59)
474 {
476 }
477 if ((int)argumentValues[1] == 14 && (int)argumentValues[2] > 0)
478 {
480 }
481 if ((int)argumentValues[1] == -14 && (int)argumentValues[2] < 0)
482 {
484 }
485 return new DateTimeOffset((DateTime)argumentValues[0], new TimeSpan((int)argumentValues[1], (int)argumentValues[2], 0));
486 default:
488 }
489 }
490
491 internal void Check()
492 {
493 if (_info < 0)
494 {
496 }
497 if (s_funcs[_info]._isVariantArgumentList)
498 {
500 {
501 if (s_funcs[_info]._id == FunctionId.In)
502 {
504 }
506 }
507 }
509 {
511 }
512 }
513}
static unsafe void Copy(Array sourceArray, Array destinationArray, int length)
Definition Array.cs:624
static ? string ToString(object? value)
Definition Convert.cs:2321
static int ToInt32(object? value)
Definition Convert.cs:1320
static DateTime ToDateTime(DateTime value)
Definition Convert.cs:2211
static double ToDouble(object? value)
Definition Convert.cs:1991
static readonly DBNull Value
Definition DBNull.cs:8
static bool IsObjectNull(object value)
static StorageType GetStorageType(Type dataType)
static DateTimeOffset ConvertStringToDateTimeOffset(string value, IFormatProvider formatProvider)
static object ChangeType2(object value, StorageType stype, Type type, IFormatProvider formatProvider)
static bool ToBoolean(object value)
static Exception InWithoutList()
static Exception InvalidMinutesArgument()
static Exception InvalidType(string typeName)
static Exception FunctionArgumentOutOfRange(string arg, string func)
static Exception ArgumentTypeInteger(string function, int arg)
static Exception FunctionArgumentCount(string name)
static Exception ArgumentType(string function, int arg, Type type)
static Exception InvalidHoursArgument()
static Exception MismatchKindandTimeSpan()
static Exception NYI(string moreinfo)
static Exception ComputeNotAggregate(string expr)
static Exception UndefinedFunction(string name)
static Exception DatatypeConvertion(Type type1, Type type2)
static Exception InvalidTimeZoneRange()
static Exception NonConstantArgument()
static bool IsInteger(StorageType type)
void Bind(DataTable table, List< DataColumn > list)
void BindTable(DataTable table)
static bool IsIntegerSql(StorageType type)
static bool IsNumeric(StorageType type)
static bool IsFloatSql(StorageType type)
ExpressionNode Optimize()
override bool HasLocalAggregate()
override bool HasRemoteAggregate()
override bool DependsOn(DataColumn column)
override void Bind(DataTable table, List< DataColumn > list)
override object Eval(int[] recordNos)
object EvalFunction(FunctionId id, object[] argumentValues, DataRow row, DataRowVersion version)
override object Eval(DataRow row, DataRowVersion version)
FunctionNode(DataTable table, string name)
readonly TypeLimiter _capturedLimiter
override object Eval()
Type GetDataType(ExpressionNode node)
override bool IsTableConstant()
static readonly Function[] s_funcs
readonly string _name
override ExpressionNode Optimize()
ExpressionNode[] _arguments
override bool IsConstant()
void AddArgument(ExpressionNode argument)
static TypeLimiter Capture()
static void EnsureTypeIsAllowed(Type type, TypeLimiter capturedLimiter=null)
static double Abs(double value)
static DeserializationToken StartDeserialization()
static ? Type GetType(string typeName, bool throwOnError, bool ignoreCase)
Definition Type.cs:408
static DateTimeOffset Now