Skip to content

Commit 67ddeed

Browse files
fix sql parsing problem (#919)
* fix parsing error * fix parsing problem * fix lint problem * fix statistic sql for plan data * use string to pass planhash
1 parent 0e31344 commit 67ddeed

6 files changed

Lines changed: 66 additions & 23 deletions

File tree

internal/dashboard/model/sql/plan_info.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ type PlanIdentity struct {
2929

3030
type PlanMeta struct {
3131
PlanIdentity `json:",inline"`
32-
PlanHash uint64 `json:"planHash" binding:"required"`
32+
PlanHash uint64 `json:"planHash,string" binding:"required"`
3333
GeneratedTime int64 `json:"generatedTime" binding:"required"`
3434
}
3535

internal/sql-analyzer/analyzer/manager.go

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func (m *Manager) Analyze(sql string, indexes []model.IndexInfo) []model.SqlDiag
6969

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

7474
// Parse the SQL (assuming 'Sql_stmt' is the entry point rule)
7575
parseStart := time.Now()
@@ -78,11 +78,16 @@ func (m *Manager) Analyze(sql string, indexes []model.IndexInfo) []model.SqlDiag
7878
defer func() {
7979
if r := recover(); r != nil {
8080
// Fallback to LL prediction mode
81-
stream.Seek(0)
82-
p.SetTokenStream(stream)
83-
p.GetInterpreter().SetPredictionMode(antlr.PredictionModeLL)
84-
p.SetErrorHandler(antlr.NewDefaultErrorStrategy())
85-
tree = p.Sql_stmt()
81+
// Recreate the entire stack to ensure no state pollution
82+
inputStream := antlr.NewInputStream(sql)
83+
lexer := obmysql.NewOBLexer(inputStream)
84+
stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)
85+
86+
p2 := obmysql.NewOBParser(stream)
87+
p2.RemoveErrorListeners()
88+
p2.GetInterpreter().SetPredictionMode(antlr.PredictionModeLL)
89+
p2.SetErrorHandler(antlr.NewDefaultErrorStrategy())
90+
tree = p2.Sql_stmt()
8691
}
8792
}()
8893
tree = p.Sql_stmt()
@@ -113,3 +118,19 @@ func (m *Manager) Analyze(sql string, indexes []model.IndexInfo) []model.SqlDiag
113118

114119
return diagnostics
115120
}
121+
122+
type CustomBailErrorStrategy struct {
123+
*antlr.BailErrorStrategy
124+
}
125+
126+
func NewCustomBailErrorStrategy() *CustomBailErrorStrategy {
127+
return &CustomBailErrorStrategy{
128+
BailErrorStrategy: antlr.NewBailErrorStrategy(),
129+
}
130+
}
131+
132+
func (s *CustomBailErrorStrategy) ReportError(_ antlr.Parser, _ antlr.RecognitionException) {
133+
// Avoid calling DefaultErrorStrategy.ReportError which might panic with "implement me"
134+
// Instead, explicitly bail out with ParseCancellationException, which is what BailErrorStrategy intends.
135+
panic(antlr.NewParseCancellationException())
136+
}

internal/sql-analyzer/api/model/sql_detail.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ type PlanStats struct {
3535
SvrIP string `json:"svrIp"`
3636
SvrPort int64 `json:"svrPort"`
3737
PlanID int64 `json:"planId"`
38-
PlanHash uint64 `json:"planHash"`
38+
PlanHash uint64 `json:"planHash,string"`
3939
GeneratedTime int64 `json:"generatedTime"`
4040
IoCost int64 `json:"ioCost"`
4141
CpuCost int64 `json:"cpuCost"`

internal/sql-analyzer/const/sql/sql_plan.go

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -97,20 +97,42 @@ const (
9797
FROM sql_plan
9898
WHERE SQL_ID = ?
9999
GROUP BY TENANT_ID, SVR_IP, SVR_PORT, PLAN_ID, PLAN_HASH
100+
),
101+
PlanStats AS (
102+
SELECT
103+
PLAN_HASH,
104+
CAST(AVG(IO_COST) AS BIGINT) as IO_COST,
105+
CAST(AVG(CPU_COST) AS BIGINT) as CPU_COST,
106+
CAST(AVG(COST) AS BIGINT) as COST,
107+
CAST(AVG(REAL_COST) AS BIGINT) as REAL_COST
108+
FROM PlanAgg
109+
GROUP BY PLAN_HASH
110+
),
111+
LatestPlan AS (
112+
SELECT
113+
TENANT_ID,
114+
SVR_IP,
115+
SVR_PORT,
116+
PLAN_ID,
117+
PLAN_HASH,
118+
GMT_CREATE,
119+
ROW_NUMBER() OVER (PARTITION BY PLAN_HASH ORDER BY GMT_CREATE DESC, PLAN_ID DESC) as rn
120+
FROM PlanAgg
100121
)
101122
SELECT
102-
MAX(TENANT_ID) as TENANT_ID,
103-
MAX(SVR_IP) as SVR_IP,
104-
MAX(SVR_PORT) as SVR_PORT,
105-
MAX(PLAN_ID) as PLAN_ID,
106-
PLAN_HASH,
107-
MAX(GMT_CREATE) as GMT_CREATE,
108-
CAST(AVG(IO_COST) AS BIGINT) as IO_COST,
109-
CAST(AVG(CPU_COST) AS BIGINT) as CPU_COST,
110-
CAST(AVG(COST) AS BIGINT) as COST,
111-
CAST(AVG(REAL_COST) AS BIGINT) as REAL_COST
112-
FROM PlanAgg
113-
GROUP BY PLAN_HASH
123+
lp.TENANT_ID,
124+
lp.SVR_IP,
125+
lp.SVR_PORT,
126+
lp.PLAN_ID,
127+
lp.PLAN_HASH,
128+
lp.GMT_CREATE,
129+
ps.IO_COST,
130+
ps.CPU_COST,
131+
ps.COST,
132+
ps.REAL_COST
133+
FROM LatestPlan lp
134+
JOIN PlanStats ps ON lp.PLAN_HASH = ps.PLAN_HASH
135+
WHERE lp.rn = 1
114136
`
115137
GetTableInfo = `
116138
SELECT

ui/src/api/generated/api.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7886,7 +7886,7 @@ export interface SqlPlanDetail {
78867886
* @type {number}
78877887
* @memberof SqlPlanDetail
78887888
*/
7889-
'planHash': number;
7889+
'planHash': string;
78907890
/**
78917891
*
78927892
* @type {number}
@@ -8033,7 +8033,7 @@ export interface SqlPlanStatistic {
80338033
* @type {number}
80348034
* @memberof SqlPlanStatistic
80358035
*/
8036-
'planHash': number;
8036+
'planHash': string;
80378037
/**
80388038
*
80398039
* @type {number}

ui/src/type/sql.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ declare namespace API {
111111
}
112112

113113
export interface PlanMeta extends PlanIdentity {
114-
planHash: number;
114+
planHash: string;
115115
generatedTime: number;
116116
}
117117

0 commit comments

Comments
 (0)