Skip to content

GSP Java v3.x to v4 Migration Guide

Version: 4.0 Last Updated: January 2026 Applies to: GSP Java SQL Parser Library


Table of Contents

  1. Executive Summary
  2. Quick Start
  3. Switching Between Resolvers
  4. Why TSQLResolver2 is Better
  5. Deprecated APIs Reference
  6. New APIs Reference
  7. API Comparison and Migration Table
  8. Class Location Changes
  9. Code Migration Examples
  10. Best Practices for Migration
  11. Known Limitations and Considerations
  12. Troubleshooting
  13. Support and Resources

1. Executive Summary

Purpose of the Upgrade

GSP Java v4 introduces TSQLResolver2, a completely redesigned semantic analysis engine that replaces the existing TSQLResolver. The primary focus is on name resolution - building correct relationships between columns and tables used in SQL statements.

Backward Compatibility

Good News: No immediate code changes are required for basic usage.

TSQLResolver2 automatically synchronizes resolution data back to existing APIs (like TTable.getLinkedColumns() and TObjectName.getSourceTable()), ensuring your existing code continues to work without modification.

Deprecation Timeline

Important: APIs marked as deprecated will be removed after 2026/12/31.

Plan your migration to new APIs before this deadline to ensure continued compatibility.

Production Readiness Warning

Caution: Do NOT use v4 in production environments without thorough testing.

Due to the significant refactoring, not all SQL syntax variations have been fully tested. Carefully validate your specific SQL patterns before deploying to production.


2. Quick Start

For Users Who Just Want v4 to Work

If you're currently using GSP Java v3.x and want to upgrade to v4 with minimal changes:

  1. Update your dependency to GSP Java v4.x
  2. Run your existing code - it should work without modifications
  3. Test thoroughly - verify output matches your expectations
  4. Monitor deprecation warnings - plan to update deprecated API usage before 2026/12/31

For Users Who Want to Leverage New Features

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import gudusoft.gsqlparser.*;
import gudusoft.gsqlparser.resolver2.*;
import gudusoft.gsqlparser.resolver2.model.*;

TGSqlParser parser = new TGSqlParser(EDbVendor.dbvoracle);
parser.setResolverType(EResolverType.RESOLVER2);  // Explicitly use new resolver
parser.sqltext = "SELECT a.id, b.name FROM table_a a JOIN table_b b ON a.id = b.id";
parser.parse();

// Access new resolution APIs
for (TCustomSqlStatement stmt : parser.sqlstatements) {
    for (int i = 0; i < stmt.tables.size(); i++) {
        TTable table = stmt.tables.getTable(i);
        // ... use new ColumnSource APIs for detailed resolution info
    }
}

3. Switching Between Resolvers

3.1 Global Level Configuration (TBaseType)

Control the default resolver for all parser instances:

1
2
3
4
5
// Enable TSQLResolver2 (new resolver - default in v4)
TBaseType.setEnableResolver2(true);

// Enable TSQLResolver (old resolver)
TBaseType.setEnableResolver(true);

Important Notes: - TBaseType.isEnableResolver2() returns true by default in v4 - You cannot enable both resolvers simultaneously - an IllegalStateException will be thrown - To switch resolvers, disable one before enabling the other:

1
2
3
// Switch from RESOLVER2 to RESOLVER
TBaseType.setEnableResolver2(false);
TBaseType.setEnableResolver(true);

3.2 Parser Level Configuration (TGSqlParser)

Override global settings for individual parser instances:

1
2
TGSqlParser parser = new TGSqlParser(EDbVendor.dbvoracle);
parser.setResolverType(EResolverType resolverType);

EResolverType Values:

Value Description
EResolverType.DEFAULT Use global TBaseType setting (resolution order: RESOLVER2 > RESOLVER > NONE)
EResolverType.RESOLVER Force legacy TSQLResolver
EResolverType.RESOLVER2 Force new TSQLResolver2
EResolverType.NONE Disable resolution entirely

3.3 Configuration Precedence

  1. Instance-level setResolverType() takes highest precedence
  2. If DEFAULT, falls back to global TBaseType settings
  3. If both disabled in TBaseType, no resolution is performed

4. Why TSQLResolver2 is Better

TSQLResolver2 provides significant improvements over the legacy resolver:

4.1 Namespace-based Architecture

Uses a proper namespace hierarchy for accurate column resolution: - GlobalScopeSelectScopeFromScope - TableNamespace, SubqueryNamespace, CTENamespace, UnionNamespace

4.2 Better Subquery and CTE Handling

