6 Commits

10 changed files with 75 additions and 53 deletions

View File

@@ -24,6 +24,8 @@ public class ModelDetail {
private String tableQuery; private String tableQuery;
private String filterSql;
private List<Identify> identifiers = Lists.newArrayList(); private List<Identify> identifiers = Lists.newArrayList();
private List<Dimension> dimensions = Lists.newArrayList(); private List<Dimension> dimensions = Lists.newArrayList();

View File

@@ -19,6 +19,8 @@ public class ModelBuildReq {
private String sql; private String sql;
private String filterSql;
private String catalog; private String catalog;
private String db; private String db;

View File

@@ -50,19 +50,19 @@ public class SqlQueryParser implements QueryParser {
queryFields.removeAll(queryAliases); queryFields.removeAll(queryAliases);
Ontology ontology = queryStatement.getOntology(); Ontology ontology = queryStatement.getOntology();
OntologyQuery ontologyQuery = buildOntologyQuery(ontology, queryFields); OntologyQuery ontologyQuery = buildOntologyQuery(ontology, queryFields);
// check if there are fields not matched with any metric or dimension // // check if there are fields not matched with any metric or dimension
if (queryFields.size() > ontologyQuery.getMetrics().size() // if (queryFields.size() > ontologyQuery.getMetrics().size()
+ ontologyQuery.getDimensions().size()) { // + ontologyQuery.getDimensions().size()) {
List<String> semanticFields = Lists.newArrayList(); // List<String> semanticFields = Lists.newArrayList();
ontologyQuery.getMetrics().forEach(m -> semanticFields.add(m.getName())); // ontologyQuery.getMetrics().forEach(m -> semanticFields.add(m.getName()));
ontologyQuery.getDimensions().forEach(d -> semanticFields.add(d.getName())); // ontologyQuery.getDimensions().forEach(d -> semanticFields.add(d.getName()));
String errMsg = // String errMsg =
String.format("Querying columns[%s] not matched with semantic fields[%s].", // String.format("Querying columns[%s] not matched with semantic fields[%s].",
queryFields, semanticFields); // queryFields, semanticFields);
queryStatement.setErrMsg(errMsg); // queryStatement.setErrMsg(errMsg);
queryStatement.setStatus(QueryState.INVALID); // queryStatement.setStatus(QueryState.INVALID);
return; // return;
} // }
queryStatement.setOntologyQuery(ontologyQuery); queryStatement.setOntologyQuery(ontologyQuery);
AggOption sqlQueryAggOption = getAggOption(sqlQuery.getSql(), ontologyQuery.getMetrics()); AggOption sqlQueryAggOption = getAggOption(sqlQuery.getSql(), ontologyQuery.getMetrics());

View File

@@ -40,11 +40,23 @@ public class DataModelNode extends SemanticNode {
.equalsIgnoreCase(EngineType.POSTGRESQL.getName())) { .equalsIgnoreCase(EngineType.POSTGRESQL.getName())) {
String fullTableName = String.join(".public.", String fullTableName = String.join(".public.",
dataModel.getModelDetail().getTableQuery().split("\\.")); dataModel.getModelDetail().getTableQuery().split("\\."));
sqlTable = "select * from " + fullTableName; sqlTable = "SELECT * FROM " + fullTableName;
} else { } else {
sqlTable = "select * from " + dataModel.getModelDetail().getTableQuery(); sqlTable = "SELECT * FROM " + dataModel.getModelDetail().getTableQuery();
} }
} }
// String filterSql = dataModel.getFilterSql();
String filterSql = dataModel.getModelDetail().getFilterSql();
if (filterSql != null && !filterSql.isEmpty()) {
boolean sqlContainWhere = sqlTable.toUpperCase().matches("(?s).*\\bWHERE\\b.*");
if (sqlContainWhere) {
sqlTable = String.format("%s AND %s", sqlTable, filterSql);
} else {
sqlTable = String.format("%s WHERE %s", sqlTable, filterSql);
}
}
if (sqlTable.isEmpty()) { if (sqlTable.isEmpty()) {
throw new Exception("DataModelNode build error [tableSqlNode not found]"); throw new Exception("DataModelNode build error [tableSqlNode not found]");
} }

