001
002package gudusoft.gsqlparser.pp.stmtformatter;
003
004import gudusoft.gsqlparser.EDbVendor;
005import gudusoft.gsqlparser.ETokenType;
006import gudusoft.gsqlparser.TCustomSqlStatement;
007import gudusoft.gsqlparser.TGSqlParser;
008import gudusoft.gsqlparser.TSourceToken;
009import gudusoft.gsqlparser.TSourceTokenList;
010import gudusoft.gsqlparser.pp.para.GFmtOpt;
011import gudusoft.gsqlparser.pp.para.GFmtOptFactory;
012import gudusoft.gsqlparser.pp.para.styleenums.TAlignStyle;
013import gudusoft.gsqlparser.pp.para.styleenums.TCaseOption;
014import gudusoft.gsqlparser.pp.para.styleenums.TLinefeedsCommaOption;
015import gudusoft.gsqlparser.pp.print.IPrinter;
016import gudusoft.gsqlparser.pp.print.PrinterFactory;
017
018import java.io.ByteArrayOutputStream;
019import java.io.OutputStream;
020import java.util.concurrent.Callable;
021import java.util.concurrent.FutureTask;
022
023public class SqlFormatter
024{
025
026        public String format( TGSqlParser parser, GFmtOpt option )
027        {
028                if (option.removeComment) {
029                        parser = preHandleRemoveComment(parser);
030                }
031                
032                OutputStream o = new ByteArrayOutputStream( );
033                IPrinter printer = PrinterFactory.createTextPrinter( o );
034
035                FormatterFactory.createAllStmtsFormatter( option )
036                                .beforeFormat( parser.sqlstatements );
037
038                for ( int i = 0; i < parser.sqlstatements.size( ); i++ )
039                {
040                        TCustomSqlStatement sql = parser.sqlstatements.get( i );
041                        FormatterFactory.processStatement( option, sql );
042                }
043                if ( parser.sqlstatements != null && parser.sqlstatements.size( ) > 0 )
044                {
045                        FormatterFactory.createAllStmtsFormatter( option )
046                                        .doFormat( parser.sqlstatements );
047                        FormatterFactory.createAllStmtsFormatter( option )
048                                        .afterFormat( parser.sqlstatements );
049
050                        printer.setOutputConfig( FormatterFactory.outputConfigFor( option, parser.getDbVendor( ) ) );
051                        printer.print( parser.sqlstatements.get( 0 ).getStartToken( ).container );
052                }
053
054                FormatterFactory.clearAllObject( option.sessionId );
055                return o.toString( );
056        }
057
058        public static TGSqlParser preHandleRemoveComment(TGSqlParser parser) {
059                Callable<String> removeCommenTask = new Callable<String>() {
060            @Override
061            public String call() throws Exception {
062                GFmtOpt removeCommentOption = GFmtOptFactory.newInstance();
063                removeCommentOption.removeComment = true;
064                OutputStream o = new ByteArrayOutputStream();
065                IPrinter printer = PrinterFactory.createTextPrinter(o);
066
067                TSourceToken startToken = parser.sqlstatements.get( 0 ).getStartToken( );
068                        TSourceTokenList list = startToken.container;
069                                for (int i = 0; i < list.size(); i++) {
070                                        TSourceToken t = list.get(i);
071                                        if (t.tokentype == ETokenType.ttsimplecomment || t.tokentype == ETokenType.ttbracketedcomment) {
072                                                if ( t.toString( ).startsWith( "/*+" ) )
073                                                        continue;
074                                                t.setAstext(" ");
075                                                t.tokentype = ETokenType.ttwhitespace;
076                                        }
077                                }
078                                
079                                // SQL whatever the caller prints with: this text is parsed again (printed as HTML, the
080                                // HTML itself was parsed and formatted into a second layer of HTML)
081                                printer.setOutputConfig( null );
082                                printer.print( parser.sqlstatements.get( 0 ).getStartToken( ).container );
083                        
084                                
085                FormatterFactory.clearAllObject(removeCommentOption.sessionId);
086                return o.toString();
087            }
088        };
089
090        FutureTask<String> futureTask = new FutureTask<>(removeCommenTask);
091        Thread thread = new Thread(futureTask);
092        thread.start();
093
094        try {
095            String removeCommentSql = futureTask.get();
096            TGSqlParser removeCommentParser = new TGSqlParser( parser.getDbVendor() );
097            removeCommentParser.sqltext = removeCommentSql;
098            removeCommentParser.parse();
099            return removeCommentParser;
100        } catch (Exception e) {
101        }
102                return parser;
103        }
104
105        public static void main( String[] args )
106        {
107                GFmtOpt option = GFmtOptFactory.newInstance( );
108                option.linenumberEnabled = false;
109                option.parametersStyle = TAlignStyle.AsStacked;
110                option.parametersComma = TLinefeedsCommaOption.LfbeforeCommaWithSpace;
111                option.beStyleFunctionRightBEOnNewline = false;
112//              option.removeComment = true;
113                option.caseKeywords = TCaseOption.CoLowercase;
114                option.caseWhenThenInSameLine = true;
115//              option.linenumberEnabled = true;
116                TGSqlParser sqlparser = new TGSqlParser( EDbVendor.dbvpostgresql );
117                sqlparser.sqltext =
118
119
120                                "\n" +
121                                "WITH RECURSIVE employee_recursive(distance, employee_name, manager_name) AS (\n" +
122                                "    SELECT 1, employee_name, manager_name\n" +
123                                "    FROM employee\n" +
124                                "    WHERE manager_name = 'Mary'\n" +
125                                "  UNION ALL\n" +
126                                "    SELECT er.distance + 1, e.employee_name, e.manager_name\n" +
127                                "    FROM employee_recursive er, employee e\n" +
128                                "    WHERE er.employee_name = e.manager_name\n" +
129                                "  )\n" +
130                                "SELECT distance, employee_name FROM employee_recursive;\n";
131                sqlparser.parse( );
132                String result = new SqlFormatter( ).format( sqlparser, option );
133                System.out.println( result );
134
135        }
136}