Correctly traces columns through nested subqueries and CTEs:

1
2
3
// SQL: SELECT sub.col1 FROM (SELECT t.id AS col1 FROM my_table t) sub
ColumnSource source = column.getColumnSource();
TTable finalTable = source.getFinalTable();  // Returns my_table, not sub

4.3 Confidence Scoring

Provides confidence scores [0.0, 1.0] for resolution results:

1
2
ColumnSource source = column.getColumnSource();
double confidence = source.getConfidence();  // e.g., 1.0 for exact match

4.4 Evidence-based Resolution

Tracks evidence explaining how each column was resolved:

1
2
String evidence = source.getEvidence();
// e.g., "Matched by qualified name against table alias"

4.5 Physical Table Tracing

Traces columns back to their final physical table through subqueries/CTEs:

Method Returns
column.getSourceTable() Immediate source (subquery, CTE, or physical table)
source.getFinalTable() Final physical table after tracing
source.getAllFinalTables() All final tables (for UNION queries)

4.6 Improved Star Column Handling

Better expansion and tracking of SELECT * columns with proper scope awareness.

4.7 Union Query Support

Correctly handles columns from UNION queries with multiple source tables:

1
List<TTable> allTables = source.getAllFinalTables();  // Returns all source tables

4.8 Ambiguous Column Detection

Better detection and handling of ambiguous column references:

1
2
3
if (source.isAmbiguous()) {
    List<TTable> candidates = source.getCandidateTables();
}

5. Deprecated APIs Reference

The following APIs are deprecated and will be removed after 2026/12/31.

In V4, the semantic analysis engine was replaced by TSQLResolver2, which uses a namespace-based architecture (INamespace, ColumnSource, ResolutionResult) instead of the old TAttributeNode-based approach. This section provides a complete inventory of every public class, method, and field that is deprecated or superseded.

5.1 TAttributeNode (Core Class — Entire Class Superseded)

Package: gudusoft.gsqlparser.TAttributeNode Replaced by: gudusoft.gsqlparser.resolver2.model.ColumnSource

The TAttributeNode class represented columns/fields exposed by a table/relation. In V4, this role is filled by ColumnSource, which provides richer information including confidence scoring, evidence tracking, and physical table tracing.

Deprecated Constructors:

Constructor V4 Replacement
TAttributeNode(String, TTable) ColumnSource created internally by TSQLResolver2
TAttributeNode(String, TTable, TSQLColumn) ColumnSource with database metadata
TAttributeNode(String, TTable, TResultColumn) ColumnSource with subquery tracing
TAttributeNode(String, TTable, TColumnDefinition, TResultColumn) ColumnSource for struct fields
TAttributeNode(String, TTable, TResultColumn, int) ColumnSource with position tracking
TAttributeNode(String, TTable, TSQLColumn, TResultColumn, int) ColumnSource (full)

Deprecated Methods:

Method Return Type V4 Replacement
getName() String ColumnSource.getExposedName()
getLastPartOfName() String ColumnSource.getExposedName()
getTable_ref() TTable ColumnSource.getSourceNamespace().getSourceTable()
getSubLevelResultColumn() TResultColumn ColumnSource.getDefinitionNode()
getSqlColumn() TSQLColumn Database metadata accessed via TSQLEnv
getColumnDefinition() TColumnDefinition ColumnSource.getDefinitionNode()
getStructResultColumn() TResultColumn ColumnSource struct field access
getIndex() int Managed internally by TSQLResolver2
getAccompaniedAttributeNodes() ArrayList<TAttributeNode> ColumnSource.getAllFinalTables() (for UNION)
addAttributeRefToThisNode(TObjectName) void Handled internally by TSQLResolver2
addNodeToList(TAttributeNode, ArrayList) boolean (static) Not needed; namespaces manage column lists
addAllNodesToList(ArrayList, ArrayList) boolean (static) Not needed; namespaces manage column lists

5.2 IRelation Interface (Superseded)

Package: gudusoft.gsqlparser.IRelation Replaced by: INamespace hierarchy in resolver2

Method V4 Replacement
getAttributes() INamespace.getAllColumnSources()
getRelationName() INamespace.getName()
size() INamespace.getAllColumnSources().size()

All implementing classes have a deprecated getAttributes() method:

Class V4 Replacement
TTable TableNamespace.getAllColumnSources()
TCustomSqlStatement IResolutionResult.getColumns(stmt)
TSelectSqlStatement SelectScope via IResolutionResult
TJoinExpr Resolved through FromScope namespaces
TFromClause FromScope.getAllColumnSources()
TPivotClause Pivot handling in ScopeBuilder
TTableFunction TableNamespace for function return

