/
krasninja
/
querycat
Обзор
Документация
Войти
/
krasninja
/
querycat
Код
Пакеты
0
Релизы
0
Аналитика
Безопасность
develop
src/QueryCat.Backend/Commands/Select/Inputs/SetKeysRowsInput.cs
146 строк
4 KB
Ivan Kozhin
Partial support for In operator in SetKeysRowsInput
25 мар 2024, 08:17
25 мар 2024, 08:17
f8a79c3
Код
Авторство
О чём код?
using Microsoft.Extensions.Logging; using QueryCat.Backend.Core; using QueryCat.Backend.Core.Data; using QueryCat.Backend.Core.Types; namespace QueryCat.Backend.Commands.Select.Inputs; internal sealed class SetKeysRowsInput : RowsInput, IRowsInputKeys { private record struct ConditionJoint(SelectQueryCondition Condition, int ColumnIndex); private ConditionJoint[] _conditions = Array.Empty<ConditionJoint>(); private readonly IRowsInputKeys _rowsInput; private readonly SelectQueryConditions _selectQueryConditions; private bool _keysFilled; private int _currentFuncValueIndex = -1; // Special mode for "WHERE id IN (x, y, z)" condition. private bool _multipleRowsMode; private readonly ILogger _logger = Application.LoggerFactory.CreateLogger(nameof(SetKeysRowsInput)); /// <inheritdoc /> public override QueryContext QueryContext { get => _rowsInput.QueryContext; set => _rowsInput.QueryContext = value; } /// <inheritdoc /> public override Column[] Columns { get; protected set; } public IRowsInputKeys InnerRowsInput => _rowsInput; public SetKeysRowsInput(IRowsInputKeys rowsInput, SelectQueryConditions conditions) { Columns = rowsInput.Columns; _rowsInput = rowsInput; _selectQueryConditions = conditions; } /// <inheritdoc /> public override void Open() => _rowsInput.Open(); /// <inheritdoc /> public override void Close() => _rowsInput.Close(); /// <inheritdoc /> public override void Reset() { _currentFuncValueIndex = -1; _keysFilled = false; _rowsInput.Reset(); } /// <inheritdoc /> public override ErrorCode ReadValue(int columnIndex, out VariantValue value) => _rowsInput.ReadValue(columnIndex, out value); /// <inheritdoc /> public override bool ReadNext() { base.ReadNext(); if (!_keysFilled) { FillKeys(); _keysFilled = true; } var hasData = _rowsInput.ReadNext(); // We need to repeat "ReadNext" call in case of multiple func values. if (_multipleRowsMode && !hasData) { _rowsInput.Reset(); hasData = FillKeys(); if (!hasData) { return false; } hasData = _rowsInput.ReadNext(); } return hasData; } private bool FillKeys() { if (_multipleRowsMode) { _currentFuncValueIndex++; var valueFuncs = _conditions[0].Condition.ValueFuncs; if (_currentFuncValueIndex >= valueFuncs.Count) { return false; } var value = valueFuncs[_currentFuncValueIndex].Invoke(); _rowsInput.SetKeyColumnValue(_conditions[0].ColumnIndex, value, _conditions[0].Condition.Operation); } else { foreach (var conditionJoint in _conditions) { var value = conditionJoint.Condition.ValueFunc.Invoke(); _rowsInput.SetKeyColumnValue(conditionJoint.ColumnIndex, value, conditionJoint.Condition.Operation); } } return true; } /// <inheritdoc /> protected override void Load() { // Find all related conditions. var list = new List<ConditionJoint>(); foreach (var condition in _selectQueryConditions.GetConditionsColumns(_rowsInput)) { foreach (var inputKeyCondition in condition.Conditions) { list.Add(new ConditionJoint(inputKeyCondition, condition.KeyColumn.ColumnIndex)); } } _conditions = list.ToArray(); // Special mode for "WHERE id IN (x, y, z)" condition. _multipleRowsMode = _conditions.Length == 1 && _conditions[0].Condition.Operation == VariantValue.Operation.Equals && _conditions[0].Condition.ValueFuncs.Count > 1; base.Load(); } /// <inheritdoc /> public override void Explain(IndentedStringBuilder stringBuilder) { stringBuilder.AppendRowsInputsWithIndent("SetKeys", _rowsInput); } /// <inheritdoc /> public IReadOnlyList<KeyColumn> GetKeyColumns() => _rowsInput.GetKeyColumns(); /// <inheritdoc /> public void SetKeyColumnValue(int columnIndex, VariantValue value, VariantValue.Operation operation) { // Do not passthru set key value calls. } }