@Override
  public SqlNode visitSelectStatementNode(SelectStatementNode node, Void p) {
    if (processed) {
      return node;
    }
    processed = true;

    OrderByClauseNode originalOrderBy = node.getOrderByClauseNode();
    OrderByClauseNode orderBy = node.getOrderByClauseNode();
    if (originalOrderBy != null) {
      orderBy = new OrderByClauseNode(originalOrderBy.getWordNode());
      for (SqlNode child : originalOrderBy.getChildren()) {
        orderBy.addNode(child);
      }
    } else {
      orderBy = new OrderByClauseNode("");
    }
    orderBy.addNode(new FragmentNode(" limit "));
    if (limit >= 0) {
      orderBy.addNode(new FragmentNode(String.valueOf(limit)));
    } else {
      orderBy.addNode(new FragmentNode("0"));
    }
    if (offset >= 0) {
      orderBy.addNode(new FragmentNode(" offset "));
      orderBy.addNode(new FragmentNode(String.valueOf(offset)));
    }
    ForUpdateClauseNode forUpdate = node.getForUpdateClauseNode();
    if (forUpdate != null) {
      orderBy.addNode(new FragmentNode(" "));
    }

    SelectStatementNode result = new SelectStatementNode();
    result.setSelectClauseNode(node.getSelectClauseNode());
    result.setFromClauseNode(node.getFromClauseNode());
    result.setWhereClauseNode(node.getWhereClauseNode());
    result.setGroupByClauseNode(node.getGroupByClauseNode());
    result.setHavingClauseNode(node.getHavingClauseNode());
    result.setOrderByClauseNode(orderBy);
    result.setForUpdateClauseNode(forUpdate);
    return result;
  }
  protected SqlNode appendTopNode(SelectStatementNode node) {
    SelectClauseNode select = new SelectClauseNode(node.getSelectClauseNode().getWordNode());
    select.appendNode(new FragmentNode(" top (" + limit + ")"));
    for (SqlNode child : node.getSelectClauseNode().getChildren()) {
      select.appendNode(child);
    }

    SelectStatementNode result = new SelectStatementNode();
    result.setSelectClauseNode(select);
    result.setFromClauseNode(node.getFromClauseNode());
    result.setWhereClauseNode(node.getWhereClauseNode());
    result.setGroupByClauseNode(node.getGroupByClauseNode());
    result.setHavingClauseNode(node.getHavingClauseNode());
    result.setOrderByClauseNode(node.getOrderByClauseNode());
    result.setForUpdateClauseNode(node.getForUpdateClauseNode());
    result.setOptionClauseNode(node.getOptionClauseNode());
    return result;
  }