internal async Task NextResultAsync()

in MySQL.Data/src/MySqlDataReader.cs [1302:1409]


    internal async Task<bool> NextResultAsync(bool execAsync, CancellationToken cancellationToken)
    {
      if (!_isOpen)
        Throw(new MySqlException(Resources.NextResultIsClosed));

      bool isCaching = Command.CommandType == CommandType.TableDirect && Command.EnableCaching &&
        (CommandBehavior & CommandBehavior.SequentialAccess) == 0;

      // this will clear out any unread data
      if (ResultSet != null)
      {
        await ResultSet.CloseAsync(execAsync).ConfigureAwait(false);
        if (isCaching)
          TableCache.AddToCache(Command.CommandText, ResultSet);
      }

      // single result means we only return a single resultset.  If we have already
      // returned one, then we return false
      // TableDirect is basically a select * from a single table so it will generate
      // a single result also
      if (ResultSet != null &&
        ((CommandBehavior & CommandBehavior.SingleResult) != 0 || isCaching))
        return false;

      // next load up the next resultset if any
      try
      {
        do
        {
          ResultSet = null;
          // if we are table caching, then try to retrieve the resultSet from the cache
          if (isCaching)
            ResultSet = TableCache.RetrieveFromCache(Command.CommandText, Command.CacheAge);

          if (ResultSet == null)
          {
            ResultSet = await driver.NextResultAsync(Statement.StatementId, false, execAsync).ConfigureAwait(false);

            if (ResultSet == null) return false;

            if (ResultSet.IsOutputParameters && Command.CommandType == CommandType.StoredProcedure)
            {
              StoredProcedure sp = Statement as StoredProcedure;
              sp.ProcessOutputParameters(this);
              await ResultSet.CloseAsync(execAsync).ConfigureAwait(false);

              for (int i = 0; i < ResultSet.Fields.Length; i++)
              {
                if (ResultSet.Fields[i].ColumnName.StartsWith("@" + StoredProcedure.ParameterPrefix, StringComparison.OrdinalIgnoreCase))
                {
                  ResultSet = null;
                  break;
                }
              }

              if (!sp.ServerProvidingOutputParameters) return false;
              // if we are using server side output parameters then we will get our ok packet
              // *after* the output parameters resultset
              ResultSet = await driver.NextResultAsync(Statement.StatementId, true, execAsync).ConfigureAwait(false);
            }
            else if (ResultSet.IsOutputParameters && Command.CommandType == CommandType.Text && !Command.IsPrepared && !Command.InternallyCreated)
            {
              Command.ProcessOutputParameters(this);
              await ResultSet.CloseAsync(execAsync).ConfigureAwait(false);

              for (int i = 0; i < ResultSet.Fields.Length; i++)
              {
                if (ResultSet.Fields[i].ColumnName.StartsWith("@" + MySqlCommand.ParameterPrefix, StringComparison.OrdinalIgnoreCase))
                {
                  ResultSet = null;
                  break;
                }
              }

              if (!Statement.ServerProvidingOutputParameters) return false;

              ResultSet = await driver.NextResultAsync(Statement.StatementId, true, execAsync).ConfigureAwait(false);
            }
            ResultSet.Cached = isCaching;
          }

          if (ResultSet.Size == 0)
          {
            if (Command.LastInsertedId == -1) Command.LastInsertedId = ResultSet.InsertedId;
            else {
              if (ResultSet.InsertedId > 0) Command.LastInsertedId = ResultSet.InsertedId;
            }

            if (affectedRows == -1)
              affectedRows = ResultSet.AffectedRows;
            else
              affectedRows += ResultSet.AffectedRows;
          }
        } while (ResultSet.Size == 0);

        return true;
      }
      catch (MySqlException ex)
      {
        if (ex.IsFatal)
          await _connection.AbortAsync(execAsync, CancellationToken.None).ConfigureAwait(false);
        if (ex.Number == 0)
          throw new MySqlException(Resources.FatalErrorReadingResult, ex);
        if ((CommandBehavior & CommandBehavior.CloseConnection) != 0)
          await CloseAsync(execAsync).ConfigureAwait(false);
        throw;
      }
    }