Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion internal/dashboard/model/sql/plan_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ type PlanIdentity struct {

type PlanMeta struct {
PlanIdentity `json:",inline"`
PlanHash uint64 `json:"planHash" binding:"required"`
PlanHash uint64 `json:"planHash,string" binding:"required"`
GeneratedTime int64 `json:"generatedTime" binding:"required"`
}

Expand Down
33 changes: 27 additions & 6 deletions internal/sql-analyzer/analyzer/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func (m *Manager) Analyze(sql string, indexes []model.IndexInfo) []model.SqlDiag

// Use SLL prediction mode for better performance, fallback to LL if it fails
p.GetInterpreter().SetPredictionMode(antlr.PredictionModeSLL)
p.SetErrorHandler(antlr.NewBailErrorStrategy())
p.SetErrorHandler(NewCustomBailErrorStrategy())

// Parse the SQL (assuming 'Sql_stmt' is the entry point rule)
parseStart := time.Now()
Expand All @@ -78,11 +78,16 @@ func (m *Manager) Analyze(sql string, indexes []model.IndexInfo) []model.SqlDiag
defer func() {
if r := recover(); r != nil {
// Fallback to LL prediction mode
stream.Seek(0)
p.SetTokenStream(stream)
p.GetInterpreter().SetPredictionMode(antlr.PredictionModeLL)
p.SetErrorHandler(antlr.NewDefaultErrorStrategy())
tree = p.Sql_stmt()
// Recreate the entire stack to ensure no state pollution
inputStream := antlr.NewInputStream(sql)
lexer := obmysql.NewOBLexer(inputStream)
stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)

p2 := obmysql.NewOBParser(stream)
p2.RemoveErrorListeners()
p2.GetInterpreter().SetPredictionMode(antlr.PredictionModeLL)
p2.SetErrorHandler(antlr.NewDefaultErrorStrategy())
tree = p2.Sql_stmt()
}
}()
tree = p.Sql_stmt()
Expand Down Expand Up @@ -113,3 +118,19 @@ func (m *Manager) Analyze(sql string, indexes []model.IndexInfo) []model.SqlDiag

return diagnostics
}

type CustomBailErrorStrategy struct {
*antlr.BailErrorStrategy
}

func NewCustomBailErrorStrategy() *CustomBailErrorStrategy {
return &CustomBailErrorStrategy{
BailErrorStrategy: antlr.NewBailErrorStrategy(),
}
}

func (s *CustomBailErrorStrategy) ReportError(_ antlr.Parser, _ antlr.RecognitionException) {
// Avoid calling DefaultErrorStrategy.ReportError which might panic with "implement me"
// Instead, explicitly bail out with ParseCancellationException, which is what BailErrorStrategy intends.
panic(antlr.NewParseCancellationException())
}
2 changes: 1 addition & 1 deletion internal/sql-analyzer/api/model/sql_detail.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type PlanStats struct {
SvrIP string `json:"svrIp"`
SvrPort int64 `json:"svrPort"`
PlanID int64 `json:"planId"`
PlanHash uint64 `json:"planHash"`
PlanHash uint64 `json:"planHash,string"`
GeneratedTime int64 `json:"generatedTime"`
IoCost int64 `json:"ioCost"`
CpuCost int64 `json:"cpuCost"`
Expand Down
46 changes: 34 additions & 12 deletions internal/sql-analyzer/const/sql/sql_plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,20 +97,42 @@ const (
FROM sql_plan
WHERE SQL_ID = ?
GROUP BY TENANT_ID, SVR_IP, SVR_PORT, PLAN_ID, PLAN_HASH
),
PlanStats AS (
SELECT
PLAN_HASH,
CAST(AVG(IO_COST) AS BIGINT) as IO_COST,
CAST(AVG(CPU_COST) AS BIGINT) as CPU_COST,
CAST(AVG(COST) AS BIGINT) as COST,
CAST(AVG(REAL_COST) AS BIGINT) as REAL_COST
FROM PlanAgg
GROUP BY PLAN_HASH
),
LatestPlan AS (
SELECT
TENANT_ID,
SVR_IP,
SVR_PORT,
PLAN_ID,
PLAN_HASH,
GMT_CREATE,
ROW_NUMBER() OVER (PARTITION BY PLAN_HASH ORDER BY GMT_CREATE DESC, PLAN_ID DESC) as rn
FROM PlanAgg
)
SELECT
MAX(TENANT_ID) as TENANT_ID,
MAX(SVR_IP) as SVR_IP,
MAX(SVR_PORT) as SVR_PORT,
MAX(PLAN_ID) as PLAN_ID,
PLAN_HASH,
MAX(GMT_CREATE) as GMT_CREATE,
CAST(AVG(IO_COST) AS BIGINT) as IO_COST,
CAST(AVG(CPU_COST) AS BIGINT) as CPU_COST,
CAST(AVG(COST) AS BIGINT) as COST,
CAST(AVG(REAL_COST) AS BIGINT) as REAL_COST
FROM PlanAgg
GROUP BY PLAN_HASH
lp.TENANT_ID,
lp.SVR_IP,
lp.SVR_PORT,
lp.PLAN_ID,
lp.PLAN_HASH,
lp.GMT_CREATE,
ps.IO_COST,
ps.CPU_COST,
ps.COST,
ps.REAL_COST
FROM LatestPlan lp
JOIN PlanStats ps ON lp.PLAN_HASH = ps.PLAN_HASH
WHERE lp.rn = 1
`
GetTableInfo = `
SELECT
Expand Down
4 changes: 2 additions & 2 deletions ui/src/api/generated/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7886,7 +7886,7 @@ export interface SqlPlanDetail {
* @type {number}
* @memberof SqlPlanDetail
*/
'planHash': number;
'planHash': string;
/**
*
* @type {number}
Expand Down Expand Up @@ -8033,7 +8033,7 @@ export interface SqlPlanStatistic {
* @type {number}
* @memberof SqlPlanStatistic
*/
'planHash': number;
'planHash': string;
/**
*
* @type {number}
Expand Down
2 changes: 1 addition & 1 deletion ui/src/type/sql.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ declare namespace API {
}

export interface PlanMeta extends PlanIdentity {
planHash: number;
planHash: string;
generatedTime: number;
}

Expand Down