5.3 TTable Class

Deprecated API Deprecated Since V4 Replacement
getAttributes() v3.3.1.0 TableNamespace.getAllColumnSources()
getLinkedColumns() v3.3.1.0 IResolutionResult.getColumnsForTable(stmt, table)
initStarAttribute() Implicit Star expansion handled by TSQLResolver2
initAttributeForXMLTable() Implicit XML table attributes resolved by ScopeBuilder
initAttributeForTableFunction() Implicit Function return types resolved by ScopeBuilder
initAttributeForRowList() Implicit VALUES clause resolved by ScopeBuilder
initAttributesFromCTE(TCTE) Implicit CTE resolution via CTENamespace
initAttributesFromSubquery(TSelectSqlStatement, String) Implicit Subquery resolution via SubqueryNamespace
initAttributesForPivotTable() Implicit Pivot resolution in ScopeBuilder
initAttributesForJoin() Implicit JOIN resolution via FromScope
initAttributesForUnnest(TSQLEnv, TSelectSqlStatement) Implicit UNNEST resolution in ScopeBuilder
addAttribute(TAttributeNode) Implicit Namespaces manage their own columns
getAttributesReferenceToThisRelation() Implicit IResolutionResult.getColumnsForTable()

5.4 TCustomSqlStatement Class

Deprecated API Deprecated Since V4 Replacement
getAttributes() Implicit (via IRelation) IResolutionResult.getColumns(stmt)
getSymbolTable() v2.5.3.5 TStmtScope (and now further to SelectScope)

5.5 TObjectName Class

Deprecated API Deprecated Since V4 Replacement
getSourceAttributeNode() v3.4.0.5 getColumnSource() or getResolution().getColumnSource()
setSourceAttributeNode(TAttributeNode) v3.4.0.5 setResolution(ResolutionResult)
getAttributeNodesDerivedFromFromClause() Implicit Star expansion managed by TSQLResolver2
getCandidateAttributeNodes() Implicit getColumnSource().getCandidateTables()
setSourceTableBySQLResolver(...) Implicit setResolution(ResolutionResult)

5.6 TResultColumn Class

Deprecated API Deprecated Since V4 Replacement
getAttributesFromUpLevelReferenceToStarColumn() Implicit Integrated into TSQLResolver2 star column handling

Package: gudusoft.gsqlparser.compiler.TStmtScope

Deprecated API V4 Replacement
setSourceAttributes(ArrayList<TAttributeNode>) SelectScope / FromScope manage columns via namespaces
doResolve() (Phase 2 resolution) NameResolver.resolve() in TSQLResolver2

5.8 TCTE Class

Deprecated API V4 Replacement
initAttributesFromColumnList() CTENamespace maps CTE columns automatically
initAttributesFromSubQuery() CTENamespace resolves subquery columns

5.9 TJoinExpr Class

Deprecated API V4 Replacement
getAttributes() FromScope aggregates join table namespaces
initAttributes(int roundNo) JOIN resolution handled by ScopeBuilder

5.10 TPivotClause Class

Deprecated API V4 Replacement
getAttributes() Pivot attributes resolved by ScopeBuilder
initAttributes() Pivot handling in ScopeBuilder

5.11 TColumnTableMatch Class (Entire Class Superseded)

Package: gudusoft.gsqlparser.resolver.TColumnTableMatch Replaced by: ColumnSource with getConfidence()

Method V4 Replacement
getAttributeNode() ColumnSource
getTable() ColumnSource.getSourceNamespace().getSourceTable()

5.12 Old Resolver Package (Entire Package Superseded)

Package: gudusoft.gsqlparser.resolver Replaced by: gudusoft.gsqlparser.resolver2

All classes in the old resolver package are superseded:

Deprecated Class Purpose V4 Replacement
TSQLResolver Main orchestrator TSQLResolver2
TRelationResolver Collects attributes per table ScopeBuilder
TRelationResolver2 Alternative relation resolver ScopeBuilder
TAttributeResolver Links columns to attributes NameResolver
TStarColumnExpander Expands SELECT * TSQLResolver2 star expansion
TStarColumnPushDownResolver Pushes columns through stars TSQLResolver2 iterative resolution
TMetadataCollector Collects DDL metadata TSQLResolver2 metadata handling
TDatabaseObjectResolver Links DB object references ScopeBuilder
TBaseResolver Base visitor class Not needed
TResolverHelpUtils Utility functions Internal utilities in resolver2
TColumnTableMatch Wraps TAttributeNode + priority ColumnSource with confidence score

