private ExecutionResult execution(
      long queryId,
      SessionInfo session,
      String sql,
      boolean userQuery,
      BiFunction<MPPQueryContext, Long, IQueryExecution> iQueryExecutionFactory) {
    long startTime = System.currentTimeMillis();
    QueryId globalQueryId = queryIdGenerator.createNextQueryId();
    MPPQueryContext queryContext = null;
    try (SetThreadName queryName = new SetThreadName(globalQueryId.getId())) {
      if (sql != null && !sql.isEmpty()) {
        LOGGER.debug("[QueryStart] sql: {}", sql);
      }
      queryContext =
          new MPPQueryContext(
              sql,
              globalQueryId,
              queryId,
              session,
              DataNodeEndPoints.LOCAL_HOST_DATA_BLOCK_ENDPOINT,
              DataNodeEndPoints.LOCAL_HOST_INTERNAL_ENDPOINT);
      queryContext.setUserQuery(userQuery);
      IQueryExecution execution = iQueryExecutionFactory.apply(queryContext, startTime);
      if (execution.isQuery()) {
        queryExecutionMap.put(queryId, execution);
      } else {
        // we won't limit write operation's execution time
        queryContext.setTimeOut(Long.MAX_VALUE);
      }
      execution.start();
      ExecutionResult result = execution.getStatus();
      if (!execution.isQuery() && result.status != null && needRetry(result.status)) {
        // if it's write request and the result status needs to retry
        result.status.setNeedRetry(true);
      }
      return result;
    } finally {
      if (queryContext != null) {
        queryContext.releaseAllMemoryReservedForFrontEnd();
      }
      DataNodeSchemaLockManager.getInstance().releaseReadLock(queryContext);
    }
  }
The coordinator for MPP. It manages all the queries which are executed in current Node. And it
will be responsible for the lifecycle of a query. A query request will be represented as a
QueryExecution.
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java