Merge branch 'tencentmusic:master' into master

This commit is contained in:
beat4ocean
2025-03-14 09:56:00 +08:00
committed by GitHub
4 changed files with 46 additions and 19 deletions

View File

@@ -170,6 +170,9 @@ public class QueryStructReq extends SemanticQueryReq {
// 5. Set the limit clause
plainSelect.setLimit(buildLimit(queryStructReq));
// 6. Set having clause
plainSelect.setHaving(buildHavingClause(queryStructReq));
select.setSelect(plainSelect);
// 6. Set where clause
@@ -239,7 +242,8 @@ public class QueryStructReq extends SemanticQueryReq {
private GroupByElement buildGroupByElement(QueryStructReq queryStructReq) {
List<String> groups = queryStructReq.getGroups();
if (!CollectionUtils.isEmpty(groups) && !queryStructReq.getAggregators().isEmpty()) {
if ((!CollectionUtils.isEmpty(groups) && !queryStructReq.getAggregators().isEmpty())
|| !queryStructReq.getMetricFilters().isEmpty()) {
GroupByElement groupByElement = new GroupByElement();
for (String group : groups) {
groupByElement.addGroupByExpression(new Column(group));
@@ -289,4 +293,23 @@ public class QueryStructReq extends SemanticQueryReq {
}
return Constants.TABLE_PREFIX + StringUtils.join(modelIds, "_");
}
public Expression buildHavingClause(QueryStructReq queryStructReq) {
if (queryStructReq.getMetricFilters().isEmpty()) {
return null;
}
List<Filter> filters = queryStructReq.getMetricFilters();
SqlFilterUtils sqlFilterUtils = ContextUtils.getBean(SqlFilterUtils.class);
String havingClause = sqlFilterUtils.getWhereClause(filters, false);
if (StringUtils.isNotBlank(havingClause)) {
try {
return CCJSqlParserUtil.parseCondExpression(havingClause);
} catch (JSQLParserException e) {
log.error("Failed to parse having clause", e);
}
}
return null;
}
}

View File

@@ -34,6 +34,18 @@ public class SqlVariableParseUtilsTest {
Assertions.assertEquals(expectedSql, actualSql);
}
@Test
void testParseSql_if() {
String sql = "select * from t_$interval$ where id = $id$ $if(name)$and name = $name$$endif$";
List<SqlVariable> variables = Lists.newArrayList(mockNumSqlVariable(),
mockExprSqlVariable(), mockStrSqlVariable());
List<Param> params =
Lists.newArrayList(mockIdParam(), mockNameParam(), mockIntervalParam());
String actualSql = SqlVariableParseUtils.parse(sql, variables, params);
String expectedSql = "select * from t_wk where id = 2 and name = 'alice'";
Assertions.assertEquals(expectedSql, actualSql);
}
private SqlVariable mockNumSqlVariable() {
return mockSqlVariable("id", VariableValueType.NUMBER, 1);
}

View File

@@ -18,7 +18,7 @@ import { isFunction } from 'lodash';
import FullScreen from '@/components/FullScreen';
import SqlEditor from '@/components/SqlEditor';
import type { TaskResultItem, TaskResultColumn } from '../data';
import { executeSql, listColumnsBySql } from '@/pages/SemanticModel/service';
import { executeSql } from '@/pages/SemanticModel/service';
import SqlParams from './SqlParams';
import styles from '../style.less';
@@ -248,19 +248,12 @@ const SqlDetail: React.FC<IProps> = ({
id: currentDatabaseItem.key,
sqlVariables: sqlParams,
});
const { code: getColumnCode, data: getColumnData } = await listColumnsBySql({
sql: value,
databaseId: currentDatabaseItem.key,
});
setResultTableLoading(false);
if (code === 200 && getColumnCode === 200) {
const columnData = getColumnData.map((item) => {
if (code === 200) {
const columnData = (data.columns || []).map((item: any) => {
return {
...item,
nameEn: item.columnName,
type: item.dataType,
columnName: item.nameEn,
};
});
fetchTaskResult(data, columnData);

View File

@@ -373,12 +373,6 @@ export async function executeSql(params: ExcuteSqlParams) {
return request.post(`${process.env.API_BASE_URL}database/executeSql`, { data });
}
export async function listColumnsBySql(data: { databaseId: number; sql: string }) {
return request.post(`${process.env.API_BASE_URL}database/listColumnsBySql`, {
data,
});
}
export function getCatalogs(dbId: number): Promise<any> {
return request(`${process.env.API_BASE_URL}database/getCatalogs`, {
method: 'GET',
@@ -409,7 +403,12 @@ export function getTables(databaseId: number, catalog: string, dbName: string):
});
}
export function getColumns(databaseId: number, catalog: string, dbName: string, tableName: string): Promise<any> {
export function getColumns(
databaseId: number,
catalog: string,
dbName: string,
tableName: string,
): Promise<any> {
return request(`${process.env.API_BASE_URL}database/getColumnsByName`, {
method: 'GET',
params: {