ai-query对接新版freesun-agent接口的分支
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

159 lines
5.7 KiB

'use strict';
const { VALIDATED_QUERY_BLOCK_TYPES } = require('./constants');
const { hasOwn, toInt, ensureObjectPayload } = require('./helpers');
const { ensureDataSource, ensureInstance, ensureTemplate } = require('./repository');
const clickhouse = require('./clickhouse');
const dataease = require('./dataease');
const resolveDataSourceType = dataSource => String(dataSource?.type || '').trim().toLowerCase();
const getAdapterByType = type => {
switch (type) {
case 'clickhouse':
return clickhouse;
case 'dataease':
return dataease;
default:
throw `unsupported data source type: ${type}`;
}
};
const getAdapterByDataSource = dataSource => {
return getAdapterByType(resolveDataSourceType(dataSource));
};
const getDataSourceTables = async (ctx, dataSourceId, transaction = null) => {
const dataSource = await ensureDataSource(ctx, dataSourceId, transaction);
const adapter = getAdapterByDataSource(dataSource);
if (resolveDataSourceType(dataSource) === 'clickhouse') {
const payload = await adapter.listClickHouseTables(ctx, dataSource, transaction);
return { sourceType: 'clickhouse', ...payload };
}
const rows = await adapter.listDataEaseDatasets(ctx, dataSource);
return {
sourceType: 'dataease',
dataSourceId: toInt(dataSourceId),
clientKey: null,
database: null,
rows,
};
};
const getDataSourceTableColumns = async (ctx, dataSourceId, tableId, transaction = null) => {
const dataSource = await ensureDataSource(ctx, dataSourceId, transaction);
const type = resolveDataSourceType(dataSource);
const adapter = getAdapterByDataSource(dataSource);
if (type === 'clickhouse') {
const payload = await adapter.getClickHouseTableColumnsPayload(ctx, dataSource, tableId, transaction);
return { sourceType: 'clickhouse', ...payload };
}
const payload = await adapter.getDataEaseDatasetColumns(ctx, dataSource, tableId);
return {
sourceType: 'dataease',
dataSourceId: toInt(dataSourceId),
clientKey: payload.clientKey,
database: payload.database,
table: payload.datasetId,
datasetName: payload.datasetName,
rows: payload.rows,
};
};
const previewDataSourceQuery = async (ctx, dataSourceId, rawDsl, transaction = null) => {
const dataSource = await ensureDataSource(ctx, dataSourceId, transaction);
const type = resolveDataSourceType(dataSource);
const adapter = getAdapterByDataSource(dataSource);
if (type === 'clickhouse') {
const payload = await adapter.previewClickHouseQuery(ctx, dataSource, rawDsl, transaction);
return {
sourceType: 'clickhouse',
dataSourceId: toInt(dataSourceId),
...payload,
};
}
const payload = await adapter.previewDataEaseQuery(ctx, dataSource, rawDsl);
return {
...payload,
dataSourceId: toInt(dataSourceId),
};
};
const normalizeBlockConfigForDataSource = async (ctx, dataSourceId, blockType, config, transaction = null) => {
const normalizedBlockType = String(blockType || 'text').trim().toLowerCase();
if (!VALIDATED_QUERY_BLOCK_TYPES.has(normalizedBlockType)) {
if (config === null || config === undefined) return {};
return ensureObjectPayload(config, 'config');
}
const safeConfig = ensureObjectPayload(config, 'config');
const dslPayload = hasOwn(safeConfig, 'query')
? ensureObjectPayload(safeConfig.query, 'config.query')
: safeConfig;
const parsedDataSourceId = toInt(dataSourceId);
if (!parsedDataSourceId) throw 'missing param: dataSourceId';
const dataSource = await ensureDataSource(ctx, parsedDataSourceId, transaction);
const type = resolveDataSourceType(dataSource);
let normalizedDsl = null;
if (type === 'clickhouse') {
const dataSourceContext = await clickhouse.resolveClickHouseDataSourceContext(ctx, parsedDataSourceId, transaction);
normalizedDsl = await clickhouse.validateStructuredQueryDsl(dataSourceContext, dslPayload);
} else if (type === 'dataease') {
normalizedDsl = (await dataease.validateDataEaseStructuredQueryDsl(ctx, dataSource, dslPayload)).normalizedDsl;
} else {
throw `unsupported data source type: ${type}`;
}
if (hasOwn(safeConfig, 'query')) {
return {
...safeConfig,
dataSourceId: parsedDataSourceId,
query: {
...normalizedDsl,
dataSourceId: parsedDataSourceId,
},
};
}
return {
...safeConfig,
...normalizedDsl,
dataSourceId: parsedDataSourceId,
};
};
const normalizeBlockConfigForStorage = async (ctx, instanceId, blockType, config, transaction = null) => {
const instance = await ensureInstance(ctx, instanceId, transaction);
const safeConfig = ensureObjectPayload(config || {}, 'config');
const dslPayload = hasOwn(safeConfig, 'query')
? ensureObjectPayload(safeConfig.query, 'config.query')
: safeConfig;
const dataSourceId = toInt(instance.dataSourceId || dslPayload.dataSourceId || safeConfig.dataSourceId);
return normalizeBlockConfigForDataSource(ctx, dataSourceId, blockType, safeConfig, transaction);
};
const normalizeTemplateBlockConfigForStorage = async (ctx, templateId, blockType, config, transaction = null) => {
const template = await ensureTemplate(ctx, templateId, transaction);
const safeConfig = ensureObjectPayload(config || {}, 'config');
const dataSourceId = toInt(template.dataSourceId);
if (!dataSourceId) throw '模板未绑定数据源';
return normalizeBlockConfigForDataSource(ctx, dataSourceId, blockType, safeConfig, transaction);
};
module.exports = {
getDataSourceTables,
getDataSourceTableColumns,
previewDataSourceQuery,
normalizeBlockConfigForDataSource,
normalizeBlockConfigForStorage,
normalizeTemplateBlockConfigForStorage,
};