refactor: dbms与标签管理优化

This commit is contained in:
meilin.huang
2024-03-21 17:15:52 +08:00
parent b13d27ccd6
commit b2cfd1517c
43 changed files with 536 additions and 564 deletions

View File

@@ -56,7 +56,7 @@
"prettier": "^3.2.5",
"sass": "^1.69.0",
"typescript": "^5.3.2",
"vite": "^5.1.6",
"vite": "^5.2.2",
"vue-eslint-parser": "^9.4.2"
},
"browserslist": [

View File

@@ -9,6 +9,7 @@
:show-selection="true"
v-model:selection-data="state.selectionData"
:columns="columns"
lazy
>
<template #instanceSelect>
<el-select remote :remote-method="getInstances" v-model="query.instanceId" placeholder="输入并选择实例" filterable clearable>
@@ -222,6 +223,13 @@ import ResourceTags from '../component/ResourceTags.vue';
const DbEdit = defineAsyncComponent(() => import('./DbEdit.vue'));
const props = defineProps({
lazy: {
type: [Boolean],
default: false,
},
});
const perms = {
base: 'db',
saveDb: 'db:save',
@@ -336,6 +344,9 @@ onMounted(async () => {
if (Object.keys(actionBtns).length > 0) {
columns.value.push(actionColumn);
}
if (!props.lazy) {
search();
}
});
const checkRouteTagPath = (query: any) => {
@@ -345,7 +356,10 @@ const checkRouteTagPath = (query: any) => {
return query;
};
const search = async () => {
const search = async (tagPath: string = '') => {
if (tagPath) {
state.query.tagPath = tagPath;
}
pageTableRef.value.search();
};
@@ -515,6 +529,8 @@ const supportAction = (action: string, dbType: string): boolean => {
}
return actions.includes(action);
};
defineExpose({ search });
</script>
<style lang="scss">
.db-list {

View File

@@ -131,6 +131,7 @@ import { reactive, ref, toRefs, watch } from 'vue';
import { ElMessage } from 'element-plus';
import SqlExecBox from '../sqleditor/SqlExecBox';
import { DbType, getDbDialect, IndexDefinition, RowDefinition } from '../../dialect/index';
import { DbInst } from '../../db';
const props = defineProps({
visible: {
@@ -500,6 +501,7 @@ watch(
state.tableData.indexs.res = [];
// 索引列下拉选
state.tableData.indexs.columns = [];
DbInst.initColumns(columns);
// 回显列
if (columns && Array.isArray(columns) && columns.length > 0) {
columns.forEach((a) => {

View File

@@ -175,6 +175,9 @@ export class DbInst {
db: dbName,
tableName: table,
});
DbInst.initColumns(columns);
db.columnsMap.set(table, columns);
return columns;
}
@@ -466,6 +469,32 @@ export class DbInst {
const flexWidth: number = contentWidth > columnWidth ? contentWidth : columnWidth;
return flexWidth > 500 ? 500 : flexWidth;
};
// 初始化所有列信息完善需要显示的列类型包含长度等如varchar(20)
static initColumns(columns: any[]) {
for (let col of columns) {
if (col.charMaxLength > 0) {
col.showDataType = `${col.dataType}(${col.charMaxLength})`;
col.showLength = col.charMaxLength;
col.showScale = null;
continue;
}
if (col.numPrecision > 0) {
if (col.numScale > 0) {
col.showDataType = `${col.dataType}(${col.numPrecision},${col.numScale})`;
col.showScale = col.numScale;
} else {
col.showDataType = `${col.dataType}(${col.numPrecision})`;
col.showScale = null;
}
col.showLength = col.numPrecision;
continue;
}
col.showDataType = col.dataType;
}
}
}
/**

View File

@@ -9,6 +9,7 @@
:show-selection="true"
v-model:selection-data="state.selectionData"
:columns="columns"
:lazy="true"
>
<template #tableHeader>
<el-button v-auth="perms.addMachine" type="primary" icon="plus" @click="openFormDialog(false)" plain>添加 </el-button>
@@ -205,6 +206,13 @@ const MachineStats = defineAsyncComponent(() => import('./MachineStats.vue'));
const MachineRec = defineAsyncComponent(() => import('./MachineRec.vue'));
const ProcessList = defineAsyncComponent(() => import('./ProcessList.vue'));
const props = defineProps({
lazy: {
type: [Boolean],
default: false,
},
});
const router = useRouter();
const route = useRoute();
const terminalDialogRef: any = ref(null);
@@ -282,7 +290,11 @@ const state = reactive({
const { params, infoDialog, selectionData, serviceDialog, processDialog, fileDialog, machineStatsDialog, machineEditDialog, machineRecDialog } = toRefs(state);
onMounted(async () => {});
onMounted(async () => {
if (!props.lazy) {
search();
}
});
const checkRouteTagPath = (query: any) => {
if (route.query.tagPath) {
@@ -396,7 +408,10 @@ const showMachineStats = async (machine: any) => {
state.machineStatsDialog.visible = true;
};
const search = async () => {
const search = async (tagPath: string = '') => {
if (tagPath) {
state.params.tagPath = tagPath;
}
pageTableRef.value.search();
};
@@ -437,6 +452,8 @@ const showRec = (row: any) => {
state.machineRecDialog.machineId = row.id;
state.machineRecDialog.visible = true;
};
defineExpose({ search });
</script>
<style>

View File

@@ -127,6 +127,12 @@ const handleClose = () => {
</script>
<style lang="scss">
#terminalRecDialog {
overflow: hidden;
#rc-player {
overflow: hidden;
}
.el-overlay .el-overlay-dialog .el-dialog .el-dialog__body {
padding: 0px !important;
}

View File

@@ -9,6 +9,7 @@
:show-selection="true"
v-model:selection-data="selectionData"
:columns="columns"
lazy
>
<template #tableHeader>
<el-button type="primary" icon="plus" @click="editMongo(true)" plain>添加</el-button>
@@ -56,6 +57,13 @@ const MongoEdit = defineAsyncComponent(() => import('./MongoEdit.vue'));
const MongoDbs = defineAsyncComponent(() => import('./MongoDbs.vue'));
const MongoRunCommand = defineAsyncComponent(() => import('./MongoRunCommand.vue'));
const props = defineProps({
lazy: {
type: [Boolean],
default: false,
},
});
const route = useRoute();
const pageTableRef: Ref<any> = ref(null);
@@ -92,7 +100,11 @@ const state = reactive({
const { selectionData, query, mongoEditDialog, dbsVisible, usersVisible } = toRefs(state);
onMounted(async () => {});
onMounted(() => {
if (!props.lazy) {
search();
}
});
const checkRouteTagPath = (query: any) => {
if (route.query.tagPath) {
@@ -126,7 +138,10 @@ const deleteMongo = async () => {
}
};
const search = async () => {
const search = async (tagPath: string = '') => {
if (tagPath) {
state.query.tagPath = tagPath;
}
pageTableRef.value.search();
};
@@ -140,6 +155,8 @@ const editMongo = async (data: any) => {
}
state.mongoEditDialog.visible = true;
};
defineExpose({ search });
</script>
<style></style>

View File

@@ -9,6 +9,7 @@
:show-selection="true"
v-model:selection-data="selectionData"
:columns="columns"
lazy
>
<template #tableHeader>
<el-button type="primary" icon="plus" @click="editRedis(false)" plain>添加</el-button>
@@ -161,6 +162,13 @@ import { TagResourceTypeEnum } from '@/common/commonEnum';
import { useRoute } from 'vue-router';
import { getTagPathSearchItem } from '../component/tag';
const props = defineProps({
lazy: {
type: [Boolean],
default: false,
},
});
const route = useRoute();
const pageTableRef: Ref<any> = ref(null);
@@ -213,7 +221,11 @@ const state = reactive({
const { selectionData, query, detailDialog, clusterInfoDialog, infoDialog, redisEditDialog } = toRefs(state);
onMounted(async () => {});
onMounted(() => {
if (!props.lazy) {
search();
}
});
const checkRouteTagPath = (query: any) => {
if (route.query.tagPath) {
@@ -261,7 +273,10 @@ const onShowClusterInfo = async (redis: any) => {
state.clusterInfoDialog.visible = true;
};
const search = () => {
const search = async (tagPath: string = '') => {
if (tagPath) {
state.query.tagPath = tagPath;
}
pageTableRef.value.search();
};
@@ -275,6 +290,8 @@ const editRedis = async (data: any) => {
}
state.redisEditDialog.visible = true;
};
defineExpose({ search });
</script>
<style></style>

View File

@@ -1,18 +1,24 @@
<template>
<div class="tag-tree-list card">
<div class="card pd10">
<el-input v-model="filterTag" clearable placeholder="输入关键字过滤(右击进行操作)" style="width: 220px; margin-right: 10px" />
<el-button v-if="useUserInfo().userInfo.username == 'admin'" v-auth="'tag:save'" type="primary" icon="plus" @click="showSaveTagDialog(null)"
>添加</el-button
>
<Splitpanes class="default-theme">
<Pane size="25" min-size="20" max-size="30">
<div class="card pd5 mr5">
<el-input v-model="filterTag" clearable placeholder="关键字过滤(右击操作)" style="width: 200px; margin-right: 10px" />
<el-button
v-if="useUserInfo().userInfo.username == 'admin'"
v-auth="'tag:save'"
type="primary"
icon="plus"
@click="showSaveTagDialog(null)"
></el-button>
<div style="float: right">
<el-tooltip placement="top">
<template #content>
1. 用于将资产进行归类
<br />2. 可在团队管理中进行分配用于资源隔离 <br />3. 拥有父标签的团队成员可访问操作其自身或子标签关联的资源
</template>
<span
>标签作用<el-icon>
<span>
<el-icon>
<question-filled />
</el-icon>
</span>
@@ -24,6 +30,7 @@
ref="tagTreeRef"
class="none-select"
node-key="id"
:highlight-current="true"
:props="props"
:data="data"
@node-expand="handleNodeExpand"
@@ -31,7 +38,7 @@
@node-contextmenu="nodeContextmenu"
@node-click="treeNodeClick"
:default-expanded-keys="defaultExpandedKeys"
:expand-on-click-node="true"
:expand-on-click-node="false"
:filter-node-method="filterNode"
>
<template #default="{ data }">
@@ -47,6 +54,44 @@
</template>
</el-tree>
</el-scrollbar>
</Pane>
<Pane min-size="40">
<div class="ml10">
<el-tabs @tab-change="tabChange" v-model="state.activeTabName" v-if="currentTag">
<el-tab-pane label="标签详情" :name="TagDetail">
<el-descriptions :column="2" border>
<el-descriptions-item label="code">{{ currentTag.code }}</el-descriptions-item>
<el-descriptions-item label="code路径">{{ currentTag.codePath }}</el-descriptions-item>
<el-descriptions-item label="名称">{{ currentTag.name }}</el-descriptions-item>
<el-descriptions-item label="备注">{{ currentTag.remark }}</el-descriptions-item>
<el-descriptions-item label="创建者">{{ currentTag.creator }}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ dateFormat(currentTag.createTime) }}</el-descriptions-item>
<el-descriptions-item label="修改者">{{ currentTag.modifier }}</el-descriptions-item>
<el-descriptions-item label="更新时间">{{ dateFormat(currentTag.updateTime) }}</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
<el-tab-pane :label="`机器 (${resourceCount.machine})`" :name="MachineTag">
<MachineList lazy ref="machineListRef" />
</el-tab-pane>
<el-tab-pane :label="`数据库 (${resourceCount.db})`" :name="DbTag">
<DbList lazy ref="dbListRef" />
</el-tab-pane>
<el-tab-pane :label="`Redis (${resourceCount.redis})`" :name="RedisTag">
<RedisList lazy ref="redisListRef" />
</el-tab-pane>
<el-tab-pane :label="`Mongo (${resourceCount.mongo})`" :name="MongoTag">
<MongoList lazy ref="mongoListRef" />
</el-tab-pane>
</el-tabs>
</div>
</Pane>
</Splitpanes>
<el-dialog width="500px" :title="saveTabDialog.title" :before-close="cancelSaveTag" v-model="saveTabDialog.visible">
<el-form ref="tagForm" :rules="rules" :model="saveTabDialog.form" label-width="auto">
@@ -68,55 +113,22 @@
</template>
</el-dialog>
<el-dialog v-model="infoDialog.visible">
<el-descriptions title="节点信息" :column="2" border>
<el-descriptions-item label="code">{{ infoDialog.data.code }}</el-descriptions-item>
<el-descriptions-item label="code路径">{{ infoDialog.data.codePath }}</el-descriptions-item>
<el-descriptions-item label="名称">{{ infoDialog.data.name }}</el-descriptions-item>
<el-descriptions-item label="备注">{{ infoDialog.data.remark }}</el-descriptions-item>
<el-descriptions-item label="创建者">{{ infoDialog.data.creator }}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ dateFormat(infoDialog.data.createTime) }}</el-descriptions-item>
<el-descriptions-item label="修改者">{{ infoDialog.data.modifier }}</el-descriptions-item>
<el-descriptions-item label="更新时间">{{ dateFormat(infoDialog.data.updateTime) }}</el-descriptions-item>
</el-descriptions>
</el-dialog>
<el-dialog :title="`[ ${resourceDialog.tagPath} ] 关联的资源`" v-model="resourceDialog.visible" width="500px">
<el-table max-height="300" :data="resourceDialog.data">
<el-table-column property="resourceType" label="资源类型" min-width="50" show-overflow-tooltip>
<template #default="scope">
{{ EnumValue.getLabelByValue(TagResourceTypeEnum, scope.row.resourceType) }}
</template>
</el-table-column>
<el-table-column property="count" label="数量" min-width="50" show-overflow-tooltip> </el-table-column>
<el-table-column label="操作" min-width="50" show-overflow-tooltip>
<template #default="scope">
<el-button v-auth="scope.row.showAuthCode" @click="showResources(scope.row.resourceType, resourceDialog.tagPath)" link type="success"
>查看</el-button
>
</template>
</el-table-column>
</el-table>
</el-dialog>
<contextmenu :dropdown="state.contextmenu.dropdown" :items="state.contextmenu.items" ref="contextmenuRef" />
</div>
</template>
<script lang="ts" setup>
import { toRefs, ref, watch, reactive, onMounted } from 'vue';
import { toRefs, ref, watch, reactive, onMounted, Ref } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { tagApi } from './api';
import { dateFormat } from '@/common/utils/date';
import { Contextmenu, ContextmenuItem } from '@/components/contextmenu/index';
import { TagResourceTypeEnum } from '../../../common/commonEnum';
import EnumValue from '@/common/Enum';
import { useRouter } from 'vue-router';
import { hasPerm } from '@/components/auth/auth';
import { useUserInfo } from '@/store/userInfo';
import { Splitpanes, Pane } from 'splitpanes';
import MachineList from '../machine/MachineList.vue';
import RedisList from '../redis/RedisList.vue';
import MongoList from '../mongo/MongoList.vue';
import DbList from '../db/DbList.vue';
interface Tree {
id: number;
@@ -125,14 +137,20 @@ interface Tree {
children?: Tree[];
}
const router = useRouter();
const tagForm: any = ref(null);
const tagTreeRef: any = ref(null);
const filterTag = ref('');
const contextmenuRef = ref();
const machineListRef: Ref<any> = ref(null);
const dbListRef: Ref<any> = ref(null);
const redisListRef: Ref<any> = ref(null);
const mongoListRef: Ref<any> = ref(null);
const contextmenuInfo = new ContextmenuItem('info', '详情').withIcon('view').withOnClick((data: any) => info(data));
const TagDetail = 'tagDetail';
const MachineTag = 'machineTag';
const DbTag = 'dbTag';
const RedisTag = 'redisTag';
const MongoTag = 'mongoTag';
const contextmenuAdd = new ContextmenuItem('addTag', '添加子标签')
.withIcon('circle-plus')
@@ -153,14 +171,6 @@ const contextmenuDel = new ContextmenuItem('delete', '删除')
})
.withOnClick((data: any) => deleteTag(data));
const contextmenuShowRelateResource = new ContextmenuItem('showRelateResources', '查看关联资源')
.withIcon('view')
.withHideFunc((data: any) => {
// 存在子标签,则不允许查看关联资源
return data.children;
})
.withOnClick((data: any) => showRelateResource(data));
const state = reactive({
data: [],
saveTabDialog: {
@@ -168,12 +178,6 @@ const state = reactive({
visible: false,
form: { id: 0, pid: 0, code: '', name: '', remark: '' },
},
infoDialog: {
title: '',
visible: false,
// 资源类型选择是否选
data: null as any,
},
resourceDialog: {
title: '',
visible: false,
@@ -187,11 +191,14 @@ const state = reactive({
x: 0,
y: 0,
},
items: [contextmenuInfo, contextmenuEdit, contextmenuAdd, contextmenuDel, contextmenuShowRelateResource],
items: [contextmenuEdit, contextmenuAdd, contextmenuDel],
},
activeTabName: 'tagDetail',
currentTag: null as any,
resourceCount: {} as any,
});
const { data, saveTabDialog, infoDialog, resourceDialog, defaultExpandedKeys } = toRefs(state);
const { data, saveTabDialog, currentTag, resourceCount, defaultExpandedKeys } = toRefs(state);
const props = {
label: 'name',
@@ -199,14 +206,7 @@ const props = {
};
const rules = {
code: [
{ required: true, message: '标识符不能为空', trigger: 'blur' },
// {
// pattern: /^\w+$/g,
// message: '标识符只能为空数字字母下划线等',
// trigger: 'blur',
// },
],
code: [{ required: true, message: '标识符不能为空', trigger: 'blur' }],
name: [{ required: true, message: '名称不能为空', trigger: 'blur' }],
};
@@ -218,6 +218,40 @@ watch(filterTag, (val) => {
tagTreeRef.value!.filter(val);
});
watch(
() => state.currentTag,
(val: any) => {
tagApi.countTagResource.request({ tagPath: val.codePath }).then((res: any) => {
state.resourceCount = res;
});
setNowTabData();
}
);
const tabChange = () => {
setNowTabData();
};
const setNowTabData = () => {
const tagPath = state.currentTag.codePath;
switch (state.activeTabName) {
case MachineTag:
machineListRef.value.search(tagPath);
break;
case DbTag:
dbListRef.value.search(tagPath);
break;
case RedisTag:
redisListRef.value.search(tagPath);
break;
case MongoTag:
mongoListRef.value.search(tagPath);
break;
default:
break;
}
};
const filterNode = (value: string, data: Tree) => {
if (!value) return true;
return data.codePath.includes(value) || data.name.includes(value);
@@ -236,16 +270,12 @@ const nodeContextmenu = (event: any, data: any) => {
contextmenuRef.value.openContextmenu(data);
};
const treeNodeClick = () => {
const treeNodeClick = (data: any) => {
state.currentTag = data;
// 关闭可能存在的右击菜单
contextmenuRef.value.closeContextmenu();
};
const info = async (data: any) => {
state.infoDialog.data = data;
state.infoDialog.visible = true;
};
const showSaveTagDialog = (data: any) => {
if (data) {
state.saveTabDialog.form.pid = data.id;
@@ -265,66 +295,6 @@ const showEditTagDialog = (data: any) => {
state.saveTabDialog.visible = true;
};
const showRelateResource = async (data: any) => {
const resourceMap = new Map();
state.resourceDialog.tagPath = data.codePath;
const tagResources = await tagApi.getTagResources.request({ tagId: data.id });
for (let tagResource of tagResources) {
const resourceType = tagResource.resourceType;
const exist = resourceMap.get(resourceType);
if (exist) {
exist.count = exist.count + 1;
continue;
}
// 相关管理页面基础权限
let showAuthCode = '';
if (resourceType == TagResourceTypeEnum.Machine.value) {
showAuthCode = 'machine';
}
if (resourceType == TagResourceTypeEnum.Db.value) {
showAuthCode = 'db';
}
if (resourceType == TagResourceTypeEnum.Redis.value) {
showAuthCode = 'redis:manage';
}
if (resourceType == TagResourceTypeEnum.Mongo.value) {
showAuthCode = 'mongo:manage:base';
}
resourceMap.set(resourceType, { resourceType, showAuthCode, count: 1, tagPath: tagResource.tagPath });
}
state.resourceDialog.data = Array.from(resourceMap.values());
state.resourceDialog.visible = true;
};
const showResources = (resourceType: any, tagPath: string) => {
hasPerm;
state.resourceDialog.visible = false;
setTimeout(() => {
let toPath = '';
if (resourceType == TagResourceTypeEnum.Machine.value) {
toPath = '/machine/machines';
}
if (resourceType == TagResourceTypeEnum.Db.value) {
toPath = '/dbms/dbs';
}
if (resourceType == TagResourceTypeEnum.Redis.value) {
toPath = '/redis/manage';
}
if (resourceType == TagResourceTypeEnum.Mongo.value) {
toPath = '/mongo/mongo-manage';
}
router.push({
path: toPath,
query: {
tagPath,
},
});
}, 350);
};
const saveTag = async () => {
tagForm.value.validate(async (valid: any) => {
if (valid) {
@@ -333,6 +303,7 @@ const saveTag = async () => {
ElMessage.success('保存成功');
search();
cancelSaveTag();
state.currentTag = null;
}
});
};
@@ -403,6 +374,11 @@ const removeDeafultExpandId = (id: any) => {
line-height: 40px;
}
}
.el-tree {
display: inline-block;
min-width: 100%;
}
}
.none-select {

View File

@@ -8,6 +8,7 @@ export const tagApi = {
getResourceTagPaths: Api.newGet('/tag-trees/resources/{resourceType}/tag-paths'),
getTagResources: Api.newGet('/tag-trees/resources'),
countTagResource: Api.newGet('/tag-trees/resources/count'),
getTeams: Api.newGet('/teams'),
saveTeam: Api.newPost('/teams'),

View File

@@ -3,23 +3,24 @@ module mayfly-go
go 1.22
require (
gitee.com/chunanyong/dm v1.8.13
gitee.com/chunanyong/dm v1.8.14
gitee.com/liuzongyang/libpq v1.0.9
github.com/buger/jsonparser v1.1.1
github.com/emirpasic/gods v1.18.1
github.com/gin-gonic/gin v1.9.1
github.com/glebarez/sqlite v1.10.0
github.com/glebarez/sqlite v1.11.0
github.com/go-gormigrate/gormigrate/v2 v2.1.0
github.com/go-ldap/ldap/v3 v3.4.6
github.com/go-playground/locales v0.14.1
github.com/go-playground/universal-translator v0.18.1
github.com/go-playground/validator/v10 v10.14.0
github.com/go-sql-driver/mysql v1.7.1
github.com/go-sql-driver/mysql v1.8.0
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/google/uuid v1.6.0
github.com/gorilla/websocket v1.5.1
github.com/kanzihuang/vitess/go/vt/sqlparser v0.0.0-20231018071450-ac8d9f0167e9
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20230712084735-068dc2aee82d
github.com/may-fly/cast v1.6.1
github.com/microsoft/go-mssqldb v1.7.0
github.com/mojocn/base64Captcha v1.3.6 //
github.com/pkg/errors v0.9.1
@@ -27,20 +28,21 @@ require (
github.com/pquerna/otp v1.4.0
github.com/redis/go-redis/v9 v9.5.1
github.com/robfig/cron/v3 v3.0.1 //
github.com/sijms/go-ora/v2 v2.8.9
github.com/sijms/go-ora/v2 v2.8.10
github.com/stretchr/testify v1.8.4
go.mongodb.org/mongo-driver v1.14.0 // mongo
golang.org/x/crypto v0.21.0 // ssh
golang.org/x/oauth2 v0.17.0
golang.org/x/oauth2 v0.18.0
golang.org/x/sync v0.6.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gopkg.in/yaml.v3 v3.0.1
// gorm
gorm.io/driver/mysql v1.5.4
gorm.io/gorm v1.25.7
gorm.io/driver/mysql v1.5.5
gorm.io/gorm v1.25.8
)
require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
github.com/bytedance/sonic v1.9.1 // indirect
@@ -86,7 +88,7 @@ require (
golang.org/x/arch v0.3.0 // indirect
golang.org/x/exp v0.0.0-20230519143937-03e91628a987 // indirect
golang.org/x/image v0.13.0 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/net v0.22.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/appengine v1.6.7 // indirect

View File

@@ -2,8 +2,9 @@ package config
import (
sysapp "mayfly-go/internal/sys/application"
"mayfly-go/pkg/utils/conv"
"mayfly-go/pkg/utils/stringx"
"github.com/may-fly/cast"
)
const (
@@ -27,8 +28,8 @@ func GetAccountLoginSecurity() *AccountLoginSecurity {
als := new(AccountLoginSecurity)
als.UseCaptcha = c.ConvBool(jm["useCaptcha"], true)
als.UseOtp = c.ConvBool(jm["useOtp"], false)
als.LoginFailCount = conv.Str2Int(jm["loginFailCount"], 5)
als.LoginFailMin = conv.Str2Int(jm["loginFailMin"], 10)
als.LoginFailCount = cast.ToIntD(jm["loginFailCount"], 5)
als.LoginFailMin = cast.ToIntD(jm["loginFailMin"], 10)
otpIssuer := jm["otpIssuer"]
if otpIssuer == "" {
otpIssuer = "mayfly-go"

View File

@@ -435,7 +435,7 @@ func (d *Db) HintTables(rc *req.Ctx) {
res[tName] = make([]string, 0)
}
columnName := fmt.Sprintf("%s [%s]", v.ColumnName, v.ShowDataType)
columnName := fmt.Sprintf("%s [%s]", v.ColumnName, v.GetColumnType())
comment := v.ColumnComment
// 如果字段备注不为空,则加上备注信息
if comment != "" {

View File

@@ -6,7 +6,9 @@ import (
"mayfly-go/pkg/biz"
"mayfly-go/pkg/req"
"mayfly-go/pkg/utils/collx"
"mayfly-go/pkg/utils/conv"
"github.com/may-fly/cast"
"strings"
)
@@ -19,7 +21,7 @@ func (d *DbSqlExec) DbSqlExecs(rc *req.Ctx) {
if statusStr := rc.Query("status"); statusStr != "" {
queryCond.Status = collx.ArrayMap[string, int8](strings.Split(statusStr, ","), func(val string) int8 {
return int8(conv.Str2Int(val, 0))
return cast.ToInt8(val)
})
}
res, err := d.DbSqlExecApp.GetPageList(queryCond, page, new([]entity.DbSqlExec))

View File

@@ -169,8 +169,6 @@ func (app *dbTransferAppImpl) transferTables(task *entity.DbTransferTask, srcCon
srcDialect.ToCommonColumn(colPtr)
// 公共列转为目标库列
targetDialect.ToColumn(colPtr)
// 初始化列显示类型
colPtr.InitShowNum()
targetCols = append(targetCols, *colPtr)
}
@@ -197,7 +195,7 @@ func (app *dbTransferAppImpl) transferTables(task *entity.DbTransferTask, srcCon
// 迁移索引信息
logx.Infof("开始迁移索引: 表名:%s", tbName)
err = app.transferIndex(ctx, tableMap[tbName], srcConn, srcDialect, targetConn, targetDialect)
err = app.transferIndex(ctx, tableMap[tbName], srcConn, targetDialect)
if err != nil {
end(fmt.Sprintf("迁移索引失败: 表名:%s, error: %s", tbName, err.Error()), err)
return
@@ -302,7 +300,7 @@ func (app *dbTransferAppImpl) transfer2Target(targetConn *dbi.DbConn, cols []*db
return err
}
func (app *dbTransferAppImpl) transferIndex(ctx context.Context, tableInfo dbi.Table, srcConn *dbi.DbConn, srcDialect dbi.Dialect, targetConn *dbi.DbConn, targetDialect dbi.Dialect) error {
func (app *dbTransferAppImpl) transferIndex(_ context.Context, tableInfo dbi.Table, srcConn *dbi.DbConn, targetDialect dbi.Dialect) error {
// 查询源表索引信息
indexs, err := srcConn.GetMetaData().GetTableIndex(tableInfo.TableName)

View File

@@ -2,9 +2,10 @@ package config
import (
sysapp "mayfly-go/internal/sys/application"
"mayfly-go/pkg/utils/conv"
"path/filepath"
"runtime"
"github.com/may-fly/cast"
)
const (
@@ -26,8 +27,8 @@ func GetDbms() *Dbms {
dbmsConf := new(Dbms)
dbmsConf.QuerySqlSave = c.ConvBool(jm["querySqlSave"], false)
dbmsConf.MaxResultSet = conv.Str2Int(jm["maxResultSet"], 0)
dbmsConf.SqlExecTl = conv.Str2Int(jm["sqlExecTl"], 60)
dbmsConf.MaxResultSet = cast.ToInt(jm["maxResultSet"])
dbmsConf.SqlExecTl = cast.ToIntD(jm["sqlExecTl"], 60)
return dbmsConf
}

View File

@@ -53,7 +53,6 @@ type DbServer struct {
// 表信息
type Table struct {
TableName string `json:"tableName"` // 表名
TableNewName string `json:"tableNewName"` // 新表名复制表生成ddl时需要传入新表名
TableComment string `json:"tableComment"` // 表备注
CreateTime string `json:"createTime"` // 创建时间
TableRows int `json:"tableRows"`
@@ -75,38 +74,22 @@ type Column struct {
NumPrecision int `json:"numPrecision"` // 精度(总数字位数)
NumScale int `json:"numScale"` // 小数点位数
Extra collx.M `json:"extra"` // 其他额外信息
ShowLength int `json:"showLength"`
ShowScale int `json:"showScale"`
ShowDataType string `json:"showDataType"` // 显示数据类型
}
// 初始化列显示类型,拼接数据类型与长度等。如varchar(2000)decimal(20,2)
func (c *Column) InitShowNum() string {
// 拼接数据类型与长度等。如varchar(2000)decimal(20,2)
func (c *Column) GetColumnType() string {
if c.CharMaxLength > 0 {
c.ShowDataType = fmt.Sprintf("%s(%d)", c.DataType, c.CharMaxLength)
c.ShowLength = c.CharMaxLength
c.ShowScale = 0
return c.ShowDataType
return fmt.Sprintf("%s(%d)", c.DataType, c.CharMaxLength)
}
if c.NumPrecision > 0 {
if c.NumScale > 0 {
c.ShowDataType = fmt.Sprintf("%s(%d,%d)", c.DataType, c.NumPrecision, c.NumScale)
c.ShowScale = c.NumScale
return fmt.Sprintf("%s(%d,%d)", c.DataType, c.NumPrecision, c.NumScale)
} else {
c.ShowDataType = fmt.Sprintf("%s(%d)", c.DataType, c.NumPrecision)
c.ShowScale = 0
return fmt.Sprintf("%s(%d)", c.DataType, c.NumPrecision)
}
c.ShowLength = c.NumPrecision
return c.ShowDataType
}
c.ShowDataType = string(c.DataType)
c.ShowLength = 0
c.ShowScale = 0
return c.ShowDataType
return string(c.DataType)
}
// 表索引信息

View File

@@ -113,7 +113,7 @@ func baseType(t reflect.Type, expected reflect.Kind) (reflect.Type, error) {
// struct is expected but something else is given
func structOnlyError(t reflect.Type) error {
isStruct := t.Kind() == reflect.Struct
isScanner := reflect.PtrTo(t).Implements(_scannerInterface)
isScanner := reflect.PointerTo(t).Implements(_scannerInterface)
if !isStruct {
return fmt.Errorf("expected %s but got %s", reflect.Struct, t.Kind())
}

View File

@@ -77,7 +77,6 @@ func (dd *DMDialect) batchInsertMerge(tx *sql.Tx, tableName string, columns []st
}
// 查询唯一索引涉及到的字段并组装到match条件内
indexs, _ := metadata.GetTableIndex(tableName)
if indexs != nil {
for _, index := range indexs {
if index.IsUnique {
cols := strings.Split(index.ColumnName, ",")
@@ -89,7 +88,6 @@ func (dd *DMDialect) batchInsertMerge(tx *sql.Tx, tableName string, columns []st
caseSqls = append(caseSqls, fmt.Sprintf("( %s )", strings.Join(tmp, " AND ")))
}
}
}
// 重复数据处理策略
phs := make([]string, 0)
@@ -102,7 +100,7 @@ func (dd *DMDialect) batchInsertMerge(tx *sql.Tx, tableName string, columns []st
upds = append(upds, fmt.Sprintf("T1.%s = T2.%s", column, column))
}
if !collx.ArrayContains(identityCols, column) {
insertCols = append(insertCols, fmt.Sprintf("%s", column))
insertCols = append(insertCols, column)
insertVals = append(insertVals, fmt.Sprintf("T2.%s", column))
}
@@ -218,7 +216,3 @@ func (dd *DMDialect) CreateIndex(tableInfo dbi.Table, indexs []dbi.Index) error
_, err := dd.dc.Exec(strings.Join(sqls, ";"))
return err
}
func (dd *DMDialect) UpdateSequence(tableName string, columns []dbi.Column) {
}

View File

@@ -11,6 +11,8 @@ import (
"regexp"
"strings"
"time"
"github.com/may-fly/cast"
)
const (
@@ -33,7 +35,7 @@ func (dd *DMMetaData) GetDbServer() (*dbi.DbServer, error) {
return nil, err
}
ds := &dbi.DbServer{
Version: anyx.ConvString(res[0]["SVR_VERSION"]),
Version: cast.ToString(res[0]["SVR_VERSION"]),
}
return ds, nil
}
@@ -46,7 +48,7 @@ func (dd *DMMetaData) GetDbNames() ([]string, error) {
databases := make([]string, 0)
for _, re := range res {
databases = append(databases, anyx.ConvString(re["DBNAME"]))
databases = append(databases, cast.ToString(re["DBNAME"]))
}
return databases, nil
@@ -73,12 +75,12 @@ func (dd *DMMetaData) GetTables(tableNames ...string) ([]dbi.Table, error) {
tables := make([]dbi.Table, 0)
for _, re := range res {
tables = append(tables, dbi.Table{
TableName: anyx.ConvString(re["TABLE_NAME"]),
TableComment: anyx.ConvString(re["TABLE_COMMENT"]),
CreateTime: anyx.ConvString(re["CREATE_TIME"]),
TableRows: anyx.ConvInt(re["TABLE_ROWS"]),
DataLength: anyx.ConvInt64(re["DATA_LENGTH"]),
IndexLength: anyx.ConvInt64(re["INDEX_LENGTH"]),
TableName: cast.ToString(re["TABLE_NAME"]),
TableComment: cast.ToString(re["TABLE_COMMENT"]),
CreateTime: cast.ToString(re["CREATE_TIME"]),
TableRows: cast.ToInt(re["TABLE_ROWS"]),
DataLength: cast.ToInt64(re["DATA_LENGTH"]),
IndexLength: cast.ToInt64(re["INDEX_LENGTH"]),
})
}
return tables, nil
@@ -98,21 +100,18 @@ func (dd *DMMetaData) GetColumns(tableNames ...string) ([]dbi.Column, error) {
columns := make([]dbi.Column, 0)
for _, re := range res {
column := dbi.Column{
TableName: anyx.ConvString(re["TABLE_NAME"]),
ColumnName: anyx.ConvString(re["COLUMN_NAME"]),
TableName: cast.ToString(re["TABLE_NAME"]),
ColumnName: cast.ToString(re["COLUMN_NAME"]),
DataType: dbi.ColumnDataType(anyx.ToString(re["DATA_TYPE"])),
CharMaxLength: anyx.ConvInt(re["CHAR_MAX_LENGTH"]),
ColumnComment: anyx.ConvString(re["COLUMN_COMMENT"]),
Nullable: anyx.ConvString(re["NULLABLE"]),
IsPrimaryKey: anyx.ConvInt(re["IS_PRIMARY_KEY"]) == 1,
IsIdentity: anyx.ConvInt(re["IS_IDENTITY"]) == 1,
ColumnDefault: anyx.ConvString(re["COLUMN_DEFAULT"]),
NumPrecision: anyx.ConvInt(re["NUM_PRECISION"]),
NumScale: anyx.ConvInt(re["NUM_SCALE"]),
CharMaxLength: cast.ToInt(re["CHAR_MAX_LENGTH"]),
ColumnComment: cast.ToString(re["COLUMN_COMMENT"]),
Nullable: cast.ToString(re["NULLABLE"]),
IsPrimaryKey: cast.ToInt(re["IS_PRIMARY_KEY"]) == 1,
IsIdentity: cast.ToInt(re["IS_IDENTITY"]) == 1,
ColumnDefault: cast.ToString(re["COLUMN_DEFAULT"]),
NumPrecision: cast.ToInt(re["NUM_PRECISION"]),
NumScale: cast.ToInt(re["NUM_SCALE"]),
}
// 初始化列展示的长度,精度
column.InitShowNum()
columns = append(columns, column)
}
return columns, nil
@@ -145,12 +144,12 @@ func (dd *DMMetaData) GetTableIndex(tableName string) ([]dbi.Index, error) {
indexs := make([]dbi.Index, 0)
for _, re := range res {
indexs = append(indexs, dbi.Index{
IndexName: anyx.ConvString(re["INDEX_NAME"]),
ColumnName: anyx.ConvString(re["COLUMN_NAME"]),
IndexType: anyx.ConvString(re["INDEX_TYPE"]),
IndexComment: anyx.ConvString(re["INDEX_COMMENT"]),
IsUnique: anyx.ConvInt(re["IS_UNIQUE"]) == 1,
SeqInIndex: anyx.ConvInt(re["SEQ_IN_INDEX"]),
IndexName: cast.ToString(re["INDEX_NAME"]),
ColumnName: cast.ToString(re["COLUMN_NAME"]),
IndexType: cast.ToString(re["INDEX_TYPE"]),
IndexComment: cast.ToString(re["INDEX_COMMENT"]),
IsUnique: cast.ToInt(re["IS_UNIQUE"]) == 1,
SeqInIndex: cast.ToInt(re["SEQ_IN_INDEX"]),
})
}
// 把查询结果以索引名分组,索引字段以逗号连接
@@ -207,7 +206,7 @@ func (dd *DMMetaData) genColumnBasicSql(column dbi.Column) string {
}
}
columnSql := fmt.Sprintf(" %s %s %s %s %s", colName, column.ShowDataType, incr, nullAble, defVal)
columnSql := fmt.Sprintf(" %s %s %s %s %s", colName, column.GetColumnType(), incr, nullAble, defVal)
return columnSql
}
@@ -328,7 +327,7 @@ func (dd *DMMetaData) GetSchemas() ([]string, error) {
}
schemaNames := make([]string, 0)
for _, re := range res {
schemaNames = append(schemaNames, anyx.ConvString(re["SCHEMA_NAME"]))
schemaNames = append(schemaNames, cast.ToString(re["SCHEMA_NAME"]))
}
return schemaNames, nil
}
@@ -346,8 +345,6 @@ var (
dateRegexp = regexp.MustCompile(`(?i)date`)
// 时间类型
timeRegexp = regexp.MustCompile(`(?i)time`)
// 定义正则表达式,匹配括号内的数字
bracketsRegexp = regexp.MustCompile(`\((\d+)\)`)
converter = new(DataConverter)

View File

@@ -16,22 +16,6 @@ type MssqlDialect struct {
dc *dbi.DbConn
}
// 从连接信息中获取数据库和schema信息
func (md *MssqlDialect) currentSchema() string {
dbName := md.dc.Info.Database
schema := ""
arr := strings.Split(dbName, "/")
if len(arr) == 2 {
schema = arr[1]
}
return schema
}
// GetDbProgram 获取数据库程序模块,用于数据库备份与恢复
func (md *MssqlDialect) GetDbProgram() (dbi.DbProgram, error) {
return nil, fmt.Errorf("该数据库类型不支持数据库备份与恢复: %v", md.dc.Info.Type)
}
func (md *MssqlDialect) BatchInsert(tx *sql.Tx, tableName string, columns []string, values [][]any, duplicateStrategy int) (int64, error) {
if duplicateStrategy == dbi.DuplicateStrategyUpdate {
@@ -143,6 +127,9 @@ func (md *MssqlDialect) batchInsertMerge(tx *sql.Tx, tableName string, columns [
// 查询取出自增列字段, merge update不能修改自增列
identityCols := make([]string, 0)
cols, err := msMetadata.GetColumns(tableName)
if err != nil {
return 0, err
}
for _, col := range cols {
if col.IsIdentity {
identityCols = append(identityCols, col.ColumnName)
@@ -166,7 +153,7 @@ func (md *MssqlDialect) batchInsertMerge(tx *sql.Tx, tableName string, columns [
if !collx.ArrayContains(identityCols, msMetadata.RemoveQuote(column)) {
upds = append(upds, fmt.Sprintf("T1.%s = T2.%s", column, column))
}
insertCols = append(insertCols, fmt.Sprintf("%s", column))
insertCols = append(insertCols, column)
insertVals = append(insertVals, fmt.Sprintf("T2.%s", column))
phs = append(phs, fmt.Sprintf("? %s", column))
}
@@ -309,7 +296,3 @@ func (md *MssqlDialect) CreateIndex(tableInfo dbi.Table, indexs []dbi.Index) err
_, err := md.dc.Exec(strings.Join(sqlArr, ";"))
return err
}
func (md *MssqlDialect) UpdateSequence(tableName string, columns []dbi.Column) {
}

View File

@@ -11,6 +11,8 @@ import (
"regexp"
"strings"
"time"
"github.com/may-fly/cast"
)
const (
@@ -34,7 +36,7 @@ func (md *MssqlMetaData) GetDbServer() (*dbi.DbServer, error) {
return nil, err
}
ds := &dbi.DbServer{
Version: anyx.ConvString(res[0]["version"]),
Version: cast.ToString(res[0]["version"]),
}
return ds, nil
}
@@ -47,7 +49,7 @@ func (md *MssqlMetaData) GetDbNames() ([]string, error) {
databases := make([]string, 0)
for _, re := range res {
databases = append(databases, anyx.ConvString(re["dbname"]))
databases = append(databases, cast.ToString(re["dbname"]))
}
return databases, nil
@@ -63,9 +65,6 @@ func (md *MssqlMetaData) GetTables(tableNames ...string) ([]dbi.Table, error) {
var res []map[string]any
var err error
if err != nil {
return nil, err
}
sql, err := stringx.TemplateParse(dbi.GetLocalSql(MSSQL_META_FILE, MSSQL_TABLE_INFO_KEY), collx.M{"tableNames": names})
if err != nil {
@@ -80,12 +79,12 @@ func (md *MssqlMetaData) GetTables(tableNames ...string) ([]dbi.Table, error) {
tables := make([]dbi.Table, 0)
for _, re := range res {
tables = append(tables, dbi.Table{
TableName: anyx.ConvString(re["tableName"]),
TableComment: anyx.ConvString(re["tableComment"]),
CreateTime: anyx.ConvString(re["createTime"]),
TableRows: anyx.ConvInt(re["tableRows"]),
DataLength: anyx.ConvInt64(re["dataLength"]),
IndexLength: anyx.ConvInt64(re["indexLength"]),
TableName: cast.ToString(re["tableName"]),
TableComment: cast.ToString(re["tableComment"]),
CreateTime: cast.ToString(re["createTime"]),
TableRows: cast.ToInt(re["tableRows"]),
DataLength: cast.ToInt64(re["dataLength"]),
IndexLength: cast.ToInt64(re["indexLength"]),
})
}
return tables, nil
@@ -110,14 +109,14 @@ func (md *MssqlMetaData) GetColumns(tableNames ...string) ([]dbi.Column, error)
TableName: anyx.ToString(re["TABLE_NAME"]),
ColumnName: anyx.ToString(re["COLUMN_NAME"]),
DataType: dbi.ColumnDataType(anyx.ToString(re["DATA_TYPE"])),
CharMaxLength: anyx.ConvInt(re["CHAR_MAX_LENGTH"]),
CharMaxLength: cast.ToInt(re["CHAR_MAX_LENGTH"]),
ColumnComment: anyx.ToString(re["COLUMN_COMMENT"]),
Nullable: anyx.ToString(re["NULLABLE"]),
IsPrimaryKey: anyx.ConvInt(re["IS_PRIMARY_KEY"]) == 1,
IsIdentity: anyx.ConvInt(re["IS_IDENTITY"]) == 1,
ColumnDefault: anyx.ConvString(re["COLUMN_DEFAULT"]),
NumPrecision: anyx.ConvInt(re["NUM_PRECISION"]),
NumScale: anyx.ConvInt(re["NUM_SCALE"]),
IsPrimaryKey: cast.ToInt(re["IS_PRIMARY_KEY"]) == 1,
IsIdentity: cast.ToInt(re["IS_IDENTITY"]) == 1,
ColumnDefault: cast.ToString(re["COLUMN_DEFAULT"]),
NumPrecision: cast.ToInt(re["NUM_PRECISION"]),
NumScale: cast.ToInt(re["NUM_SCALE"]),
}
dataType := strings.ToLower(string(column.DataType))
@@ -137,8 +136,6 @@ func (md *MssqlMetaData) GetColumns(tableNames ...string) ([]dbi.Column, error)
column.CharMaxLength = column.CharMaxLength / 2
}
// 初始化列展示的长度,精度
column.InitShowNum()
columns = append(columns, column)
}
return columns, nil
@@ -171,12 +168,12 @@ func (md *MssqlMetaData) getTableIndexWithPK(tableName string) ([]dbi.Index, err
indexs := make([]dbi.Index, 0)
for _, re := range res {
indexs = append(indexs, dbi.Index{
IndexName: anyx.ConvString(re["indexName"]),
ColumnName: anyx.ConvString(re["columnName"]),
IndexType: anyx.ConvString(re["indexType"]),
IndexComment: anyx.ConvString(re["indexComment"]),
IsUnique: anyx.ConvInt(re["isUnique"]) == 1,
SeqInIndex: anyx.ConvInt(re["seqInIndex"]),
IndexName: cast.ToString(re["indexName"]),
ColumnName: cast.ToString(re["columnName"]),
IndexType: cast.ToString(re["indexType"]),
IndexComment: cast.ToString(re["indexComment"]),
IsUnique: cast.ToInt(re["isUnique"]) == 1,
SeqInIndex: cast.ToInt(re["seqInIndex"]),
})
}
// 把查询结果以索引名分组,多个索引字段以逗号连接
@@ -208,6 +205,7 @@ func (md *MssqlMetaData) GetTableIndex(tableName string) ([]dbi.Index, error) {
if strings.HasPrefix(in, "PK__") {
continue
}
result = append(result, v)
}
return result, nil
}
@@ -224,9 +222,8 @@ func (md *MssqlMetaData) CopyTableDDL(tableName string, newTableName string) (st
return "", err
}
tabInfo := &dbi.Table{
TableName: tableName,
TableName: newTableName,
TableComment: tbs[0].TableComment,
TableNewName: newTableName,
}
// 查询列信息
@@ -250,12 +247,7 @@ func (md *MssqlMetaData) CopyTableDDL(tableName string, newTableName string) (st
// 获取建索引ddl
func (md *MssqlMetaData) GenerateIndexDDL(indexs []dbi.Index, tableInfo dbi.Table) []string {
tbName := tableInfo.TableName
if tableInfo.TableNewName != "" {
tbName = tableInfo.TableNewName
}
sqls := make([]string, 0)
comments := make([]string, 0)
for _, index := range indexs {
@@ -277,6 +269,10 @@ func (md *MssqlMetaData) GenerateIndexDDL(indexs []dbi.Index, tableInfo dbi.Tabl
comments = append(comments, fmt.Sprintf("EXECUTE sp_addextendedproperty N'MS_Description', N'%s', N'SCHEMA', N'%s', N'TABLE', N'%s', N'INDEX', N'%s'", index.IndexComment, md.dc.Info.CurrentSchema(), tbName, indexName))
}
}
if len(comments) > 0 {
sqls = append(sqls, comments...)
}
return sqls
}
@@ -316,18 +312,13 @@ func (md *MssqlMetaData) genColumnBasicSql(column dbi.Column) string {
}
}
columnSql := fmt.Sprintf(" %s %s %s %s %s", colName, column.ShowDataType, incr, nullAble, defVal)
columnSql := fmt.Sprintf(" %s %s %s %s %s", colName, column.GetColumnType(), incr, nullAble, defVal)
return columnSql
}
// 获取建表ddl
func (md *MssqlMetaData) GenerateTableDDL(columns []dbi.Column, tableInfo dbi.Table, dropBeforeCreate bool) []string {
tbName := tableInfo.TableName
if tableInfo.TableNewName != "" {
tbName = tableInfo.TableNewName
}
meta := md.dc.GetMetaData()
replacer := strings.NewReplacer(";", "", "'", "")
@@ -424,7 +415,7 @@ func (md *MssqlMetaData) GetSchemas() ([]string, error) {
schemas := make([]string, 0)
for _, re := range res {
schemas = append(schemas, anyx.ConvString(re["SCHEMA_NAME"]))
schemas = append(schemas, cast.ToString(re["SCHEMA_NAME"]))
}
return schemas, nil
}
@@ -448,8 +439,7 @@ var (
timeRegexp = regexp.MustCompile(`(?i)time`)
converter = new(DataConverter)
// 定义正则表达式,匹配括号内的数字
bracketsRegexp = regexp.MustCompile(`\((\d+)\)`)
// mssql数据类型 对应 公共数据类型
commonColumnTypeMap = map[string]dbi.ColumnDataType{
"bigint": dbi.CommonTypeBigint,

View File

@@ -14,6 +14,7 @@ import (
"time"
"github.com/kanzihuang/vitess/go/vt/sqlparser"
"github.com/may-fly/cast"
)
const (
@@ -36,7 +37,7 @@ func (md *MysqlMetaData) GetDbServer() (*dbi.DbServer, error) {
return nil, err
}
ds := &dbi.DbServer{
Version: anyx.ConvString(res[0]["version"]),
Version: cast.ToString(res[0]["version"]),
}
return ds, nil
}
@@ -49,7 +50,7 @@ func (md *MysqlMetaData) GetDbNames() ([]string, error) {
databases := make([]string, 0)
for _, re := range res {
databases = append(databases, anyx.ConvString(re["dbname"]))
databases = append(databases, cast.ToString(re["dbname"]))
}
return databases, nil
}
@@ -76,12 +77,12 @@ func (md *MysqlMetaData) GetTables(tableNames ...string) ([]dbi.Table, error) {
tables := make([]dbi.Table, 0)
for _, re := range res {
tables = append(tables, dbi.Table{
TableName: anyx.ConvString(re["tableName"]),
TableComment: anyx.ConvString(re["tableComment"]),
CreateTime: anyx.ConvString(re["createTime"]),
TableRows: anyx.ConvInt(re["tableRows"]),
DataLength: anyx.ConvInt64(re["dataLength"]),
IndexLength: anyx.ConvInt64(re["indexLength"]),
TableName: cast.ToString(re["tableName"]),
TableComment: cast.ToString(re["tableComment"]),
CreateTime: cast.ToString(re["createTime"]),
TableRows: cast.ToInt(re["tableRows"]),
DataLength: cast.ToInt64(re["dataLength"]),
IndexLength: cast.ToInt64(re["indexLength"]),
})
}
return tables, nil
@@ -103,21 +104,19 @@ func (md *MysqlMetaData) GetColumns(tableNames ...string) ([]dbi.Column, error)
for _, re := range res {
column := dbi.Column{
TableName: anyx.ConvString(re["tableName"]),
ColumnName: anyx.ConvString(re["columnName"]),
DataType: dbi.ColumnDataType(anyx.ConvString(re["dataType"])),
ColumnComment: anyx.ConvString(re["columnComment"]),
Nullable: anyx.ConvString(re["nullable"]),
IsPrimaryKey: anyx.ConvInt(re["isPrimaryKey"]) == 1,
IsIdentity: anyx.ConvInt(re["isIdentity"]) == 1,
ColumnDefault: anyx.ConvString(re["columnDefault"]),
CharMaxLength: anyx.ConvInt(re["charMaxLength"]),
NumPrecision: anyx.ConvInt(re["numPrecision"]),
NumScale: anyx.ConvInt(re["numScale"]),
TableName: cast.ToString(re["tableName"]),
ColumnName: cast.ToString(re["columnName"]),
DataType: dbi.ColumnDataType(cast.ToString(re["dataType"])),
ColumnComment: cast.ToString(re["columnComment"]),
Nullable: cast.ToString(re["nullable"]),
IsPrimaryKey: cast.ToInt(re["isPrimaryKey"]) == 1,
IsIdentity: cast.ToInt(re["isIdentity"]) == 1,
ColumnDefault: cast.ToString(re["columnDefault"]),
CharMaxLength: cast.ToInt(re["charMaxLength"]),
NumPrecision: cast.ToInt(re["numPrecision"]),
NumScale: cast.ToInt(re["numScale"]),
}
// 初始化列展示的长度,精度
column.InitShowNum()
columns = append(columns, column)
}
return columns, nil
@@ -152,12 +151,12 @@ func (md *MysqlMetaData) GetTableIndex(tableName string) ([]dbi.Index, error) {
indexs := make([]dbi.Index, 0)
for _, re := range res {
indexs = append(indexs, dbi.Index{
IndexName: anyx.ConvString(re["indexName"]),
ColumnName: anyx.ConvString(re["columnName"]),
IndexType: anyx.ConvString(re["indexType"]),
IndexComment: anyx.ConvString(re["indexComment"]),
IsUnique: anyx.ConvInt(re["isUnique"]) == 1,
SeqInIndex: anyx.ConvInt(re["seqInIndex"]),
IndexName: cast.ToString(re["indexName"]),
ColumnName: cast.ToString(re["columnName"]),
IndexType: cast.ToString(re["indexType"]),
IndexComment: cast.ToString(re["indexComment"]),
IsUnique: cast.ToInt(re["isUnique"]) == 1,
SeqInIndex: cast.ToInt(re["seqInIndex"]),
})
}
// 把查询结果以索引名分组,索引字段以逗号连接
@@ -243,7 +242,7 @@ func (md *MysqlMetaData) genColumnBasicSql(column dbi.Column) string {
comment = fmt.Sprintf(" COMMENT '%s'", commentStr)
}
columnSql := fmt.Sprintf(" %s %s %s %s %s %s", md.dc.GetMetaData().QuoteIdentifier(column.ColumnName), column.ShowDataType, nullAble, incr, defVal, comment)
columnSql := fmt.Sprintf(" %s %s %s %s %s %s", md.dc.GetMetaData().QuoteIdentifier(column.ColumnName), column.GetColumnType(), nullAble, incr, defVal, comment)
return columnSql
}
@@ -260,7 +259,7 @@ func (md *MysqlMetaData) GenerateTableDDL(columns []dbi.Column, tableInfo dbi.Ta
createSql := fmt.Sprintf("CREATE TABLE %s (\n", meta.QuoteIdentifier(tableInfo.TableName))
fields := make([]string, 0)
pks := make([]string, 0)
// 把通用类型转换为达梦类型
for _, column := range columns {
if column.IsPrimaryKey {
pks = append(pks, column.ColumnName)

View File

@@ -211,7 +211,3 @@ func (od *OracleDialect) CreateIndex(tableInfo dbi.Table, indexs []dbi.Index) er
_, err := od.dc.Exec(strings.Join(sqlArr, ";"))
return err
}
func (od *OracleDialect) UpdateSequence(tableName string, columns []dbi.Column) {
}

View File

@@ -4,10 +4,10 @@ import (
"database/sql"
"fmt"
"mayfly-go/internal/db/dbm/dbi"
"mayfly-go/pkg/utils/anyx"
"mayfly-go/pkg/utils/jsonx"
"strings"
"github.com/may-fly/cast"
go_ora "github.com/sijms/go-ora/v2"
)
@@ -56,8 +56,8 @@ func (md *OraMeta) GetSqlDb(d *dbi.DbInfo) (*sql.DB, error) {
serviceName := ""
if d.Extra != "" {
extraMap := jsonx.ToMap(d.Extra)
serviceName = anyx.ConvString(extraMap["serviceName"])
if sid := anyx.ConvString(extraMap["sid"]); sid != "" {
serviceName = cast.ToString(extraMap["serviceName"])
if sid := cast.ToString(extraMap["sid"]); sid != "" {
urlOptions["SID"] = sid
}
}

View File

@@ -11,6 +11,8 @@ import (
"regexp"
"strings"
"time"
"github.com/may-fly/cast"
)
// ---------------------------------- DM元数据 -----------------------------------
@@ -34,7 +36,7 @@ func (od *OracleMetaData) GetDbServer() (*dbi.DbServer, error) {
return nil, err
}
ds := &dbi.DbServer{
Version: anyx.ConvString(res[0]["VERSION"]),
Version: cast.ToString(res[0]["VERSION"]),
}
return ds, nil
}
@@ -47,7 +49,7 @@ func (od *OracleMetaData) GetDbNames() ([]string, error) {
databases := make([]string, 0)
for _, re := range res {
databases = append(databases, anyx.ConvString(re["DBNAME"]))
databases = append(databases, cast.ToString(re["DBNAME"]))
}
return databases, nil
@@ -75,12 +77,12 @@ func (od *OracleMetaData) GetTables(tableNames ...string) ([]dbi.Table, error) {
tables := make([]dbi.Table, 0)
for _, re := range res {
tables = append(tables, dbi.Table{
TableName: anyx.ConvString(re["TABLE_NAME"]),
TableComment: anyx.ConvString(re["TABLE_COMMENT"]),
CreateTime: anyx.ConvString(re["CREATE_TIME"]),
TableRows: anyx.ConvInt(re["TABLE_ROWS"]),
DataLength: anyx.ConvInt64(re["DATA_LENGTH"]),
IndexLength: anyx.ConvInt64(re["INDEX_LENGTH"]),
TableName: cast.ToString(re["TABLE_NAME"]),
TableComment: cast.ToString(re["TABLE_COMMENT"]),
CreateTime: cast.ToString(re["CREATE_TIME"]),
TableRows: cast.ToInt(re["TABLE_ROWS"]),
DataLength: cast.ToInt64(re["DATA_LENGTH"]),
IndexLength: cast.ToInt64(re["INDEX_LENGTH"]),
})
}
return tables, nil
@@ -118,25 +120,23 @@ func (od *OracleMetaData) GetColumns(tableNames ...string) ([]dbi.Column, error)
columns := make([]dbi.Column, 0)
for _, re := range res {
defaultVal := anyx.ConvString(re["COLUMN_DEFAULT"])
defaultVal := cast.ToString(re["COLUMN_DEFAULT"])
// 如果默认值包含.nextval说明是序列默认值为null
if strings.Contains(defaultVal, ".nextval") {
defaultVal = ""
}
column := dbi.Column{
TableName: anyx.ConvString(re["TABLE_NAME"]),
ColumnName: anyx.ConvString(re["COLUMN_NAME"]),
DataType: dbi.ColumnDataType(anyx.ConvString(re["DATA_TYPE"])),
ColumnComment: anyx.ConvString(re["COLUMN_COMMENT"]),
Nullable: anyx.ConvString(re["NULLABLE"]),
IsPrimaryKey: anyx.ConvInt(re["IS_PRIMARY_KEY"]) == 1,
IsIdentity: anyx.ConvInt(re["IS_IDENTITY"]) == 1,
TableName: cast.ToString(re["TABLE_NAME"]),
ColumnName: cast.ToString(re["COLUMN_NAME"]),
DataType: dbi.ColumnDataType(cast.ToString(re["DATA_TYPE"])),
ColumnComment: cast.ToString(re["COLUMN_COMMENT"]),
Nullable: cast.ToString(re["NULLABLE"]),
IsPrimaryKey: cast.ToInt(re["IS_PRIMARY_KEY"]) == 1,
IsIdentity: cast.ToInt(re["IS_IDENTITY"]) == 1,
ColumnDefault: defaultVal,
NumScale: anyx.ConvInt(re["NUM_SCALE"]),
NumScale: cast.ToInt(re["NUM_SCALE"]),
}
// 初始化列展示的长度,精度
column.InitShowNum()
columns = append(columns, column)
}
return columns, nil
@@ -169,12 +169,12 @@ func (od *OracleMetaData) GetTableIndex(tableName string) ([]dbi.Index, error) {
indexs := make([]dbi.Index, 0)
for _, re := range res {
indexs = append(indexs, dbi.Index{
IndexName: anyx.ConvString(re["INDEX_NAME"]),
ColumnName: anyx.ConvString(re["COLUMN_NAME"]),
IndexType: anyx.ConvString(re["INDEX_TYPE"]),
IndexComment: anyx.ConvString(re["INDEX_COMMENT"]),
IsUnique: anyx.ConvInt(re["IS_UNIQUE"]) == 1,
SeqInIndex: anyx.ConvInt(re["SEQ_IN_INDEX"]),
IndexName: cast.ToString(re["INDEX_NAME"]),
ColumnName: cast.ToString(re["COLUMN_NAME"]),
IndexType: cast.ToString(re["INDEX_TYPE"]),
IndexComment: cast.ToString(re["INDEX_COMMENT"]),
IsUnique: cast.ToInt(re["IS_UNIQUE"]) == 1,
SeqInIndex: cast.ToInt(re["SEQ_IN_INDEX"]),
})
}
// 把查询结果以索引名分组,索引字段以逗号连接
@@ -271,7 +271,7 @@ func (od *OracleMetaData) genColumnBasicSql(column dbi.Column) string {
if collx.ArrayAnyMatches([]string{"NUM", "INT"}, dataType) {
match := bracketsRegexp.FindStringSubmatch(dataType)
if len(match) > 1 {
length := anyx.ConvInt(match[1])
length := cast.ToInt(match[1])
defVal = fmt.Sprintf(" DEFAULT %d", length)
} else {
defVal = fmt.Sprintf(" DEFAULT 0")
@@ -282,7 +282,7 @@ func (od *OracleMetaData) genColumnBasicSql(column dbi.Column) string {
}
}
columnSql := fmt.Sprintf(" %s %s %s %s", colName, column.ShowDataType, defVal, nullAble)
columnSql := fmt.Sprintf(" %s %s %s %s", colName, column.GetColumnType(), defVal, nullAble)
return columnSql
}
@@ -389,7 +389,7 @@ func (od *OracleMetaData) GetSchemas() ([]string, error) {
}
schemaNames := make([]string, 0)
for _, re := range res {
schemaNames = append(schemaNames, anyx.ConvString(re["USERNAME"]))
schemaNames = append(schemaNames, cast.ToString(re["USERNAME"]))
}
return schemaNames, nil
}
@@ -485,7 +485,7 @@ func (dc *DataConverter) FormatData(dbColumnValue any, dataType dbi.DataType) st
func (dc *DataConverter) ParseData(dbColumnValue any, dataType dbi.DataType) any {
// oracle把日期类型的数据转化为time类型
if dataType == dbi.DataTypeDateTime {
res, _ := time.Parse(time.RFC3339, anyx.ConvString(dbColumnValue))
res, _ := time.Parse(time.RFC3339, cast.ToString(dbColumnValue))
return res
}
return dbColumnValue

View File

@@ -8,6 +8,8 @@ import (
"mayfly-go/pkg/utils/collx"
"strings"
"time"
"github.com/may-fly/cast"
)
type PgsqlDialect struct {
@@ -141,7 +143,7 @@ func (pd *PgsqlDialect) CopyTable(copy *dbi.DbCopyTable) error {
}
for _, re := range res {
colName := anyx.ConvString(re["column_name"])
colName := cast.ToString(re["column_name"])
if colName != "" {
// 查询自增列当前最大值
@@ -149,7 +151,7 @@ func (pd *PgsqlDialect) CopyTable(copy *dbi.DbCopyTable) error {
if err != nil {
return err
}
maxVal := anyx.ConvInt(maxRes[0]["max_val"])
maxVal := cast.ToInt(maxRes[0]["max_val"])
// 序列起始值为1或当前最大值+1
if maxVal <= 0 {
maxVal = 1

View File

@@ -11,6 +11,8 @@ import (
"regexp"
"strings"
"time"
"github.com/may-fly/cast"
)
const (
@@ -33,7 +35,7 @@ func (pd *PgsqlMetaData) GetDbServer() (*dbi.DbServer, error) {
return nil, err
}
ds := &dbi.DbServer{
Version: anyx.ConvString(res[0]["server_version"]),
Version: cast.ToString(res[0]["server_version"]),
}
return ds, nil
}
@@ -46,7 +48,7 @@ func (pd *PgsqlMetaData) GetDbNames() ([]string, error) {
databases := make([]string, 0)
for _, re := range res {
databases = append(databases, anyx.ConvString(re["dbname"]))
databases = append(databases, cast.ToString(re["dbname"]))
}
return databases, nil
@@ -75,11 +77,11 @@ func (pd *PgsqlMetaData) GetTables(tableNames ...string) ([]dbi.Table, error) {
for _, re := range res {
tables = append(tables, dbi.Table{
TableName: re["tableName"].(string),
TableComment: anyx.ConvString(re["tableComment"]),
CreateTime: anyx.ConvString(re["createTime"]),
TableRows: anyx.ConvInt(re["tableRows"]),
DataLength: anyx.ConvInt64(re["dataLength"]),
IndexLength: anyx.ConvInt64(re["indexLength"]),
TableComment: cast.ToString(re["tableComment"]),
CreateTime: cast.ToString(re["createTime"]),
TableRows: cast.ToInt(re["tableRows"]),
DataLength: cast.ToInt64(re["dataLength"]),
IndexLength: cast.ToInt64(re["indexLength"]),
})
}
return tables, nil
@@ -100,21 +102,19 @@ func (pd *PgsqlMetaData) GetColumns(tableNames ...string) ([]dbi.Column, error)
columns := make([]dbi.Column, 0)
for _, re := range res {
column := dbi.Column{
TableName: anyx.ConvString(re["tableName"]),
ColumnName: anyx.ConvString(re["columnName"]),
DataType: dbi.ColumnDataType(anyx.ConvString(re["dataType"])),
CharMaxLength: anyx.ConvInt(re["charMaxLength"]),
ColumnComment: anyx.ConvString(re["columnComment"]),
Nullable: anyx.ConvString(re["nullable"]),
IsPrimaryKey: anyx.ConvInt(re["isPrimaryKey"]) == 1,
IsIdentity: anyx.ConvInt(re["isIdentity"]) == 1,
ColumnDefault: anyx.ConvString(re["columnDefault"]),
NumPrecision: anyx.ConvInt(re["numPrecision"]),
NumScale: anyx.ConvInt(re["numScale"]),
TableName: cast.ToString(re["tableName"]),
ColumnName: cast.ToString(re["columnName"]),
DataType: dbi.ColumnDataType(cast.ToString(re["dataType"])),
CharMaxLength: cast.ToInt(re["charMaxLength"]),
ColumnComment: cast.ToString(re["columnComment"]),
Nullable: cast.ToString(re["nullable"]),
IsPrimaryKey: cast.ToInt(re["isPrimaryKey"]) == 1,
IsIdentity: cast.ToInt(re["isIdentity"]) == 1,
ColumnDefault: cast.ToString(re["columnDefault"]),
NumPrecision: cast.ToInt(re["numPrecision"]),
NumScale: cast.ToInt(re["numScale"]),
}
// 初始化列展示的长度,精度
column.InitShowNum()
columns = append(columns, column)
}
return columns, nil
@@ -147,12 +147,12 @@ func (pd *PgsqlMetaData) GetTableIndex(tableName string) ([]dbi.Index, error) {
indexs := make([]dbi.Index, 0)
for _, re := range res {
indexs = append(indexs, dbi.Index{
IndexName: anyx.ConvString(re["indexName"]),
ColumnName: anyx.ConvString(re["columnName"]),
IndexType: anyx.ConvString(re["IndexType"]),
IndexComment: anyx.ConvString(re["indexComment"]),
IsUnique: anyx.ConvInt(re["isUnique"]) == 1,
SeqInIndex: anyx.ConvInt(re["seqInIndex"]),
IndexName: cast.ToString(re["indexName"]),
ColumnName: cast.ToString(re["columnName"]),
IndexType: cast.ToString(re["IndexType"]),
IndexComment: cast.ToString(re["indexComment"]),
IsUnique: cast.ToInt(re["isUnique"]) == 1,
SeqInIndex: cast.ToInt(re["seqInIndex"]),
})
}
// 把查询结果以索引名分组,索引字段以逗号连接
@@ -234,7 +234,7 @@ func (pd *PgsqlMetaData) genColumnBasicSql(column dbi.Column) string {
column.DataType = "bigserial"
}
return fmt.Sprintf(" %s %s NOT NULL", colName, column.ShowDataType)
return fmt.Sprintf(" %s %s NOT NULL", colName, column.GetColumnType())
}
nullAble := ""
@@ -284,7 +284,7 @@ func (pd *PgsqlMetaData) genColumnBasicSql(column dbi.Column) string {
}
}
columnSql := fmt.Sprintf(" %s %s %s %s ", colName, column.ShowDataType, nullAble, defVal)
columnSql := fmt.Sprintf(" %s %s %s %s ", colName, column.GetColumnType(), nullAble, defVal)
return columnSql
}
@@ -386,7 +386,7 @@ func (pd *PgsqlMetaData) GetSchemas() ([]string, error) {
}
schemaNames := make([]string, 0)
for _, re := range res {
schemaNames = append(schemaNames, anyx.ConvString(re["schemaName"]))
schemaNames = append(schemaNames, cast.ToString(re["schemaName"]))
}
return schemaNames, nil
}
@@ -506,7 +506,7 @@ func (dc *DataConverter) FormatData(dbColumnValue any, dataType dbi.DataType) st
res, _ := time.Parse(time.RFC3339, str)
return res.Format(time.TimeOnly)
}
return anyx.ConvString(dbColumnValue)
return cast.ToString(dbColumnValue)
}
func (dc *DataConverter) ParseData(dbColumnValue any, dataType dbi.DataType) any {

View File

@@ -127,7 +127,3 @@ func (sd *SqliteDialect) CreateIndex(tableInfo dbi.Table, indexs []dbi.Index) er
}
return nil
}
func (sd *SqliteDialect) UpdateSequence(tableName string, columns []dbi.Column) {
}

View File

@@ -11,6 +11,8 @@ import (
"regexp"
"strings"
"time"
"github.com/may-fly/cast"
)
const (
@@ -31,7 +33,7 @@ func (sd *SqliteMetaData) GetDbServer() (*dbi.DbServer, error) {
return nil, err
}
ds := &dbi.DbServer{
Version: anyx.ConvString(res[0]["version"]),
Version: cast.ToString(res[0]["version"]),
}
return ds, nil
}
@@ -43,7 +45,7 @@ func (sd *SqliteMetaData) GetDbNames() ([]string, error) {
return nil, err
}
for _, re := range res {
databases = append(databases, anyx.ConvString(re["name"]))
databases = append(databases, cast.ToString(re["name"]))
}
return databases, nil
@@ -71,12 +73,12 @@ func (sd *SqliteMetaData) GetTables(tableNames ...string) ([]dbi.Table, error) {
tables := make([]dbi.Table, 0)
for _, re := range res {
tables = append(tables, dbi.Table{
TableName: anyx.ConvString(re["tableName"]),
TableComment: anyx.ConvString(re["tableComment"]),
CreateTime: anyx.ConvString(re["createTime"]),
TableRows: anyx.ConvInt(re["tableRows"]),
DataLength: anyx.ConvInt64(re["dataLength"]),
IndexLength: anyx.ConvInt64(re["indexLength"]),
TableName: cast.ToString(re["tableName"]),
TableComment: cast.ToString(re["tableComment"]),
CreateTime: cast.ToString(re["createTime"]),
TableRows: cast.ToInt(re["tableRows"]),
DataLength: cast.ToInt64(re["dataLength"]),
IndexLength: cast.ToInt64(re["indexLength"]),
})
}
return tables, nil
@@ -108,40 +110,38 @@ func (sd *SqliteMetaData) GetColumns(tableNames ...string) ([]dbi.Column, error)
}
for _, re := range res {
nullable := "YES"
if anyx.ConvInt(re["notnull"]) == 1 {
if cast.ToInt(re["notnull"]) == 1 {
nullable = "NO"
}
// 去掉默认值的引号
defaultValue := anyx.ConvString(re["dflt_value"])
defaultValue := cast.ToString(re["dflt_value"])
if strings.Contains(defaultValue, "'") {
defaultValue = strings.ReplaceAll(defaultValue, "'", "")
}
column := dbi.Column{
TableName: tableName,
ColumnName: anyx.ConvString(re["name"]),
ColumnName: cast.ToString(re["name"]),
ColumnComment: "",
Nullable: nullable,
IsPrimaryKey: anyx.ConvInt(re["pk"]) == 1,
IsIdentity: anyx.ConvInt(re["pk"]) == 1,
IsPrimaryKey: cast.ToInt(re["pk"]) == 1,
IsIdentity: cast.ToInt(re["pk"]) == 1,
ColumnDefault: defaultValue,
NumScale: 0,
}
// 切割类型和长度如果长度内有逗号则说明是decimal类型
columnType := anyx.ConvString(re["type"])
columnType := cast.ToString(re["type"])
dataType, length, scale := sd.getDataTypes(columnType)
if scale != "0" && scale != "" {
column.NumPrecision = anyx.ConvInt(length)
column.NumScale = anyx.ConvInt(scale)
column.NumPrecision = cast.ToInt(length)
column.NumScale = cast.ToInt(scale)
column.CharMaxLength = 0
} else {
column.CharMaxLength = anyx.ConvInt(length)
column.CharMaxLength = cast.ToInt(length)
}
column.DataType = dbi.ColumnDataType(dataType)
// 初始化列展示的长度,精度
column.InitShowNum()
columns = append(columns, column)
}
}
@@ -154,8 +154,8 @@ func (sd *SqliteMetaData) GetPrimaryKey(tableName string) (string, error) {
return "", err
}
for _, re := range res {
if anyx.ConvInt(re["pk"]) == 1 {
return anyx.ConvString(re["name"]), nil
if cast.ToInt(re["pk"]) == 1 {
return cast.ToString(re["name"]), nil
}
}
@@ -187,14 +187,14 @@ func (sd *SqliteMetaData) GetTableIndex(tableName string) ([]dbi.Index, error) {
indexs := make([]dbi.Index, 0)
for _, re := range res {
indexSql := anyx.ConvString(re["indexSql"])
indexSql := cast.ToString(re["indexSql"])
isUnique := strings.Contains(indexSql, "CREATE UNIQUE INDEX")
indexs = append(indexs, dbi.Index{
IndexName: anyx.ConvString(re["indexName"]),
IndexName: cast.ToString(re["indexName"]),
ColumnName: extractIndexFields(indexSql),
IndexType: anyx.ConvString(re["indexType"]),
IndexComment: anyx.ConvString(re["indexComment"]),
IndexType: cast.ToString(re["indexType"]),
IndexComment: cast.ToString(re["indexComment"]),
IsUnique: isUnique,
SeqInIndex: 1,
})
@@ -262,7 +262,7 @@ func (sd *SqliteMetaData) genColumnBasicSql(column dbi.Column) string {
}
}
return fmt.Sprintf(" %s %s %s %s", sd.dc.GetMetaData().QuoteIdentifier(column.ColumnName), column.ShowDataType, nullAble, defVal)
return fmt.Sprintf(" %s %s %s %s", sd.dc.GetMetaData().QuoteIdentifier(column.ColumnName), column.GetColumnType(), nullAble, defVal)
}
// 获取建表ddl
@@ -296,7 +296,7 @@ func (sd *SqliteMetaData) GetTableDDL(tableName string) (string, error) {
}
var builder strings.Builder
for _, re := range res {
builder.WriteString(anyx.ConvString(re["sql"]) + "; \n\n")
builder.WriteString(cast.ToString(re["sql"]) + "; \n\n")
}
return builder.String(), nil

View File

@@ -4,7 +4,8 @@ import (
sysapp "mayfly-go/internal/sys/application"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/utils/bytex"
"mayfly-go/pkg/utils/conv"
"github.com/may-fly/cast"
)
const (
@@ -41,6 +42,6 @@ func GetMachine() *Machine {
}
}
mc.UploadMaxFileSize = uploadMaxFileSize
mc.TermOpSaveDays = conv.Str2Int(jm["termOpSaveDays"], 30)
mc.TermOpSaveDays = cast.ToIntD(jm["termOpSaveDays"], 30)
return mc
}

View File

@@ -8,8 +8,9 @@ import (
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
"mayfly-go/pkg/utils/collx"
"strconv"
"strings"
"github.com/may-fly/cast"
)
type machineRepoImpl struct {
@@ -31,8 +32,7 @@ func (m *machineRepoImpl) GetMachineList(condition *entity.MachineQuery, pagePar
if condition.Ids != "" {
// ,分割id转为id数组
qd.In("id", collx.ArrayMap[string, uint64](strings.Split(condition.Ids, ","), func(val string) uint64 {
id, _ := strconv.Atoi(val)
return uint64(id)
return cast.ToUint64(val)
}))
}

View File

@@ -5,7 +5,9 @@ import (
"io"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/utils/conv"
"github.com/may-fly/cast"
"strings"
"time"
"unicode/utf8"
@@ -69,7 +71,7 @@ func NewTerminalSession(sessionId string, ws *websocket.Conn, cli *Cli, rows, co
}
func (r TerminalSession) Start() {
go r.readFormTerminal()
go r.readFromTerminal()
go r.writeToWebsocket()
r.receiveWsMsg()
}
@@ -87,7 +89,7 @@ func (r TerminalSession) Stop() {
}
}
func (ts TerminalSession) readFormTerminal() {
func (ts TerminalSession) readFromTerminal() {
for {
select {
case <-ts.ctx.Done():
@@ -207,15 +209,15 @@ func parseMsg(msg []byte) (*WsMsg, error) {
}
// 获取消息类型, 提取第一个 "|" 之前的内容
msgType := conv.Str2Int(msgStr[:index], Ping)
msgType := cast.ToIntD(msgStr[:index], Ping)
// 其余内容则为消息内容
msgContent := msgStr[index+1:]
wsMsg := &WsMsg{Type: msgType, Msg: msgContent}
if msgType == Resize {
rowsAndCols := strings.Split(msgContent, MsgSplit)
wsMsg.Rows = conv.Str2Int(rowsAndCols[0], 80)
wsMsg.Cols = conv.Str2Int(rowsAndCols[1], 80)
wsMsg.Rows = cast.ToIntD(rowsAndCols[0], 80)
wsMsg.Cols = cast.ToIntD(rowsAndCols[1], 80)
}
return wsMsg, nil
}

View File

@@ -1,8 +1,6 @@
package rdm
import (
"mayfly-go/pkg/utils/anyx"
)
import "github.com/may-fly/cast"
// write cmd
var writeCmd = map[string]string{
@@ -95,6 +93,6 @@ var writeCmd = map[string]string{
// 判断命令是否写命令
func IsWriteCmd(cmd any) bool {
_, ok := writeCmd[anyx.ConvString(cmd)]
_, ok := writeCmd[cast.ToString(cmd)]
return ok
}

View File

@@ -13,12 +13,13 @@ import (
"mayfly-go/pkg/model"
"mayfly-go/pkg/req"
"mayfly-go/pkg/utils/collx"
"mayfly-go/pkg/utils/conv"
"mayfly-go/pkg/utils/cryptox"
"mayfly-go/pkg/utils/structx"
"strconv"
"strings"
"time"
"github.com/may-fly/cast"
)
const (
@@ -136,7 +137,7 @@ func (a *Account) SimpleAccounts(rc *req.Ctx) {
idsStr := rc.Query("ids")
if idsStr != "" {
condition.Ids = collx.ArrayMap[string, uint64](strings.Split(idsStr, ","), func(val string) uint64 {
return uint64(conv.Str2Int(val, 0))
return cast.ToUint64(val)
})
}
res, err := a.AccountApp.GetPageList(condition, rc.GetPageParam(), new([]vo.SimpleAccountVO))

View File

@@ -7,10 +7,11 @@ import (
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/req"
"mayfly-go/pkg/utils/anyx"
"mayfly-go/pkg/utils/collx"
"strconv"
"strings"
"github.com/may-fly/cast"
)
type Role struct {
@@ -24,7 +25,7 @@ func (r *Role) Roles(rc *req.Ctx) {
notIdsStr := rc.Query("notIds")
if notIdsStr != "" {
cond.NotIds = collx.ArrayMap[string, uint64](strings.Split(notIdsStr, ","), func(val string) uint64 {
return uint64(anyx.ConvInt(val))
return cast.ToUint64(val)
})
}

View File

@@ -3,7 +3,8 @@ package entity
import (
"encoding/json"
"mayfly-go/pkg/model"
"mayfly-go/pkg/utils/conv"
"github.com/may-fly/cast"
)
const (
@@ -49,7 +50,7 @@ func (c *Config) IntValue(defaultValue int) int {
if c.Id == 0 {
return defaultValue
}
return conv.Str2Int(c.Value, defaultValue)
return cast.ToIntD(c.Value, defaultValue)
}
// 转换配置中的值为bool类型默认"1"或"true"为true其他为false

View File

@@ -93,6 +93,18 @@ func (p *TagTree) TagResources(rc *req.Ctx) {
rc.ResData = tagPaths
}
// 统计当前用户指定标签下关联的资源数量
func (p *TagTree) CountTagResource(rc *req.Ctx) {
tagPath := rc.Query("tagPath")
accountId := rc.GetLoginAccount().Id
rc.ResData = collx.M{
"machine": len(p.TagTreeApp.GetAccountResourceCodes(accountId, consts.TagResourceTypeMachine, tagPath)),
"db": len(p.TagTreeApp.GetAccountResourceCodes(accountId, consts.TagResourceTypeDb, tagPath)),
"redis": len(p.TagTreeApp.GetAccountResourceCodes(accountId, consts.TagResourceTypeRedis, tagPath)),
"mongo": len(p.TagTreeApp.GetAccountResourceCodes(accountId, consts.TagResourceTypeMongo, tagPath)),
}
}
// 资源标签关联信息查询
func (p *TagTree) QueryTagResources(rc *req.Ctx) {
var trs []*entity.TagResource

View File

@@ -127,7 +127,7 @@ func (p *tagTreeAppImpl) GetAccountTagResources(accountId uint64, resourceType i
}
}
tagResourceQuery.TagPath = tagPath
tagResourceQuery.TagPathLike = tagPath
tagResourceQuery.TagPathLikes = accountTagPaths
p.tagResourceApp.ListByQuery(tagResourceQuery, &tagResources)
return tagResources

View File

@@ -28,6 +28,8 @@ func InitTagTreeRouter(router *gin.RouterGroup) {
req.NewGet("/resources/:rtype/tag-paths", m.TagResources),
req.NewGet("/resources/count", m.CountTagResource),
req.NewGet("/resources", m.QueryTagResources),
}

View File

@@ -13,6 +13,8 @@ import (
"net/http"
"os"
"time"
"github.com/may-fly/cast"
)
// 默认超时
@@ -131,7 +133,7 @@ func (r *RequestWrapper) PostMulipart(files []MultipartFile, reqParams collx.M)
}
// 如果有其他参数则写入body
for k, v := range reqParams {
if err := writer.WriteField(k, anyx.ConvString(v)); err != nil {
if err := writer.WriteField(k, cast.ToString(v)); err != nil {
return &ResponseWrapper{err: err}
}
}

View File

@@ -2,64 +2,10 @@ package anyx
import (
"encoding/json"
"math"
"reflect"
"strconv"
)
// any类型转换为string, 如果any为nil则返回空字符串
func ConvString(val any) string {
if value, ok := val.(string); !ok {
return ""
} else {
return value
}
}
// any类型转换为int可将字符串或int64转换, 如果any为nil则返回0
func ConvInt(val any) int {
switch value := val.(type) {
case int:
return value
case string:
if intV, err := strconv.Atoi(value); err == nil {
return intV
}
case int64:
return int(value)
case uint64:
return int(value)
case int32:
return int(value)
case uint32:
return int(value)
case int16:
return int(value)
case uint16:
return int(value)
case int8:
return int(value)
case uint8:
return int(value)
case float32:
return int(value)
case float64:
return int(math.Round(value))
default:
return 0
}
return 0
}
// any类型转换为int64, 如果any为nil则返回0
func ConvInt64(val any) int64 {
if value, ok := val.(int64); !ok {
return int64(ConvInt(val))
} else {
return value
}
}
func IsBlank(value any) bool {
if value == nil {
return true

View File

@@ -1,19 +0,0 @@
package conv
import (
"mayfly-go/pkg/logx"
"strconv"
)
// 将字符串值转为int值, 若value为空或者转换失败则返回默认值
func Str2Int(value string, defaultValue int) int {
if value == "" {
return defaultValue
}
if intV, err := strconv.Atoi(value); err != nil {
logx.ErrorTrace("str conv int error: ", err)
return defaultValue
} else {
return intV
}
}