feat(starrocks): 新增 StarRocks 数据源与高级对象能力

- 后端接入:新增独立 starrocks 可选驱动,复用 MySQL wire 协议并支持默认 9030 端口
- 驱动管理:补齐 manifest、build tag、revision、driver-agent provider 和构建脚本
- 前端接入:新增 StarRocks 连接类型、图标、能力矩阵、URI 解析、保存回显和 SQL 自动 LIMIT
- 方言增强:新增 StarRocks 类型、关键字、函数补全和专属建表 SQL 生成
- 高级对象:支持物化视图对象浏览、Rollup 模板、外部 Catalog 模板和高级表设计器参数
- CI 发布:将 StarRocks driver-agent 纳入 dev/release 构建与 release 资产校验
This commit is contained in:
Syngnat
2026-05-15 17:30:08 +08:00
parent 2580e4d6f3
commit 569edbb11a
49 changed files with 1164 additions and 62 deletions

View File

@@ -120,13 +120,23 @@ const DefinitionViewer: React.FC<DefinitionViewerProps> = ({ tab }) => {
return `CREATE OR REPLACE MACRO ${qualifiedName}(${parameters}) AS ${macroDefinition};`;
};
const buildShowViewQueries = (dialect: string, viewName: string, dbName: string): string[] => {
const buildShowViewQueries = (dialect: string, viewName: string, dbName: string, viewKind?: string): string[] => {
const { schema, name } = parseSchemaAndName(viewName);
const safeName = escapeSQLLiteral(name);
const safeDbName = escapeSQLLiteral(dbName);
switch (dialect) {
case 'mysql':
case 'starrocks':
if (dialect === 'starrocks' && viewKind === 'materialized') {
const mvRef = schema
? `\`${schema.replace(/`/g, '``')}\`.\`${name.replace(/`/g, '``')}\``
: `\`${name.replace(/`/g, '``')}\``;
return [
`SHOW CREATE MATERIALIZED VIEW ${mvRef}`,
`SHOW CREATE TABLE ${mvRef}`,
];
}
return [
`SHOW CREATE VIEW \`${name.replace(/`/g, '``')}\``,
safeDbName
@@ -172,6 +182,7 @@ const DefinitionViewer: React.FC<DefinitionViewerProps> = ({ tab }) => {
switch (dialect) {
case 'mysql':
case 'starrocks':
return [
`SHOW CREATE ${upperType} \`${name.replace(/`/g, '``')}\``,
safeDbName
@@ -277,7 +288,8 @@ const DefinitionViewer: React.FC<DefinitionViewerProps> = ({ tab }) => {
const row = data[0];
switch (dialect) {
case 'mysql': {
case 'mysql':
case 'starrocks': {
const keys = Object.keys(row);
const textDefinition = row.view_definition || row.VIEW_DEFINITION;
if (textDefinition) return normalizeMySQLViewDDL(textDefinition);
@@ -305,7 +317,8 @@ const DefinitionViewer: React.FC<DefinitionViewerProps> = ({ tab }) => {
if (!data || data.length === 0) return '-- 未找到函数/存储过程定义';
switch (dialect) {
case 'mysql': {
case 'mysql':
case 'starrocks': {
const row = data[0];
const keys = Object.keys(row);
if (row.routine_definition || row.ROUTINE_DEFINITION) {
@@ -380,9 +393,9 @@ const DefinitionViewer: React.FC<DefinitionViewerProps> = ({ tab }) => {
setLoading(false);
return;
}
queries = buildShowViewQueries(dialect, viewName, dbName);
queries = buildShowViewQueries(dialect, viewName, dbName, tab.viewKind);
extractFn = extractViewDefinition;
objectLabel = '视图';
objectLabel = tab.viewKind === 'materialized' ? '物化视图' : '视图';
} else {
const routineName = tab.routineName || '';
const routineType = tab.routineType || 'FUNCTION';
@@ -443,9 +456,9 @@ const DefinitionViewer: React.FC<DefinitionViewerProps> = ({ tab }) => {
};
loadDefinition();
}, [tab.connectionId, tab.dbName, tab.viewName, tab.routineName, tab.routineType, tab.type, connections]);
}, [tab.connectionId, tab.dbName, tab.viewName, tab.viewKind, tab.routineName, tab.routineType, tab.type, connections]);
const objectLabel = tab.type === 'view-def' ? '视图' : '函数/存储过程';
const objectLabel = tab.type === 'view-def' ? (tab.viewKind === 'materialized' ? '物化视图' : '视图') : '函数/存储过程';
const objectName = tab.type === 'view-def' ? tab.viewName : tab.routineName;
if (loading) {