mirror of
				https://gitee.com/dromara/mayfly-go
				synced 2025-11-04 00:10:25 +08:00 
			
		
		
		
	feat: 新增数据库版本查看
This commit is contained in:
		@@ -95,6 +95,16 @@ export function useApiFetch<T>(api: Api, params: any = null, reqOptions: Request
 | 
				
			|||||||
                    return rejectPromise;
 | 
					                    return rejectPromise;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                const respStatus = uaf.response.value?.status;
 | 
				
			||||||
 | 
					                if (respStatus == 404) {
 | 
				
			||||||
 | 
					                    ElMessage.error('请求接口不存在');
 | 
				
			||||||
 | 
					                    return rejectPromise;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (respStatus == 500) {
 | 
				
			||||||
 | 
					                    ElMessage.error('服务器响应异常');
 | 
				
			||||||
 | 
					                    return rejectPromise;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                console.error(e);
 | 
					                console.error(e);
 | 
				
			||||||
                ElMessage.error('网络请求错误');
 | 
					                ElMessage.error('网络请求错误');
 | 
				
			||||||
                return rejectPromise;
 | 
					                return rejectPromise;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -184,6 +184,10 @@ defineExpose({
 | 
				
			|||||||
    z-index: 2190;
 | 
					    z-index: 2190;
 | 
				
			||||||
    position: fixed;
 | 
					    position: fixed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .el-dropdown-menu__item {
 | 
				
			||||||
 | 
					        padding: 5px 10px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .el-dropdown-menu__item {
 | 
					    .el-dropdown-menu__item {
 | 
				
			||||||
        font-size: 12px !important;
 | 
					        font-size: 12px !important;
 | 
				
			||||||
        white-space: nowrap;
 | 
					        white-space: nowrap;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,14 @@
 | 
				
			|||||||
                <tag-tree :resource-type="TagResourceTypeEnum.Db.value" :tag-path-node-type="NodeTypeTagPath" ref="tagTreeRef">
 | 
					                <tag-tree :resource-type="TagResourceTypeEnum.Db.value" :tag-path-node-type="NodeTypeTagPath" ref="tagTreeRef">
 | 
				
			||||||
                    <template #prefix="{ data }">
 | 
					                    <template #prefix="{ data }">
 | 
				
			||||||
                        <span v-if="data.type.value == SqlExecNodeType.DbInst">
 | 
					                        <span v-if="data.type.value == SqlExecNodeType.DbInst">
 | 
				
			||||||
                            <el-popover :show-after="500" placement="right-start" title="数据库实例信息" trigger="hover" :width="250">
 | 
					                            <el-popover
 | 
				
			||||||
 | 
					                                @show="showDbInfo(data.params)"
 | 
				
			||||||
 | 
					                                :show-after="500"
 | 
				
			||||||
 | 
					                                placement="right-start"
 | 
				
			||||||
 | 
					                                title="数据库实例信息"
 | 
				
			||||||
 | 
					                                trigger="hover"
 | 
				
			||||||
 | 
					                                :width="250"
 | 
				
			||||||
 | 
					                            >
 | 
				
			||||||
                                <template #reference>
 | 
					                                <template #reference>
 | 
				
			||||||
                                    <SvgIcon :name="getDbDialect(data.params.type).getInfo().icon" :size="18" />
 | 
					                                    <SvgIcon :name="getDbDialect(data.params.type).getInfo().icon" :size="18" />
 | 
				
			||||||
                                </template>
 | 
					                                </template>
 | 
				
			||||||
@@ -17,6 +24,9 @@
 | 
				
			|||||||
                                        <el-descriptions-item label="host">
 | 
					                                        <el-descriptions-item label="host">
 | 
				
			||||||
                                            {{ `${data.params.host}:${data.params.port}` }}
 | 
					                                            {{ `${data.params.host}:${data.params.port}` }}
 | 
				
			||||||
                                        </el-descriptions-item>
 | 
					                                        </el-descriptions-item>
 | 
				
			||||||
 | 
					                                        <el-descriptions-item label="数据库版本">
 | 
				
			||||||
 | 
					                                            <span v-loading="loadingServerInfo"> {{ `${dbServerInfo?.version}` }}</span>
 | 
				
			||||||
 | 
					                                        </el-descriptions-item>
 | 
				
			||||||
                                        <el-descriptions-item label="user">
 | 
					                                        <el-descriptions-item label="user">
 | 
				
			||||||
                                            {{ data.params.username }}
 | 
					                                            {{ data.params.username }}
 | 
				
			||||||
                                        </el-descriptions-item>
 | 
					                                        </el-descriptions-item>
 | 
				
			||||||
@@ -381,10 +391,19 @@ const state = reactive({
 | 
				
			|||||||
    tabs,
 | 
					    tabs,
 | 
				
			||||||
    dataTabsTableHeight: '600px',
 | 
					    dataTabsTableHeight: '600px',
 | 
				
			||||||
    tablesOpHeight: '600',
 | 
					    tablesOpHeight: '600',
 | 
				
			||||||
 | 
					    dbServerInfo: {
 | 
				
			||||||
 | 
					        loading: true,
 | 
				
			||||||
 | 
					        version: '',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { nowDbInst } = toRefs(state);
 | 
					const { nowDbInst } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const serverInfoReqParam = ref({
 | 
				
			||||||
 | 
					    instanceId: 0,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					const { execute: getDbServerInfo, isFetching: loadingServerInfo, data: dbServerInfo } = dbApi.getInstanceServerInfo.useApi<any>(serverInfoReqParam);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onMounted(() => {
 | 
					onMounted(() => {
 | 
				
			||||||
    setHeight();
 | 
					    setHeight();
 | 
				
			||||||
    // 监听浏览器窗口大小变化,更新对应组件高度
 | 
					    // 监听浏览器窗口大小变化,更新对应组件高度
 | 
				
			||||||
@@ -403,6 +422,14 @@ const setHeight = () => {
 | 
				
			|||||||
    state.tablesOpHeight = window.innerHeight - 225 + 'px';
 | 
					    state.tablesOpHeight = window.innerHeight - 225 + 'px';
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const showDbInfo = async (db: any) => {
 | 
				
			||||||
 | 
					    if (dbServerInfo.value) {
 | 
				
			||||||
 | 
					        dbServerInfo.value.version = '';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    serverInfoReqParam.value.instanceId = db.instanceId;
 | 
				
			||||||
 | 
					    await getDbServerInfo();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 选择数据库,改变当前正在操作的数据库信息
 | 
					// 选择数据库,改变当前正在操作的数据库信息
 | 
				
			||||||
const changeDb = (db: any, dbName: string) => {
 | 
					const changeDb = (db: any, dbName: string) => {
 | 
				
			||||||
    state.nowDbInst = DbInst.getOrNewInst(db);
 | 
					    state.nowDbInst = DbInst.getOrNewInst(db);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,6 +36,7 @@ export const dbApi = {
 | 
				
			|||||||
    instances: Api.newGet('/instances'),
 | 
					    instances: Api.newGet('/instances'),
 | 
				
			||||||
    getInstance: Api.newGet('/instances/{instanceId}'),
 | 
					    getInstance: Api.newGet('/instances/{instanceId}'),
 | 
				
			||||||
    getAllDatabase: Api.newGet('/instances/{instanceId}/databases'),
 | 
					    getAllDatabase: Api.newGet('/instances/{instanceId}/databases'),
 | 
				
			||||||
 | 
					    getInstanceServerInfo: Api.newGet('/instances/{instanceId}/server-info'),
 | 
				
			||||||
    testConn: Api.newPost('/instances/test-conn'),
 | 
					    testConn: Api.newPost('/instances/test-conn'),
 | 
				
			||||||
    saveInstance: Api.newPost('/instances'),
 | 
					    saveInstance: Api.newPost('/instances'),
 | 
				
			||||||
    getInstancePwd: Api.newGet('/instances/{id}/pwd'),
 | 
					    getInstancePwd: Api.newGet('/instances/{id}/pwd'),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -64,17 +64,12 @@
 | 
				
			|||||||
                                        </el-text>
 | 
					                                        </el-text>
 | 
				
			||||||
                                    </div>
 | 
					                                    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                    <el-dropdown trigger="click" class="column-header-op">
 | 
					                                    <el-dropdown trigger="click" class="column-header-op" size="small">
 | 
				
			||||||
                                        <SvgIcon :size="16" name="CaretBottom" />
 | 
					                                        <SvgIcon :size="16" name="CaretBottom" />
 | 
				
			||||||
                                        <template #dropdown>
 | 
					                                        <template #dropdown>
 | 
				
			||||||
                                            <el-dropdown-menu>
 | 
					                                            <el-dropdown-menu>
 | 
				
			||||||
                                                <template v-for="menu in tableHeadlerMenu">
 | 
					                                                <template v-for="menu in tableHeadlerMenu">
 | 
				
			||||||
                                                    <el-dropdown-item
 | 
					                                                    <el-dropdown-item :key="menu.clickId" v-if="!menu.isHide(column)" @click="menu?.onClickFunc(column)">
 | 
				
			||||||
                                                        :key="menu.clickId"
 | 
					 | 
				
			||||||
                                                        v-if="!menu.isHide(column)"
 | 
					 | 
				
			||||||
                                                        @click="menu?.onClickFunc(column)"
 | 
					 | 
				
			||||||
                                                        class="font12"
 | 
					 | 
				
			||||||
                                                    >
 | 
					 | 
				
			||||||
                                                        <SvgIcon v-if="menu.icon" :name="menu.icon" />
 | 
					                                                        <SvgIcon v-if="menu.icon" :name="menu.icon" />
 | 
				
			||||||
                                                        {{ menu.txt }}
 | 
					                                                        {{ menu.txt }}
 | 
				
			||||||
                                                    </el-dropdown-item>
 | 
					                                                    </el-dropdown-item>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,8 +26,8 @@ require (
 | 
				
			|||||||
	github.com/robfig/cron/v3 v3.0.1 // 定时任务
 | 
						github.com/robfig/cron/v3 v3.0.1 // 定时任务
 | 
				
			||||||
	github.com/stretchr/testify v1.8.4
 | 
						github.com/stretchr/testify v1.8.4
 | 
				
			||||||
	go.mongodb.org/mongo-driver v1.13.1 // mongo
 | 
						go.mongodb.org/mongo-driver v1.13.1 // mongo
 | 
				
			||||||
	golang.org/x/crypto v0.16.0 // ssh
 | 
						golang.org/x/crypto v0.17.0 // ssh
 | 
				
			||||||
	golang.org/x/oauth2 v0.14.0
 | 
						golang.org/x/oauth2 v0.15.0
 | 
				
			||||||
	gopkg.in/yaml.v3 v3.0.1
 | 
						gopkg.in/yaml.v3 v3.0.1
 | 
				
			||||||
	// gorm
 | 
						// gorm
 | 
				
			||||||
	gorm.io/driver/mysql v1.5.2
 | 
						gorm.io/driver/mysql v1.5.2
 | 
				
			||||||
@@ -79,7 +79,7 @@ require (
 | 
				
			|||||||
	golang.org/x/arch v0.3.0 // indirect
 | 
						golang.org/x/arch v0.3.0 // indirect
 | 
				
			||||||
	golang.org/x/exp v0.0.0-20230519143937-03e91628a987
 | 
						golang.org/x/exp v0.0.0-20230519143937-03e91628a987
 | 
				
			||||||
	golang.org/x/image v0.13.0 // indirect
 | 
						golang.org/x/image v0.13.0 // indirect
 | 
				
			||||||
	golang.org/x/net v0.18.0 // indirect
 | 
						golang.org/x/net v0.19.0 // indirect
 | 
				
			||||||
	golang.org/x/sync v0.1.0 // indirect
 | 
						golang.org/x/sync v0.1.0 // indirect
 | 
				
			||||||
	golang.org/x/sys v0.15.0 // indirect
 | 
						golang.org/x/sys v0.15.0 // indirect
 | 
				
			||||||
	golang.org/x/text v0.14.0 // indirect
 | 
						golang.org/x/text v0.14.0 // indirect
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -339,7 +339,7 @@ func (d *Db) dumpDb(writer *gzipWriter, dbId uint64, dbName string, tables []str
 | 
				
			|||||||
		if needStruct {
 | 
							if needStruct {
 | 
				
			||||||
			writer.WriteString(fmt.Sprintf("\n-- ----------------------------\n-- 表结构: %s \n-- ----------------------------\n", table))
 | 
								writer.WriteString(fmt.Sprintf("\n-- ----------------------------\n-- 表结构: %s \n-- ----------------------------\n", table))
 | 
				
			||||||
			writer.WriteString(fmt.Sprintf("DROP TABLE IF EXISTS %s;\n", quotedTable))
 | 
								writer.WriteString(fmt.Sprintf("DROP TABLE IF EXISTS %s;\n", quotedTable))
 | 
				
			||||||
			ddl, err := dbMeta.GetCreateTableDdl(table)
 | 
								ddl, err := dbMeta.GetTableDDL(table)
 | 
				
			||||||
			biz.ErrIsNil(err)
 | 
								biz.ErrIsNil(err)
 | 
				
			||||||
			writer.WriteString(ddl + "\n")
 | 
								writer.WriteString(ddl + "\n")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -441,17 +441,15 @@ func (d *Db) HintTables(rc *req.Ctx) {
 | 
				
			|||||||
	rc.ResData = res
 | 
						rc.ResData = res
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *Db) GetCreateTableDdl(rc *req.Ctx) {
 | 
					func (d *Db) GetTableDDL(rc *req.Ctx) {
 | 
				
			||||||
	tn := rc.GinCtx.Query("tableName")
 | 
						tn := rc.GinCtx.Query("tableName")
 | 
				
			||||||
	biz.NotEmpty(tn, "tableName不能为空")
 | 
						biz.NotEmpty(tn, "tableName不能为空")
 | 
				
			||||||
	res, err := d.getDbConn(rc.GinCtx).GetDialect().GetCreateTableDdl(tn)
 | 
						res, err := d.getDbConn(rc.GinCtx).GetDialect().GetTableDDL(tn)
 | 
				
			||||||
	biz.ErrIsNilAppendErr(err, "获取表ddl失败: %s")
 | 
						biz.ErrIsNilAppendErr(err, "获取表ddl失败: %s")
 | 
				
			||||||
	rc.ResData = res
 | 
						rc.ResData = res
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *Db) GetPgsqlSchemas(rc *req.Ctx) {
 | 
					func (d *Db) GetSchemas(rc *req.Ctx) {
 | 
				
			||||||
	conn := d.getDbConn(rc.GinCtx)
 | 
					 | 
				
			||||||
	biz.IsTrue(conn.Info.Type == dbm.DbTypePostgres || conn.Info.Type == dbm.DM, "非postgres无法获取该schemas")
 | 
					 | 
				
			||||||
	res, err := d.getDbConn(rc.GinCtx).GetDialect().GetSchemas()
 | 
						res, err := d.getDbConn(rc.GinCtx).GetDialect().GetSchemas()
 | 
				
			||||||
	biz.ErrIsNilAppendErr(err, "获取schemas失败: %s")
 | 
						biz.ErrIsNilAppendErr(err, "获取schemas失败: %s")
 | 
				
			||||||
	rc.ResData = res
 | 
						rc.ResData = res
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -89,11 +89,7 @@ func (d *Instance) DeleteInstance(rc *req.Ctx) {
 | 
				
			|||||||
		value, err := strconv.Atoi(v)
 | 
							value, err := strconv.Atoi(v)
 | 
				
			||||||
		biz.ErrIsNilAppendErr(err, "string类型转换为int异常: %s")
 | 
							biz.ErrIsNilAppendErr(err, "string类型转换为int异常: %s")
 | 
				
			||||||
		instanceId := uint64(value)
 | 
							instanceId := uint64(value)
 | 
				
			||||||
		if d.DbApp.Count(&entity.DbQuery{InstanceId: instanceId}) != 0 {
 | 
							biz.IsTrue(d.DbApp.Count(&entity.DbQuery{InstanceId: instanceId}) == 0, "不能删除数据库实例【%d】, 请先删除其关联的数据库资源", instanceId)
 | 
				
			||||||
			instance, err := d.InstanceApp.GetById(new(entity.DbInstance), instanceId, "name")
 | 
					 | 
				
			||||||
			biz.ErrIsNil(err, "获取数据库实例错误,数据库实例ID为: %d", instance.Id)
 | 
					 | 
				
			||||||
			biz.IsTrue(false, "不能删除数据库实例【%s】,请先删除其关联的数据库资源。", instance.Name)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		d.InstanceApp.Delete(rc.MetaCtx, instanceId)
 | 
							d.InstanceApp.Delete(rc.MetaCtx, instanceId)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -109,6 +105,16 @@ func (d *Instance) GetDatabaseNames(rc *req.Ctx) {
 | 
				
			|||||||
	rc.ResData = res
 | 
						rc.ResData = res
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 获取数据库实例server信息
 | 
				
			||||||
 | 
					func (d *Instance) GetDbServer(rc *req.Ctx) {
 | 
				
			||||||
 | 
						instanceId := getInstanceId(rc.GinCtx)
 | 
				
			||||||
 | 
						conn, err := d.DbApp.GetDbConnByInstanceId(instanceId)
 | 
				
			||||||
 | 
						biz.ErrIsNil(err)
 | 
				
			||||||
 | 
						res, err := conn.GetDialect().GetDbServer()
 | 
				
			||||||
 | 
						biz.ErrIsNil(err)
 | 
				
			||||||
 | 
						rc.ResData = res
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getInstanceId(g *gin.Context) uint64 {
 | 
					func getInstanceId(g *gin.Context) uint64 {
 | 
				
			||||||
	instanceId, _ := strconv.Atoi(g.Param("instanceId"))
 | 
						instanceId, _ := strconv.Atoi(g.Param("instanceId"))
 | 
				
			||||||
	biz.IsTrue(instanceId > 0, "instanceId 错误")
 | 
						biz.IsTrue(instanceId > 0, "instanceId 错误")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,8 +31,12 @@ type Db interface {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// 获取数据库连接实例
 | 
						// 获取数据库连接实例
 | 
				
			||||||
	// @param id 数据库id
 | 
						// @param id 数据库id
 | 
				
			||||||
	// @param dbName 数据库
 | 
						//
 | 
				
			||||||
 | 
						// @param dbName 数据库名
 | 
				
			||||||
	GetDbConn(dbId uint64, dbName string) (*dbm.DbConn, error)
 | 
						GetDbConn(dbId uint64, dbName string) (*dbm.DbConn, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 根据数据库实例id获取连接,随机返回该instanceId下已连接的conn,若不存在则是使用该instanceId关联的db进行连接并返回。
 | 
				
			||||||
 | 
						GetDbConnByInstanceId(instanceId uint64) (*dbm.DbConn, error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newDbApp(dbRepo repository.Db, dbSqlRepo repository.DbSql, dbInstanceApp Instance, tagApp tagapp.TagTree) Db {
 | 
					func newDbApp(dbRepo repository.Db, dbSqlRepo repository.DbSql, dbInstanceApp Instance, tagApp tagapp.TagTree) Db {
 | 
				
			||||||
@@ -168,8 +172,26 @@ func (d *dbAppImpl) GetDbConn(dbId uint64, dbName string) (*dbm.DbConn, error) {
 | 
				
			|||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (d *dbAppImpl) GetDbConnByInstanceId(instanceId uint64) (*dbm.DbConn, error) {
 | 
				
			||||||
 | 
						conn := dbm.GetDbConnByInstanceId(instanceId)
 | 
				
			||||||
 | 
						if conn != nil {
 | 
				
			||||||
 | 
							return conn, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var dbs []*entity.Db
 | 
				
			||||||
 | 
						err := d.ListByCond(&entity.Db{InstanceId: instanceId}, &dbs, "id", "database")
 | 
				
			||||||
 | 
						if err != nil || len(dbs) == 0 {
 | 
				
			||||||
 | 
							return nil, errorx.NewBiz("该实例未配置数据库, 请先进行配置")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 使用该实例关联的已配置数据库中的第一个库进行连接并返回
 | 
				
			||||||
 | 
						firstDb := dbs[0]
 | 
				
			||||||
 | 
						return d.GetDbConn(firstDb.Id, strings.Split(firstDb.Database, " ")[0])
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func toDbInfo(instance *entity.DbInstance, dbId uint64, database string, tagPath ...string) *dbm.DbInfo {
 | 
					func toDbInfo(instance *entity.DbInstance, dbId uint64, database string, tagPath ...string) *dbm.DbInfo {
 | 
				
			||||||
	di := new(dbm.DbInfo)
 | 
						di := new(dbm.DbInfo)
 | 
				
			||||||
 | 
						di.InstanceId = instance.Id
 | 
				
			||||||
	di.Id = dbId
 | 
						di.Id = dbId
 | 
				
			||||||
	di.Database = database
 | 
						di.Database = database
 | 
				
			||||||
	di.TagPath = tagPath
 | 
						di.TagPath = tagPath
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -67,6 +67,17 @@ func GetDbConn(dbId uint64, database string, getDbInfo func() (*DbInfo, error))
 | 
				
			|||||||
	return dbConn, nil
 | 
						return dbConn, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 根据实例id获取连接
 | 
				
			||||||
 | 
					func GetDbConnByInstanceId(instanceId uint64) *DbConn {
 | 
				
			||||||
 | 
						for _, connItem := range connCache.Items() {
 | 
				
			||||||
 | 
							conn := connItem.Value.(*DbConn)
 | 
				
			||||||
 | 
							if conn.Info.InstanceId == instanceId {
 | 
				
			||||||
 | 
								return conn
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 删除db缓存并关闭该数据库所有连接
 | 
					// 删除db缓存并关闭该数据库所有连接
 | 
				
			||||||
func CloseDb(dbId uint64, db string) {
 | 
					func CloseDb(dbId uint64, db string) {
 | 
				
			||||||
	connCache.Delete(GetDbConnId(dbId, db))
 | 
						connCache.Delete(GetDbConnId(dbId, db))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,10 +3,17 @@ package dbm
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"embed"
 | 
						"embed"
 | 
				
			||||||
	"mayfly-go/pkg/biz"
 | 
						"mayfly-go/pkg/biz"
 | 
				
			||||||
 | 
						"mayfly-go/pkg/utils/collx"
 | 
				
			||||||
	"mayfly-go/pkg/utils/stringx"
 | 
						"mayfly-go/pkg/utils/stringx"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 数据库服务实例信息
 | 
				
			||||||
 | 
					type DbServer struct {
 | 
				
			||||||
 | 
						Version string  `json:"version"` // 版本信息
 | 
				
			||||||
 | 
						Extra   collx.M `json:"extra"`   // 其他额外信息
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 表信息
 | 
					// 表信息
 | 
				
			||||||
type Table struct {
 | 
					type Table struct {
 | 
				
			||||||
	TableName    string `json:"tableName"`    // 表名
 | 
						TableName    string `json:"tableName"`    // 表名
 | 
				
			||||||
@@ -27,7 +34,7 @@ type Column struct {
 | 
				
			|||||||
	ColumnDefault string  `json:"columnDefault"` // 默认值
 | 
						ColumnDefault string  `json:"columnDefault"` // 默认值
 | 
				
			||||||
	Nullable      string  `json:"nullable"`      // 是否可为null
 | 
						Nullable      string  `json:"nullable"`      // 是否可为null
 | 
				
			||||||
	NumScale      string  `json:"numScale"`      // 小数点
 | 
						NumScale      string  `json:"numScale"`      // 小数点
 | 
				
			||||||
	Extra         string `json:"extra"`         // 其他信息
 | 
						Extra         collx.M `json:"extra"`         // 其他额外信息
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 表索引信息
 | 
					// 表索引信息
 | 
				
			||||||
@@ -43,6 +50,9 @@ type Index struct {
 | 
				
			|||||||
// -----------------------------------元数据接口定义------------------------------------------
 | 
					// -----------------------------------元数据接口定义------------------------------------------
 | 
				
			||||||
// 数据库方言、元信息接口(表、列、获取表数据等元信息)
 | 
					// 数据库方言、元信息接口(表、列、获取表数据等元信息)
 | 
				
			||||||
type DbDialect interface {
 | 
					type DbDialect interface {
 | 
				
			||||||
 | 
						// 获取数据库服务实例信息
 | 
				
			||||||
 | 
						GetDbServer() (*DbServer, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 获取数据库名称列表
 | 
						// 获取数据库名称列表
 | 
				
			||||||
	GetDbNames() ([]string, error)
 | 
						GetDbNames() ([]string, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -59,7 +69,7 @@ type DbDialect interface {
 | 
				
			|||||||
	GetTableIndex(tableName string) ([]Index, error)
 | 
						GetTableIndex(tableName string) ([]Index, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 获取建表ddl
 | 
						// 获取建表ddl
 | 
				
			||||||
	GetCreateTableDdl(tableName string) (string, error)
 | 
						GetTableDDL(tableName string) (string, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 获取指定表的数据-分页查询
 | 
						// 获取指定表的数据-分页查询
 | 
				
			||||||
	// @return columns: 列字段名;result: 结果集;error: 错误
 | 
						// @return columns: 列字段名;result: 结果集;error: 错误
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,6 +42,17 @@ type DMDialect struct {
 | 
				
			|||||||
	dc *DbConn
 | 
						dc *DbConn
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (dd *DMDialect) GetDbServer() (*DbServer, error) {
 | 
				
			||||||
 | 
						_, res, err := dd.dc.Query("select * from v$instance")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ds := &DbServer{
 | 
				
			||||||
 | 
							Version: anyx.ConvString(res[0]["SVR_VERSION"]),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ds, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (pd *DMDialect) GetDbNames() ([]string, error) {
 | 
					func (pd *DMDialect) GetDbNames() ([]string, error) {
 | 
				
			||||||
	_, res, err := pd.dc.Query("SELECT name AS DBNAME FROM v$database")
 | 
						_, res, err := pd.dc.Query("SELECT name AS DBNAME FROM v$database")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -168,7 +179,7 @@ func (pd *DMDialect) GetTableIndex(tableName string) ([]Index, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 获取建表ddl
 | 
					// 获取建表ddl
 | 
				
			||||||
func (pd *DMDialect) GetCreateTableDdl(tableName string) (string, error) {
 | 
					func (pd *DMDialect) GetTableDDL(tableName string) (string, error) {
 | 
				
			||||||
	ddlSql := fmt.Sprintf("CALL SP_TABLEDEF((SELECT SF_GET_SCHEMA_NAME_BY_ID(CURRENT_SCHID)), '%s')", tableName)
 | 
						ddlSql := fmt.Sprintf("CALL SP_TABLEDEF((SELECT SF_GET_SCHEMA_NAME_BY_ID(CURRENT_SCHID)), '%s')", tableName)
 | 
				
			||||||
	_, res, err := pd.dc.Query(ddlSql)
 | 
						_, res, err := pd.dc.Query(ddlSql)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -185,7 +196,9 @@ func (pd *DMDialect) GetCreateTableDdl(tableName string) (string, error) {
 | 
				
			|||||||
			select OWNER, COMMENTS from DBA_TAB_COMMENTS where TABLE_TYPE='TABLE' and TABLE_NAME = '%s'
 | 
								select OWNER, COMMENTS from DBA_TAB_COMMENTS where TABLE_TYPE='TABLE' and TABLE_NAME = '%s'
 | 
				
			||||||
		    and owner = (SELECT SF_GET_SCHEMA_NAME_BY_ID(CURRENT_SCHID))
 | 
							    and owner = (SELECT SF_GET_SCHEMA_NAME_BY_ID(CURRENT_SCHID))
 | 
				
			||||||
			                                      `, tableName))
 | 
								                                      `, tableName))
 | 
				
			||||||
	if res != nil {
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	for _, re := range res {
 | 
						for _, re := range res {
 | 
				
			||||||
		// COMMENT ON TABLE "SYS_MENU" IS '菜单表';
 | 
							// COMMENT ON TABLE "SYS_MENU" IS '菜单表';
 | 
				
			||||||
		if re["COMMENTS"] != nil {
 | 
							if re["COMMENTS"] != nil {
 | 
				
			||||||
@@ -193,7 +206,6 @@ func (pd *DMDialect) GetCreateTableDdl(tableName string) (string, error) {
 | 
				
			|||||||
			builder.WriteString(tableComment)
 | 
								builder.WriteString(tableComment)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 字段注释
 | 
						// 字段注释
 | 
				
			||||||
	fieldSql := fmt.Sprintf(`
 | 
						fieldSql := fmt.Sprintf(`
 | 
				
			||||||
@@ -203,7 +215,10 @@ func (pd *DMDialect) GetCreateTableDdl(tableName string) (string, error) {
 | 
				
			|||||||
		  AND TABLE_NAME = '%s'
 | 
							  AND TABLE_NAME = '%s'
 | 
				
			||||||
		`, tableName)
 | 
							`, tableName)
 | 
				
			||||||
	_, res, err = pd.dc.Query(fieldSql)
 | 
						_, res, err = pd.dc.Query(fieldSql)
 | 
				
			||||||
	if res != nil {
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	builder.WriteString("\n")
 | 
						builder.WriteString("\n")
 | 
				
			||||||
	for _, re := range res {
 | 
						for _, re := range res {
 | 
				
			||||||
		// COMMENT ON COLUMN "SYS_MENU"."BIZ_CODE" IS '业务编码,应用编码1';
 | 
							// COMMENT ON COLUMN "SYS_MENU"."BIZ_CODE" IS '业务编码,应用编码1';
 | 
				
			||||||
@@ -212,7 +227,6 @@ func (pd *DMDialect) GetCreateTableDdl(tableName string) (string, error) {
 | 
				
			|||||||
			builder.WriteString(fieldComment)
 | 
								builder.WriteString(fieldComment)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 索引信息
 | 
						// 索引信息
 | 
				
			||||||
	indexSql := fmt.Sprintf(`
 | 
						indexSql := fmt.Sprintf(`
 | 
				
			||||||
@@ -223,11 +237,12 @@ func (pd *DMDialect) GetCreateTableDdl(tableName string) (string, error) {
 | 
				
			|||||||
		and indexdef(b.object_id,1) != '禁止查看系统定义的索引信息'
 | 
							and indexdef(b.object_id,1) != '禁止查看系统定义的索引信息'
 | 
				
			||||||
	`, tableName)
 | 
						`, tableName)
 | 
				
			||||||
	_, res, err = pd.dc.Query(indexSql)
 | 
						_, res, err = pd.dc.Query(indexSql)
 | 
				
			||||||
	if res != nil {
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	for _, re := range res {
 | 
						for _, re := range res {
 | 
				
			||||||
		builder.WriteString("\n\n" + re["INDEX_DEF"].(string))
 | 
							builder.WriteString("\n\n" + re["INDEX_DEF"].(string))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return builder.String(), nil
 | 
						return builder.String(), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,6 +43,17 @@ type MysqlDialect struct {
 | 
				
			|||||||
	dc *DbConn
 | 
						dc *DbConn
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (md *MysqlDialect) GetDbServer() (*DbServer, error) {
 | 
				
			||||||
 | 
						_, res, err := md.dc.Query("SELECT VERSION() version")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ds := &DbServer{
 | 
				
			||||||
 | 
							Version: anyx.ConvString(res[0]["version"]),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ds, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (md *MysqlDialect) GetDbNames() ([]string, error) {
 | 
					func (md *MysqlDialect) GetDbNames() ([]string, error) {
 | 
				
			||||||
	_, res, err := md.dc.Query("SELECT SCHEMA_NAME AS dbname FROM SCHEMATA")
 | 
						_, res, err := md.dc.Query("SELECT SCHEMA_NAME AS dbname FROM SCHEMATA")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -166,7 +177,7 @@ func (md *MysqlDialect) GetTableIndex(tableName string) ([]Index, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 获取建表ddl
 | 
					// 获取建表ddl
 | 
				
			||||||
func (md *MysqlDialect) GetCreateTableDdl(tableName string) (string, error) {
 | 
					func (md *MysqlDialect) GetTableDDL(tableName string) (string, error) {
 | 
				
			||||||
	_, res, err := md.dc.Query(fmt.Sprintf("show create table `%s` ", tableName))
 | 
						_, res, err := md.dc.Query(fmt.Sprintf("show create table `%s` ", tableName))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return "", err
 | 
							return "", err
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -106,6 +106,17 @@ type PgsqlDialect struct {
 | 
				
			|||||||
	dc *DbConn
 | 
						dc *DbConn
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (pd *PgsqlDialect) GetDbServer() (*DbServer, error) {
 | 
				
			||||||
 | 
						_, res, err := pd.dc.Query("SHOW server_version")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ds := &DbServer{
 | 
				
			||||||
 | 
							Version: anyx.ConvString(res[0]["server_version"]),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ds, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (pd *PgsqlDialect) GetDbNames() ([]string, error) {
 | 
					func (pd *PgsqlDialect) GetDbNames() ([]string, error) {
 | 
				
			||||||
	_, res, err := pd.dc.Query("SELECT datname AS dbname FROM pg_database WHERE datistemplate = false AND has_database_privilege(datname, 'CONNECT')")
 | 
						_, res, err := pd.dc.Query("SELECT datname AS dbname FROM pg_database WHERE datistemplate = false AND has_database_privilege(datname, 'CONNECT')")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -227,7 +238,7 @@ func (pd *PgsqlDialect) GetTableIndex(tableName string) ([]Index, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 获取建表ddl
 | 
					// 获取建表ddl
 | 
				
			||||||
func (pd *PgsqlDialect) GetCreateTableDdl(tableName string) (string, error) {
 | 
					func (pd *PgsqlDialect) GetTableDDL(tableName string) (string, error) {
 | 
				
			||||||
	_, err := pd.dc.Exec(GetLocalSql(PGSQL_META_FILE, PGSQL_TABLE_DDL_KEY))
 | 
						_, err := pd.dc.Exec(GetLocalSql(PGSQL_META_FILE, PGSQL_TABLE_DDL_KEY))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return "", err
 | 
							return "", err
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,8 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type DbInfo struct {
 | 
					type DbInfo struct {
 | 
				
			||||||
	Id   uint64
 | 
						InstanceId uint64 // 实例id
 | 
				
			||||||
 | 
						Id         uint64 // dbId
 | 
				
			||||||
	Name       string
 | 
						Name       string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Type     DbType // 类型,mysql postgres等
 | 
						Type     DbType // 类型,mysql postgres等
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,9 +29,9 @@ func InitDbRouter(router *gin.RouterGroup) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		req.NewDelete(":dbId", d.DeleteDb).Log(req.NewLogSave("db-删除数据库信息")),
 | 
							req.NewDelete(":dbId", d.DeleteDb).Log(req.NewLogSave("db-删除数据库信息")),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		req.NewGet(":dbId/t-create-ddl", d.GetCreateTableDdl),
 | 
							req.NewGet(":dbId/t-create-ddl", d.GetTableDDL),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		req.NewGet(":dbId/pg/schemas", d.GetPgsqlSchemas),
 | 
							req.NewGet(":dbId/pg/schemas", d.GetSchemas),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		req.NewPost(":dbId/exec-sql", d.ExecSql).Log(req.NewLog("db-执行Sql")),
 | 
							req.NewPost(":dbId/exec-sql", d.ExecSql).Log(req.NewLog("db-执行Sql")),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,10 +25,14 @@ func InitInstanceRouter(router *gin.RouterGroup) {
 | 
				
			|||||||
		req.NewPost("", d.SaveInstance).Log(req.NewLogSave("db-保存数据库实例信息")),
 | 
							req.NewPost("", d.SaveInstance).Log(req.NewLogSave("db-保存数据库实例信息")),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		req.NewGet(":instanceId", d.GetInstance),
 | 
							req.NewGet(":instanceId", d.GetInstance),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		req.NewGet(":instanceId/pwd", d.GetInstancePwd),
 | 
							req.NewGet(":instanceId/pwd", d.GetInstancePwd),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// 获取数据库实例的所有数据库名
 | 
							// 获取数据库实例的所有数据库名
 | 
				
			||||||
		req.NewGet(":instanceId/databases", d.GetDatabaseNames),
 | 
							req.NewGet(":instanceId/databases", d.GetDatabaseNames),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							req.NewGet(":instanceId/server-info", d.GetDbServer),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		req.NewDelete(":instanceId", d.DeleteInstance).Log(req.NewLogSave("db-删除数据库实例")),
 | 
							req.NewDelete(":instanceId", d.DeleteInstance).Log(req.NewLogSave("db-删除数据库实例")),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user