5.13 Import Migration

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Old imports (deprecated)
import gudusoft.gsqlparser.TAttributeNode;
import gudusoft.gsqlparser.IRelation;
import gudusoft.gsqlparser.resolver.TSQLResolver;
import gudusoft.gsqlparser.resolver.TColumnTableMatch;

// New imports (V4)
import gudusoft.gsqlparser.resolver2.TSQLResolver2;
import gudusoft.gsqlparser.resolver2.TSQLResolverConfig;
import gudusoft.gsqlparser.resolver2.model.ColumnSource;
import gudusoft.gsqlparser.resolver2.model.ResolutionResult;
import gudusoft.gsqlparser.resolver2.result.IResolutionResult;

5.14 APIs NOT Deprecated (Still Valid)

The following APIs remain valid and work with both resolvers:

API Class Notes
getSourceTable() TObjectName Enhanced to work with both resolvers; returns null for ambiguous columns in RESOLVER2
getSourceColumn() TObjectName Still used by both resolvers
getLinkedColumnDef() TObjectName Still valid for DDL statements
getResolution() TObjectName New in V4 — returns ResolutionResult
getColumnSource() TObjectName New in V4 — shortcut to ColumnSource
setResolution(ResolutionResult) TObjectName New in V4 — set by TSQLResolver2

6. New APIs Reference

6.1 TObjectName New Methods

Package: gudusoft.gsqlparser.nodes.TObjectName

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
 * Get the resolution result containing column source information.
 * @return ResolutionResult or null if not resolved
 */
public ResolutionResult getResolution()

/**
 * Get the column source directly (shortcut).
 * @return ColumnSource or null if not resolved
 */
public ColumnSource getColumnSource()

/**
 * Set resolution result (called by TSQLResolver2).
 * @param resolution the resolution result to set
 */
public void setResolution(ResolutionResult resolution)

/**
 * Get source table (enhanced to work with both resolvers).
 * Returns null if the column is ambiguous in RESOLVER2.
 * @return TTable representing the immediate source, or null
 */
public TTable getSourceTable()

6.2 ColumnSource Class

Package: gudusoft.gsqlparser.resolver2.model.ColumnSource

This is the primary class for accessing detailed resolution information:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Namespace information
INamespace getSourceNamespace()    // Where this column is exposed
String getExposedName()            // Name by which column is exposed

// Definition node
TParseTreeNode getDefinitionNode() // AST node where column is defined

// Confidence and evidence
double getConfidence()             // Score [0.0, 1.0]
String getEvidence()               // Why this resolution was chosen

// Table tracing
TTable getFinalTable()             // Final physical table
List<TTable> getAllFinalTables()   // All final tables (for UNION)

// Ambiguity handling
boolean isAmbiguous()              // Is resolution ambiguous?
List<TTable> getCandidateTables()  // Possible source tables

// Column characteristics
boolean isCalculatedColumn()       // Is column computed?
boolean isColumnAlias()            // Is column renamed via AS?
boolean isCTEExplicitColumn()      // Is CTE explicit column?

// Struct/record field access
boolean hasFieldPath()             // Has field path?
boolean isStructFieldAccess()      // Is struct field access?
List<String> getFieldPath()        // Get field path

6.3 ResolutionResult Class

Package: gudusoft.gsqlparser.resolver2.model.ResolutionResult

Container for resolution outcomes:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// Factory methods
static ResolutionResult exactMatch(ColumnSource source)
static ResolutionResult ambiguous(AmbiguousColumnSource source)
static ResolutionResult notFound(String columnName)
static ResolutionResult notFound(String columnName, String errorMessage)

// Status checks
ResolutionStatus getStatus()       // EXACT_MATCH, AMBIGUOUS, NOT_FOUND
boolean isExactMatch()
boolean isAmbiguous()
boolean isNotFound()
boolean isResolved()               // True if not NOT_FOUND

// Access results
ColumnSource getColumnSource()     // Get exact match result
AmbiguousColumnSource getAmbiguousSource()  // Get ambiguous details
String getErrorMessage()           // Get error for unresolved columns

6.4 IResolutionResult Interface

Package: gudusoft.gsqlparser.resolver2.result.IResolutionResult

Statement-level query interface for resolution results:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// Statement-level queries
IScope getScope(TCustomSqlStatement stmt)
List<TTable> getTables(TCustomSqlStatement stmt)
List<TTable> getTables(TCustomSqlStatement stmt, TableFilterOptions options)
List<TObjectName> getColumns(TCustomSqlStatement stmt)
List<TObjectName> getColumnsForTable(TCustomSqlStatement stmt, TTable table)
List<TObjectName> getOrphanColumns(TCustomSqlStatement stmt)
List<TCTE> getCTEs(TCustomSqlStatement stmt)

