private void autoCreateDatabaseIfNecessary(final String database) {
    if (ALREADY_CREATED_TABLE_MODEL_DATABASES.contains(database)) {
      return;
    }

    Coordinator.getInstance().getAccessControl().checkCanCreateDatabase(username, database);
    final TDatabaseSchema schema = new TDatabaseSchema(new TDatabaseSchema(database));
    schema.setIsTableModel(true);

    final CreateDBTask task = new CreateDBTask(schema, true);
    try {
      final ListenableFuture<ConfigTaskResult> future =
          task.execute(ClusterConfigTaskExecutor.getInstance());
      final ConfigTaskResult result = future.get();
      final int statusCode = result.getStatusCode().getStatusCode();
      if (statusCode != TSStatusCode.SUCCESS_STATUS.getStatusCode()
          && statusCode != TSStatusCode.DATABASE_ALREADY_EXISTS.getStatusCode()) {
        throw new PipeException(
            String.format(
                "Auto create database failed: %s, status code: %s",
                database, result.getStatusCode()));
      }
    } catch (final ExecutionException | InterruptedException e) {
      if (e instanceof InterruptedException) {
        Thread.currentThread().interrupt();
      }
      throw new PipeException("Auto create database failed because: " + e.getMessage());
    }

    ALREADY_CREATED_TABLE_MODEL_DATABASES.add(database);
  }
For {@link InsertRowsStatement} and {@link InsertMultiTabletsStatement}, the returned {@link
TSStatus} will use sub-status to record the endpoint for redirection. Each sub-status records
the redirection endpoint for one device path, and the order is the same as the order of the
device paths in the statement. However, this order is not guaranteed to be the same as in the
request. So for each sub-status which needs to redirect, we record the device path using the
message field.
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/thrift/IoTDBDataNodeReceiver.java