content: /*
   * Copyright (C) 2016-2023 ActionTech.
   * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher.
   */
  
  package com.actiontech.dble.plan.node;
  
  import com.actiontech.dble.config.ErrorCode;
  import com.actiontech.dble.plan.NamedField;
  import com.actiontech.dble.plan.common.exception.MySQLOutPutException;
  import com.actiontech.dble.plan.common.item.Item;
  import com.actiontech.dble.plan.common.item.function.operator.cmpfunc.ItemFuncEqual;
  import com.actiontech.dble.plan.common.item.function.sumfunc.ItemFuncGroupConcat;
  import com.actiontech.dble.plan.util.ToStringUtil;
  import com.actiontech.dble.route.parser.druid.RouteTableConfigInfo;
  
  import java.util.ArrayList;
  import java.util.List;
  
  public class ModifyNode extends PlanNode {
  
      /**
       * filter in where
       */
      List<ItemFuncEqual> setItemList = new ArrayList<>();
  
      public PlanNodeType type() {
          return PlanNodeType.MODIFY;
      }
  
      public ModifyNode(PlanNode child) {
          this(child, null);
      }
  
      public ModifyNode(PlanNode child, Item filter) {
          this.whereFilter = filter;
          for (PlanNode childChild : child.getChildren()) {
              this.addChild(childChild);
          }
          this.keepFieldSchema = false;
      }
  
      @Override
      public RouteTableConfigInfo findFieldSourceFromIndex(int index) throws Exception {
          if (columnsSelected.size() > index) {
              Item sourceColumns = columnsSelected.get(index);
              for (int i = 0; i < this.getChild().columnsSelected.size(); i++) {
                  Item cSelected = this.getChild().columnsSelected.get(i);
                  if (cSelected.getAlias() != null && cSelected.getAlias().equals(sourceColumns.getItemName())) {
                      return this.getChild().findFieldSourceFromIndex(i);
                  } else if (cSelected.getAlias() == null && cSelected.getItemName().equals(sourceColumns.getItemName())) {
                      return this.getChild().findFieldSourceFromIndex(i);
                  }
              }
              return null;
          }
          return null;
      }
  
  
      public void setChild(PlanNode child) {
          if (child == null) {
              return;
          }
          children.clear();
          addChild(child);
      }
  
      @Override
      public String getPureName() {
          return this.getChild().getAlias();
      }
  
      @Override
      public String getPureSchema() {
          return this.getChild().getPureSchema();
      }
  
      @Override
      public ModifyNode copy() {
          ModifyNode newTableNode = new ModifyNode(this.getChild().copy());
          this.copySelfTo(newTableNode);
          return newTableNode;
      }
  
      @Override
      public int getHeight() {
          return getChild().getHeight() + 1;
      }
  
      public List<ItemFuncEqual> getSetItemList() {
          return setItemList;
      }
  
      public void addSetItem(ItemFuncEqual setItem) {
          this.setItemList.add(setItem);
      }
  
  
      public PlanNode getLeftNode() {
          if (children.isEmpty())
              return null;
          return children.get(0);
  
      }
  
      public PlanNode getRightNode() {
          if (children.size() < 2)
              return null;
          return children.get(1);
      }
  
      public void setUpFields() {
          super.setUpFields();
          setUpSetItem();
      }
  
      private void setUpSetItem() {
          nameContext.setFindInSelect(false);
          nameContext.setSelectFirst(false);
          for (ItemFuncEqual setItem : setItemList) {
              for (Item argument : setItem.arguments()) {
                  setUpItem(argument);
                  if (argument instanceof ItemFuncGroupConcat) {
                      ((ItemFuncGroupConcat) argument).fixOrders(nameContext, referContext);
                  }
                  NamedField field = makeOutNamedField(argument);
                  if (outerFields.containsKey(field) && isDuplicateField(this))
                      throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "duplicate field");
                  outerFields.put(field, argument);
              }
              setItem.setItemName(null);
          }
      }
  
      @Override
      public String toString(int level) {
          StringBuilder sb = new StringBuilder();
          String tabTittle = ToStringUtil.getTab(level);
          String tabContent = ToStringUtil.getTab(level + 1);
  
          ToStringUtil.appendln(sb, tabTittle + "Update");
          ToStringUtil.appendln(sb, tabContent + "set: " + ToStringUtil.itemListString(setItemList));
          ToStringUtil.appendln(sb, tabContent + "where: " + ToStringUtil.itemString(whereFilter));
          ToStringUtil.appendln(sb, tabContent + "orderBy: " + ToStringUtil.orderListString(orderBys));
          if (this.getLimitFrom() >= 0L && this.getLimitTo() > 0L) {
              ToStringUtil.appendln(sb, tabContent + "limitFrom: " + this.getLimitFrom());
              ToStringUtil.appendln(sb, tabContent + "limitTo: " + this.getLimitTo());
          }
          ToStringUtil.appendln(sb, tabContent + "sql: " + this.getSql());
  
          ToStringUtil.appendln(sb, tabContent + "left:");
          sb.append(this.getLeftNode().toString(level + 2));
          ToStringUtil.appendln(sb, tabContent + "right:");
          sb.append(this.getRightNode().toString(level + 2));
          return sb.toString();
      }
  
  }
  