// Global queries
List<String> getAllTableNames()
List<String> getAllFieldNames()    // table.column format
List<String> getAllCTENames()
List<TObjectName> getAllResolvedColumns()
List<TObjectName> getAllUnresolvedColumns()
ResolutionStatistics getStatistics()

6.5 TSQLResolver2 Main Class

Package: gudusoft.gsqlparser.resolver2.TSQLResolver2

Main entry point for the new resolver:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// Construction
TSQLResolver2(TContext context, TStatementList statements)
TSQLResolver2(TContext context, TStatementList statements, TSQLResolverConfig config)

// Execution
boolean resolve()                  // Main entry point

// Result access
IResolutionResult getResult()      // Statement-level result interface
ScopeBuildResult getScopeBuildResult()  // Scope tree and mappings
ResolutionStatistics getStatistics()

// Configuration
TSQLResolverConfig getConfig()
void setSqlEnv(TSQLEnv sqlEnv)     // Set table metadata
TSQLEnv getSqlEnv()

6.6 TSQLResolverConfig Class

Package: gudusoft.gsqlparser.resolver2.TSQLResolverConfig

Configuration options for TSQLResolver2:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
// Core settings
INameMatcher nameMatcher           // Name matching rules
boolean legacyCompatibilityEnabled // Sync to TTable.linkedColumns (default: true)
double legacySyncMinConfidence     // Min confidence for legacy sync (default: 1.0)
int maxIterations                  // Max iterations for resolution (default: 10)

// Display settings
boolean showDatatype               // Include column datatypes
boolean showCTE                    // Include CTE tables

// Confidence thresholds
double minDefiniteConfidence       // Min for "definite" results (default: 0.9)
double minConfidenceToGuess        // Min to allow guessing (default: 0.95)

// Factory methods
static TSQLResolverConfig createDefault()
static TSQLResolverConfig createCaseSensitive()
static TSQLResolverConfig createStandalone()     // No legacy sync
static TSQLResolverConfig createWithDatatype()
static TSQLResolverConfig createWithCTE()
static TSQLResolverConfig createForVendor(EDbVendor vendor)

7. API Comparison and Migration Table

7.1 Complete Migration Reference

Use Case Old API (v3.x) New API (v4) Notes
Get columns linked to a table table.getLinkedColumns() Iterate resolver.getResult().getColumnsForTable(stmt, table) Use IResolutionResult interface
Get table attributes table.getAttributes() Use namespace classes: TableNamespace.getAllColumnSources() Direct namespace access
Get source table for column column.getSourceTable() column.getSourceTable() (still works) or column.getColumnSource().getSourceNamespace().getSourceTable() Both work
Get final physical table N/A (limited support) column.getColumnSource().getFinalTable() New capability
Get all final tables (UNION) N/A column.getColumnSource().getAllFinalTables() New capability
Check resolution confidence N/A column.getColumnSource().getConfidence() New capability
Get resolution evidence N/A column.getColumnSource().getEvidence() New capability
Handle ambiguous columns column.getCandidateAttributeNodes() column.getColumnSource().getCandidateTables() Simplified API
Get source attribute node column.getSourceAttributeNode() column.getResolution().getColumnSource() Complete replacement
Get CTE columns cteTable.getAttributes() CTENamespace.getAllColumnSources() Direct namespace access
Get unresolved columns Manual tracking resolver.getResult().getOrphanColumns(stmt) New capability
Get all table names Manual iteration resolver.getResult().getAllTableNames() New capability
Get resolution statistics N/A resolver.getStatistics() New capability

7.2 Deprecated Method Replacement Summary

Deprecated Method Direct Replacement
TTable.getLinkedColumns() IResolutionResult.getColumnsForTable(stmt, table)
TTable.getAttributes() INamespace.getAllColumnSources()
TCustomSqlStatement.getAttributes() Iterate through resolved columns via IResolutionResult
TObjectName.getSourceAttributeNode() TObjectName.getColumnSource()
TObjectName.getCandidateAttributeNodes() TObjectName.getColumnSource().getCandidateTables()
TResultColumn.getAttributesFromUpLevelReferenceToStarColumn() Integrated into TSQLResolver2's star column handling

8. Class Location Changes

Class Old Package (v3.x) New Package (v4)
TGetTableColumn demos.gettablecolumns gudusoft.gsqlparser.util

