001 002package gudusoft.gsqlparser.pp.stmtformatter; 003 004import gudusoft.gsqlparser.TCustomSqlStatement; 005import gudusoft.gsqlparser.ETokenType; 006import gudusoft.gsqlparser.TGSqlParser; 007import gudusoft.gsqlparser.TSourceToken; 008import gudusoft.gsqlparser.TSourceTokenList; 009import gudusoft.gsqlparser.TStatementList; 010import gudusoft.gsqlparser.pp.mediator.MediatorFactory; 011import gudusoft.gsqlparser.pp.output.OutputConfig; 012import gudusoft.gsqlparser.pp.output.OutputConfigFactory; 013import gudusoft.gsqlparser.pp.para.GFmtOpt; 014import gudusoft.gsqlparser.pp.para.styleenums.TCompactMode; 015import gudusoft.gsqlparser.pp.print.IPrinter; 016import gudusoft.gsqlparser.pp.print.PrinterFactory; 017import gudusoft.gsqlparser.pp.processor.ProcessorFactory; 018import gudusoft.gsqlparser.pp.stmtformatter.builder.AbstractStmtFormatterBuilder; 019import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.AllStmtsFormatterBuilder; 020import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.AlterTableStmtFormatterBuilder; 021import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.CommonStmtFormatterBuilder; 022import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.CompactModeStmtFormatterBuilder; 023import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.CreateTableStmtFormatterBuilder; 024import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.CreateViewStmtFormatterBuilder; 025import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.DeclareStmtFormatterBuilder; 026import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.DeleteStmtFormatterBuilder; 027import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.ExecuteStmtFormatterBuilder; 028import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.GoStmtFormatterBuilder; 029import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.IfStmtFormatterBuilder; 030import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.InsertStmtFormatterBuilder; 031import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.MergeStmtFormatterBuilder; 032import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.PlsqlBlockStmtFormatterBuilder; 033import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.PlsqlIfStmtFormatterBuilder; 034import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.PlsqlStmtFormatterBuilder; 035import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.ReturnStmtFormatterBuilder; 036import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.SelectStmtFormatterBuilder; 037import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.SetStmtFormatterBuilder; 038import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.UpdateStmtFormatterBuilder; 039import gudusoft.gsqlparser.pp.stmtformatter.type.AbstractStmtFormatter; 040import gudusoft.gsqlparser.pp.stmtformatter.type.comm.AllStmtsFormatter; 041import gudusoft.gsqlparser.pp.stmtformatter.type.comm.AlterTableStmtFormatter; 042import gudusoft.gsqlparser.pp.stmtformatter.type.comm.CommonStmtFormatter; 043import gudusoft.gsqlparser.pp.stmtformatter.type.comm.CompactModeStmtFormatter; 044import gudusoft.gsqlparser.pp.stmtformatter.type.comm.CreateTableStmtFormatter; 045import gudusoft.gsqlparser.pp.stmtformatter.type.comm.CreateViewStmtFormatter; 046import gudusoft.gsqlparser.pp.stmtformatter.type.comm.DeclareStmtFormatter; 047import gudusoft.gsqlparser.pp.stmtformatter.type.comm.DeleteStmtFormatter; 048import gudusoft.gsqlparser.pp.stmtformatter.type.comm.ExecuteStmtFormatter; 049import gudusoft.gsqlparser.pp.stmtformatter.type.comm.GoStmtFormatter; 050import gudusoft.gsqlparser.pp.stmtformatter.type.comm.IfStmtFormatter; 051import gudusoft.gsqlparser.pp.stmtformatter.type.comm.InsertStmtFormatter; 052import gudusoft.gsqlparser.pp.stmtformatter.type.comm.MergeStmtFormatter; 053import gudusoft.gsqlparser.pp.stmtformatter.type.comm.PlsqlBlockStmtFormatter; 054import gudusoft.gsqlparser.pp.stmtformatter.type.comm.PlsqlIfStmtFormatter; 055import gudusoft.gsqlparser.pp.stmtformatter.type.comm.PlsqlStmtFormatter; 056import gudusoft.gsqlparser.pp.stmtformatter.type.comm.ReturnStmtFormatter; 057import gudusoft.gsqlparser.pp.stmtformatter.type.comm.SelectStmtFormatter; 058import gudusoft.gsqlparser.pp.stmtformatter.type.comm.SetStmtFormatter; 059import gudusoft.gsqlparser.pp.stmtformatter.type.comm.UpdateStmtFormatter; 060import gudusoft.gsqlparser.pp.utils.SourceTokenOperator; 061import gudusoft.gsqlparser.stmt.TAlterTableStatement; 062import gudusoft.gsqlparser.stmt.TCommonBlock; 063import gudusoft.gsqlparser.stmt.TCreateTableSqlStatement; 064import gudusoft.gsqlparser.stmt.TCreateViewSqlStatement; 065import gudusoft.gsqlparser.stmt.TDeleteSqlStatement; 066import gudusoft.gsqlparser.stmt.TIfStmt; 067import gudusoft.gsqlparser.stmt.TInsertSqlStatement; 068import gudusoft.gsqlparser.stmt.TMergeSqlStatement; 069import gudusoft.gsqlparser.stmt.TSelectSqlStatement; 070import gudusoft.gsqlparser.stmt.TStoredProcedureSqlStatement; 071import gudusoft.gsqlparser.stmt.TUpdateSqlStatement; 072import gudusoft.gsqlparser.stmt.mssql.TMssqlBlock; 073import gudusoft.gsqlparser.stmt.mssql.TMssqlDeclare; 074import gudusoft.gsqlparser.stmt.mssql.TMssqlExecute; 075import gudusoft.gsqlparser.stmt.mssql.TMssqlGo; 076import gudusoft.gsqlparser.stmt.mssql.TMssqlIfElse; 077import gudusoft.gsqlparser.stmt.mssql.TMssqlReturn; 078import gudusoft.gsqlparser.stmt.mssql.TMssqlSet; 079import gudusoft.gsqlparser.pp2.Pp2FormatOptions; 080import gudusoft.gsqlparser.pp2.Pp2FormatResult; 081import gudusoft.gsqlparser.pp2.engine.Pp2Engine; 082 083import java.io.ByteArrayOutputStream; 084import java.io.OutputStream; 085import java.util.ArrayList; 086import java.util.List; 087import java.util.Map; 088import java.util.concurrent.ConcurrentHashMap; 089 090public class FormatterFactory 091{ 092 093 /** 094 * all formatters 095 */ 096 private volatile static Map<String, AbstractStmtFormatter> formatter = new ConcurrentHashMap<String, AbstractStmtFormatter>( ); 097 098 private static Object object = new Object( ); 099 100 private static OutputConfig outputConfig; 101 102 /** 103 * create select statment formatter 104 * 105 * @param opt 106 * options 107 * @return instance 108 */ 109 public static SelectStmtFormatter createSelectStmtFormatter( GFmtOpt opt ) 110 { 111 return createFormatter( opt, 112 SelectStmtFormatter.class, 113 new IFormatterBuilderCreator<SelectStmtFormatter>( ) { 114 115 public AbstractStmtFormatterBuilder<SelectStmtFormatter> create( ) 116 { 117 return new SelectStmtFormatterBuilder( ); 118 } 119 } ); 120 } 121 122 public static InsertStmtFormatter createInsertStmtFormatter( GFmtOpt opt ) 123 { 124 return createFormatter( opt, 125 InsertStmtFormatter.class, 126 new IFormatterBuilderCreator<InsertStmtFormatter>( ) { 127 128 public AbstractStmtFormatterBuilder<InsertStmtFormatter> create( ) 129 { 130 return new InsertStmtFormatterBuilder( ); 131 } 132 } ); 133 } 134 135 public static DeleteStmtFormatter createDeleteStmtFormatter( GFmtOpt opt ) 136 { 137 return createFormatter( opt, 138 DeleteStmtFormatter.class, 139 new IFormatterBuilderCreator<DeleteStmtFormatter>( ) { 140 141 public AbstractStmtFormatterBuilder<DeleteStmtFormatter> create( ) 142 { 143 return new DeleteStmtFormatterBuilder( ); 144 } 145 } ); 146 } 147 148 public static UpdateStmtFormatter createUpdateStmtFormatter( GFmtOpt opt ) 149 { 150 return createFormatter( opt, 151 UpdateStmtFormatter.class, 152 new IFormatterBuilderCreator<UpdateStmtFormatter>( ) { 153 154 public AbstractStmtFormatterBuilder<UpdateStmtFormatter> create( ) 155 { 156 return new UpdateStmtFormatterBuilder( ); 157 } 158 } ); 159 } 160 161 public static CreateTableStmtFormatter createCreateTableStmtFormatter( 162 GFmtOpt opt ) 163 { 164 return createFormatter( opt, 165 CreateTableStmtFormatter.class, 166 new IFormatterBuilderCreator<CreateTableStmtFormatter>( ) { 167 168 public AbstractStmtFormatterBuilder<CreateTableStmtFormatter> create( ) 169 { 170 return new CreateTableStmtFormatterBuilder( ); 171 } 172 } ); 173 } 174 175 public static DeclareStmtFormatter createDeclareStmtFormatter( GFmtOpt opt ) 176 { 177 return createFormatter( opt, 178 DeclareStmtFormatter.class, 179 new IFormatterBuilderCreator<DeclareStmtFormatter>( ) { 180 181 public AbstractStmtFormatterBuilder<DeclareStmtFormatter> create( ) 182 { 183 return new DeclareStmtFormatterBuilder( ); 184 } 185 } ); 186 } 187 188 public static ExecuteStmtFormatter createExecuteStmtFormatter( GFmtOpt opt ) 189 { 190 return createFormatter( opt, 191 ExecuteStmtFormatter.class, 192 new IFormatterBuilderCreator<ExecuteStmtFormatter>( ) { 193 194 public AbstractStmtFormatterBuilder<ExecuteStmtFormatter> create( ) 195 { 196 return new ExecuteStmtFormatterBuilder( ); 197 } 198 } ); 199 } 200 201 public static SetStmtFormatter createSetStmtFormatter( GFmtOpt opt ) 202 { 203 return createFormatter( opt, 204 SetStmtFormatter.class, 205 new IFormatterBuilderCreator<SetStmtFormatter>( ) { 206 207 public AbstractStmtFormatterBuilder<SetStmtFormatter> create( ) 208 { 209 return new SetStmtFormatterBuilder( ); 210 } 211 } ); 212 } 213 214 public static IfStmtFormatter createIfStmtFormatter( GFmtOpt opt ) 215 { 216 return createFormatter( opt, 217 IfStmtFormatter.class, 218 new IFormatterBuilderCreator<IfStmtFormatter>( ) { 219 220 public AbstractStmtFormatterBuilder<IfStmtFormatter> create( ) 221 { 222 return new IfStmtFormatterBuilder( ); 223 } 224 } ); 225 } 226 227 public static PlsqlIfStmtFormatter createPlsqlIfStmtFormatter( GFmtOpt opt ) 228 { 229 return createFormatter( opt, 230 PlsqlIfStmtFormatter.class, 231 new IFormatterBuilderCreator<PlsqlIfStmtFormatter>( ) { 232 233 public AbstractStmtFormatterBuilder<PlsqlIfStmtFormatter> create( ) 234 { 235 return new PlsqlIfStmtFormatterBuilder( ); 236 } 237 } ); 238 } 239 240 public static PlsqlStmtFormatter createPlsqlStmtFormatter( GFmtOpt opt ) 241 { 242 return createFormatter( opt, 243 PlsqlStmtFormatter.class, 244 new IFormatterBuilderCreator<PlsqlStmtFormatter>( ) { 245 246 public AbstractStmtFormatterBuilder<PlsqlStmtFormatter> create( ) 247 { 248 return new PlsqlStmtFormatterBuilder( ); 249 } 250 } ); 251 } 252 253 public static GoStmtFormatter createGoStmtFormatter( GFmtOpt opt ) 254 { 255 return createFormatter( opt, 256 GoStmtFormatter.class, 257 new IFormatterBuilderCreator<GoStmtFormatter>( ) { 258 259 public AbstractStmtFormatterBuilder<GoStmtFormatter> create( ) 260 { 261 return new GoStmtFormatterBuilder( ); 262 } 263 } ); 264 } 265 266 public static CompactModeStmtFormatter createCompactModeStmtFormatter( 267 GFmtOpt opt ) 268 { 269 return createFormatter( opt, 270 CompactModeStmtFormatter.class, 271 new IFormatterBuilderCreator<CompactModeStmtFormatter>( ) { 272 273 public AbstractStmtFormatterBuilder<CompactModeStmtFormatter> create( ) 274 { 275 return new CompactModeStmtFormatterBuilder( ); 276 } 277 } ); 278 } 279 280 public static ReturnStmtFormatter createReturnStmtFormatter( GFmtOpt opt ) 281 { 282 return createFormatter( opt, 283 ReturnStmtFormatter.class, 284 new IFormatterBuilderCreator<ReturnStmtFormatter>( ) { 285 286 public AbstractStmtFormatterBuilder<ReturnStmtFormatter> create( ) 287 { 288 return new ReturnStmtFormatterBuilder( ); 289 } 290 } ); 291 } 292 293 public static CreateViewStmtFormatter createCreateViewStmtFormatter( 294 GFmtOpt opt ) 295 { 296 return createFormatter( opt, 297 CreateViewStmtFormatter.class, 298 new IFormatterBuilderCreator<CreateViewStmtFormatter>( ) { 299 300 public AbstractStmtFormatterBuilder<CreateViewStmtFormatter> create( ) 301 { 302 return new CreateViewStmtFormatterBuilder( ); 303 } 304 } ); 305 } 306 307 public static gudusoft.gsqlparser.pp.stmtformatter.type.comm.CreateMaterializedViewStmtFormatter createCreateMaterializedViewStmtFormatter( 308 GFmtOpt opt ) 309 { 310 return createFormatter( opt, 311 gudusoft.gsqlparser.pp.stmtformatter.type.comm.CreateMaterializedViewStmtFormatter.class, 312 new IFormatterBuilderCreator<gudusoft.gsqlparser.pp.stmtformatter.type.comm.CreateMaterializedViewStmtFormatter>( ) { 313 314 public AbstractStmtFormatterBuilder<gudusoft.gsqlparser.pp.stmtformatter.type.comm.CreateMaterializedViewStmtFormatter> create( ) 315 { 316 return new gudusoft.gsqlparser.pp.stmtformatter.builder.comm.CreateMaterializedViewStmtFormatterBuilder( ); 317 } 318 } ); 319 } 320 321 public static AlterTableStmtFormatter createAlterTableStatement( GFmtOpt opt ) 322 { 323 return createFormatter( opt, 324 AlterTableStmtFormatter.class, 325 new IFormatterBuilderCreator<AlterTableStmtFormatter>( ) { 326 327 public AbstractStmtFormatterBuilder<AlterTableStmtFormatter> create( ) 328 { 329 return new AlterTableStmtFormatterBuilder( ); 330 } 331 } ); 332 } 333 334 /** 335 * the callback interface to achieve the formatter builder 336 * 337 * @author zhoujun 338 * 339 */ 340 public interface IFormatterBuilderCreator<E extends AbstractStmtFormatter> 341 { 342 343 AbstractStmtFormatterBuilder<E> create( ); 344 } 345 346 /** 347 * create the formatter 348 * 349 * @param <E> 350 * @param opt 351 * @param clazz 352 * @param creater 353 * @return 354 */ 355 public static <E extends AbstractStmtFormatter> E createFormatter( 356 GFmtOpt opt, Class<E> clazz, IFormatterBuilderCreator<E> creater ) 357 { 358 String id = opt.sessionId + clazz.getName( ); 359 if ( !formatter.containsKey( id ) ) 360 { 361 synchronized ( FormatterFactory.class ) 362 { 363 if ( !formatter.containsKey( id ) ) 364 { 365 AbstractStmtFormatterBuilder builder = creater.create( ); 366 builder.setOption( opt ); 367 formatter.put( id, builder.build( ) ); 368 } 369 } 370 } 371 return (E) formatter.get( id ); 372 } 373 374 public static void processStatement( GFmtOpt option, TCustomSqlStatement sql ) 375 { 376 if ( option.compactMode == TCompactMode.Cpmugly ) 377 { 378 FormatterFactory.createCompactModeStmtFormatter( option ) 379 .format( sql ); 380 return; 381 } 382 383 if ( isNotNeedFormat( sql ) ) 384 { 385 return; 386 } 387 if ( sql instanceof TSelectSqlStatement ) 388 { 389 FormatterFactory.createSelectStmtFormatter( option ) 390 .format( (TSelectSqlStatement) sql ); 391 } 392 else if ( sql instanceof TInsertSqlStatement ) 393 { 394 FormatterFactory.createInsertStmtFormatter( option ) 395 .format( (TInsertSqlStatement) sql ); 396 } 397 else if ( sql instanceof TDeleteSqlStatement ) 398 { 399 FormatterFactory.createDeleteStmtFormatter( option ) 400 .format( (TDeleteSqlStatement) sql ); 401 } 402 else if ( sql instanceof TUpdateSqlStatement ) 403 { 404 FormatterFactory.createUpdateStmtFormatter( option ) 405 .format( (TUpdateSqlStatement) sql ); 406 } 407 else if ( sql instanceof TCreateTableSqlStatement ) 408 { 409 FormatterFactory.createCreateTableStmtFormatter( option ) 410 .format( (TCreateTableSqlStatement) sql ); 411 } 412 else if ( sql instanceof TMssqlDeclare ) 413 { 414 FormatterFactory.createDeclareStmtFormatter( option ) 415 .format( (TMssqlDeclare) sql ); 416 } 417 else if ( sql instanceof TMssqlExecute ) 418 { 419 FormatterFactory.createExecuteStmtFormatter( option ) 420 .format( (TMssqlExecute) sql ); 421 } 422 else if ( sql instanceof TStoredProcedureSqlStatement ) 423 { 424 FormatterFactory.createPlsqlStmtFormatter( option ) 425 .format( (TStoredProcedureSqlStatement) sql ); 426 } 427 else if ( sql instanceof TMssqlSet ) 428 { 429 FormatterFactory.createSetStmtFormatter( option ) 430 .format( (TMssqlSet) sql ); 431 } 432 else if ( sql instanceof TMssqlIfElse ) 433 { 434 FormatterFactory.createIfStmtFormatter( option ) 435 .format( (TMssqlIfElse) sql ); 436 } 437 else if ( sql instanceof TMssqlGo ) 438 { 439 FormatterFactory.createGoStmtFormatter( option ) 440 .format( (TMssqlGo) sql ); 441 } 442 else if ( sql instanceof TMssqlReturn ) 443 { 444 FormatterFactory.createReturnStmtFormatter( option ) 445 .format( (TMssqlReturn) sql ); 446 } 447 else if ( sql instanceof TCreateViewSqlStatement ) 448 { 449 FormatterFactory.createCreateViewStmtFormatter( option ) 450 .format( (TCreateViewSqlStatement) sql ); 451 } 452 else if ( sql instanceof gudusoft.gsqlparser.stmt.TCreateMaterializedSqlStatement ) 453 { 454 FormatterFactory.createCreateMaterializedViewStmtFormatter( option ) 455 .format( (gudusoft.gsqlparser.stmt.TCreateMaterializedSqlStatement) sql ); 456 } 457 else if ( sql instanceof TAlterTableStatement ) 458 { 459 FormatterFactory.createAlterTableStatement( option ) 460 .format( (TAlterTableStatement) sql ); 461 } 462 else if ( sql instanceof TMergeSqlStatement ) 463 { 464 FormatterFactory.createMergeSqlStatement( option ) 465 .format( (TMergeSqlStatement) sql ); 466 } 467 else if ( sql instanceof TIfStmt ) 468 { 469 FormatterFactory.createPlsqlIfStmtFormatter( option ) 470 .format( (TIfStmt) sql ); 471 } 472 else 473 { 474 FormatterFactory.createCommonStatement( option ).format( sql ); 475 } 476 } 477 478 private static AbstractStmtFormatter<TCommonBlock> createPlsqlBlockStmtFormatter( 479 GFmtOpt opt ) 480 { 481 return createFormatter( opt, 482 PlsqlBlockStmtFormatter.class, 483 new IFormatterBuilderCreator<PlsqlBlockStmtFormatter>( ) { 484 485 public AbstractStmtFormatterBuilder<PlsqlBlockStmtFormatter> create( ) 486 { 487 return new PlsqlBlockStmtFormatterBuilder( ); 488 } 489 } ); 490 } 491 492 private static MergeStmtFormatter createMergeSqlStatement( GFmtOpt opt ) 493 { 494 return createFormatter( opt, 495 MergeStmtFormatter.class, 496 new IFormatterBuilderCreator<MergeStmtFormatter>( ) { 497 498 public AbstractStmtFormatterBuilder<MergeStmtFormatter> create( ) 499 { 500 return new MergeStmtFormatterBuilder( ); 501 } 502 } ); 503 } 504 505 private static CommonStmtFormatter createCommonStatement( GFmtOpt opt ) 506 { 507 return createFormatter( opt, 508 CommonStmtFormatter.class, 509 new IFormatterBuilderCreator<CommonStmtFormatter>( ) { 510 511 public AbstractStmtFormatterBuilder<CommonStmtFormatter> create( ) 512 { 513 return new CommonStmtFormatterBuilder( ); 514 } 515 } ); 516 } 517 518 public static boolean isNotNeedFormat( TCustomSqlStatement sql ) 519 { 520 if ( sql == null ) 521 { 522 // the null statement needn't formatting. 523 return true; 524 } 525 if ( sql.getStartToken( ) != null ) 526 { 527 TSourceToken t = sql.getStartToken( ); 528 return isNotNeedFormat( t ); 529 } 530 return false; 531 } 532 533 public static boolean isNotNeedFormat( TSourceToken t ) 534 { 535 if ( t == null ) 536 { 537 return false; 538 } 539 TSourceTokenList bts = t.getTokensBefore( ); 540 if ( bts.size( ) > 0 ) 541 { 542 for ( int i = 0; i < bts.size( ); i++ ) 543 { 544 if ( SourceTokenOperator.createNoFormatFlagToken( ) 545 .equals( bts.get( i ) ) ) 546 { 547 return true; 548 } 549 } 550 } 551 return false; 552 } 553 554 public static void processBlockStmt( GFmtOpt opt, TMssqlBlock stmt, 555 TSourceToken ifToken ) 556 { 557 TSourceToken startToken = stmt.getStartToken( ); 558 TSourceToken endToken = stmt.getEndToken( ); 559 if ( startToken == null || endToken == null ) 560 { 561 return; 562 } 563 int curBeginIndent = SourceTokenOperator.curColumnNumberVT( ifToken ); 564 if ( opt.beStyleBlockLeftBEOnNewline ) 565 { 566 curBeginIndent += opt.beStyleBlockLeftBEIndentSize; 567 // process the begin token 568 SourceTokenOperator.addBefore( opt, 569 startToken, 570 SourceTokenOperator.createReturnSourceToken( ) ); 571 SourceTokenOperator.addBefore( opt, 572 startToken, 573 SourceTokenOperator.createWhitespaceSourceToken( curBeginIndent ) ); 574 } 575 // process the end token 576 int curEndIndent = SourceTokenOperator.curColumnNumberVT( ifToken ) 577 + ( opt.beStyleBlockLeftBEOnNewline ? opt.beStyleBlockLeftBEIndentSize 578 : opt.beStyleBlockRightBEIndentSize ); 579 SourceTokenOperator.addBefore( opt, 580 endToken, 581 SourceTokenOperator.createReturnSourceToken( ) ); 582 SourceTokenOperator.addBefore( opt, 583 endToken, 584 SourceTokenOperator.createWhitespaceSourceToken( curEndIndent ) ); 585 586 TStatementList list = stmt.getBodyStatements( ); 587 588 // first, process the indent for the first statement 589 if ( list != null && list.size( ) > 0 ) 590 { 591 int curBlockIndent = curEndIndent + opt.beStyleBlockIndentSize; 592 TCustomSqlStatement bstmt = list.get( 0 ); 593 TSourceToken bstartToken = bstmt.getStartToken( ); 594 if ( bstartToken != null ) 595 { 596 SourceTokenOperator.addBefore( opt, 597 bstartToken, 598 SourceTokenOperator.createReturnSourceToken( ) ); 599 SourceTokenOperator.addBefore( opt, 600 bstartToken, 601 SourceTokenOperator.createWhitespaceSourceToken( curBlockIndent ) ); 602 } 603 } 604 // second, process all the empty lines between the statements 605 AllStmtsFormatter.processEmptyLine( list, opt, true ); 606 607 // third, format the statements in the begin-end block 608 if ( list != null && list.size( ) > 0 ) 609 { 610 // int curBlockIndent = curEndIndent + opt.beStyleBlockIndentSize; 611 for ( int i = 0; i < list.size( ); i++ ) 612 { 613 TCustomSqlStatement bstmt = list.get( i ); 614 // TSourceToken bstartToken = bstmt.getStartToken(); 615 // if (bstartToken != null) { 616 // SourceTokenOperator.addBefore(opt, bstartToken, 617 // SourceTokenOperator.createReturnSourceToken()); 618 // if (i != 0 && opt.insertBlankLineInBatchSqls) { 619 // TCustomSqlStatement preBstmt = list.get(i - 1); 620 // TSourceToken preBEndToken = preBstmt.getEndToken(); 621 // if (preBEndToken != null) { 622 // SourceTokenOperator.addAfter(opt, preBstmt.getEndToken(), 623 // SourceTokenOperator.createReturnSourceToken()); 624 // } 625 // } 626 // SourceTokenOperator.addBefore(opt, bstartToken, 627 // SourceTokenOperator.createWhitespaceSourceToken(curBlockIndent)); 628 // 629 // } 630 FormatterFactory.processStatement( opt, bstmt ); 631 632 } 633 } 634 635 } 636 637 /** 638 * A statement that starts on the line of the previous statement's 639 * terminator ({@code SELECT x FROM t; SELECT y ...}) gets a line break 640 * first. Every column the processors compute for it is measured from the 641 * last line break, so without one the whole statement was laid out as if 642 * it started at the column after the terminator. 643 */ 644 private static void startOnNewLine( GFmtOpt opt, TCustomSqlStatement prev, TCustomSqlStatement sql ) 645 { 646 TSourceToken start = sql.getStartToken( ); 647 TSourceToken prevEnd = prev.getEndToken( ); 648 if ( start == null || prevEnd == null || start.container == null 649 || start.container != prevEnd.container || prevEnd.posinlist >= start.posinlist 650 || start.lineNo <= 0 || prevEnd.lineNo <= 0 ) 651 { 652 return; 653 } 654 // the original line numbers: the whitespace pre-pass has already rewritten the tokens between 655 if ( start.lineNo != prevEnd.lineNo ) 656 { 657 return; 658 } 659 TSourceTokenList before = start.getTokensBefore( ); 660 for ( int i = 0; before != null && i < before.size( ); i++ ) 661 { 662 if ( before.get( i ) == SourceTokenOperator.createNoFormatFlagToken( ) ) 663 { 664 return; // a no-format zone is reproduced verbatim 665 } 666 } 667 SourceTokenOperator.removeWhitespaceAndReturnFromEnd( opt, start.container, start.posinlist ); 668 SourceTokenOperator.addBefore( opt, start, SourceTokenOperator.createStatementBreakToken( ) ); 669 } 670 671 public static String pp( TGSqlParser parser, GFmtOpt option ) 672 { 673 if (option.removeComment) { 674 parser = SqlFormatter.preHandleRemoveComment(parser); 675 } 676 OutputStream o = new ByteArrayOutputStream( ); 677 IPrinter printer = PrinterFactory.createTextPrinter( o ); 678 679 FormatterFactory.createAllStmtsFormatter( option ) 680 .beforeFormat( parser.sqlstatements ); 681 682 for ( int i = 0; i < parser.sqlstatements.size( ); i++ ) 683 { 684 TCustomSqlStatement sql = parser.sqlstatements.get( i ); 685 if ( i > 0 ) 686 { 687 startOnNewLine( option, parser.sqlstatements.get( i - 1 ), sql ); 688 } 689 processStatement( option, sql ); 690 } 691 if ( parser.sqlstatements != null && parser.sqlstatements.size( ) > 0 ) 692 { 693 FormatterFactory.createAllStmtsFormatter( option ) 694 .doFormat( parser.sqlstatements ); 695 FormatterFactory.createAllStmtsFormatter( option ) 696 .afterFormat( parser.sqlstatements ); 697 698 if ( outputConfig == null ) 699 { 700 outputConfig = OutputConfigFactory.getOutputConfig( option, 701 parser.getDbVendor( ) ); 702 } 703 704 printer.setOutputConfig( outputConfig ); 705 printer.print( parser.sqlstatements.get( 0 ).getStartToken( ).container ); 706 } 707 708 clearAllObject( option.sessionId ); 709 return o.toString( ); 710 711 } 712 713 /** 714 * Fault-tolerant formatter entry point (pp2). Unlike {@link #pp(TGSqlParser, GFmtOpt)}, 715 * this does <b>not</b> require {@code parser.parse()} to have returned 0: it 716 * re-tokenizes {@code parser.sqltext} internally, splits the script into 717 * statement regions, formats each region independently, and recovers 718 * gracefully from malformed input. It never throws for non-null inputs and 719 * preserves every solid input token. 720 * 721 * <p>This is the single additive pp2 bridge (plan ยง4.1/S17). It does not 722 * change the behavior of {@link #pp(TGSqlParser, GFmtOpt)} or any other 723 * existing method. The heavy lifting lives in 724 * {@code gudusoft.gsqlparser.pp2.engine.Pp2Engine}. 725 * 726 * @param parser carries the SQL text ({@code parser.sqltext}) and dialect 727 * ({@code parser.getDbVendor()}); need not be parsed first 728 * @param opts pp2 formatting options; must not be null 729 * @return a structured {@link Pp2FormatResult} with per-region renderer 730 * choice, status, and diagnostics; never null 731 * @throws NullPointerException if {@code parser} or {@code opts} is null 732 */ 733 public static Pp2FormatResult pp2( TGSqlParser parser, Pp2FormatOptions opts ) 734 { 735 if ( parser == null ) throw new NullPointerException( "parser" ); 736 if ( opts == null ) throw new NullPointerException( "opts" ); 737 String sql = parser.sqltext == null ? "" : parser.sqltext; 738 return new Pp2Engine( ).format( sql, parser.getDbVendor( ), opts ); 739 } 740 741 /** 742 * Convenience overload mirroring the {@link #pp(TGSqlParser, GFmtOpt)} 743 * signature: returns the formatted text directly. The caller's 744 * {@link GFmtOpt} is copied into a {@link Pp2FormatOptions} via 745 * {@link Pp2FormatOptions#from(GFmtOpt)} so casing/comma/indent options 746 * carry over (giving byte-parity with {@code pp()} on parseable input). 747 * 748 * @param parser carries the SQL text and dialect; need not be parsed first 749 * @param opt existing formatter options; must not be null 750 * @return the formatted SQL text; never null 751 * @throws NullPointerException if {@code parser} or {@code opt} is null 752 */ 753 public static String pp2( TGSqlParser parser, GFmtOpt opt ) 754 { 755 if ( parser == null ) throw new NullPointerException( "parser" ); 756 if ( opt == null ) throw new NullPointerException( "opt" ); 757 return pp2( parser, Pp2FormatOptions.from( opt ) ).getText( ); 758 } 759 760 public static OutputConfig getOutputConfig( ) 761 { 762 return outputConfig; 763 } 764 765 public static void setOutputConfig( OutputConfig outputConfig ) 766 { 767 FormatterFactory.outputConfig = outputConfig; 768 } 769 770 public static AllStmtsFormatter createAllStmtsFormatter( GFmtOpt option ) 771 { 772 return AllStmtsFormatterBuilder.create( option ); 773 } 774 775 public static void clearAllObject( String sessionId ) 776 { 777 FormatterFactory.clear( sessionId ); 778 ProcessorFactory.clear( sessionId ); 779 MediatorFactory.clear( sessionId ); 780 } 781 782 public static void clear( String sessionId ) 783 { 784 synchronized ( object ) 785 { 786 List<String> removedKeys = new ArrayList<String>( ); 787 for ( String key : formatter.keySet( ) ) 788 { 789 if ( key.startsWith( sessionId ) ) 790 { 791 removedKeys.add( key ); 792 } 793 } 794 for ( String key : removedKeys ) 795 { 796 formatter.remove( key ); 797 } 798 } 799 } 800}