blob: d59bfb714a601e7035c4a1440f3e6d5b0836bee3 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
import org.apache.doris.regression.suite.Suite
def anlyzedPlanShowFields = [
LogicalProject : ['projects'],
LogicalSort : ['orderKeys'],
LogicalFilter : ['predicates'],
LogicalHaving : ['predicates'],
LogicalQualify : ['predicates'],
LogicalAggregate : ['groupByExpr', 'outputExpr'],
LogicalOlapScan : ['qualified'],
LogicalResultSink : ['outputExprs'],
LogicalJoin : ['type', 'markJoinSlotReference', 'hashJoinConjuncts', 'otherJoinConjuncts', 'markJoinConjuncts'],
]
def extractAttributes(String input) {
// 正则解释:
// (\w+) - 匹配key
// = - 等号
// (.+?) - 非贪婪匹配value(任意字符)
// (?= - 正向向前查找
// \s*,\s*\w+= - 后面是逗号+空格+下一个key=
// | - 或
// \s*\) - 后面是空格+右括号
// | - 或
// $ - 字符串结束
// )
// def pattern = /(\w+)=(.+?)(?=\s*,\s*\w+=|\s*\)|$)/
def pattern = /(\w+)=(.+?)(?=\s*,\s*\w+=|\s\)|$)/
def matcher = input =~ pattern
def result = [:]
matcher.each { match ->
result[match[1]] = match[2].trim()
}
return result
}
def convertPlanRow = { row, showFieldMap ->
def cell = row[0]
def s = ""
for (def line : cell.split("\n")) {
if (!s.isEmpty()) {
s += "\n"
}
def p1 = line.findIndexOf { Character.isLetter(it as char) }
if (p1 == -1) {
s += line
continue
}
def p2 = p1 + line.substring(p1).findIndexOf { !Character.isLetter(it as char) }
if (p2 < p1) {
s += line
continue
}
def planName = line.substring(p1, p2)
def showFields = showFieldMap.getOrDefault(planName, [])
s += line.substring(0, p2)
s += " ( "
def showAttrs = []
def attrs = extractAttributes(line)
for (def field : showFields) {
if (attrs.containsKey(field)) {
showAttrs.add("${field}=${attrs[field]}".toString())
}
}
s += showAttrs.join(", ")
s += " )"
}
return [s]
}
Suite.metaClass.explainAndResult = { String tag, String sql ->
"qt_${tag}_shape" "explain shape plan ${sql}"
"qt_${tag}_result" "${sql}"
}
Suite.metaClass.explainAndOrderResult = { String tag, String sql ->
"qt_${tag}_shape" "explain shape plan ${sql}"
"order_qt_${tag}_result" "${sql}"
}
Suite.metaClass.explainAnalyzedPlan = { String tag, String sql, overwriteShowFields = [:] ->
def showFields = anlyzedPlanShowFields
if (!overwriteShowFields.isEmpty()) {
showFields = [:]
showFields.putAll(anlyzedPlanShowFields)
showFields.putAll(overwriteShowFields)
}
delegate.quickRunTest(
tag,
"explain analyzed plan ${sql}".toString(),
false,
{row -> convertPlanRow(row, showFields) }
)
}