Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
Select.cs
Go to the documentation of this file.
5
6namespace System.Data;
7
8internal sealed class Select
9{
10 private sealed class ColumnInfo
11 {
12 public bool flag;
13
14 public bool equalsOperator;
15
17 }
18
19 private readonly DataTable _table;
20
21 private readonly IndexField[] _indexFields;
22
24
25 private readonly DataExpression _rowFilter;
26
27 private readonly ExpressionNode _expression;
28
29 private Index _index;
30
31 private int[] _records;
32
33 private int _recordCount;
34
36
38
40
41 private int _nCandidates;
42
43 private int _matchedCandidates;
44
45 [RequiresUnreferencedCode("Members of types used in the filter expression might be trimmed.")]
57
58 private bool IsSupportedOperator(int op)
59 {
60 if ((op < 7 || op > 11) && op != 13)
61 {
62 return op == 39;
63 }
64 return true;
65 }
66
67 private void AnalyzeExpression(BinaryNode expr)
68 {
70 {
71 return;
72 }
73 if (expr._op == 27)
74 {
76 return;
77 }
78 if (expr._op == 26)
79 {
80 bool flag = false;
81 bool flag2 = false;
82 if (expr._left is BinaryNode)
83 {
86 {
87 return;
88 }
89 flag = true;
90 }
91 else
92 {
93 UnaryNode unaryNode = expr._left as UnaryNode;
94 if (unaryNode != null)
95 {
96 while (unaryNode._op == 0 && unaryNode._right is UnaryNode && ((UnaryNode)unaryNode._right)._op == 0)
97 {
99 }
100 if (unaryNode._op == 0 && unaryNode._right is BinaryNode)
101 {
104 {
105 return;
106 }
107 flag = true;
108 }
109 }
110 }
111 if (expr._right is BinaryNode)
112 {
115 {
116 return;
117 }
118 flag2 = true;
119 }
120 else
121 {
122 UnaryNode unaryNode2 = expr._right as UnaryNode;
123 if (unaryNode2 != null)
124 {
125 while (unaryNode2._op == 0 && unaryNode2._right is UnaryNode && ((UnaryNode)unaryNode2._right)._op == 0)
126 {
128 }
129 if (unaryNode2._op == 0 && unaryNode2._right is BinaryNode)
130 {
133 {
134 return;
135 }
136 flag2 = true;
137 }
138 }
139 }
140 if (!(flag && flag2))
141 {
142 ExpressionNode expressionNode = (flag ? expr._right : expr._left);
144 }
145 return;
146 }
147 if (IsSupportedOperator(expr._op))
148 {
149 if (expr._left is NameNode && expr._right is ConstNode)
150 {
151 ColumnInfo columnInfo = _candidateColumns[((NameNode)expr._left)._column.Ordinal];
152 columnInfo.expr = ((columnInfo.expr == null) ? expr : new BinaryNode(_table, 26, expr, columnInfo.expr));
153 if (expr._op == 7)
154 {
155 columnInfo.equalsOperator = true;
156 }
158 return;
159 }
160 if (expr._right is NameNode && expr._left is ConstNode)
161 {
162 ExpressionNode left = expr._left;
163 expr._left = expr._right;
164 expr._right = left;
165 switch (expr._op)
166 {
167 case 8:
168 expr._op = 9;
169 break;
170 case 9:
171 expr._op = 8;
172 break;
173 case 10:
174 expr._op = 11;
175 break;
176 case 11:
177 expr._op = 10;
178 break;
179 }
180 ColumnInfo columnInfo2 = _candidateColumns[((NameNode)expr._left)._column.Ordinal];
181 columnInfo2.expr = ((columnInfo2.expr == null) ? expr : new BinaryNode(_table, 26, expr, columnInfo2.expr));
182 if (expr._op == 7)
183 {
184 columnInfo2.equalsOperator = true;
185 }
187 return;
188 }
189 }
190 _linearExpression = ((_linearExpression == null) ? expr : new BinaryNode(_table, 26, expr, _linearExpression));
191 }
192
193 private bool CompareSortIndexDesc(IndexField[] fields)
194 {
195 if (fields.Length < _indexFields.Length)
196 {
197 return false;
198 }
199 int num = 0;
200 for (int i = 0; i < fields.Length; i++)
201 {
202 if (num >= _indexFields.Length)
203 {
204 break;
205 }
206 if (fields[i] == _indexFields[num])
207 {
208 num++;
209 continue;
210 }
212 if (columnInfo == null || !columnInfo.equalsOperator)
213 {
214 return false;
215 }
216 }
217 return num == _indexFields.Length;
218 }
219
220 private bool FindSortIndex()
221 {
222 _index = null;
223 _table._indexesLock.EnterUpgradeableReadLock();
224 try
225 {
227 for (int i = 0; i < count; i++)
228 {
230 if (index.RecordStates == _recordStates && index.IsSharable && CompareSortIndexDesc(index._indexFields))
231 {
232 _index = index;
233 return true;
234 }
235 }
236 }
237 finally
238 {
239 _table._indexesLock.ExitUpgradeableReadLock();
240 }
241 return false;
242 }
243
245 {
246 int num = ((fields.Length < _nCandidates) ? fields.Length : _nCandidates);
247 int i;
248 for (i = 0; i < num; i++)
249 {
251 if (columnInfo == null || columnInfo.expr == null)
252 {
253 break;
254 }
255 if (!columnInfo.equalsOperator)
256 {
257 return i + 1;
258 }
259 }
260 return i;
261 }
262
264 {
265 _index = null;
267 bool flag = true;
268 _table._indexesLock.EnterUpgradeableReadLock();
269 try
270 {
272 for (int i = 0; i < count; i++)
273 {
275 if (index.RecordStates != _recordStates || !index.IsSharable)
276 {
277 continue;
278 }
279 int num = CompareClosestCandidateIndexDesc(index._indexFields);
280 if (num > _matchedCandidates || (num == _matchedCandidates && !flag))
281 {
282 _matchedCandidates = num;
283 _index = index;
284 flag = CompareSortIndexDesc(index._indexFields);
285 if (_matchedCandidates == _nCandidates && flag)
286 {
287 return true;
288 }
289 }
290 }
291 }
292 finally
293 {
294 _table._indexesLock.ExitUpgradeableReadLock();
295 }
296 if (_index == null)
297 {
298 return false;
299 }
300 return flag;
301 }
302
303 private void InitCandidateColumns()
304 {
305 _nCandidates = 0;
307 if (_rowFilter == null)
308 {
309 return;
310 }
312 for (int i = 0; i < dependency.Length; i++)
313 {
314 if (dependency[i].Table == _table)
315 {
316 _candidateColumns[dependency[i].Ordinal] = new ColumnInfo();
317 _nCandidates++;
318 }
319 }
320 }
321
322 private void CreateIndex()
323 {
324 if (_index != null)
325 {
326 return;
327 }
328 if (_nCandidates == 0)
329 {
331 _index.AddRef();
332 return;
333 }
334 int num = _candidateColumns.Length;
335 int num2 = _indexFields.Length;
336 bool flag = true;
337 int i;
338 for (i = 0; i < num; i++)
339 {
340 if (_candidateColumns[i] != null && !_candidateColumns[i].equalsOperator)
341 {
342 flag = false;
343 break;
344 }
345 }
346 int num3 = 0;
347 for (i = 0; i < num2; i++)
348 {
350 if (columnInfo != null)
351 {
352 columnInfo.flag = true;
353 num3++;
354 }
355 }
356 int num4 = num2 - num3;
358 if (flag)
359 {
360 num3 = 0;
361 for (i = 0; i < num; i++)
362 {
363 if (_candidateColumns[i] != null)
364 {
365 array[num3++] = new IndexField(_table.Columns[i], isDescending: false);
366 _candidateColumns[i].flag = false;
367 }
368 }
369 for (i = 0; i < num2; i++)
370 {
372 if (columnInfo2 == null || columnInfo2.flag)
373 {
374 array[num3++] = _indexFields[i];
375 if (columnInfo2 != null)
376 {
377 columnInfo2.flag = false;
378 }
379 }
380 }
381 for (i = 0; i < _candidateColumns.Length; i++)
382 {
383 if (_candidateColumns[i] != null)
384 {
385 _candidateColumns[i].flag = false;
386 }
387 }
388 _index = new Index(_table, array, _recordStates, null);
390 {
391 _index.AddRef();
392 }
394 return;
395 }
396 for (i = 0; i < num2; i++)
397 {
398 array[i] = _indexFields[i];
400 if (columnInfo3 != null)
401 {
402 columnInfo3.flag = true;
403 }
404 }
405 num3 = i;
406 for (i = 0; i < num; i++)
407 {
408 if (_candidateColumns[i] != null)
409 {
410 if (!_candidateColumns[i].flag)
411 {
412 array[num3++] = new IndexField(_table.Columns[i], isDescending: false);
413 }
414 else
415 {
416 _candidateColumns[i].flag = false;
417 }
418 }
419 }
420 _index = new Index(_table, array, _recordStates, null);
423 {
425 while (_matchedCandidates < num3)
426 {
428 if (columnInfo4 == null || columnInfo4.expr == null)
429 {
430 break;
431 }
433 if (!columnInfo4.equalsOperator)
434 {
435 break;
436 }
437 }
438 }
439 for (i = 0; i < _candidateColumns.Length; i++)
440 {
441 if (_candidateColumns[i] != null)
442 {
443 _candidateColumns[i].flag = false;
444 }
445 }
446 }
447
449 {
451 {
452 return true;
453 }
454 return false;
455 }
456
458 {
460 int num = indexFields.Length;
461 for (int i = 0; i < _matchedCandidates; i++)
462 {
464 columnInfo.flag = true;
465 }
466 int num2 = _candidateColumns.Length;
467 for (int i = 0; i < num2; i++)
468 {
469 if (_candidateColumns[i] == null)
470 {
471 continue;
472 }
473 if (!_candidateColumns[i].flag)
474 {
476 if (expr != null)
477 {
479 }
480 }
481 else
482 {
483 _candidateColumns[i].flag = false;
484 }
485 }
486 }
487
489 {
490 bool flag = true;
493 {
496 {
498 }
500 {
501 for (int i = 0; i < _candidateColumns.Length; i++)
502 {
503 if (_candidateColumns[i] != null)
504 {
506 _candidateColumns[i].expr = null;
507 }
508 }
509 }
510 else
511 {
513 }
514 }
515 else
516 {
518 }
519 if (_index == null && (_indexFields.Length != 0 || _linearExpression == _expression))
520 {
521 flag = !FindSortIndex();
522 }
523 if (_index == null)
524 {
525 CreateIndex();
526 flag = false;
527 }
528 if (_index.RecordCount == 0)
529 {
530 return _table.NewRowArray(0);
531 }
532 Range range;
533 if (_matchedCandidates == 0)
534 {
535 range = new Range(0, _index.RecordCount - 1);
538 }
540 if (range.Count == 0)
541 {
542 return _table.NewRowArray(0);
543 }
545 {
547 }
548 if (!flag)
549 {
551 }
553 _recordCount = _records.Length;
554 if (_recordCount == 0)
555 {
556 return _table.NewRowArray(0);
557 }
558 Sort(0, _recordCount - 1);
559 return GetRows();
560 }
561
562 public DataRow[] GetRows()
563 {
565 for (int i = 0; i < array.Length; i++)
566 {
568 }
569 return array;
570 }
571
572 [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "All constructors are marked as unsafe.")]
573 private bool AcceptRecord(int record)
574 {
576 if (dataRow == null)
577 {
578 return true;
579 }
580 DataRowVersion version = DataRowVersion.Default;
581 if (dataRow._oldRecord == record)
582 {
583 version = DataRowVersion.Original;
584 }
585 else if (dataRow._newRecord == record)
586 {
587 version = DataRowVersion.Current;
588 }
589 else if (dataRow._tempRecord == record)
590 {
591 version = DataRowVersion.Proposed;
592 }
593 object value = _linearExpression.Eval(dataRow, version);
594 try
595 {
597 }
599 {
601 }
602 }
603
604 [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "All constructors are marked as unsafe.")]
605 private int Eval(BinaryNode expr, DataRow row, DataRowVersion version)
606 {
607 if (expr._op == 26)
608 {
609 int num = Eval((BinaryNode)expr._left, row, version);
610 if (num != 0)
611 {
612 return num;
613 }
614 int num2 = Eval((BinaryNode)expr._right, row, version);
615 if (num2 != 0)
616 {
617 return num2;
618 }
619 return 0;
620 }
621 long num3 = 0L;
622 object obj = expr._left.Eval(row, version);
623 if (expr._op != 13 && expr._op != 39)
624 {
625 object obj2 = expr._right.Eval(row, version);
626 bool flag = expr._left is ConstNode;
627 bool flag2 = expr._right is ConstNode;
629 {
630 return -1;
631 }
633 {
634 return 1;
635 }
637 if (StorageType.Char == storageType)
638 {
640 }
642 StorageType storageType3 = ((!expr._left.IsSqlColumn && !expr._right.IsSqlColumn) ? expr.ResultType(storageType, storageType2, flag, flag2, expr._op) : expr.ResultSqlType(storageType, storageType2, flag, flag2, expr._op));
643 if (storageType3 == StorageType.Empty)
644 {
645 expr.SetTypeMismatchError(expr._op, obj.GetType(), obj2.GetType());
646 }
647 NameNode nameNode = null;
648 CompareInfo comparer = (((flag && !flag2 && storageType == StorageType.String && storageType2 == StorageType.Guid && expr._right is NameNode nameNode2 && nameNode2._column.DataType == typeof(Guid)) || (flag2 && !flag && storageType2 == StorageType.String && storageType == StorageType.Guid && expr._left is NameNode nameNode3 && nameNode3._column.DataType == typeof(Guid))) ? CultureInfo.InvariantCulture.CompareInfo : null);
650 }
651 switch (expr._op)
652 {
653 case 7:
654 num3 = ((num3 != 0L) ? ((num3 >= 0) ? 1 : (-1)) : 0);
655 break;
656 case 8:
657 num3 = ((num3 <= 0) ? (-1) : 0);
658 break;
659 case 9:
660 num3 = ((num3 >= 0) ? 1 : 0);
661 break;
662 case 10:
663 num3 = ((num3 < 0) ? (-1) : 0);
664 break;
665 case 11:
666 num3 = ((num3 > 0) ? 1 : 0);
667 break;
668 case 13:
669 num3 = ((obj != DBNull.Value) ? (-1) : 0);
670 break;
671 case 39:
672 num3 = ((obj == DBNull.Value) ? 1 : 0);
673 break;
674 }
675 return (int)num3;
676 }
677
678 private int Evaluate(int record)
679 {
681 if (dataRow == null)
682 {
683 return 0;
684 }
685 DataRowVersion version = DataRowVersion.Default;
686 if (dataRow._oldRecord == record)
687 {
688 version = DataRowVersion.Original;
689 }
690 else if (dataRow._newRecord == record)
691 {
692 version = DataRowVersion.Current;
693 }
694 else if (dataRow._tempRecord == record)
695 {
696 version = DataRowVersion.Proposed;
697 }
699 for (int i = 0; i < _matchedCandidates; i++)
700 {
702 int num = Eval(columnInfo.expr, dataRow, version);
703 if (num != 0)
704 {
705 if (!indexFields[i].IsDescending)
706 {
707 return num;
708 }
709 return -num;
710 }
711 }
712 return 0;
713 }
714
716 {
717 int result = -1;
718 int num = 0;
719 int num2 = _index.RecordCount - 1;
720 while (num <= num2)
721 {
722 int num3 = num + num2 >> 1;
724 int num4 = Evaluate(record);
725 if (num4 == 0)
726 {
727 result = num3;
728 }
729 if (num4 < 0)
730 {
731 num = num3 + 1;
732 }
733 else
734 {
735 num2 = num3 - 1;
736 }
737 }
738 return result;
739 }
740
741 private int FindLastMatchingRecord(int lo)
742 {
743 int result = -1;
744 int num = _index.RecordCount - 1;
745 while (lo <= num)
746 {
747 int num2 = lo + num >> 1;
749 int num3 = Evaluate(record);
750 if (num3 == 0)
751 {
752 result = num2;
753 }
754 if (num3 <= 0)
755 {
756 lo = num2 + 1;
757 }
758 else
759 {
760 num = num2 - 1;
761 }
762 }
763 return result;
764 }
765
767 {
768 if (_matchedCandidates == 0)
769 {
770 return new Range(0, _index.RecordCount - 1);
771 }
772 int num = FindFirstMatchingRecord();
773 if (num == -1)
774 {
775 return default(Range);
776 }
777 int max = FindLastMatchingRecord(num);
778 return new Range(num, max);
779 }
780
782 {
783 if (_linearExpression == null)
784 {
785 int[] array = new int[range.Count];
786 RBTree<int>.RBTreeEnumerator enumerator = _index.GetEnumerator(range.Min);
787 for (int i = 0; i < range.Count; i++)
788 {
789 if (!enumerator.MoveNext())
790 {
791 break;
792 }
793 array[i] = enumerator.Current;
794 }
795 return array;
796 }
797 List<int> list = new List<int>();
798 RBTree<int>.RBTreeEnumerator enumerator2 = _index.GetEnumerator(range.Min);
799 for (int j = 0; j < range.Count; j++)
800 {
801 if (!enumerator2.MoveNext())
802 {
803 break;
804 }
805 if (AcceptRecord(enumerator2.Current))
806 {
807 list.Add(enumerator2.Current);
808 }
809 }
810 return list.ToArray();
811 }
812
814 {
815 if (_linearExpression == null)
816 {
817 return _index.GetRows(range);
818 }
820 RBTree<int>.RBTreeEnumerator enumerator = _index.GetEnumerator(range.Min);
821 for (int i = 0; i < range.Count; i++)
822 {
823 if (!enumerator.MoveNext())
824 {
825 break;
826 }
827 if (AcceptRecord(enumerator.Current))
828 {
830 }
831 }
833 list.CopyTo(array);
834 return array;
835 }
836
837 private int CompareRecords(int record1, int record2)
838 {
839 int num = _indexFields.Length;
840 for (int i = 0; i < num; i++)
841 {
843 if (num2 != 0)
844 {
845 if (_indexFields[i].IsDescending)
846 {
847 num2 = -num2;
848 }
849 return num2;
850 }
851 }
856 long num3 = dataRow3?.rowID ?? 0;
857 long num4 = dataRow4?.rowID ?? 0;
858 int num5 = ((num3 < num4) ? (-1) : ((num4 < num3) ? 1 : 0));
859 if (num5 == 0 && record1 != record2 && dataRow3 != null && dataRow4 != null)
860 {
861 num3 = (long)dataRow3.GetRecordState(record1);
862 num4 = (long)dataRow4.GetRecordState(record2);
863 num5 = ((num3 < num4) ? (-1) : ((num4 < num3) ? 1 : 0));
864 }
865 return num5;
866 }
867
868 private void Sort(int left, int right)
869 {
870 int num;
871 do
872 {
873 num = left;
874 int num2 = right;
875 int record = _records[num + num2 >> 1];
876 while (true)
877 {
878 if (CompareRecords(_records[num], record) < 0)
879 {
880 num++;
881 continue;
882 }
883 while (CompareRecords(_records[num2], record) > 0)
884 {
885 num2--;
886 }
887 if (num <= num2)
888 {
889 int num3 = _records[num];
890 _records[num] = _records[num2];
891 _records[num2] = num3;
892 num++;
893 num2--;
894 }
895 if (num > num2)
896 {
897 break;
898 }
899 }
900 if (left < num2)
901 {
902 Sort(left, num2);
903 }
904 left = num;
905 }
906 while (num < right);
907 }
908}
static char ToChar(object? value)
Definition Convert.cs:618
static readonly DBNull Value
Definition DBNull.cs:8
StorageType ResultSqlType(StorageType left, StorageType right, bool lc, bool rc, int op)
StorageType ResultType(StorageType left, StorageType right, bool lc, bool rc, int op)
ExpressionNode _left
Definition BinaryNode.cs:51
int BinaryCompare(object vLeft, object vRight, StorageType resultType, int op)
void SetTypeMismatchError(int op, Type left, Type right)
ExpressionNode _right
Definition BinaryNode.cs:53
static bool IsCatchableExceptionType(Exception e)
Definition ADP.cs:790
static bool IsObjectSqlNull(object value)
static StorageType GetStorageType(Type dataType)
static object ChangeType2(object value, StorageType stype, Type type, IFormatProvider formatProvider)
int Compare(int record1, int record2)
static bool ToBoolean(object value)
IFormatProvider FormatProvider
Definition DataTable.cs:435
readonly ReaderWriterLockSlim _indexesLock
Definition DataTable.cs:194
readonly List< Index > _indexes
Definition DataTable.cs:76
DataColumnCollection Columns
Definition DataTable.cs:327
IndexField[] ParseSortString(string sortString)
DataRow[] NewRowArray(int size)
readonly RecordManager _recordManager
Definition DataTable.cs:74
static Exception FilterConvertion(string expr)
void AddRef()
Definition Index.cs:196
RBTree< int >.RBTreeEnumerator GetEnumerator(int startIndex)
Definition Index.cs:366
readonly IndexField[] _indexFields
Definition Index.cs:34
DataRow[] GetRows(object[] values)
Definition Index.cs:611
int GetRecord(int recordIndex)
Definition Index.cs:148
int Add(K item)
Definition RBTree.cs:1225
bool _candidatesForBinarySearch
Definition Select.cs:37
bool FindSortIndex()
Definition Select.cs:220
ColumnInfo[] _candidateColumns
Definition Select.cs:39
void AnalyzeExpression(BinaryNode expr)
Definition Select.cs:67
void CreateIndex()
Definition Select.cs:322
void Sort(int left, int right)
Definition Select.cs:868
DataRow[] GetRows()
Definition Select.cs:562
int Eval(BinaryNode expr, DataRow row, DataRowVersion version)
Definition Select.cs:605
bool FindClosestCandidateIndex()
Definition Select.cs:263
Range GetBinaryFilteredRecords()
Definition Select.cs:766
int _matchedCandidates
Definition Select.cs:43
bool AcceptRecord(int record)
Definition Select.cs:573
ExpressionNode _linearExpression
Definition Select.cs:35
readonly DataViewRowState _recordStates
Definition Select.cs:23
int CompareRecords(int record1, int record2)
Definition Select.cs:837
readonly DataTable _table
Definition Select.cs:19
int Evaluate(int record)
Definition Select.cs:678
bool IsOperatorIn(ExpressionNode enode)
Definition Select.cs:448
bool IsSupportedOperator(int op)
Definition Select.cs:58
int[] GetLinearFilteredRecords(Range range)
Definition Select.cs:781
int CompareClosestCandidateIndexDesc(IndexField[] fields)
Definition Select.cs:244
int FindLastMatchingRecord(int lo)
Definition Select.cs:741
int FindFirstMatchingRecord()
Definition Select.cs:715
readonly ExpressionNode _expression
Definition Select.cs:27
void BuildLinearExpression()
Definition Select.cs:457
DataRow[] SelectRows()
Definition Select.cs:488
readonly DataExpression _rowFilter
Definition Select.cs:25
bool CompareSortIndexDesc(IndexField[] fields)
Definition Select.cs:193
Select(DataTable table, string filterExpression, string sort, DataViewRowState recordStates)
Definition Select.cs:46
void InitCandidateColumns()
Definition Select.cs:303
readonly IndexField[] _indexFields
Definition Select.cs:21
DataRow[] GetLinearFilteredRows(Range range)
Definition Select.cs:813
readonly int _op
Definition UnaryNode.cs:10
readonly DataColumn Column
Definition IndexField.cs:7