Skip navigation links
General SQL Parser Documentation | ← Back to Docs

Package gudusoft.gsqlparser.pp2

Fault-tolerant SQL formatter (pp2) — augments, does not replace, the parse-dependent gudusoft.gsqlparser.pp formatter.

See: Description

Package gudusoft.gsqlparser.pp2 Description

Fault-tolerant SQL formatter (pp2) — augments, does not replace, the parse-dependent gudusoft.gsqlparser.pp formatter.

The one-sentence summary: on parseable SQL, pp2 is pp

pp2 has no layout style of its own for SQL that parses. When the whole input parses, pp2 calls FormatterFactory.pp on the whole document with the same options and returns pp's own output, byte for byte. pp2 exists for the input pp cannot handle at all: pp() requires parser.parse() == 0, so a single syntax error anywhere in a script leaves the caller with no formatted output. pp2 degrades that all-or-nothing failure into a per-statement one.

The ladder

Every format call stops at the first rung that succeeds:

  1. Whole-document pp. Parse the whole text; on success run FormatterFactory.pp over it and check the output with TokenEquivalence (same solid and comment tokens, same order, ignoring whitespace and keyword case). Guard passes → that text is the result, status OK, all regions GUARDED_AST. Governed by Pp2FormatOptions.wholeDocumentFastPath (default true).
  2. Per-region pp. Otherwise split the script into statement regions and parse each one alone. Each region that parses is still formatted by FormatterFactory.pp (through GuardedAstDelegate), behind the same guard. A broken statement costs pp-quality layout for that statement only.
  3. pp2's own renderers. A region that does not parse — or on which pp threw, or whose pp output failed the guard — goes to LexicalIslandRenderer, and failing that to ConservativeTokenRenderer. Neither consults an AST, so neither can fail on malformed input; the trade-off is plainer layout. The region is reported as LEXICAL_ISLAND or CONSERVATIVE and the overall status becomes OK_WITH_RECOVERY.

So Pp2FormatResult.getRegions() is readable as a map of where pp reached: a region tagged GUARDED_AST was formatted by pp; any other tag marks input pp could not reach.

Worked example


 TGSqlParser parser = new TGSqlParser(EDbVendor.dbvoracle);
 parser.sqltext = "select a,b from t where a=1 and b=2;";
 // parser.parse() is NOT required

 Pp2FormatResult r = FormatterFactory.pp2(parser, Pp2FormatOptions.defaults());
 r.getStatus();                        // OK
 r.getRegions().get(0).getRendererId() // GUARDED_AST  -> this is pp's output
 r.getText();                          // byte-identical to FormatterFactory.pp(...)
 

Give it SQL that does not parse ("select a,, from where;") and the same call still returns formatted text, with status OK_WITH_RECOVERY and the region tagged CONSERVATIVE or LEXICAL_ISLAND.

Implementation

The pp2 engine is a region-hybrid formatter built on a source-span ledger, an immutable token spine, a guarded AST delegate that wraps the existing FormatterFactory.pp() machinery, a conservative MVP renderer, and (post-Phase-3) a lexical island fallback ported from the Delphi TSQLion algorithm. Together these handle well-formed, partially broken, or completely invalid SQL without throwing, without OOM, and without StackOverflowError.

Design and slice plan: gsp_java_core/doc/formatter/v2/final_granular_plan.md.

Invariants

The public entry point is FormatterFactory.pp2(TGSqlParser, Pp2FormatOptions) (and its GFmtOpt overload returning the text directly), added in slice S17. Pp2Formatter is the internal facade the slices test against.

Since:
4.1
Skip navigation links
General SQL Parser Documentation | ← Back to Docs

Copyright © 1980 Gudu Software. All rights reserved. | Back to Documentation | Full Documentation Site