Exemple #1
0
        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);
            }
        }
Exemple #2
0
        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);
        }