Update your import statements:

1
2
3
4
5
// Old import (v3.x)
import demos.gettablecolumns.TGetTableColumn;

// New import (v4)
import gudusoft.gsqlparser.util.TGetTableColumn;

9. Code Migration Examples

9.1 Example 1: Iterating Through Table Columns

Old Way (v3.x):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
TGSqlParser parser = new TGSqlParser(EDbVendor.dbvoracle);
parser.sqltext = "SELECT a.id, b.name FROM table_a a JOIN table_b b ON a.id = b.id";
parser.parse();

TCustomSqlStatement stmt = parser.sqlstatements.get(0);
for (int i = 0; i < stmt.tables.size(); i++) {
    TTable table = stmt.tables.getTable(i);
    System.out.println("Table: " + table.getName());

    // Old way - using deprecated getLinkedColumns()
    for (int j = 0; j < table.getLinkedColumns().size(); j++) {
        TObjectName col = table.getLinkedColumns().getObjectName(j);
        System.out.println("  Column: " + col.getColumnNameOnly());
    }
}

New Way (v4):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
TGSqlParser parser = new TGSqlParser(EDbVendor.dbvoracle);
parser.setResolverType(EResolverType.RESOLVER2);
parser.sqltext = "SELECT a.id, b.name FROM table_a a JOIN table_b b ON a.id = b.id";
parser.parse();

// Get resolution result
TSQLResolver2 resolver = parser.getResolver2();
IResolutionResult result = resolver.getResult();

TCustomSqlStatement stmt = parser.sqlstatements.get(0);
for (TTable table : result.getTables(stmt)) {
    System.out.println("Table: " + table.getFullName());

    for (TObjectName col : result.getColumnsForTable(stmt, table)) {
        System.out.println("  Column: " + col.getColumnNameOnly());

        // New: Access resolution details
        ColumnSource source = col.getColumnSource();
        if (source != null) {
            System.out.println("    Confidence: " + source.getConfidence());
            System.out.println("    Final Table: " + source.getFinalTable());
        }
    }
}

9.2 Example 2: Tracing Column Through Subquery

New Capability in v4:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// SQL: SELECT sub.col1 FROM (SELECT t.id AS col1 FROM my_table t) sub
TGSqlParser parser = new TGSqlParser(EDbVendor.dbvoracle);
parser.setResolverType(EResolverType.RESOLVER2);
parser.sqltext = "SELECT sub.col1 FROM (SELECT t.id AS col1 FROM my_table t) sub";
parser.parse();

// Find the column reference
TSelectSqlStatement selectStmt = (TSelectSqlStatement) parser.sqlstatements.get(0);
TResultColumn resultCol = selectStmt.getResultColumnList().getResultColumn(0);
TObjectName column = resultCol.getExpr().getObjectOperand();

ColumnSource source = column.getColumnSource();
if (source != null) {
    // Get immediate source (the subquery 'sub')
    TTable immediateSource = column.getSourceTable();
    System.out.println("Immediate source: " + immediateSource.getAliasName()); // "sub"

    // Get final physical table (my_table)
    TTable finalTable = source.getFinalTable();
    System.out.println("Final physical table: " + finalTable.getName()); // "my_table"

    // Get confidence score
    System.out.println("Confidence: " + source.getConfidence()); // 1.0
}

9.3 Example 3: Handling Ambiguous Columns

Old Way (v3.x):

1
2
3
4
5
TObjectName column = /* some ambiguous column */;
ArrayList<TColumnTableMatch> candidates = column.getCandidateAttributeNodes();
for (TColumnTableMatch match : candidates) {
    System.out.println("Candidate: " + match.getTable().getName());
}

New Way (v4):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
TObjectName column = /* some ambiguous column */;
ColumnSource source = column.getColumnSource();

if (source != null && source.isAmbiguous()) {
    System.out.println("Column is ambiguous!");
    List<TTable> candidates = source.getCandidateTables();
    for (TTable candidate : candidates) {
        System.out.println("Candidate: " + candidate.getName());
    }
}

9.4 Example 4: Using TGetTableColumn (Works with Both Resolvers)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import gudusoft.gsqlparser.util.TGetTableColumn;  // Note: new package location

// TGetTableColumn works seamlessly with both resolvers
TGetTableColumn gtc = new TGetTableColumn(EDbVendor.dbvoracle);

// Optional: Force specific resolver
gtc.setResolverType(EResolverType.RESOLVER2);

// Configure display options
gtc.showCTE = true;
gtc.showDatatype = true;
gtc.showColumnLocation = true;

