content: /*
   * Copyright 1999-2017 Alibaba Group Holding Ltd.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package com.alibaba.druid.sql.dialect.mysql.visitor.transform;
  
  import com.alibaba.druid.sql.ast.SQLExpr;
  import com.alibaba.druid.sql.ast.SQLName;
  import com.alibaba.druid.sql.ast.SQLOrderBy;
  import com.alibaba.druid.sql.ast.statement.SQLSelect;
  import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
  import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;
  import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
  import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock;
  import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter;
  import com.alibaba.druid.util.FnvHash;
  
  import java.util.ArrayList;
  import java.util.List;
  
  /**
   * Created by wenshao on 27/07/2017.
   */
  public class OrderByResolve extends OracleASTVisitorAdapter {
      static final long DBMS_RANDOM_VALUE = FnvHash.hashCode64("DBMS_RANDOM.value");
  
      public boolean visit(SQLSelect x) {
          SQLSelectQueryBlock queryBlock = x.getQueryBlock();
          if (queryBlock == null) {
              return super.visit(x);
          }
  
          if (x.getOrderBy() != null && queryBlock.isForUpdate() && queryBlock.getOrderBy() == null) {
              queryBlock.setOrderBy(x.getOrderBy());
              x.setOrderBy(null);
          }
  
          SQLOrderBy orderBy = queryBlock.getOrderBy();
          if (orderBy == null) {
              return super.visit(x);
          }
  
          if (!queryBlock.selectItemHasAllColumn(false)) {
              List<SQLSelectOrderByItem> notContainsOrderBy = new ArrayList<SQLSelectOrderByItem>();
  
              for (SQLSelectOrderByItem orderByItem : orderBy.getItems()) {
                  SQLExpr orderByExpr = orderByItem.getExpr();
  
                  if (orderByExpr instanceof SQLName) {
                      if (((SQLName) orderByExpr).hashCode64() == DBMS_RANDOM_VALUE) {
                          continue;
                      }
  
                      long hashCode64 = ((SQLName) orderByExpr).nameHashCode64();
                      SQLSelectItem selectItem = queryBlock.findSelectItem(hashCode64);
                      if (selectItem == null) {
                          queryBlock.addSelectItem(orderByExpr.clone());
                      }
                  }
              }
  
              if (notContainsOrderBy.size() > 0) {
                  for (SQLSelectOrderByItem orderByItem : notContainsOrderBy) {
                      queryBlock.addSelectItem(orderByItem.getExpr());
                  }
  
                  OracleSelectQueryBlock queryBlock1 = new OracleSelectQueryBlock();
                  queryBlock1.setFrom(queryBlock, "x");
                  x.setQuery(queryBlock1);
              }
          }
  
          return super.visit(x);
      }
  }
  