`

SQL格式化工具

阅读更多
package com.hengyu.ticket.common;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import java.util.StringTokenizer;

public class SQLFormat {


	  private static final Set<String> BEGIN_CLAUSES = new HashSet<String>();
	  private static final Set<String> END_CLAUSES = new HashSet<String>();
	  private static final Set<String> LOGICAL = new HashSet<String>();
	  private static final Set<String> QUANTIFIERS = new HashSet<String>();
	  private static final Set<String> DML = new HashSet<String>();
	  private static final Set<String> MISC = new HashSet<String>();
	  public static final String WHITESPACE = " \n\r\f\t";
	  static {
	    BEGIN_CLAUSES.add( "left" );
	    BEGIN_CLAUSES.add( "right" );
	    BEGIN_CLAUSES.add( "inner" );
	    BEGIN_CLAUSES.add( "outer" );
	    BEGIN_CLAUSES.add( "group" );
	    BEGIN_CLAUSES.add( "order" );

	    END_CLAUSES.add( "where" );
	    END_CLAUSES.add( "set" );
	    END_CLAUSES.add( "having" );
	    END_CLAUSES.add( "join" );
	    END_CLAUSES.add( "from" );
	    END_CLAUSES.add( "by" );
	    END_CLAUSES.add( "join" );
	    END_CLAUSES.add( "into" );
	    END_CLAUSES.add( "union" );
	    END_CLAUSES.add( "top" );
	    END_CLAUSES.add( "limit" );

	    LOGICAL.add( "and" );
	    LOGICAL.add( "or" );
	    LOGICAL.add( "when" );
	    LOGICAL.add( "else" );
	    LOGICAL.add( "end" );

	    QUANTIFIERS.add( "in" );
	    QUANTIFIERS.add( "all" );
	    QUANTIFIERS.add( "exists" );
	    QUANTIFIERS.add( "some" );
	    QUANTIFIERS.add( "any" );

	    DML.add( "insert" );
	    DML.add( "update" );
	    DML.add( "delete" );

	    MISC.add( "select" );
	    MISC.add( "on" );
	  }

	  static final String indentString = "    ";
	  static final String initial = "\n    ";

	  public String format(String source) {
	    return new FormatProcess( source ).perform();
	  }

	  private static class FormatProcess {
	    boolean beginLine = true;
	    boolean afterBeginBeforeEnd = false;
	    boolean afterByOrSetOrFromOrSelect = false;
	    boolean afterOn = false;
	    boolean afterBetween = false;
	    boolean afterInsert = false;
	    int inFunction = 0;
	    int parensSinceSelect = 0;
	    private LinkedList<Integer> parenCounts = new LinkedList<Integer>();
	    private LinkedList<Boolean> afterByOrFromOrSelects = new LinkedList<Boolean>();

	    int indent = 1;

	    StringBuilder result = new StringBuilder();
	    StringTokenizer tokens;
	    String lastToken;
	    String token;
	    String lcToken;

	    public FormatProcess(String sql) {
	      tokens = new StringTokenizer(
	          sql,
	          "()+*/-=<>'`\"[]," + WHITESPACE,
	          true
	      );
	    }

	    public String perform() {

	      result.append( initial );

	      while ( tokens.hasMoreTokens() ) {
	        token = tokens.nextToken();
	        lcToken = token.toLowerCase();

	        if ( "'".equals( token ) ) {
	          String t;
	          do {
	            t = tokens.nextToken();
	            token += t;
	          }
	          while ( !"'".equals( t ) && tokens.hasMoreTokens() ); // cannot handle single quotes
	        }
	        else if ( "\"".equals( token ) ) {
	          String t;
	          do {
	            t = tokens.nextToken();
	            token += t;
	          }
	          while ( !"\"".equals( t ) );
	        }

	        if ( afterByOrSetOrFromOrSelect && ",".equals( token ) ) {
	          commaAfterByOrFromOrSelect();
	        }
	        else if ( afterOn && ",".equals( token ) ) {
	          commaAfterOn();
	        }

	        else if ( "(".equals( token ) ) {
	          openParen();
	        }
	        else if ( ")".equals( token ) ) {
	          closeParen();
	        }

	        else if ( BEGIN_CLAUSES.contains( lcToken ) ) {
	          beginNewClause();
	        }

	        else if ( END_CLAUSES.contains( lcToken ) ) {
	          endNewClause();
	        }

	        else if ( "select".equals( lcToken ) ) {
	          select();
	        }

	        else if ( DML.contains( lcToken ) ) {
	          updateOrInsertOrDelete();
	        }

	        else if ( "values".equals( lcToken ) ) {
	          values();
	        }

	        else if ( "on".equals( lcToken ) ) {
	          on();
	        }

	        else if ( afterBetween && lcToken.equals( "and" ) ) {
	          misc();
	          afterBetween = false;
	        }

	        else if ( LOGICAL.contains( lcToken ) ) {
	          logical();
	        }

	        else if ( isWhitespace( token ) ) {
	          white();
	        }

	        else {
	          misc();
	        }

	        if ( !isWhitespace( token ) ) {
	          lastToken = lcToken;
	        }

	      }
	      return result.toString();
	    }

	    private void commaAfterOn() {
	      out();
	      indent--;
	      newline();
	      afterOn = false;
	      afterByOrSetOrFromOrSelect = true;
	    }

	    private void commaAfterByOrFromOrSelect() {
	      out();
	      newline();
	    }

	    private void logical() {
	      if ( "end".equals( lcToken ) ) {
	        indent--;
	      }
	      newline();
	      out();
	      beginLine = false;
	    }

	    private void on() {
	      indent++;
	      afterOn = true;
	      newline();
	      out();
	      beginLine = false;
	    }

	    private void misc() {
	      out();
	      if ( "between".equals( lcToken ) ) {
	        afterBetween = true;
	      }
	      if ( afterInsert ) {
	        newline();
	        afterInsert = false;
	      }
	      else {
	        beginLine = false;
	        if ( "case".equals( lcToken ) ) {
	          indent++;
	        }
	      }
	    }

	    private void white() {
	      if ( !beginLine ) {
	        result.append( " " );
	      }
	    }

	    private void updateOrInsertOrDelete() {
	      out();
	      indent++;
	      beginLine = false;
	      if ( "update".equals( lcToken ) ) {
	        newline();
	      }
	      if ( "insert".equals( lcToken ) ) {
	        afterInsert = true;
	      }
	    }

	    private void select() {
	      out();
	      indent++;
	      newline();
	      parenCounts.addLast( Integer.valueOf( parensSinceSelect ) );
	      afterByOrFromOrSelects.addLast( Boolean.valueOf( afterByOrSetOrFromOrSelect ) );
	      parensSinceSelect = 0;
	      afterByOrSetOrFromOrSelect = true;
	    }

	    private void out() {
	      result.append( token );
	    }

	    private void endNewClause() {
	      if ( !afterBeginBeforeEnd ) {
	        indent--;
	        if ( afterOn ) {
	          indent--;
	          afterOn = false;
	        }
	        newline();
	      }
	      out();
	      if ( !"union".equals( lcToken ) ) {
	        indent++;
	      }
	      newline();
	      afterBeginBeforeEnd = false;
	      afterByOrSetOrFromOrSelect = "by".equals( lcToken )
	          || "set".equals( lcToken )
	          || "from".equals( lcToken );
	    }

	    private void beginNewClause() {
	      if ( !afterBeginBeforeEnd ) {
	        if ( afterOn ) {
	          indent--;
	          afterOn = false;
	        }
	        indent--;
	        newline();
	      }
	      out();
	      beginLine = false;
	      afterBeginBeforeEnd = true;
	    }

	    private void values() {
	      indent--;
	      newline();
	      out();
	      indent++;
	      newline();
	    }

	    private void closeParen() {
	      parensSinceSelect--;
	      if ( parensSinceSelect < 0 ) {
	        indent--;
	        parensSinceSelect = parenCounts.removeLast().intValue();
	        afterByOrSetOrFromOrSelect = afterByOrFromOrSelects.removeLast().booleanValue();
	      }
	      if ( inFunction > 0 ) {
	        inFunction--;
	        out();
	      }
	      else {
	        if ( !afterByOrSetOrFromOrSelect ) {
	          indent--;
	          newline();
	        }
	        out();
	      }
	      beginLine = false;
	    }

	    private void openParen() {
	      if ( isFunctionName( lastToken ) || inFunction > 0 ) {
	        inFunction++;
	      }
	      beginLine = false;
	      if ( inFunction > 0 ) {
	        out();
	      }
	      else {
	        out();
	        if ( !afterByOrSetOrFromOrSelect ) {
	          indent++;
	          newline();
	          beginLine = true;
	        }
	      }
	      parensSinceSelect++;
	    }

	    private static boolean isFunctionName(String tok) {
	      final char begin = tok.charAt( 0 );
	      final boolean isIdentifier = Character.isJavaIdentifierStart( begin ) || '"' == begin;
	      return isIdentifier &&
	          !LOGICAL.contains( tok ) &&
	          !END_CLAUSES.contains( tok ) &&
	          !QUANTIFIERS.contains( tok ) &&
	          !DML.contains( tok ) &&
	          !MISC.contains( tok );
	    }

	    private static boolean isWhitespace(String token) {
	      return WHITESPACE.indexOf( token ) >= 0;
	    }

	    private void newline() {
	      result.append( "\n" );
	      for ( int i = 0; i < indent; i++ ) {
	        result.append( indentString );
	      }
	      beginLine = true;
	    }
	  }
}

 