View File

@@ -36,6 +36,7 @@ public class ModelYamlManager {
} else { } else {
dataModelYamlTpl.setTableQuery(modelDetail.getTableQuery()); dataModelYamlTpl.setTableQuery(modelDetail.getTableQuery());
} }
dataModelYamlTpl.setFilterSql(modelDetail.getFilterSql());
dataModelYamlTpl.setFields(modelResp.getModelDetail().getFields()); dataModelYamlTpl.setFields(modelResp.getModelDetail().getFields());
dataModelYamlTpl.setId(modelResp.getId()); dataModelYamlTpl.setId(modelResp.getId());
return dataModelYamlTpl; return dataModelYamlTpl;

View File

@@ -97,6 +97,7 @@ public class SemanticSchemaManager {
modelDetail.setDbType(d.getType()); modelDetail.setDbType(d.getType());
modelDetail.setSqlQuery(d.getSqlQuery()); modelDetail.setSqlQuery(d.getSqlQuery());
modelDetail.setTableQuery(d.getTableQuery()); modelDetail.setTableQuery(d.getTableQuery());
modelDetail.setFilterSql(d.getFilterSql());
modelDetail.getIdentifiers().addAll(getIdentify(d.getIdentifiers())); modelDetail.getIdentifiers().addAll(getIdentify(d.getIdentifiers()));
modelDetail.getMeasures().addAll(getMeasureParams(d.getMeasures())); modelDetail.getMeasures().addAll(getMeasureParams(d.getMeasures()));
modelDetail.getDimensions().addAll(getDimensions(d.getDimensions())); modelDetail.getDimensions().addAll(getDimensions(d.getDimensions()));

View File

@@ -21,6 +21,8 @@ public class DataModelYamlTpl {
private String tableQuery; private String tableQuery;
private String filterSql;
private List<IdentifyYamlTpl> identifiers; private List<IdentifyYamlTpl> identifiers;
private List<DimensionYamlTpl> dimensions; private List<DimensionYamlTpl> dimensions;

View File

@@ -157,6 +157,7 @@ public class ModelConverter {
modelDetail.setQueryType(ModelDefineType.TABLE_QUERY.getName()); modelDetail.setQueryType(ModelDefineType.TABLE_QUERY.getName());
modelDetail.setTableQuery(String.format("%s.%s", modelBuildReq.getDb(), tableName)); modelDetail.setTableQuery(String.format("%s.%s", modelBuildReq.getDb(), tableName));
} }
modelDetail.setFilterSql(modelBuildReq.getFilterSql());
for (ColumnSchema columnSchema : modelSchema.getColumnSchemas()) { for (ColumnSchema columnSchema : modelSchema.getColumnSchemas()) {
FieldType fieldType = columnSchema.getFiledType(); FieldType fieldType = columnSchema.getFiledType();
if (getIdentifyType(fieldType) != null) { if (getIdentifyType(fieldType) != null) {

View File

@@ -48,12 +48,13 @@ const MetricTrend: React.FC<Props> = ({
const { queryColumns, queryResults, aggregateInfo, entityInfo, chatContext } = data; const { queryColumns, queryResults, aggregateInfo, entityInfo, chatContext } = data;
const [chartType, setChartType] = useState('line'); const [chartType, setChartType] = useState('line');
const dateField: any = queryColumns?.find( const dateField = queryColumns?.find(
(column: any) => column.showType === 'DATE' || column.type === 'DATE' (column: any) => column.showType === 'DATE' || column.type === 'DATE'
); );
const dateColumnName = dateField?.bizName || ''; const dateColumnName = dateField?.bizName || '';
const categoryColumnName = let categoryColumnName =
queryColumns?.find((column: any) => column.showType === 'CATEGORY')?.bizName || ''; queryColumns?.find((column: any) => column.showType === 'CATEGORY')?.bizName || '';
categoryColumnName = categoryColumnName === dateColumnName ? '' : categoryColumnName;
const metricFields = queryColumns?.filter((column: any) => column.showType === 'NUMBER'); const metricFields = queryColumns?.filter((column: any) => column.showType === 'NUMBER');
const currentMetricField = queryColumns?.find((column: any) => column.showType === 'NUMBER'); const currentMetricField = queryColumns?.find((column: any) => column.showType === 'NUMBER');
@@ -80,11 +81,11 @@ const MetricTrend: React.FC<Props> = ({
<MetricInfo aggregateInfo={aggregateInfo} currentMetricField={currentMetricField} /> <MetricInfo aggregateInfo={aggregateInfo} currentMetricField={currentMetricField} />
)} )}
<div className={`${prefixCls}-select-options`}> <div className={`${prefixCls}-select-options`}>
<DateOptions {/*<DateOptions*/}
chatContext={chatContext} {/* chatContext={chatContext}*/}
currentDateOption={currentDateOption} {/* currentDateOption={currentDateOption}*/}
onSelectDateOption={onSelectDateOption} {/* onSelectDateOption={onSelectDateOption}*/}
/> {/*/>*/}
<div> <div>
<Select <Select
defaultValue="line" defaultValue="line"

View File

@@ -8,7 +8,7 @@ import { ISemantic } from '../../data';
import { import {
AGG_OPTIONS, AGG_OPTIONS,
DATE_FORMATTER, DATE_FORMATTER,
DATE_OPTIONS, // DATE_OPTIONS,
DIM_OPTIONS, DIM_OPTIONS,
EnumDataSourceType, EnumDataSourceType,
EnumModelDataType, EnumModelDataType,
@@ -275,7 +275,7 @@ const ModelFieldForm: React.FC<Props> = ({
} }
} }
if ([EnumDataSourceType.TIME, EnumDataSourceType.PARTITION_TIME].includes(type)) { if ([EnumDataSourceType.TIME, EnumDataSourceType.PARTITION_TIME].includes(type)) {
const { dateFormat, timeGranularity } = record; const { dateFormat } = record;
const dateFormatterOptions = const dateFormatterOptions =
type === EnumDataSourceType.PARTITION_TIME ? PARTITION_TIME_FORMATTER : DATE_FORMATTER; type === EnumDataSourceType.PARTITION_TIME ? PARTITION_TIME_FORMATTER : DATE_FORMATTER;
@@ -302,25 +302,25 @@ const ModelFieldForm: React.FC<Props> = ({
<ExclamationCircleOutlined /> <ExclamationCircleOutlined />
</Tooltip> </Tooltip>
</Space> </Space>
<Space> {/*<Space>*/}
<span>:</span> {/* <span>时间粒度:</span>*/}
<Select {/* <Select*/}
placeholder="时间粒度" {/* placeholder="时间粒度"*/}
value={timeGranularity === '' ? undefined : timeGranularity} {/* value={timeGranularity === '' ? undefined : timeGranularity}*/}
onChange={(value) => { {/* onChange={(value) => {*/}
handleFieldChange(record, 'timeGranularity', value); {/* handleFieldChange(record, 'timeGranularity', value);*/}
}} {/* }}*/}
defaultValue={timeGranularity === '' ? undefined : DATE_OPTIONS[0]} {/* defaultValue={timeGranularity === '' ? undefined : DATE_OPTIONS[0]}*/}
style={{ minWidth: 180 }} {/* style={{ minWidth: 180 }}*/}
allowClear {/* allowClear*/}
> {/* >*/}
{DATE_OPTIONS.map((item) => ( {/* {DATE_OPTIONS.map((item) => (*/}
<Option key={item} value={item}> {/* <Option key={item} value={item}>*/}
{item} {/* {item}*/}
</Option> {/* </Option>*/}
))} {/* ))}*/}
</Select> {/* </Select>*/}
</Space> {/*</Space>*/}
</Space> </Space>
); );
} }