gtc.runText("SELECT * FROM employees WHERE dept_id = 10");

// Output is consistent regardless of resolver used
System.out.println(gtc.getInfos().toString());

9.5 Example 5: Supporting Both Resolvers During Transition

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
TObjectName column = /* some column */;

// Check if new resolution is available
ResolutionResult resolution = column.getResolution();
if (resolution != null && resolution.isExactMatch()) {
    // Use new API
    ColumnSource source = resolution.getColumnSource();
    TTable finalTable = source.getFinalTable();
    double confidence = source.getConfidence();
    System.out.println("Final table: " + finalTable.getName() +
                       " (confidence: " + confidence + ")");
} else {
    // Fall back to old API
    TTable sourceTable = column.getSourceTable();
    if (sourceTable != null) {
        System.out.println("Source table: " + sourceTable.getName());
    }
}

10. Best Practices for Migration

10.1 Migration Strategy

Phase 1: Validation (Recommended Duration: 2-4 weeks) 1. Update dependency to GSP Java v4 2. Run existing code without modifications 3. Compare output with v3.x behavior 4. Document any differences

Phase 2: Testing (Recommended Duration: 2-4 weeks) 1. Create comprehensive tests comparing both resolvers 2. Enable debug logging: TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE = true 3. Test with your specific SQL patterns 4. Identify any behavioral changes

Phase 3: API Migration (Before 2026/12/31) 1. Update deprecated API calls to new APIs 2. Remove deprecation warnings 3. Leverage new capabilities where beneficial

10.2 Code Migration Recommendations

  1. Start with Backward Compatible APIs: Since TSQLResolver2 syncs data back to existing APIs, your existing code should work without changes. Verify this first.

  2. Gradual Migration: Start by testing with EResolverType.DEFAULT (uses TSQLResolver2), then gradually update code to use new APIs.

  3. Leverage New Capabilities: Take advantage of new features like getFinalTable() for data lineage and confidence scoring.

  4. Update Tests: Ensure your test suite covers both resolvers during the transition period.

  5. Monitor Deprecation Warnings: If your IDE shows deprecation warnings, prioritize updating those usages.

10.3 Configuration Recommendations

For Legacy Compatibility:

1
2
3
4
TSQLResolverConfig config = TSQLResolverConfig.createDefault();
config.setLegacyCompatibilityEnabled(true);  // Default
config.setLegacySyncMinConfidence(1.0);       // Only sync definite results
parser.setResolver2Config(config);

For New Code (No Legacy Dependencies):

1
2
3
TSQLResolverConfig config = TSQLResolverConfig.createStandalone();
// Disables legacy sync for better performance
parser.setResolver2Config(config);

For Vendor-Specific Behavior:

1
2
3
TSQLResolverConfig config = TSQLResolverConfig.createForVendor(EDbVendor.dbvoracle);
// Uses Oracle-specific name matching rules
parser.setResolver2Config(config);

11. Known Limitations and Considerations

11.1 SQL Syntax Coverage

Due to the significant refactoring, not all SQL syntax variations have been fully tested. If you encounter unexpected behavior:

  1. Enable debug logging: TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE = true
  2. Compare with old resolver: parser.setResolverType(EResolverType.RESOLVER)
  3. Report issues with reproducible SQL examples

11.2 Performance Considerations

TSQLResolver2 may have different performance characteristics:

  • Three-phase resolution: Scope building, initial resolution, iterative enhancement
  • Namespace hierarchy: More sophisticated but potentially slower
  • Iterative passes: Complex queries may require multiple passes

Optimization Tips: - Profile specific queries if performance is critical - Use TSQLResolverConfig.createStandalone() to disable legacy sync if not needed - Consider EResolverType.RESOLVER for specific performance-critical cases

11.3 Metadata Requirements

Some advanced resolution features require providing database metadata:

1
2
3
TSQLEnv sqlEnv = new TSQLEnv();
// Load table/column metadata
resolver.setSqlEnv(sqlEnv);

Without metadata, the resolver relies on inference which may have lower confidence.

11.4 Ambiguous Column Handling

TSQLResolver2 handles ambiguous columns differently:

  • TObjectName.getSourceTable() returns null for ambiguous columns (except star columns)
  • Use ColumnSource.isAmbiguous() to check
  • Use ColumnSource.getCandidateTables() to get all possibilities

11.5 Star Column Special Cases

Star columns (SELECT *) receive special handling:

  • getSourceTable() preserves Phase 1 resolution for star columns
  • Use resolver's star column expansion for detailed tracking
  • ColumnSource.getAllFinalTables() returns all contributing tables