分享到:
评论

相关推荐

    Java Sql 格式化工具

    而其内嵌的SQL格式化工具则能够帮助开发者统一SQL语句的风格,使代码更易于阅读和理解,从而降低出错率和团队协作难度。 "SqlFor"标签可能是指这个工具是专门为Java开发者设计的SQL格式化解决方案。在Java编程环境...

    ssms的sql格式化工具

    然而,SSMS本身并不内置SQL代码的格式化功能,这就是为什么需要额外的SQL格式化工具,如SQL Pretty Printer。 SQL Pretty Printer是一款专业的SQL代码美化和格式化软件,它专门设计用于将杂乱无章的SQL脚本转换为...

    sql 格式化工具

    一款非常好用的SQL格式化工具 SQLserver必备的工具。

    超好用的sql格式化工具

    超好用的sql格式化工具,支持单个sql格式/sql文件批量格式/监控剪切板并自动将sql复制的sql语句格式化工具, 支持mssql/oracle/mysql/msaccess/generic... 一句话,不好用回帖骂我吧

    SQL格式化工具2.8.7汉化+破解

    SQL格式化工具2.8.7汉化+破解 SQL Pretty Printer是一款简单易用、功能强大的SQL格式化工具 SQL Pretty Printer自2005推出以来,一直深受广大用户的好评,是数据库管理人员和程序开发人员的得力助手。 截至2009年...

    SQL格式化功能(C#代码)

    为了提升代码的可读性和可维护性,通常会使用SQL格式化工具对查询进行美化。本文将详细讲解一个基于C#实现的SQL格式化功能,它源于Hibernate项目,并且已经去除了无用的功能,不依赖任何第三方DLL。 首先,让我们...

    SQL Prompt 6.1 5.3 sql格式化工具 SqlServer格式化工具

    SQL Prompt是一款由Red Gate Software开发的强大SQL代码编辑和格式化工具,主要针对SQL Server环境。在标题中提到的"SQL Prompt 6.1 5.3"是指该工具的两个不同版本,6.1是较新的一个,而5.3是其前任版本。SQL Prompt...

    SQL 格式化工具

    SQL格式化工具是一种专门用于美化和标准化SQL代码的软件,它可以帮助程序员和数据库管理员将混乱不堪的SQL脚本整理成整齐、易读的格式。在处理大量或复杂的SQL语句时,这种工具显得尤为重要,因为它可以提高代码的...

    SQL语句格式化工具

    - **兼容性**:Windows平台上有许多专门为该操作系统优化的SQL格式化工具,它们通常与Windows集成良好,支持拖放操作,与Windows Explorer无缝协作。 - **集成开发环境(IDE)**:许多SQL IDEs(如SQL Server ...

    SQL格式化功能(JAVA代码)

    在处理复杂的查询时,自动生成的SQL可能会变得难以阅读和理解,这就需要SQL格式化工具来帮助优化代码。 描述中提到这个功能去除了“没用的功能”,这意味着该Java代码可能是一个精简版的SQL格式化器,专注于最基本...

    sql格式化工具

    sql格式化工具使你的sql语句更加清晰

    sql格式化JS脚本

    为了解决这个问题,开发者通常会使用SQL格式化工具来美化和标准化代码。在给定的“sql格式化JS脚本”中,我们看到一个名为`SqlFormat.js`的文件,它提供了在前端环境中对SQL语句进行格式化的功能。 这个JavaScript...

Global site tag (gtag.js) - Google Analytics