diff --git a/mayfly_go_web/src/assets/iconfont/iconfont.js b/mayfly_go_web/src/assets/iconfont/iconfont.js
index ba16f984..a5702aac 100644
--- a/mayfly_go_web/src/assets/iconfont/iconfont.js
+++ b/mayfly_go_web/src/assets/iconfont/iconfont.js
@@ -1,5 +1,5 @@
(window._iconfont_svg_string_3953964 =
- ''),
+ ''),
(function (c) {
var t = (t = document.getElementsByTagName('script'))[t.length - 1],
a = t.getAttribute('data-injectcss'),
diff --git a/mayfly_go_web/src/assets/iconfont/iconfont.json b/mayfly_go_web/src/assets/iconfont/iconfont.json
index bf0a0409..2df2c56f 100644
--- a/mayfly_go_web/src/assets/iconfont/iconfont.json
+++ b/mayfly_go_web/src/assets/iconfont/iconfont.json
@@ -81,6 +81,13 @@
"font_class": "MSSQLNATIVE",
"unicode": "e600",
"unicode_decimal": 58880
+ },
+ {
+ "icon_id": "7699332",
+ "name": "gaussdb",
+ "font_class": "gauss",
+ "unicode": "e683",
+ "unicode_decimal": 59011
}
]
}
diff --git a/mayfly_go_web/src/views/ops/db/InstanceEdit.vue b/mayfly_go_web/src/views/ops/db/InstanceEdit.vue
index 549703b6..710c5b7d 100644
--- a/mayfly_go_web/src/views/ops/db/InstanceEdit.vue
+++ b/mayfly_go_web/src/views/ops/db/InstanceEdit.vue
@@ -9,13 +9,18 @@
-
-
+
+
{{ dbTypeAndDialect[1].getInfo().name }}
-
+
diff --git a/mayfly_go_web/src/views/ops/db/SqlExec.vue b/mayfly_go_web/src/views/ops/db/SqlExec.vue
index fd5ef572..1aab107c 100644
--- a/mayfly_go_web/src/views/ops/db/SqlExec.vue
+++ b/mayfly_go_web/src/views/ops/db/SqlExec.vue
@@ -443,7 +443,7 @@ onBeforeUnmount(() => {
* 设置editor高度和数据表高度
*/
const setHeight = () => {
- state.dataTabsTableHeight = window.innerHeight - 270 + 'px';
+ state.dataTabsTableHeight = window.innerHeight - 253 + 'px';
state.tablesOpHeight = window.innerHeight - 225 + 'px';
};
diff --git a/mayfly_go_web/src/views/ops/db/component/table/DbTableDataOp.vue b/mayfly_go_web/src/views/ops/db/component/table/DbTableDataOp.vue
index 64a45fe2..3ff64f89 100644
--- a/mayfly_go_web/src/views/ops/db/component/table/DbTableDataOp.vue
+++ b/mayfly_go_web/src/views/ops/db/component/table/DbTableDataOp.vue
@@ -158,21 +158,62 @@
@data-delete="onRefresh"
>
-
-
+
+
+ {{ sql }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 总 {{ state.total }} 条
+
+
-
- {{ state.sql }}
-
@@ -242,6 +283,7 @@ import { DbDialect, getDbDialect } from '@/views/ops/db/dialect';
import SvgIcon from '@/components/svgIcon/index.vue';
import ColumnFormItem from './ColumnFormItem.vue';
import { useEventListener, useStorage } from '@vueuse/core';
+import { copyToClipboard } from '@/common/utils/string';
const props = defineProps({
dbId: {
@@ -290,7 +332,10 @@ const state = reactive({
defaultPageSize * 40,
defaultPageSize * 80,
],
- count: 0,
+ setPageNum: 0,
+ total: 0,
+ showTotal: 0,
+ counting: false,
selectionDatas: [] as any,
condPopVisible: false,
columnNameSearch: '',
@@ -314,7 +359,7 @@ const state = reactive({
dbDialect: {} as DbDialect,
});
-const { datas, condition, loading, columns, pageNum, pageSize, pageSizes, count, hasUpdatedFileds, conditionDialog, addDataDialog, dbDialect } = toRefs(state);
+const { datas, condition, loading, columns, pageNum, pageSize, pageSizes, sql, hasUpdatedFileds, conditionDialog, addDataDialog, dbDialect } = toRefs(state);
watch(
() => props.tableHeight,
@@ -347,18 +392,19 @@ const onRefresh = async () => {
await selectData();
};
-/**
- * 数据tab修改页数
- */
-const pageChange = async () => {
- await selectData();
-};
+watch(
+ () => state.pageNum,
+ async () => {
+ await selectData();
+ }
+);
/**
* 单表数据信息查询数据
*/
const selectData = async () => {
state.loading = true;
+ state.setPageNum = state.pageNum;
const dbInst = getNowDbInst();
const db = props.dbName;
const table = props.tableName;
@@ -371,16 +417,10 @@ const selectData = async () => {
state.columns = columns;
}
- const countRes = await dbInst.runSql(db, dbInst.getDefaultCountSql(table, state.condition));
- state.count = parseInt(countRes.res[0].count || countRes.res[0].COUNT || 0);
let sql = dbInst.getDefaultSelectSql(db, table, state.condition, state.orderBy, state.pageNum, state.pageSize);
state.sql = sql;
- if (state.count > 0) {
- const colAndData: any = await dbInst.runSql(db, sql);
- state.datas = colAndData.res;
- } else {
- state.datas = [];
- }
+ const colAndData: any = await dbInst.runSql(db, sql);
+ state.datas = colAndData.res;
} finally {
state.loading = false;
}
@@ -392,6 +432,38 @@ const handleSizeChange = async (size: any) => {
await selectData();
};
+const handleEndPage = async () => {
+ await handleCount();
+ state.pageNum = Math.ceil(state.total / state.pageSize);
+ await selectData();
+};
+
+const handleSetPageNum = async () => {
+ state.pageNum = state.setPageNum;
+ await selectData();
+};
+const handleCount = async () => {
+ state.counting = true;
+
+ try {
+ const db = props.dbName;
+ const table = props.tableName;
+ const dbInst = getNowDbInst();
+ const countRes = await dbInst.runSql(db, dbInst.getDefaultCountSql(table, state.condition));
+ state.total = parseInt(countRes.res[0].count || countRes.res[0].COUNT || 0);
+ state.showTotal = true;
+ } catch (e) {
+ /* empty */
+ }
+
+ state.counting = false;
+};
+
+const handleCopySql = async (sql: string) => {
+ await copyToClipboard(sql);
+ ElMessage.success('复制成功');
+};
+
// 完整的条件,每次选中后会重置条件框内容,故需要这个变量在获取建议时将文本框内容保存
let completeCond = '';
// 是否存在列建议
@@ -586,4 +658,8 @@ const addRow = async () => {
};
-
+
diff --git a/mayfly_go_web/src/views/ops/db/dialect/gauss_dialect.ts b/mayfly_go_web/src/views/ops/db/dialect/gauss_dialect.ts
new file mode 100644
index 00000000..9e1e88eb
--- /dev/null
+++ b/mayfly_go_web/src/views/ops/db/dialect/gauss_dialect.ts
@@ -0,0 +1,17 @@
+import { PostgresqlDialect } from '@/views/ops/db/dialect/postgres_dialect';
+import { DialectInfo } from '@/views/ops/db/dialect/index';
+
+let gsDialectInfo: DialectInfo;
+export class GaussDialect extends PostgresqlDialect {
+ getInfo(): DialectInfo {
+ if (gsDialectInfo) {
+ return gsDialectInfo;
+ }
+
+ gsDialectInfo = {} as DialectInfo;
+ Object.assign(gsDialectInfo, super.getInfo());
+ gsDialectInfo.icon = 'iconfont icon-gauss';
+ gsDialectInfo.name = 'GaussDB';
+ return gsDialectInfo;
+ }
+}
diff --git a/mayfly_go_web/src/views/ops/db/dialect/index.ts b/mayfly_go_web/src/views/ops/db/dialect/index.ts
index e8416c46..91c1caab 100644
--- a/mayfly_go_web/src/views/ops/db/dialect/index.ts
+++ b/mayfly_go_web/src/views/ops/db/dialect/index.ts
@@ -5,6 +5,7 @@ import { OracleDialect } from '@/views/ops/db/dialect/oracle_dialect';
import { MariadbDialect } from '@/views/ops/db/dialect/mariadb_dialect';
import { SqliteDialect } from '@/views/ops/db/dialect/sqlite_dialect';
import { MssqlDialect } from '@/views/ops/db/dialect/mssql_dialect';
+import { GaussDialect } from '@/views/ops/db/dialect/gauss_dialect';
export interface sqlColumnType {
udtName: string;
@@ -116,6 +117,7 @@ export const DbType = {
mysql: 'mysql',
mariadb: 'mariadb',
postgresql: 'postgres',
+ gauss: 'gauss',
dm: 'dm', // 达梦
oracle: 'oracle',
sqlite: 'sqlite',
@@ -126,7 +128,7 @@ export const DbType = {
export const noSchemaTypes = [DbType.mysql, DbType.mariadb, DbType.sqlite];
// 有schema层的数据库
-export const schemaDbTypes = [DbType.postgresql, DbType.dm, DbType.oracle, DbType.mssql];
+export const schemaDbTypes = [DbType.postgresql, DbType.gauss, DbType.dm, DbType.oracle, DbType.mssql];
export const editDbTypes = [...noSchemaTypes, ...schemaDbTypes];
@@ -225,6 +227,7 @@ export const getDbDialect = (dbType: string): DbDialect => {
registerDbDialect(DbType.mysql, mysqlDialect);
registerDbDialect(DbType.mariadb, new MariadbDialect());
registerDbDialect(DbType.postgresql, new PostgresqlDialect());
+ registerDbDialect(DbType.gauss, new GaussDialect());
registerDbDialect(DbType.dm, new DMDialect());
registerDbDialect(DbType.oracle, new OracleDialect());
registerDbDialect(DbType.sqlite, new SqliteDialect());
diff --git a/server/internal/db/api/db_data_sync.go b/server/internal/db/api/db_data_sync.go
index b327a034..d8b0784a 100644
--- a/server/internal/db/api/db_data_sync.go
+++ b/server/internal/db/api/db_data_sync.go
@@ -14,7 +14,6 @@ import (
"strings"
"github.com/gin-gonic/gin"
- "github.com/google/uuid"
)
type DataSyncTask struct {
@@ -46,13 +45,6 @@ func (d *DataSyncTask) SaveTask(rc *req.Ctx) {
task.DataSql = sql
form.DataSql = sql
- key := task.TaskKey
- // 判断key为空就生成随机key
- if key == "" {
- key = uuid.New().String()
- task.TaskKey = key
- }
-
rc.ReqParam = form
biz.ErrIsNil(d.DataSyncTaskApp.Save(rc.MetaCtx, task))
}
@@ -88,7 +80,7 @@ func (d *DataSyncTask) ChangeStatus(rc *req.Ctx) {
func (d *DataSyncTask) Run(rc *req.Ctx) {
taskId := getTaskId(rc.GinCtx)
rc.ReqParam = taskId
- d.DataSyncTaskApp.RunCronJob(taskId)
+ _ = d.DataSyncTaskApp.RunCronJob(taskId)
}
func (d *DataSyncTask) Stop(rc *req.Ctx) {
diff --git a/server/internal/db/application/db.go b/server/internal/db/application/db.go
index 8ecf216d..ff75fad5 100644
--- a/server/internal/db/application/db.go
+++ b/server/internal/db/application/db.go
@@ -154,7 +154,7 @@ func (d *dbAppImpl) GetDbConn(dbId uint64, dbName string) (*dbi.DbConn, error) {
checkDb := dbName
// 兼容pgsql/dm db/schema模式
- if dbi.DbTypePostgres.Equal(instance.Type) || dbi.DbTypeDM.Equal(instance.Type) || dbi.DbTypeOracle.Equal(instance.Type) || dbi.DbTypeMssql.Equal(instance.Type) {
+ if dbi.DbTypePostgres.Equal(instance.Type) || dbi.DbTypeGauss.Equal(instance.Type) || dbi.DbTypeDM.Equal(instance.Type) || dbi.DbTypeOracle.Equal(instance.Type) || dbi.DbTypeMssql.Equal(instance.Type) {
ss := strings.Split(dbName, "/")
if len(ss) > 1 {
checkDb = ss[0]
diff --git a/server/internal/db/application/db_data_sync.go b/server/internal/db/application/db_data_sync.go
index 60f78c74..803b91cd 100644
--- a/server/internal/db/application/db_data_sync.go
+++ b/server/internal/db/application/db_data_sync.go
@@ -5,6 +5,7 @@ import (
"database/sql"
"encoding/json"
"fmt"
+ "github.com/google/uuid"
"mayfly-go/internal/db/dbm/dbi"
"mayfly-go/internal/db/domain/entity"
"mayfly-go/internal/db/domain/repository"
@@ -53,8 +54,8 @@ var (
dateTimeReg = regexp.MustCompile(`^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$`)
)
-func (d *dataSyncAppImpl) InjectDbDataSyncTaskRepo(repo repository.DataSyncTask) {
- d.Repo = repo
+func (app *dataSyncAppImpl) InjectDbDataSyncTaskRepo(repo repository.DataSyncTask) {
+ app.Repo = repo
}
func (app *dataSyncAppImpl) GetPageList(condition *entity.DataSyncTaskQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
@@ -64,15 +65,22 @@ func (app *dataSyncAppImpl) GetPageList(condition *entity.DataSyncTaskQuery, pag
func (app *dataSyncAppImpl) Save(ctx context.Context, taskEntity *entity.DataSyncTask) error {
var err error
if taskEntity.Id == 0 {
+ // 新建时生成key
+ taskEntity.TaskKey = uuid.New().String()
err = app.Insert(ctx, taskEntity)
} else {
err = app.UpdateById(ctx, taskEntity)
}
+
if err != nil {
return err
}
- app.AddCronJob(taskEntity)
+ task, err := app.GetById(new(entity.DataSyncTask), taskEntity.Id)
+ if err != nil {
+ return err
+ }
+ app.AddCronJob(task)
return nil
}
@@ -92,9 +100,13 @@ func (app *dataSyncAppImpl) AddCronJob(taskEntity *entity.DataSyncTask) {
// 根据状态添加新的任务
if taskEntity.Status == entity.DataSyncTaskStatusEnable {
scheduler.AddFunByKey(key, taskEntity.TaskCron, func() {
- if err := app.RunCronJob(taskEntity.Id); err != nil {
- logx.Errorf("定时执行数据同步任务失败: %s", err.Error())
- }
+ go func() {
+ taskId := taskEntity.Id
+ logx.Infof("开始执行同步任务: %d", taskId)
+ if err := app.RunCronJob(taskId); err != nil {
+ logx.Errorf("定时执行数据同步任务失败: %s", err.Error())
+ }
+ }()
})
}
}
diff --git a/server/internal/db/dbm/dbi/db_type.go b/server/internal/db/dbm/dbi/db_type.go
index 21b015f6..1a020fe6 100644
--- a/server/internal/db/dbm/dbi/db_type.go
+++ b/server/internal/db/dbm/dbi/db_type.go
@@ -14,6 +14,7 @@ const (
DbTypeMysql DbType = "mysql"
DbTypeMariadb DbType = "mariadb"
DbTypePostgres DbType = "postgres"
+ DbTypeGauss DbType = "gauss"
DbTypeDM DbType = "dm"
DbTypeOracle DbType = "oracle"
DbTypeSqlite DbType = "sqlite"
@@ -43,7 +44,7 @@ func (dbType DbType) QuoteIdentifier(name string) string {
switch dbType {
case DbTypeMysql, DbTypeMariadb:
return quoteIdentifier(name, "`")
- case DbTypePostgres:
+ case DbTypePostgres, DbTypeGauss:
return quoteIdentifier(name, `"`)
case DbTypeMssql:
return fmt.Sprintf("[%s]", name)
@@ -56,7 +57,7 @@ func (dbType DbType) RemoveQuote(name string) string {
switch dbType {
case DbTypeMysql, DbTypeMariadb:
return removeQuote(name, "`")
- case DbTypePostgres:
+ case DbTypePostgres, DbTypeGauss:
return removeQuote(name, `"`)
default:
return removeQuote(name, `"`)
@@ -69,7 +70,7 @@ func (dbType DbType) QuoteLiteral(literal string) string {
literal = strings.ReplaceAll(literal, `\`, `\\`)
literal = strings.ReplaceAll(literal, `'`, `''`)
return "'" + literal + "'"
- case DbTypePostgres:
+ case DbTypePostgres, DbTypeGauss:
return pq.QuoteLiteral(literal)
default:
return pq.QuoteLiteral(literal)
@@ -80,7 +81,7 @@ func (dbType DbType) MetaDbName() string {
switch dbType {
case DbTypeMysql, DbTypeMariadb:
return ""
- case DbTypePostgres:
+ case DbTypePostgres, DbTypeGauss:
return "postgres"
case DbTypeDM:
return ""
@@ -93,7 +94,7 @@ func (dbType DbType) Dialect() sqlparser.Dialect {
switch dbType {
case DbTypeMysql, DbTypeMariadb:
return sqlparser.MysqlDialect{}
- case DbTypePostgres:
+ case DbTypePostgres, DbTypeGauss:
return sqlparser.PostgresDialect{}
default:
return sqlparser.PostgresDialect{}
@@ -121,7 +122,7 @@ func (dbType DbType) StmtSetForeignKeyChecks(check bool) string {
} else {
return "SET FOREIGN_KEY_CHECKS = 0;\n"
}
- case DbTypePostgres:
+ case DbTypePostgres, DbTypeGauss:
// not currently supported postgres
return ""
default:
@@ -133,7 +134,7 @@ func (dbType DbType) StmtUseDatabase(dbName string) string {
switch dbType {
case DbTypeMysql, DbTypeMariadb:
return fmt.Sprintf("USE %s;\n", dbType.QuoteIdentifier(dbName))
- case DbTypePostgres:
+ case DbTypePostgres, DbTypeGauss:
// not currently supported postgres
return ""
default:
diff --git a/server/internal/db/dbm/postgres/meta.go b/server/internal/db/dbm/postgres/meta.go
index 56b1f004..b37878a3 100644
--- a/server/internal/db/dbm/postgres/meta.go
+++ b/server/internal/db/dbm/postgres/meta.go
@@ -16,13 +16,18 @@ import (
func init() {
dbi.Register(dbi.DbTypePostgres, new(PostgresMeta))
+
+ gauss := new(PostgresMeta)
+ gauss.Param = "dbtype=gauss"
+ dbi.Register(dbi.DbTypeGauss, gauss)
}
type PostgresMeta struct {
+ Param string
}
func (md *PostgresMeta) GetSqlDb(d *dbi.DbInfo) (*sql.DB, error) {
- driverName := string(d.Type)
+ driverName := "postgres"
// SSH Conect
if d.SshTunnelMachineId > 0 {
// 如果使用了隧道,则使用`postgres:ssh:隧道机器id`注册名
@@ -67,6 +72,10 @@ func (md *PostgresMeta) GetSqlDb(d *dbi.DbInfo) (*sql.DB, error) {
dsn = fmt.Sprintf("%s %s", dsn, strings.Join(strings.Split(d.Params, "&"), " "))
}
+ if md.Param != "" && !strings.Contains(dsn, "dbtype") {
+ dsn = fmt.Sprintf("%s %s", dsn, md.Param)
+ }
+
return sql.Open(driverName, dsn)
}