internal ClickHouseDataReader(ClickHouseTable table, ClickHouseTcpClient.Session session, CancellationTokenSource?sessionTokenSource) { _currentTable = table ?? throw new ArgumentNullException(nameof(table)); _session = session ?? throw new ArgumentNullException(nameof(session)); _sessionTokenSource = sessionTokenSource; _reinterpretedColumnsCache = new IClickHouseTableColumn[_currentTable.Columns.Count]; _recordsAffected = _currentTable.Header.RowCount; _blockHeader = _currentTable.Header; }
internal ClickHouseDataReader(ClickHouseTable table, ClickHouseTcpClient.Session session, ClickHouseDataReaderRowLimit rowLimit, bool ignoreProfileEvents) { _currentTable = table.Header == null || table.Columns == null ? throw new ArgumentNullException(nameof(table)) : table; _session = session ?? throw new ArgumentNullException(nameof(session)); _rowLimit = rowLimit; _ignoreProfileEvents = ignoreProfileEvents; _reinterpretedColumnsCache = new IClickHouseTableColumn[_currentTable.Columns.Count]; _recordsAffected = checked ((ulong)_currentTable.Header.RowCount); State = _rowLimit == ClickHouseDataReaderRowLimit.Zero ? ClickHouseDataReaderState.ClosePending : ClickHouseDataReaderState.Data; }
public override bool NextResult() { if (_totalsTable == null) { return(false); } _resultsetSwitched = true; _rowIndex = -1; _currentTable = _totalsTable; return(true); }
private async ValueTask <bool> Read(bool nextResult, bool async, CancellationToken cancellationToken) { if (!nextResult) { if (_rowIndex == _currentTable.Header.RowCount) { return(false); } if (++_rowIndex < _currentTable.Header.RowCount) { return(true); } } while (true) { ClickHouseTable nextTable; try { var message = _nextResultMessage; if (message == null) { message = await _session.ReadMessage(async, cancellationToken); } else { _nextResultMessage = null; } switch (message.MessageCode) { case ServerMessageCode.Data: switch (State) { case ClickHouseDataReaderState.NextResultPending: State = ClickHouseDataReaderState.Data; goto case ClickHouseDataReaderState.Data; case ClickHouseDataReaderState.Data: { var dataMessage = (ServerDataMessage)message; nextTable = await _session.ReadTable(dataMessage, _columnSettings, async, cancellationToken); break; } case ClickHouseDataReaderState.Totals: case ClickHouseDataReaderState.Extremes: { var dataMessage = (ServerDataMessage)message; var table = await _session.SkipTable(dataMessage, async, cancellationToken); if (table.RowCount != 0 || table.Columns.Count != 0) { throw new ClickHouseException(ClickHouseErrorCodes.ProtocolUnexpectedResponse, "Unexpected data block after totals or extremes."); } continue; } default: goto UNEXPECTED_RESPONSE; } break; case ServerMessageCode.Error: State = ClickHouseDataReaderState.Closed; _session.Dispose(); throw ((ServerErrorMessage)message).Exception; case ServerMessageCode.Progress: var progressMessage = (ServerProgressMessage)message; _recordsAffected = progressMessage.Rows; continue; case ServerMessageCode.EndOfStream: State = ClickHouseDataReaderState.Closed; _session.Dispose(); return(false); case ServerMessageCode.ProfileInfo: continue; case ServerMessageCode.Totals: switch (State) { case ClickHouseDataReaderState.NextResultPending: State = ClickHouseDataReaderState.Totals; goto case ClickHouseDataReaderState.Totals; case ClickHouseDataReaderState.Totals: var totalsMessage = (ServerDataMessage)message; nextTable = await _session.ReadTable(totalsMessage, _columnSettings, async, cancellationToken); break; case ClickHouseDataReaderState.Data: case ClickHouseDataReaderState.Extremes: _nextResultMessage = message; State = ClickHouseDataReaderState.NextResultPending; return(false); default: goto UNEXPECTED_RESPONSE; } break; case ServerMessageCode.Extremes: switch (State) { case ClickHouseDataReaderState.NextResultPending: State = ClickHouseDataReaderState.Extremes; goto case ClickHouseDataReaderState.Extremes; case ClickHouseDataReaderState.Extremes: var extremesMessage = (ServerDataMessage)message; nextTable = await _session.ReadTable(extremesMessage, _columnSettings, async, cancellationToken); break; case ClickHouseDataReaderState.Data: case ClickHouseDataReaderState.Totals: _nextResultMessage = message; State = ClickHouseDataReaderState.NextResultPending; return(false); default: goto UNEXPECTED_RESPONSE; } break; case ServerMessageCode.Pong: case ServerMessageCode.Hello: case ServerMessageCode.Log: UNEXPECTED_RESPONSE: throw new ClickHouseException(ClickHouseErrorCodes.ProtocolUnexpectedResponse, $"Unexpected server message: \"{message.MessageCode}\"."); default: throw new NotSupportedException($"Internal error. Message code \"{message.MessageCode}\" not supported."); } } catch (ClickHouseHandledException) { throw; } catch (ClickHouseServerException) { throw; } catch (Exception ex) { State = ClickHouseDataReaderState.Broken; var aggrEx = await _session.SetFailed(ex, true, async); if (aggrEx != null) { throw aggrEx; } throw; } if (nextTable.Header.RowCount == 0) { continue; } _currentTable = nextTable; _reinterpretedColumnsCache = new IClickHouseTableColumn[_currentTable.Columns.Count]; _recordsAffected += nextTable.Header.RowCount; _rowIndex = nextResult ? -1 : 0; return(true); } }
private async ValueTask <bool> Read(bool async, CancellationToken cancellationToken) { if (_rowIndex == _currentTable.Header.RowCount) { return(false); } if (++_rowIndex < _currentTable.Header.RowCount) { return(true); } while (true && _resultsetSwitched == false)//if we simple switched the recordset no need to fetch data { ClickHouseTable nextTable; try { var message = await _session.ReadMessage(async, cancellationToken); switch (message.MessageCode) { case ServerMessageCode.Data: var dataMessage = (ServerDataMessage)message; nextTable = await _session.ReadTable(dataMessage, _columnSettings, async, cancellationToken); break; case ServerMessageCode.Error: _isClosed = true; _session.Dispose(); throw ((ServerErrorMessage)message).Exception; case ServerMessageCode.Progress: var progressMessage = (ServerProgressMessage)message; _recordsAffected = progressMessage.Rows; continue; case ServerMessageCode.EndOfStream: _isClosed = true; _session.Dispose(); return(false); case ServerMessageCode.ProfileInfo: continue; case ServerMessageCode.Totals: var totalsMessage = (ServerDataMessage)message; _totalsTable = await _session.ReadTable(totalsMessage, _columnSettings, async, cancellationToken); continue; //or break? looks like we should break: totals is one row result and it occupy only 1 block case ServerMessageCode.Extremes: var extermesMessage = (ServerDataMessage)message; await _session.SkipTable(extermesMessage, async, cancellationToken); continue; case ServerMessageCode.Pong: case ServerMessageCode.Hello: case ServerMessageCode.Log: throw new ClickHouseException(ClickHouseErrorCodes.ProtocolUnexpectedResponse, $"Unexpected server message: \"{message.MessageCode}\"."); default: throw new NotSupportedException($"Internal error. Message code \"{message.MessageCode}\" not supported."); } } catch (ClickHouseHandledException) { throw; } catch (ClickHouseServerException) { throw; } catch (Exception ex) { _isClosed = true; var aggrEx = await _session.SetFailed(ex, true, async); if (aggrEx != null) { throw aggrEx; } throw; } if (nextTable.Header.RowCount == 0) { continue; } _currentTable = nextTable; _reinterpretedColumnsCache = new IClickHouseTableColumn[_currentTable.Columns.Count]; _recordsAffected += nextTable.Header.RowCount; _rowIndex = 0; return(true); } return(false); }