Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support the tck format for the output of EXPLAIN #265

Merged
merged 26 commits into from
Apr 3, 2023
Merged
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
139 changes: 94 additions & 45 deletions result_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -1252,6 +1252,65 @@ func (res ResultSet) MakeDotGraphByStruct() string {
return builder.String()
}

// generate profiling data for both Row and TCK formats.
func MakeProfilingData(planNodeDesc *graph.PlanNodeDescription, isTckFmt bool) string {
var profileArr []string
for i, profile := range planNodeDesc.GetProfiles() {
var statArr []string
statArr = append(statArr, fmt.Sprintf("\"version\":%d", i))
statArr = append(statArr, fmt.Sprintf("\"rows\":%d", profile.GetRows()))
if !isTckFmt {
// tck format doesn't need these fields
statArr = append(statArr, fmt.Sprintf("\"execTime\":\"%d(us)\"", profile.GetExecDurationInUs()))
statArr = append(statArr, fmt.Sprintf("\"totalTime\":\"%d(us)\"", profile.GetTotalDurationInUs()))
}
for k, v := range profile.GetOtherStats() {
s := string(v)
if matched, err := regexp.Match(`^[^{(\[]\w+`, v); err == nil && matched {
if !strings.HasPrefix(s, "\"") {
s = fmt.Sprintf("\"%s", s)
}
if !strings.HasSuffix(s, "\"") {
s = fmt.Sprintf("%s\"", s)
}
}
statArr = append(statArr, fmt.Sprintf("\"%s\": %s", k, s))
}
sort.Strings(statArr)
statStr := fmt.Sprintf("{%s}", strings.Join(statArr, ",\n"))
profileArr = append(profileArr, statStr)
}
allProfiles := strings.Join(profileArr, ",\n")
if len(profileArr) > 1 {
allProfiles = fmt.Sprintf("[%s]", allProfiles)
}
var buffer bytes.Buffer
json.Indent(&buffer, []byte(allProfiles), "", " ")
return string(buffer.Bytes())
}

// generate operator info for Row format.
func MakeOperatorInfo(planNodeDesc *graph.PlanNodeDescription) string {
var columnInfo []string
if planNodeDesc.IsSetBranchInfo() {
branchInfo := planNodeDesc.GetBranchInfo()
columnInfo = append(columnInfo, fmt.Sprintf("branch: %t, nodeId: %d\n",
branchInfo.GetIsDoBranch(), branchInfo.GetConditionNodeID()))
}

outputVar := fmt.Sprintf("outputVar: %s", prettyFormatJsonString(planNodeDesc.GetOutputVar()))
columnInfo = append(columnInfo, outputVar)

if planNodeDesc.IsSetDescription() {
desc := planNodeDesc.GetDescription()
for _, pair := range desc {
value := prettyFormatJsonString(pair.GetValue())
columnInfo = append(columnInfo, fmt.Sprintf("%s: %s", string(pair.GetKey()), value))
}
}
return strings.Join(columnInfo, "\n")
}

// explain/profile format="row"
func (res ResultSet) MakePlanByRow() [][]interface{} {
p := res.GetPlanDesc()
Expand All @@ -1272,58 +1331,48 @@ func (res ResultSet) MakePlanByRow() [][]interface{} {
}

if planNodeDesc.IsSetProfiles() {
var profileArr []string
for i, profile := range planNodeDesc.GetProfiles() {
var statArr []string
statArr = append(statArr, fmt.Sprintf("\"version\":%d", i))
statArr = append(statArr, fmt.Sprintf("\"rows\":%d", profile.GetRows()))
statArr = append(statArr, fmt.Sprintf("\"execTime\":\"%d(us)\"", profile.GetExecDurationInUs()))
statArr = append(statArr, fmt.Sprintf("\"totalTime\":\"%d(us)\"", profile.GetTotalDurationInUs()))
for k, v := range profile.GetOtherStats() {
s := string(v)
if matched, err := regexp.Match(`^[^{(\[]\w+`, v); err == nil && matched {
if !strings.HasPrefix(s, "\"") {
s = fmt.Sprintf("\"%s", s)
}
if !strings.HasSuffix(s, "\"") {
s = fmt.Sprintf("%s\"", s)
}
}
statArr = append(statArr, fmt.Sprintf("\"%s\": %s", k, s))
}
sort.Strings(statArr)
statStr := fmt.Sprintf("{%s}", strings.Join(statArr, ",\n"))
profileArr = append(profileArr, statStr)
}
allProfiles := strings.Join(profileArr, ",\n")
if len(profileArr) > 1 {
allProfiles = fmt.Sprintf("[%s]", allProfiles)
}
var buffer bytes.Buffer
json.Indent(&buffer, []byte(allProfiles), "", " ")
row = append(row, string(buffer.Bytes()))
row = append(row, MakeProfilingData(planNodeDesc, false))
} else {
row = append(row, "")
}
aaa := MakeOperatorInfo(planNodeDesc)
fmt.Println(aaa)
row = append(row, aaa)
rows = append(rows, row)
}
return rows
}

var columnInfo []string
if planNodeDesc.IsSetBranchInfo() {
branchInfo := planNodeDesc.GetBranchInfo()
columnInfo = append(columnInfo, fmt.Sprintf("branch: %t, nodeId: %d\n",
branchInfo.GetIsDoBranch(), branchInfo.GetConditionNodeID()))
}

outputVar := fmt.Sprintf("outputVar: %s", prettyFormatJsonString(planNodeDesc.GetOutputVar()))
columnInfo = append(columnInfo, outputVar)
// explain/profile format="tck"
func (res ResultSet) MakePlanByTck() [][]interface{} {
p := res.GetPlanDesc()
planNodeDescs := p.GetPlanNodeDescs()
var rows [][]interface{}
for _, planNodeDesc := range planNodeDescs {
var row []interface{}
row = append(row, planNodeDesc.GetId(), string(planNodeDesc.GetName()))

if planNodeDesc.IsSetDescription() {
desc := planNodeDesc.GetDescription()
for _, pair := range desc {
value := prettyFormatJsonString(pair.GetValue())
columnInfo = append(columnInfo, fmt.Sprintf("%s: %s", string(pair.GetKey()), value))
if planNodeDesc.IsSetDependencies() {
var deps []string
for _, dep := range planNodeDesc.GetDependencies() {
deps = append(deps, fmt.Sprintf("%d", dep))
}
row = append(row, strings.Join(deps, ","))
} else {
row = append(row, "")
}
row = append(row, strings.Join(columnInfo, "\n"))

if planNodeDesc.IsSetProfiles() {
var compactProfilingData bytes.Buffer
// compress JSON data and remove whitespace characters
json.Compact(&compactProfilingData, []byte(MakeProfilingData(planNodeDesc, true)))
row = append(row, compactProfilingData.String())
} else {
row = append(row, "")
}
// append operator info
row = append(row, "")

rows = append(rows, row)
}
return rows
Expand Down