content: /*
   * Copyright (C) 2016-2023 ActionTech.
   * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher.
   */
  
  package com.actiontech.dble.backend.mysql.nio.handler.query.impl;
  
  
  import com.actiontech.dble.backend.mysql.nio.handler.query.BaseDMLHandler;
  import com.actiontech.dble.net.Session;
  import com.actiontech.dble.net.mysql.FieldPacket;
  import com.actiontech.dble.net.mysql.RowDataPacket;
  import com.actiontech.dble.net.service.AbstractService;
  import com.actiontech.dble.plan.common.item.Item;
  import com.actiontech.dble.plan.common.item.function.ItemFuncInner;
  import com.actiontech.dble.server.NonBlockingSession;
  import com.actiontech.dble.services.FakeResponseService;
  import com.actiontech.dble.services.mysqlsharding.MySQLResponseService;
  import org.jetbrains.annotations.NotNull;
  
  import java.util.ArrayList;
  import java.util.List;
  
  /**
   * Created by szf on 2019/5/28.
   */
  public class FakeBaseSelectHandler extends BaseDMLHandler {
  
      private final boolean isInUnion;
      private final List<Item> selectList;
  
      public FakeBaseSelectHandler(long id, Session session, List<Item> selectList, MultiNodeMergeHandler next, boolean isInUnion) {
          super(id, session);
          this.nextHandler = next;
          this.isInUnion = isInUnion;
          this.selectList = selectList;
      }
  
      public void fakeExecute() {
          List<FieldPacket> fields = makeFakeField();
          List<RowDataPacket> data = makeFakeRowData(fields.size());
          if (data == null || (!isInUnion && data.size() > 1)) {
              createErrorMessage();
              return;
          }
          final MySQLResponseService service = new FakeResponseService(null);
          nextHandler.fieldEofResponse(null, null, fields, null, false, service);
          for (RowDataPacket row : data) {
              nextHandler.rowResponse(null, row, false, service);
          }
          nextHandler.rowEofResponse(null, false, service);
      }
  
      public String toSQLString() {
          StringBuffer sb = new StringBuffer("");
          for (Item i : selectList) {
              sb.append(i.getItemName() + ";");
          }
          return sb.toString();
      }
  
      private List<FieldPacket> makeFakeField() {
          List<FieldPacket> totalResult = new ArrayList<>();
          for (Item i : selectList) {
              List<FieldPacket> fields = ((ItemFuncInner) i).getField();
              totalResult.addAll(fields);
          }
          return totalResult;
      }
  
      private List<RowDataPacket> makeFakeRowData(int fieldCount) {
          if (selectList.size() > 1) {
              RowDataPacket row = new RowDataPacket(fieldCount);
              for (Item i : selectList) {
                  List<RowDataPacket> rows = ((ItemFuncInner) i).getRows(((NonBlockingSession) session).getShardingService());
                  if (rows.size() > 1) {
                      return null;
                  } else {
                      row.addAll(rows.get(0).getFieldValues());
                  }
              }
              List<RowDataPacket> result = new ArrayList<>();
              result.add(row);
              return result;
          } else {
              Item i = selectList.get(0);
              List<RowDataPacket> rows = ((ItemFuncInner) i).getRows(((NonBlockingSession) session).getShardingService());
              return rows;
          }
      }
  
      private void createErrorMessage() {
          session.onQueryError("Subquery returns more than 1 row".getBytes());
      }
  
      @Override
      public HandlerType type() {
          return null;
      }
  
      @Override
      public void fieldEofResponse(byte[] header, List<byte[]> fields, List<FieldPacket> fieldPackets, byte[] eof, boolean isLeft, @NotNull AbstractService service) {
  
      }
  
      @Override
      public boolean rowResponse(byte[] rowNull, RowDataPacket rowPacket, boolean isLeft, @NotNull AbstractService service) {
          return false;
      }
  
      @Override
      public void rowEofResponse(byte[] eof, boolean isLeft, @NotNull AbstractService service) {
  
      }
  
      @Override
      protected void onTerminate() throws Exception {
  
      }
  }
  