prepare method

Future<PreparedStmt> prepare(
  1. String query, [
  2. bool iterable = false
])

Prepares given query

Returns PreparedStmt which can be used to execute prepared statement multiple times with different parameters See PreparedStmt.execute You shoud call PreparedStmt.deallocate when you don't need prepared statement anymore to prevent memory leaks

Pass iterable true if you want to iterable result set. See execute for details

Implementation

Future<PreparedStmt> prepare(String query, [bool iterable = false]) async {
  if (!_connected) {
    throw MySQLClientException("Can not prepare stmt: connection closed");
  }

  // wait for ready state
  if (_state != _MySQLConnectionState.connectionEstablished) {
    await _waitForState(_MySQLConnectionState.connectionEstablished)
        .timeout(Duration(milliseconds: _timeoutMs));
  }

  _state = _MySQLConnectionState.waitingCommandResponse;

  final payload = MySQLPacketCommStmtPrepare(query: query);

  final packet = MySQLPacket(
    sequenceID: 0,
    payload: payload,
    payloadLength: 0,
  );

  final completer = Completer<PreparedStmt>();

  /**
   * 0 - initial
   * 1 - first packet decoded
   * 2 - eof decoded
   */
  int state = 0;
  int numOfEofPacketsParsed = 0;
  MySQLPacketStmtPrepareOK? preparedPacket;

  _responseCallback = (data) async {
    try {
      MySQLPacket? packet;

      switch (state) {
        case 0:
          packet = MySQLPacket.decodeCommPrepareStmtResponsePacket(data);
          state = 1;
          break;
        default:
          packet = null;

          if (MySQLPacket.detectPacketType(data) ==
              MySQLGenericPacketType.eof) {
            numOfEofPacketsParsed++;

            var done = false;

            assert(preparedPacket != null);

            if (preparedPacket!.numOfCols > 0 &&
                preparedPacket!.numOfParams > 0) {
              // there should be two EOF packets in this case
              if (numOfEofPacketsParsed == 2) {
                done = true;
              }
            } else {
              // there should be only one EOF packet otherwise
              done = true;
            }

            if (done) {
              state = 2;

              completer.complete(PreparedStmt._(
                preparedPacket: preparedPacket!,
                connection: this,
                iterable: iterable,
              ));

              _state = _MySQLConnectionState.connectionEstablished;

              return;
            }
          }

          break;
      }

      if (packet != null) {
        final payload = packet.payload;

        if (payload is MySQLPacketStmtPrepareOK) {
          preparedPacket = payload;
        } else if (payload is MySQLPacketError) {
          completer.completeError(
            MySQLServerException(payload.errorMessage, payload.errorCode),
          );
          _state = _MySQLConnectionState.connectionEstablished;
          return;
        } else {
          completer.completeError(
            MySQLClientException(
              "Unexpected payload received in response to COMM_STMT_PREPARE request",
            ),
            StackTrace.current,
          );
          _forceClose();
          return;
        }
      }
    } catch (e) {
      completer.completeError(e, StackTrace.current);
      _forceClose();
    }
  };

  _socket.add(packet.encode());

  return completer.future;
}