12. Troubleshooting

12.1 Common Issues and Solutions

Issue Possible Cause Solution
Column resolution differs from v3.x TSQLResolver2 resolves ambiguous cases differently Review resolution via getEvidence(), provide metadata via TSQLEnv
Missing table/column relationships Star column expansion handling changed Enable showCTE option, verify subquery handling
Performance regression TSQLResolver2 architecture overhead Profile specific queries, consider resolver switching
Deprecation warnings Using deprecated APIs Update to new APIs per migration table
getSourceTable() returns null Column is ambiguous in RESOLVER2 Check isAmbiguous(), use getCandidateTables()
Class not found: TGetTableColumn Package location changed Update import to gudusoft.gsqlparser.util.TGetTableColumn

12.2 Debug Logging

Enable detailed resolution logging:

1
TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE = true;

This outputs: - Scope tree construction - Column resolution attempts - Namespace lookups - Star column expansion - Iterative pass progress

12.3 Comparing Resolvers

To compare output between resolvers:

1
2
3
4
5
6
7
8
9
// Test with RESOLVER2
parser.setResolverType(EResolverType.RESOLVER2);
parser.parse();
// ... capture output ...

// Reset and test with RESOLVER
parser.setResolverType(EResolverType.RESOLVER);
parser.parse();
// ... compare output ...

13. Support and Resources

13.1 Documentation

  • API Reference: See JavaDoc for gudusoft.gsqlparser.resolver2 package
  • Developer Guide: resolver2/TSQLResolver2_Developer_Guide.md

13.2 Reporting Issues

When reporting issues, please include: 1. GSP Java version 2. Database vendor (EDbVendor) 3. SQL statement causing the issue 4. Expected vs actual behavior 5. Debug log output if available

13.3 Version Compatibility

GSP Java Version Default Resolver TSQLResolver2 Status
v3.x TSQLResolver Not available
v4.0 TSQLResolver2 Production (with testing)

13.4 Deprecation Schedule

Date Event
v4.0 Release TSQLResolver2 becomes default
2026/12/31 Deprecated APIs removed

Appendix A: Complete New API Package Structure

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
gudusoft.gsqlparser.resolver2/
├── TSQLResolver2.java              # Main resolver entry point
├── TSQLResolverConfig.java         # Configuration options
├── TSQLResolver2ResultFormatter.java # Output formatting
├── ScopeBuilder.java               # Builds scope tree
├── NameResolver.java               # Resolves column names
├── ScopeBuildResult.java           # Scope building result
├── model/
│   ├── ColumnSource.java           # Column resolution details
│   ├── ResolutionResult.java       # Resolution outcome container
│   └── AmbiguousColumnSource.java  # Ambiguous resolution details
├── result/
│   ├── IResolutionResult.java      # Statement-level result interface
│   └── ResolutionResultImpl.java   # Default implementation
├── scope/
│   ├── GlobalScope.java
│   ├── SelectScope.java
│   ├── FromScope.java
│   └── ... other scope types
└── namespace/
    ├── TableNamespace.java
    ├── SubqueryNamespace.java
    ├── CTENamespace.java
    └── ... other namespace types

Appendix B: Quick Reference Card

Resolver Configuration

1
2
3
4
5
6
7
8
// Global level
TBaseType.setEnableResolver2(true);   // Enable RESOLVER2
TBaseType.setEnableResolver(true);    // Enable RESOLVER (legacy)

// Parser level
parser.setResolverType(EResolverType.RESOLVER2);  // Force RESOLVER2
parser.setResolverType(EResolverType.RESOLVER);   // Force RESOLVER
parser.setResolverType(EResolverType.DEFAULT);    // Use global setting

Key New APIs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// Get resolution result
ResolutionResult result = column.getResolution();
ColumnSource source = column.getColumnSource();

// Key ColumnSource methods
source.getFinalTable()          // Physical table after tracing
source.getAllFinalTables()      // All tables (for UNION)
source.getConfidence()          // Resolution confidence [0.0, 1.0]
source.getEvidence()            // Why this resolution
source.isAmbiguous()            // Is ambiguous?
source.getCandidateTables()     // Candidate tables

Deprecated API Quick Migration

Old New
table.getLinkedColumns() result.getColumnsForTable(stmt, table)
table.getAttributes() namespace.getAllColumnSources()
column.getSourceAttributeNode() column.getColumnSource()
column.getCandidateAttributeNodes() source.getCandidateTables()

This migration guide is maintained by the GSP Java team. For the latest updates, refer to the official documentation.