4 Commits

Author SHA1 Message Date
meilin.huang
f4a64b96a9 feat: v1.7.1新增支持sqlite&oracle分页限制等问题修复 2024-01-19 21:33:37 +08:00
zongyangleo
9a59749763 !86 dbms支持sqlite和一些bug修复
* fix: 达梦数据库连接修复,以支持带特殊字符的密码和schema
* fix: oracle bug修复
* feat: dbms支持sqlite
* fix: dbms 修改字段名bug
2024-01-19 08:59:35 +00:00
kanzihuang
b017b902f8 !85 fix: 修复 BINLOG同步任务加载问题
* Merge branch 'dev' of gitee.com:dromara/mayfly-go into feat-db-bak
* fix: 修复 BINLOG 同步任务加载问题
2024-01-19 00:40:44 +00:00
meilin.huang
7c53353c60 fix: sqlite数据问题时间类型问题修复等 2024-01-18 17:18:17 +08:00
64 changed files with 2231 additions and 336 deletions

View File

@@ -24,7 +24,7 @@ COPY --from=fe-builder /mayfly/dist /mayfly/static/static
# Build
RUN GO111MODULE=on CGO_ENABLED=0 GOOS=linux \
go build -a \
go build -a -ldflags=-w \
-o mayfly-go main.go
FROM debian:bookworm-slim

View File

@@ -22,7 +22,7 @@
### 介绍
web 版 **linux(终端[终端回放] 文件 脚本 进程 计划任务)、数据库mysql postgres oracle 达梦 高斯、redis(单机 哨兵 集群)、mongo 统一管理操作平台**
web 版 **linux(终端[终端回放] 文件 脚本 进程 计划任务)、数据库mysql postgres oracle 达梦 高斯 sqlite、redis(单机 哨兵 集群)、mongo 统一管理操作平台**
### 开发语言与主要框架

View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2021 lyt-Top
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -17,7 +17,7 @@
"countup.js": "^2.7.0",
"cropperjs": "^1.5.11",
"echarts": "^5.4.3",
"element-plus": "^2.5.1",
"element-plus": "^2.5.2",
"js-base64": "^3.7.5",
"jsencrypt": "^3.3.2",
"lodash": "^4.17.21",
@@ -33,7 +33,7 @@
"splitpanes": "^3.1.5",
"sql-formatter": "^15.0.2",
"uuid": "^9.0.1",
"vue": "^3.4.14",
"vue": "^3.4.15",
"vue-router": "^4.2.5",
"xterm": "^5.3.0",
"xterm-addon-fit": "^0.8.0",

File diff suppressed because one or more lines are too long

View File

@@ -55,11 +55,11 @@
"unicode_decimal": 58905
},
{
"icon_id": "11617944",
"icon_id": "25271976",
"name": "oracle",
"font_class": "oracle",
"unicode": "e6ea",
"unicode_decimal": 59114
"unicode": "e507",
"unicode_decimal": 58631
},
{
"icon_id": "8105644",
@@ -67,6 +67,13 @@
"font_class": "mariadb",
"unicode": "e513",
"unicode_decimal": 58643
},
{
"icon_id": "13601813",
"name": "sqlite",
"font_class": "sqlite",
"unicode": "e546",
"unicode_decimal": 58694
}
]
}

View File

@@ -15,7 +15,7 @@
</el-option>
</el-select>
</el-form-item>
<el-form-item prop="host" label="host" required>
<el-form-item v-if="form.type !== DbType.sqlite" prop="host" label="host" required>
<el-col :span="18">
<el-input :disabled="form.id !== undefined" v-model.trim="form.host" placeholder="请输入主机ip" auto-complete="off"></el-input>
</el-col>
@@ -24,13 +24,18 @@
<el-input type="number" v-model.number="form.port" placeholder="端口"></el-input>
</el-col>
</el-form-item>
<el-form-item v-if="form.type === DbType.sqlite" prop="host" label="sqlite地址">
<el-input v-model.trim="form.host" placeholder="请输入sqlite文件在服务器的绝对地址"></el-input>
</el-form-item>
<el-form-item v-if="form.type === DbType.oracle" prop="sid" label="SID">
<el-input v-model.trim="form.sid" placeholder="请输入服务id"></el-input>
</el-form-item>
<el-form-item prop="username" label="用户名" required>
<el-form-item v-if="form.type !== DbType.sqlite" prop="username" label="用户名" required>
<el-input v-model.trim="form.username" placeholder="请输入用户名"></el-input>
</el-form-item>
<el-form-item prop="password" label="密码">
<el-form-item v-if="form.type !== DbType.sqlite" prop="password" label="密码">
<el-input type="password" show-password v-model.trim="form.password" placeholder="请输入密码" autocomplete="new-password">
<template v-if="form.id && form.id != 0" #suffix>
<el-popover @hide="pwd = ''" placement="right" title="原密码" :width="200" trigger="click" :content="pwd">
@@ -169,6 +174,10 @@ const dbTypes = [
type: 'oracle',
label: 'oracle',
},
{
type: 'sqlite',
label: 'sqlite',
},
];
const state = reactive({
@@ -176,7 +185,7 @@ const state = reactive({
tabActiveName: 'basic',
form: {
id: null,
type: null,
type: '',
name: null,
host: '',
port: null,
@@ -247,10 +256,12 @@ const testConn = async () => {
};
const btnOk = async () => {
if (!state.form.id) {
notBlank(state.form.password, '新增操作,密码不可为空');
} else if (state.form.username != state.oldUserName) {
notBlank(state.form.password, '已修改用户名,请输入密码');
if (state.form.type !== DbType.sqlite) {
if (!state.form.id) {
notBlank(state.form.password, '新增操作,密码不可为空');
} else if (state.form.username != state.oldUserName) {
notBlank(state.form.password, '已修改用户名,请输入密码');
}
}
dbForm.value.validate(async (valid: boolean) => {

View File

@@ -269,26 +269,24 @@ const NodeTypeDb = new NodeType(SqlExecNodeType.Db)
nParams.schema = sn;
nParams.db = nParams.db + '/' + sn;
nParams.dbs = schemaNames;
return new TagTreeNode(`${params.id}.${params.db}.schema.${sn}`, sn, NodeTypePostgresScheam).withParams(nParams).withIcon(SchemaIcon);
return new TagTreeNode(`${params.id}.${params.db}.schema.${sn}`, sn, NodeTypePostgresSchema).withParams(nParams).withIcon(SchemaIcon);
});
}
return [
new TagTreeNode(`${params.id}.${params.db}.table-menu`, '表', NodeTypeTableMenu).withParams(params).withIcon(TableIcon),
new TagTreeNode(getSqlMenuNodeKey(params.id, params.db), 'SQL', NodeTypeSqlMenu).withParams(params).withIcon(SqlIcon),
];
return NodeTypeTables(params);
})
.withNodeClickFunc(nodeClickChangeDb);
const NodeTypeTables = (params: any) => {
return [
new TagTreeNode(`${params.id}.${params.db}.table-menu`, '表', NodeTypeTableMenu).withParams(params).withIcon(TableIcon),
new TagTreeNode(getSqlMenuNodeKey(params.id, params.db), 'SQL', NodeTypeSqlMenu).withParams(params).withIcon(SqlIcon),
];
};
// postgres schema模式
const NodeTypePostgresScheam = new NodeType(SqlExecNodeType.PgSchema)
const NodeTypePostgresSchema = new NodeType(SqlExecNodeType.PgSchema)
.withContextMenuItems([new ContextmenuItem('reloadTables', '刷新').withIcon('RefreshRight').withOnClick((data: any) => reloadNode(data.key))])
.withLoadNodesFunc(async (parentNode: TagTreeNode) => {
const params = parentNode.params;
return [
new TagTreeNode(`${params.id}.${params.db}.table-menu`, '表', NodeTypeTableMenu).withParams(params).withIcon(TableIcon),
new TagTreeNode(getSqlMenuNodeKey(params.id, params.db), 'SQL', NodeTypeSqlMenu).withParams(params).withIcon(SqlIcon),
];
})
.withLoadNodesFunc(async (parentNode: TagTreeNode) => NodeTypeTables(parentNode.params))
.withNodeClickFunc(nodeClickChangeDb);
// 数据库表菜单节点
@@ -309,7 +307,8 @@ const NodeTypeTableMenu = new NodeType(SqlExecNodeType.TableMenu)
state.reloadStatus = false;
let dbTableSize = 0;
const tablesNode = tables.map((x: any) => {
dbTableSize += x.dataLength + x.indexLength;
const tableSize = x.dataLength + x.indexLength;
dbTableSize += tableSize;
return new TagTreeNode(`${id}.${db}.${x.tableName}`, x.tableName, NodeTypeTable)
.withIsLeaf(true)
.withParams({
@@ -317,13 +316,13 @@ const NodeTypeTableMenu = new NodeType(SqlExecNodeType.TableMenu)
db,
tableName: x.tableName,
tableComment: x.tableComment,
size: formatByteSize(x.dataLength + x.indexLength, 1),
size: tableSize == 0 ? '' : formatByteSize(tableSize, 1),
})
.withIcon(TableIcon)
.withLabelRemark(`${x.tableName} ${x.tableComment ? '| ' + x.tableComment : ''}`);
});
// 设置父节点参数的表大小
parentNode.params.dbTableSize = formatByteSize(dbTableSize);
parentNode.params.dbTableSize = dbTableSize == 0 ? '' : formatByteSize(dbTableSize);
return tablesNode;
})
.withNodeClickFunc(nodeClickChangeDb);

View File

@@ -868,7 +868,7 @@ defineExpose({
color: var(--el-color-info-light-3);
font-weight: bold;
position: absolute;
top: -7px;
top: -5px;
padding: 2px;
height: 12px;
}

View File

@@ -371,7 +371,7 @@ const selectData = async () => {
}
const countRes = await dbInst.runSql(db, dbInst.getDefaultCountSql(table, state.condition));
state.count = countRes.res[0].count || countRes.res[0].COUNT || 0;
state.count = parseInt(countRes.res[0].count || countRes.res[0].COUNT || 0);
let sql = dbInst.getDefaultSelectSql(table, state.condition, state.orderBy, state.pageNum, state.pageSize);
state.sql = sql;
if (state.count > 0) {

View File

@@ -1,6 +1,6 @@
<template>
<div>
<el-dialog :title="title" v-model="dialogVisible" :before-close="cancel" width="90%" :close-on-press-escape="false" :close-on-click-modal="false">
<el-dialog :title="title" v-model="dialogVisible" :before-close="cancel" width="70%" :close-on-press-escape="false" :close-on-click-modal="false">
<el-form label-position="left" ref="formRef" :model="tableData" label-width="80px">
<el-row>
<el-col :span="12">
@@ -26,7 +26,7 @@
:width="item.width"
>
<template #default="scope">
<el-input v-if="item.prop === 'name'" size="small" v-model="scope.row.name"> </el-input>
<el-input v-if="item.prop === 'name'" size="small" v-model="scope.row.name" />
<el-select v-else-if="item.prop === 'type'" filterable size="small" v-model="scope.row.type">
<el-option
@@ -42,35 +42,30 @@
</el-option>
</el-select>
<el-input v-else-if="item.prop === 'value'" size="small" v-model="scope.row.value"> </el-input>
<el-input v-else-if="item.prop === 'value'" size="small" v-model="scope.row.value" />
<el-input v-else-if="item.prop === 'length'" size="small" v-model="scope.row.length"> </el-input>
<el-input v-else-if="item.prop === 'length'" type="number" size="small" v-model.number="scope.row.length" />
<el-input v-else-if="item.prop === 'numScale'" size="small" v-model="scope.row.numScale"> </el-input>
<el-input v-else-if="item.prop === 'numScale'" type="number" size="small" v-model.number="scope.row.numScale" />
<el-checkbox v-else-if="item.prop === 'notNull'" size="small" v-model="scope.row.notNull"> </el-checkbox>
<el-checkbox v-else-if="item.prop === 'notNull'" size="small" v-model="scope.row.notNull" />
<el-checkbox v-else-if="item.prop === 'pri'" size="small" v-model="scope.row.pri"> </el-checkbox>
<el-checkbox v-else-if="item.prop === 'pri'" size="small" v-model="scope.row.pri" />
<el-checkbox
v-else-if="item.prop === 'auto_increment'"
size="small"
v-model="scope.row.auto_increment"
:disabled="dbType === DbType.postgresql"
>
</el-checkbox>
/>
<el-input v-else-if="item.prop === 'remark'" size="small" v-model="scope.row.remark"> </el-input>
<el-input v-else-if="item.prop === 'remark'" size="small" v-model="scope.row.remark" />
<el-link
v-else-if="item.prop === 'action'"
type="danger"
plain
size="small"
:underline="false"
@click.prevent="deleteRow(scope.$index)"
>删除</el-link
>
<el-popconfirm v-else-if="item.prop === 'action'" title="确定删除?" @confirm="deleteRow(scope.$index)">
<template #reference>
<el-link type="danger" plain size="small" :underline="false">删除</el-link>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
@@ -110,15 +105,11 @@
<el-input v-if="item.prop === 'indexComment'" size="small" v-model="scope.row.indexComment"> </el-input>
<el-link
v-if="item.prop === 'action'"
type="danger"
plain
size="small"
:underline="false"
@click.prevent="deleteIndex(scope.$index)"
>删除</el-link
>
<el-popconfirm v-else-if="item.prop === 'action'" title="确定删除?" @confirm="deleteIndex(scope.$index)">
<template #reference>
<el-link type="danger" plain size="small" :underline="false">删除</el-link>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
@@ -130,6 +121,7 @@
</el-tabs>
</el-form>
<template #footer>
<el-button @click="cancel()">取消</el-button>
<el-button :loading="btnloading" @click="submit()" type="primary">保存</el-button>
</template>
</el-dialog>
@@ -187,22 +179,27 @@ const state = reactive({
{
prop: 'name',
label: '字段名称',
width: 200,
},
{
prop: 'type',
label: '字段类型',
width: 120,
},
{
prop: 'length',
label: '长度',
width: 120,
},
{
prop: 'numScale',
label: '小数点',
width: 120,
},
{
prop: 'value',
label: '默认值',
width: 120,
},
{
@@ -231,6 +228,7 @@ const state = reactive({
},
] as ColName[],
res: [] as RowDefinition[],
oldFields: [] as RowDefinition[],
},
indexs: {
colNames: [
@@ -261,10 +259,12 @@ const state = reactive({
],
columns: [{ name: '', remark: '' }],
res: [] as IndexDefinition[],
oldIndexs: [] as IndexDefinition[],
},
tableName: '',
tableComment: '',
height: 450,
db: '',
},
});
@@ -359,7 +359,10 @@ const filterChangedData = (oldArr: object[], nowArr: object[], key: string): { d
nowArr.forEach((a) => {
let k = a[key];
newMap[k] = a;
if (!oldMap.hasOwnProperty(k)) {
// 取oldName因为修改了name但是oldName不会变
let oldName = a['oldName'];
oldName && (newMap[oldName] = a);
if (!oldMap.hasOwnProperty(k) && (!oldName || (oldName && !oldMap.hasOwnProperty(oldName)))) {
// 新增
data.add.push(a);
}
@@ -376,7 +379,7 @@ const filterChangedData = (oldArr: object[], nowArr: object[], key: string): { d
for (let f in a) {
let oldV = a[f];
let newV = newData[f];
if (oldV.toString() !== newV.toString()) {
if (oldV?.toString() !== newV?.toString()) {
data.upd.push(newData);
break;
}
@@ -399,11 +402,11 @@ const genSql = () => {
// 修改
if (state.activeName === '1') {
// 修改列
let changeData = filterChangedData(oldData.fields, state.tableData.fields.res, 'name');
return dbDialect.getModifyColumnSql(data.tableName, changeData);
let changeData = filterChangedData(state.tableData.fields.oldFields, state.tableData.fields.res, 'name');
return dbDialect.getModifyColumnSql(data, data.tableName, changeData);
} else if (state.activeName === '2') {
// 修改索引
let changeData = filterChangedData(oldData.indexs, state.tableData.indexs.res, 'indexName');
let changeData = filterChangedData(state.tableData.indexs.oldIndexs, state.tableData.indexs.res, 'indexName');
return dbDialect.getModifyIndexSql(data.tableName, changeData);
}
}
@@ -456,7 +459,6 @@ const indexChanges = (row: any) => {
row.indexComment = `${tableData.value.tableName}表(${name.replaceAll('_', ',')})${commentSuffix}`;
};
const oldData = { indexs: [] as any[], fields: [] as RowDefinition[] };
watch(
() => props.data,
(newValue: any) => {
@@ -464,9 +466,10 @@ watch(
// 回显表名表注释
state.tableData.tableName = row.tableName;
state.tableData.tableComment = row.tableComment;
state.tableData.db = props.db!;
// 回显列
if (columns && Array.isArray(columns) && columns.length > 0) {
oldData.fields = [];
state.tableData.fields.oldFields = [];
state.tableData.fields.res = [];
// 索引列下拉选
state.tableData.indexs.columns = [];
@@ -474,10 +477,17 @@ watch(
let typeObj = a.columnType.replace(')', '').split('(');
let type = typeObj[0];
let length = (typeObj.length > 1 && typeObj[1]) || '';
let defaultValue = '';
if (a.columnDefault) {
defaultValue = a.columnDefault.trim().replace(/^'|'$/g, '');
// 解决高斯的默认值问题
defaultValue = defaultValue.replace("'::character varying", '');
}
let data = {
name: a.columnName,
oldName: a.columnName,
type,
value: a.columnDefault || '',
value: defaultValue,
length,
numScale: a.numScale,
notNull: a.nullable !== 'YES',
@@ -486,14 +496,14 @@ watch(
remark: a.columnComment,
};
state.tableData.fields.res.push(data);
oldData.fields.push(JSON.parse(JSON.stringify(data)));
state.tableData.fields.oldFields.push(JSON.parse(JSON.stringify(data)));
// 索引字段下拉选项
state.tableData.indexs.columns.push({ name: a.columnName, remark: a.columnComment });
});
}
// 回显索引
if (indexs && Array.isArray(indexs) && indexs.length > 0) {
oldData.indexs = [];
state.tableData.indexs.oldIndexs = [];
state.tableData.indexs.res = [];
// 索引过滤掉主键
indexs
@@ -507,7 +517,7 @@ watch(
indexComment: a.indexComment,
};
state.tableData.indexs.res.push(data);
oldData.indexs.push(JSON.parse(JSON.stringify(data)));
state.tableData.indexs.oldIndexs.push(JSON.parse(JSON.stringify(data)));
});
}
}

View File

@@ -181,7 +181,7 @@ const state = reactive({
visible: false,
activeName: '1',
type: '',
enableEditTypes: [DbType.mysql, DbType.mariadb, DbType.postgresql, DbType.dm, DbType.oracle], // 支持"编辑表"的数据库类型
enableEditTypes: [DbType.mysql, DbType.mariadb, DbType.postgresql, DbType.dm, DbType.oracle, DbType.sqlite], // 支持"编辑表"的数据库类型
data: {
// 修改表时,传递修改数据
edit: false,

View File

@@ -54,6 +54,7 @@ const DM_TYPE_LIST: sqlColumnType[] = [
{ udtName: 'BFILE', dataType: 'BFILE', desc: '二进制文件', space: '', range: '100G-1' },
];
// 参考官方文档https://eco.dameng.com/document/dm/zh-cn/pm/function.html
const replaceFunctions: EditorCompletionItem[] = [
// 数值函数
{ label: 'ABS', insertText: 'ABS(n)', description: '求数值 n 的绝对值' },
@@ -367,7 +368,7 @@ class DMDialect implements DbDialect {
dmDialectInfo = {
icon: 'iconfont icon-db-dm',
defaultPort: 5236,
formatSqlDialect: 'postgresql',
formatSqlDialect: 'plsql',
columnTypes: DM_TYPE_LIST.sort((a, b) => a.udtName.localeCompare(b.udtName)),
editorCompletions,
};
@@ -500,7 +501,9 @@ class DMDialect implements DbDialect {
// 默认值
let defVal = this.getDefaultValueSql(cl);
let incr = cl.auto_increment ? 'IDENTITY' : '';
return ` "${cl.name}" ${cl.type}${length} ${incr} ${cl.notNull ? 'NOT NULL' : ''} ${defVal} `;
// 如果有原名以原名为准
let name = cl.oldName && cl.name !== cl.oldName ? cl.oldName : cl.name;
return ` ${this.quoteIdentifier(name)} ${cl.type}${length} ${incr} ${cl.notNull ? 'NOT NULL' : ''} ${defVal} `;
}
getCreateTableSql(data: any): string {
@@ -546,32 +549,75 @@ class DMDialect implements DbDialect {
return sql.join(';');
}
getModifyColumnSql(tableName: string, changeData: { del: RowDefinition[]; add: RowDefinition[]; upd: RowDefinition[] }): string {
let sql: string[] = [];
getModifyColumnSql(tableData: any, tableName: string, changeData: { del: RowDefinition[]; add: RowDefinition[]; upd: RowDefinition[] }): string {
let schemaArr = tableData.db.split('/');
let schema = schemaArr.length > 1 ? schemaArr[schemaArr.length - 1] : schemaArr[0];
let dbTable = `${this.quoteIdentifier(schema)}.${this.quoteIdentifier(tableName)}`;
let modifySql = '';
let dropSql = '';
let renameSql = '';
let commentSql = '';
// 主键字段
let priArr = new Set();
if (changeData.add.length > 0) {
changeData.add.forEach((a) => {
sql.push(`ALTER TABLE "${tableName}" add COLUMN ${this.genColumnBasicSql(a)}`);
modifySql += `ALTER TABLE ${dbTable} add COLUMN ${this.genColumnBasicSql(a)};`;
if (a.remark) {
sql.push(`comment on COLUMN "${tableName}"."${a.name}" is '${a.remark}'`);
commentSql += `COMMENT ON COLUMN ${dbTable}.${this.quoteIdentifier(a.name)} IS '${a.remark}';`;
}
if (a.pri) {
priArr.add(`"${a.name}"`);
}
});
}
if (changeData.upd.length > 0) {
changeData.upd.forEach((a) => {
sql.push(`ALTER TABLE "${tableName}" MODIFY ${this.genColumnBasicSql(a)}`);
if (a.remark) {
sql.push(`comment on COLUMN "${tableName}"."${a.name}" is '${a.remark}'`);
let cmtSql = `COMMENT ON COLUMN ${dbTable}.${this.quoteIdentifier(a.name)} IS '${a.remark}';`;
if (a.remark && a.oldName === a.name) {
commentSql += cmtSql;
}
// 修改了字段名
if (a.oldName !== a.name) {
renameSql += `ALTER TABLE ${dbTable} RENAME COLUMN ${this.quoteIdentifier(a.oldName!)} TO ${this.quoteIdentifier(a.name)};`;
if (a.remark) {
commentSql += cmtSql;
}
}
modifySql += `ALTER TABLE ${dbTable} MODIFY ${this.genColumnBasicSql(a)};`;
if (a.pri) {
priArr.add(`${this.quoteIdentifier(a.name)}`);
}
});
}
if (changeData.del.length > 0) {
changeData.del.forEach((a) => {
sql.push(`ALTER TABLE "${tableName}" DROP COLUMN ${a.name}`);
dropSql += `ALTER TABLE ${dbTable} DROP COLUMN ${a.name};`;
});
}
return sql.join(';');
// 编辑主键
let dropPkSql = '';
if (priArr.size > 0) {
let resPri = tableData.fields.res.filter((a: RowDefinition) => a.pri);
if (resPri) {
priArr.add(`${this.quoteIdentifier(resPri.name)}`);
}
// 如果有编辑主键字段,则删除主键,再添加主键
// 解析表字段中是否含有主键,有的话就删除主键
if (tableData.fields.oldFields.find((a: RowDefinition) => a.pri)) {
dropPkSql = `ALTER TABLE ${dbTable} DROP PRIMARY KEY;`;
}
}
let addPkSql = priArr.size > 0 ? `ALTER TABLE ${dbTable} ADD PRIMARY KEY (${Array.from(priArr).join(',')});` : '';
return dropPkSql + modifySql + dropSql + renameSql + addPkSql + commentSql;
}
getModifyIndexSql(tableName: string, changeData: { del: any[]; add: any[]; upd: any[] }): string {

View File

@@ -3,6 +3,7 @@ import { PostgresqlDialect } from './postgres_dialect';
import { DMDialect } from '@/views/ops/db/dialect/dm_dialect';
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';
export interface sqlColumnType {
udtName: string;
@@ -14,6 +15,7 @@ export interface sqlColumnType {
export interface RowDefinition {
name: string;
oldName?: string;
type: string;
value: string;
length: string;
@@ -110,6 +112,7 @@ export const DbType = {
postgresql: 'postgres',
dm: 'dm', // 达梦
oracle: 'oracle',
sqlite: 'sqlite',
};
export const compatibleMysql = (dbType: string): boolean => {
@@ -164,10 +167,11 @@ export interface DbDialect {
/**
* 生成编辑列sql
* @param tableData 表数据,包含表名、列数据、索引数据
* @param tableName 表名
* @param changeData 改变信息
*/
getModifyColumnSql(tableName: string, changeData: { del: RowDefinition[]; add: RowDefinition[]; upd: RowDefinition[] }): string;
getModifyColumnSql(tableData: any, tableName: string, changeData: { del: RowDefinition[]; add: RowDefinition[]; upd: RowDefinition[] }): string;
/**
* 生成编辑索引sql
@@ -177,7 +181,7 @@ export interface DbDialect {
getModifyIndexSql(tableName: string, changeData: { del: any[]; add: any[]; upd: any[] }): string;
/** 通过数据库字段类型,返回基本数据类型 */
getDataType: (columnType: string) => DataType;
getDataType(columnType: string): DataType;
/** 包装字符串数据, 如oracle需要把date类型改为 to_date(str, 'yyyy-mm-dd hh24:mi:ss') */
wrapStrValue(columnType: string, value: string): string;
@@ -188,6 +192,7 @@ let mariadbDialect = new MariadbDialect();
let postgresDialect = new PostgresqlDialect();
let dmDialect = new DMDialect();
let oracleDialect = new OracleDialect();
let sqliteDialect = new SqliteDialect();
export const getDbDialect = (dbType: string | undefined): DbDialect => {
if (!dbType) {
@@ -204,6 +209,8 @@ export const getDbDialect = (dbType: string | undefined): DbDialect => {
return dmDialect;
case DbType.oracle:
return oracleDialect;
case DbType.sqlite:
return sqliteDialect;
default:
throw new Error('不支持的数据库');
}

View File

@@ -4,6 +4,7 @@ import { language as mysqlLanguage } from 'monaco-editor/esm/vs/basic-languages/
export { MYSQL_TYPE_LIST, MysqlDialect };
// 参考官方文档https://dev.mysql.com/doc/refman/8.0/en/data-types.html
const MYSQL_TYPE_LIST = [
'bigint',
'binary',
@@ -31,6 +32,7 @@ const MYSQL_TYPE_LIST = [
'varchar',
];
// 参考官方文档https://dev.mysql.com/doc/refman/8.3/en/functions.html
const replaceFunctions: EditorCompletionItem[] = [
/** 字符串相关函数 */
{ label: 'CONCAT', insertText: 'CONCAT(str1,str2,...)', description: '多字符串合并' },
@@ -193,7 +195,7 @@ class MysqlDialect implements DbDialect {
let defVal = val ? `DEFAULT ${val}` : '';
let length = cl.length ? `(${cl.length})` : '';
let onUpdate = 'update_time' === cl.name ? ' ON UPDATE CURRENT_TIMESTAMP ' : '';
return ` ${cl.name} ${cl.type}${length} ${cl.notNull ? 'NOT NULL' : 'NULL'} ${
return ` ${this.quoteIdentifier(cl.name)} ${cl.type}${length} ${cl.notNull ? 'NOT NULL' : 'NULL'} ${
cl.auto_increment ? 'AUTO_INCREMENT' : ''
} ${defVal} ${onUpdate} comment '${cl.remark || ''}' `;
}
@@ -223,35 +225,31 @@ class MysqlDialect implements DbDialect {
return sql.substring(0, sql.length - 1) + ';';
}
getModifyColumnSql(tableName: string, changeData: { del: RowDefinition[]; add: RowDefinition[]; upd: RowDefinition[] }): string {
let addSql = '',
updSql = '',
delSql = '';
if (changeData.add.length > 0) {
addSql = `ALTER TABLE ${tableName}`;
changeData.add.forEach((a) => {
addSql += ` ADD ${this.genColumnBasicSql(a)},`;
getModifyColumnSql(tableData: any, tableName: string, changeData: { del: RowDefinition[]; add: RowDefinition[]; upd: RowDefinition[] }): string {
let sql = `ALTER TABLE ${this.quoteIdentifier(tableData.db)}.${this.quoteIdentifier(tableName)}`;
let arr = [] as string[];
if (changeData.del.length > 0) {
changeData.del.forEach((a) => {
arr.push(` DROP COLUMN ${this.quoteIdentifier(a.name)} `);
});
}
if (changeData.add.length > 0) {
changeData.add.forEach((a) => {
arr.push(` ADD COLUMN ${this.genColumnBasicSql(a)} `);
});
addSql = addSql.substring(0, addSql.length - 1);
addSql += ';';
}
if (changeData.upd.length > 0) {
updSql = `ALTER TABLE ${tableName}`;
let arr = [] as string[];
changeData.upd.forEach((a) => {
arr.push(` MODIFY ${this.genColumnBasicSql(a)}`);
if (a.name === a.oldName) {
arr.push(` MODIFY COLUMN ${this.genColumnBasicSql(a)} `);
} else {
arr.push(` CHANGE COLUMN ${this.quoteIdentifier(a.oldName!)} ${this.genColumnBasicSql(a)} `);
}
});
updSql += arr.join(',');
updSql += ';';
}
if (changeData.del.length > 0) {
changeData.del.forEach((a) => {
delSql += ` ALTER TABLE ${tableName} DROP COLUMN ${a.name}; `;
});
}
return addSql + updSql + delSql;
return sql + arr.join(',') + ';';
}
getModifyIndexSql(tableName: string, changeData: { del: any[]; add: any[]; upd: any[] }): string {

View File

@@ -14,7 +14,7 @@ import { language as sqlLanguage } from 'monaco-editor/esm/vs/basic-languages/sq
export { OracleDialect, ORACLE_TYPE_LIST };
// 参考文档:https://eco.dameng.com/document/dm/zh-cn/sql-dev/dmpl-sql-datatype.html#%E5%AD%97%E7%AC%A6%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B
// 参考官方文档https://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements001.htm
const ORACLE_TYPE_LIST: sqlColumnType[] = [
// 字符数据类型
{ udtName: 'CHAR', dataType: 'CHAR', desc: '定长字符串,自动在末尾用空格补全,非unicode', space: '', range: '1 - 2000' },
@@ -50,6 +50,7 @@ const ORACLE_TYPE_LIST: sqlColumnType[] = [
{ udtName: 'BFILE', dataType: 'BFILE', desc: '二进制文件', space: '', range: '' },
];
// 参考官方文档https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions001.htm
const replaceFunctions: EditorCompletionItem[] = [
// 字符函数
{ label: 'ASCII', insertText: 'ASCII(x)', description: '返回字符X的ASCII码' },
@@ -268,16 +269,22 @@ class OracleDialect implements DbDialect {
return '';
}
genColumnBasicSql(cl: RowDefinition): string {
genColumnBasicSql(cl: RowDefinition, create: boolean): string {
let length = this.getTypeLengthSql(cl);
// 默认值
let defVal = this.getDefaultValueSql(cl);
let incr = cl.auto_increment ? 'generated by default as IDENTITY' : '';
let pri = cl.pri ? 'PRIMARY KEY' : '';
return ` ${cl.name.toUpperCase()} ${cl.type}${length} ${incr} ${pri} ${defVal} ${cl.notNull ? 'NOT NULL' : ''} `;
let incr = cl.auto_increment && create ? 'generated by default as IDENTITY' : '';
// 如果有原名以原名为准
let name = cl.oldName && cl.name !== cl.oldName ? cl.oldName : cl.name;
let baseSql = ` ${this.quoteIdentifier(name)} ${cl.type}${length} ${incr}`;
return incr ? baseSql : ` ${baseSql} ${defVal} ${cl.notNull ? 'NOT NULL' : ''} `;
}
getCreateTableSql(data: any): string {
let schemaArr = data.db.split('/');
let schema = schemaArr.length > 1 ? schemaArr[schemaArr.length - 1] : schemaArr[0];
let dbTable = `${this.quoteIdentifier(schema)}.${this.quoteIdentifier(data.tableName)}`;
let createSql = '';
let tableCommentSql = '';
let columCommentSql = '';
@@ -285,17 +292,17 @@ class OracleDialect implements DbDialect {
// 创建表结构
let fields: string[] = [];
data.fields.res.forEach((item: any) => {
item.name && fields.push(this.genColumnBasicSql(item));
item.name && fields.push(this.genColumnBasicSql(item, true));
// 列注释
if (item.remark) {
columCommentSql += ` comment on column ${data.tableName?.toUpperCase()}.${item.name?.toUpperCase()} is '${item.remark}'; `;
columCommentSql += ` COMMENT ON COLUMN ${dbTable}.${this.quoteIdentifier(item.name)} is '${item.remark}'; `;
}
});
// 建表
createSql = `CREATE TABLE ${data.tableName?.toUpperCase()} ( ${fields.join(',')} );`;
createSql = `CREATE TABLE ${dbTable} ( ${fields.join(',')} );`;
// 表注释
if (data.tableComment) {
tableCommentSql = ` comment on table ${data.tableName?.toUpperCase()} is '${data.tableComment}'; `;
tableCommentSql = ` COMMENT ON TABLE ${dbTable} is '${data.tableComment}'; `;
}
return createSql + tableCommentSql + columCommentSql;
@@ -304,40 +311,92 @@ class OracleDialect implements DbDialect {
getCreateIndexSql(tableData: any): string {
// CREATE UNIQUE INDEX idx_column_name ON your_table (column1, column2);
// COMMENT ON INDEX idx_column_name IS 'Your index comment here';
// 创建索引
let schemaArr = tableData.db.split('/');
let schema = schemaArr.length > 1 ? schemaArr[schemaArr.length - 1] : schemaArr[0];
let dbTable = `${this.quoteIdentifier(schema)}.${this.quoteIdentifier(tableData.tableName)}`;
let sql: string[] = [];
tableData.indexs.res.forEach((a: any) => {
sql.push(` CREATE ${a.unique ? 'UNIQUE' : ''} INDEX ${a.indexName} ON "${tableData.tableName}" ("${a.columnNames.join('","')})"`);
sql.push(` CREATE ${a.unique ? 'UNIQUE' : ''} INDEX ${a.indexName} ON ${dbTable} ("${a.columnNames.join('","')})"`);
});
return sql.join(';');
}
getModifyColumnSql(tableName: string, changeData: { del: RowDefinition[]; add: RowDefinition[]; upd: RowDefinition[] }): string {
let sql: string[] = [];
if (changeData.add.length > 0) {
changeData.add.forEach((a) => {
sql.push(`ALTER TABLE "${tableName}" add COLUMN ${this.genColumnBasicSql(a)}`);
if (a.remark) {
sql.push(`comment on COLUMN "${tableName}"."${a.name}" is '${a.remark}'`);
getModifyColumnSql(tableData: any, tableName: string, changeData: { del: RowDefinition[]; add: RowDefinition[]; upd: RowDefinition[] }): string {
let schemaArr = tableData.db.split('/');
let schema = schemaArr.length > 1 ? schemaArr[schemaArr.length - 1] : schemaArr[0];
let dbTable = `${this.quoteIdentifier(schema)}.${this.quoteIdentifier(tableName)}`;
let baseSql = `ALTER TABLE ${dbTable} `;
let modifyArr: string[] = [];
let dropArr: string[] = [];
// 重命名的sql要一条条执行
let renameArr: string[] = [];
let commentArr: string[] = [];
// 主键字段
let priArr = new Set();
if (changeData.upd.length > 0) {
changeData.upd.forEach((a) => {
let commentSql = `COMMENT ON COLUMN ${dbTable}.${this.quoteIdentifier(a.name)} IS '${a.remark}'`;
if (a.remark && a.oldName === a.name) {
commentArr.push(commentSql);
}
// 修改了字段名
if (a.oldName !== a.name) {
renameArr.push(baseSql + ` RENAME COLUMN ${this.quoteIdentifier(a.oldName!)} TO ${this.quoteIdentifier(a.name)} ;`);
if (a.remark) {
commentArr.push(commentSql);
}
}
modifyArr.push(` MODIFY (${this.genColumnBasicSql(a, false)})`);
if (a.pri) {
priArr.add(`${this.quoteIdentifier(a.name)}"`);
}
});
}
if (changeData.upd.length > 0) {
changeData.upd.forEach((a) => {
sql.push(`ALTER TABLE "${tableName}" MODIFY ${this.genColumnBasicSql(a)}`);
if (changeData.add.length > 0) {
changeData.add.forEach((a) => {
modifyArr.push(` ADD (${this.genColumnBasicSql(a, false)})`);
if (a.remark) {
sql.push(`comment on COLUMN "${tableName}"."${a.name}" is '${a.remark}'`);
commentArr.push(`COMMENT ON COLUMN ${dbTable}.${this.quoteIdentifier(a.name)} is '${a.remark}'`);
}
if (a.pri) {
priArr.add(`"${a.name}"`);
}
});
}
if (changeData.del.length > 0) {
changeData.del.forEach((a) => {
sql.push(`ALTER TABLE "${tableName}" DROP COLUMN ${a.name}`);
dropArr.push(`${this.quoteIdentifier(a.name)}`);
});
}
return sql.join(';');
let dropPkSql = '';
if (priArr.size > 0) {
let resPri = tableData.fields.res.find((a: RowDefinition) => a.pri);
if (resPri) {
priArr.add(`"${resPri.name}"`);
}
// 如果有编辑主键字段,则删除主键,再添加主键
// 解析表字段中是否含有主键,有的话就删除主键
if (tableData.fields.oldFields.find((a: RowDefinition) => a.pri)) {
dropPkSql = `ALTER TABLE ${dbTable} DROP PRIMARY KEY;`;
}
}
let modifySql = baseSql + modifyArr.join(' ') + ';';
let dropSql = baseSql + ` DROP (${dropArr.join(',')}) ;`;
let renameSql = renameArr.join('');
let addPkSql = priArr.size > 0 ? `ALTER TABLE ${dbTable} ADD CONSTRAINT "PK_${tableName}" PRIMARY KEY (${Array.from(priArr).join(',')});` : '';
let commentSql = commentArr.join(';');
return dropPkSql + modifySql + dropSql + renameSql + addPkSql + commentSql;
}
getModifyIndexSql(tableName: string, changeData: { del: any[]; add: any[]; upd: any[] }): string {

View File

@@ -228,7 +228,7 @@ class PostgresqlDialect implements DbDialect {
let marks = false;
if (this.matchType(cl.type, ['char', 'time', 'date', 'text'])) {
// 默认值是now()的time或date不需要加引号
if (cl.value.toLowerCase().replace(' ', '') === 'current_timestamp' && this.matchType(cl.type, ['time', 'date'])) {
if (cl.value.toLowerCase() === 'pg_systimestamp()' && this.matchType(cl.type, ['time', 'date'])) {
marks = false;
} else {
marks = true;
@@ -260,7 +260,10 @@ class PostgresqlDialect implements DbDialect {
let length = this.getTypeLengthSql(cl);
// 默认值
let defVal = this.getDefaultValueSql(cl);
return ` ${cl.name} ${cl.type}${length} ${cl.notNull ? 'NOT NULL' : ''} ${defVal} `;
// 如果有原名以原名为准
let name = cl.oldName && cl.name !== cl.oldName ? cl.oldName : cl.name;
return ` ${this.quoteIdentifier(name)} ${cl.type}${length} ${cl.notNull ? 'NOT NULL' : ''} ${defVal} `;
}
getCreateTableSql(data: any): string {
@@ -301,7 +304,7 @@ class PostgresqlDialect implements DbDialect {
// 创建索引
let sql: string[] = [];
tableData.indexs.res.forEach((a: any) => {
sql.push(` CREATE ${a.unique ? 'UNIQUE' : ''} INDEX ${a.indexName} USING btree ("${a.columnNames.join('","')})"`);
sql.push(` create ${a.unique ? 'UNIQUE' : ''} index ${a.indexName} ("${a.columnNames.join('","')})"`);
if (a.indexComment) {
sql.push(`COMMENT ON INDEX ${a.indexName} IS '${a.indexComment}'`);
}
@@ -309,39 +312,57 @@ class PostgresqlDialect implements DbDialect {
return sql.join(';');
}
getModifyColumnSql(tableName: string, changeData: { del: RowDefinition[]; add: RowDefinition[]; upd: RowDefinition[] }): string {
let sql: string[] = [];
getModifyColumnSql(tableData: any, tableName: string, changeData: { del: RowDefinition[]; add: RowDefinition[]; upd: RowDefinition[] }): string {
let schemaArr = tableData.db.split('/');
let schema = schemaArr.length > 1 ? schemaArr[schemaArr.length - 1] : schemaArr[0];
let dbTable = `${this.quoteIdentifier(schema)}.${this.quoteIdentifier(tableName)}`;
let dropPkSql = '';
let modifySql = '';
let dropSql = '';
let renameSql = '';
let addPkSql = '';
let commentSql = '';
if (changeData.add.length > 0) {
changeData.add.forEach((a) => {
let typeLength = this.getTypeLengthSql(a);
let defaultSql = this.getDefaultValueSql(a);
sql.push(`ALTER TABLE ${tableName} add ${a.name} ${a.type}${typeLength} ${defaultSql}`);
modifySql += `alter table ${dbTable} add ${this.genColumnBasicSql(a)};`;
if (a.remark) {
sql.push(`comment on column "${tableName}"."${a.name}" is '${a.remark}'`);
commentSql += `comment on column ${dbTable}.${this.quoteIdentifier(a.name)} is '${a.remark}';`;
}
});
}
if (changeData.upd.length > 0) {
changeData.upd.forEach((a) => {
let cmtSql = `comment on column ${dbTable}.${this.quoteIdentifier(a.name)} is '${a.remark}';`;
if (a.remark && a.oldName === a.name) {
commentSql += cmtSql;
}
// 修改了字段名
if (a.oldName !== a.name) {
renameSql += `alter table ${dbTable} rename column ${this.quoteIdentifier(a.oldName!)} to ${this.quoteIdentifier(a.name)};`;
if (a.remark) {
commentSql += cmtSql;
}
}
let typeLength = this.getTypeLengthSql(a);
sql.push(`ALTER TABLE ${tableName} alter column ${a.name} type ${a.type}${typeLength}`);
// 如果有原名以原名为准
let name = a.oldName && a.name !== a.oldName ? a.oldName : a.name;
modifySql += `alter table ${dbTable} alter column ${this.quoteIdentifier(name)} type ${a.type}${typeLength} ;`;
let defaultSql = this.getDefaultValueSql(a);
if (defaultSql) {
sql.push(`alter table ${tableName} alter column ${a.name} set ${defaultSql}`);
}
if (a.remark) {
sql.push(`comment on column "${tableName}"."${a.name}" is '${a.remark}'`);
modifySql += `alter table ${dbTable} alter column ${this.quoteIdentifier(name)} set ${defaultSql} ;`;
}
});
}
if (changeData.del.length > 0) {
changeData.del.forEach((a) => {
sql.push(`ALTER TABLE ${tableName} DROP COLUMN ${a.name}`);
dropSql += `alter table ${dbTable} drop column ${a.name};`;
});
}
return sql.join(';');
return dropPkSql + modifySql + dropSql + renameSql + addPkSql + commentSql;
}
getModifyIndexSql(tableName: string, changeData: { del: any[]; add: any[]; upd: any[] }): string {

View File

@@ -0,0 +1,337 @@
import {
commonCustomKeywords,
DataType,
DbDialect,
DialectInfo,
EditorCompletion,
EditorCompletionItem,
IndexDefinition,
RowDefinition,
sqlColumnType,
} from './index';
import { DbInst } from '@/views/ops/db/db';
import { language as sqlLanguage } from 'monaco-editor/esm/vs/basic-languages/sql/sql.js';
export { SqliteDialect };
// 参考官方文档https://www.sqlite.org/datatype3.html
const SQLITE_TYPE_LIST: sqlColumnType[] = [
// INTEGER
{ udtName: 'int', dataType: 'int', desc: '', space: '', range: '' },
{ udtName: 'integer', dataType: 'integer', desc: '', space: '', range: '' },
{ udtName: 'tinyint', dataType: 'tinyint', desc: '', space: '', range: '' },
{ udtName: 'smallint', dataType: 'smallint', desc: '', space: '', range: '' },
{ udtName: 'mediumint', dataType: 'mediumint', desc: '', space: '', range: '' },
{ udtName: 'bigint', dataType: 'bigint', desc: '', space: '', range: '' },
{ udtName: 'unsigned big int', dataType: 'unsigned big int', desc: '', space: '', range: '' },
{ udtName: 'int2', dataType: 'int2', desc: '', space: '', range: '' },
{ udtName: 'int8', dataType: 'int8', desc: '', space: '', range: '' },
// TEXT
{ udtName: 'character', dataType: 'character', desc: '', space: '', range: '' },
{ udtName: 'varchar', dataType: 'varchar', desc: '', space: '', range: '' },
{ udtName: 'varying character', dataType: 'varying character', desc: '', space: '', range: '' },
{ udtName: 'nchar', dataType: 'nchar', desc: '', space: '', range: '' },
{ udtName: 'native character', dataType: 'native character', desc: '', space: '', range: '' },
{ udtName: 'nvarchar', dataType: 'nvarchar', desc: '', space: '', range: '' },
{ udtName: 'text', dataType: 'text', desc: '', space: '', range: '' },
{ udtName: 'clob', dataType: 'clob', desc: '', space: '', range: '' },
// blob
{ udtName: 'blob', dataType: 'blob', desc: '', space: '', range: '' },
{ udtName: 'no datatype specified', dataType: 'no datatype specified', desc: '', space: '', range: '' },
// REAL
{ udtName: 'real', dataType: 'real', desc: '', space: '', range: '' },
{ udtName: 'double', dataType: 'double', desc: '', space: '', range: '' },
{ udtName: 'double precision', dataType: 'double precision', desc: '', space: '', range: '' },
{ udtName: 'float', dataType: 'float', desc: '', space: '', range: '' },
// NUMERIC
{ udtName: 'numeric', dataType: 'numeric', desc: '', space: '', range: '' },
{ udtName: 'decimal', dataType: 'decimal', desc: '', space: '', range: '' },
{ udtName: 'boolean', dataType: 'boolean', desc: '', space: '', range: '' },
{ udtName: 'date', dataType: 'date', desc: '', space: '', range: '' },
{ udtName: 'datetime', dataType: 'datetime', desc: '', space: '', range: '' },
];
const addCustomKeywords = ['PRAGMA', 'database_list', 'sqlite_master'];
// 参考官方文档https://www.sqlite.org/lang_corefunc.html
const functions: EditorCompletionItem[] = [
// 字符函数
{ label: 'abs', insertText: 'abs(X)', description: '返回给定数值的绝对值' },
{ label: 'changes', insertText: 'changes()', description: '返回最近增删改影响的行数' },
{ label: 'coalesce', insertText: 'coalesce(X,Y,...)', description: '返回第一个不为空的值' },
{ label: 'hex', insertText: 'hex(X)', description: '返回给定字符的hex值' },
{ label: 'ifnull', insertText: 'ifnull(X,Y)', description: '返回第一个不为空的值' },
{ label: 'iif', insertText: 'iif(X,Y,Z)', description: '如果x为真则返回y否则返回z' },
{ label: 'instr', insertText: 'instr(X,Y)', description: '返回字符y在x的第n个位置' },
{ label: 'length', insertText: 'length(X)', description: '返回给定字符的长度' },
{ label: 'load_extension', insertText: 'load_extension(X[,Y])', description: '加载扩展块' },
{ label: 'lower', insertText: 'lower(X)', description: '返回小写字符' },
{ label: 'ltrim', insertText: 'ltrim(X[,Y])', description: '左trim' },
{ label: 'nullif', insertText: 'nullif(X,Y)', description: '比较两值相等则返回null否则返回第一个值' },
{ label: 'printf', insertText: "printf('%s',...)", description: '字符串格式化拼接,如%s %d' },
{ label: 'quote', insertText: 'quote(X)', description: '把字符串用引号包起来' },
{ label: 'random', insertText: 'random()', description: '生成随机数' },
{ label: 'randomblob', insertText: 'randomblob(N)', description: '生成一个包含N个随机字节的BLOB' },
{ label: 'replace', insertText: 'replace(X,Y,Z)', description: '替换字符串' },
{ label: 'round', insertText: 'round(X[,Y])', description: '将数值四舍五入到指定的小数位数' },
{ label: 'rtrim', insertText: 'rtrim(X[,Y])', description: '右trim' },
{ label: 'sign', insertText: 'sign(X)', description: '返回数字符号 1正 -1负 0零 null' },
{ label: 'soundex', insertText: 'soundex(X)', description: '返回字符串X的soundex编码字符串' },
{ label: 'sqlite_compileoption_get', insertText: 'sqlite_compileoption_get(N)', description: '获取指定编译选项的值' },
{ label: 'sqlite_compileoption_used', insertText: 'sqlite_compileoption_used(X)', description: '检查SQLite编译时是否使用了指定的编译选项' },
{ label: 'sqlite_source_id', insertText: 'sqlite_source_id()', description: '获取sqlite源代码标识符' },
{ label: 'sqlite_version', insertText: 'sqlite_version()', description: '获取sqlite版本' },
{ label: 'substr', insertText: 'substr(X,Y[,Z])', description: '截取字符串' },
{ label: 'substring', insertText: 'substring(X,Y[,Z])', description: '截取字符串' },
{ label: 'trim', insertText: 'trim(X[,Y])', description: '去除给定字符串前后的字符,默认空格' },
{ label: 'typeof', insertText: 'typeof(X)', description: '返回X的基本类型null,integer,real,text,blob' },
{ label: 'unicode', insertText: 'unicode(X)', description: '返回与字符串X的第一个字符相对应的数字unicode代码点' },
{ label: 'unlikely', insertText: 'unlikely(X)', description: '返回大写字符' },
{ label: 'upper', insertText: 'upper(X)', description: '返回由0x00的N个字节组成的BLOB' },
{ label: 'zeroblob', insertText: 'zeroblob(N)', description: '返回分组中的平均值' },
{ label: 'avg', insertText: 'avg(X)', description: '返回总条数' },
{ label: 'count', insertText: 'count(*)', description: '返回分组中用给定非空字符串连接的值' },
{ label: 'group_concat', insertText: 'group_concat(X[,Y])', description: '返回分组中最大值' },
{ label: 'max', insertText: 'max(X)', description: '返回分组中最小值' },
{ label: 'min', insertText: 'min(X)', description: '返回分组中非空值的总和。' },
{ label: 'sum', insertText: 'sum(X)', description: '返回分组中非空值的总和。' },
{ label: 'total', insertText: 'total(X)', description: '返回YYYY-MM-DD格式的字符串' },
{ label: 'date', insertText: 'date(time-value[, modifier, ...])', description: '返回HH:MM:SS格式的字符串' },
{ label: 'time', insertText: 'time(time-value[, modifier, ...])', description: '将日期和时间字符串转换为特定的日期和时间格式' },
{ label: 'datetime', insertText: 'datetime(time-value[, modifier, ...])', description: '计算日期和时间的儒略日数' },
{ label: 'julianday', insertText: 'julianday(time-value[, modifier, ...])', description: '将日期和时间格式化为指定的字符串' },
];
let sqliteDialectInfo: DialectInfo;
class SqliteDialect implements DbDialect {
getInfo(): DialectInfo {
if (sqliteDialectInfo) {
return sqliteDialectInfo;
}
let { keywords, operators, builtinVariables } = sqlLanguage;
let editorCompletions: EditorCompletion = {
keywords: keywords
.filter((a: string) => addCustomKeywords.indexOf(a) === -1)
.map((a: string): EditorCompletionItem => ({ label: a, description: 'keyword' }))
.concat(commonCustomKeywords.map((a): EditorCompletionItem => ({ label: a, description: 'keyword' })))
.concat(addCustomKeywords.map((a): EditorCompletionItem => ({ label: a, description: 'keyword' }))),
operators: operators.map((a: string): EditorCompletionItem => ({ label: a, description: 'operator' })),
functions,
variables: builtinVariables.map((a: string): EditorCompletionItem => ({ label: a, description: 'var' })),
};
sqliteDialectInfo = {
icon: 'iconfont icon-sqlite',
defaultPort: 0,
formatSqlDialect: 'sql',
columnTypes: SQLITE_TYPE_LIST.sort((a, b) => a.udtName.localeCompare(b.udtName)),
editorCompletions,
};
return sqliteDialectInfo;
}
getDefaultSelectSql(table: string, condition: string, orderBy: string, pageNum: number, limit: number) {
return `SELECT * FROM ${this.quoteIdentifier(table)} ${condition ? 'WHERE ' + condition : ''} ${orderBy ? orderBy : ''} ${this.getPageSql(
pageNum,
limit
)};`;
}
getPageSql(pageNum: number, limit: number) {
return ` LIMIT ${(pageNum - 1) * limit}, ${limit}`;
}
getDefaultRows(): RowDefinition[] {
return [
{ name: 'id', type: 'bigint', length: '20', numScale: '', value: '', notNull: true, pri: true, auto_increment: true, remark: '主键ID' },
{ name: 'creator_id', type: 'bigint', length: '20', numScale: '', value: '', notNull: true, pri: false, auto_increment: false, remark: '创建人id' },
{
name: 'creator',
type: 'varchar',
length: '100',
numScale: '',
value: '',
notNull: true,
pri: false,
auto_increment: false,
remark: '创建人姓名',
},
{
name: 'create_time',
type: 'datetime',
length: '',
numScale: '',
value: 'CURRENT_TIMESTAMP',
notNull: true,
pri: false,
auto_increment: false,
remark: '创建时间',
},
{ name: 'updator_id', type: 'bigint', length: '20', numScale: '', value: '', notNull: true, pri: false, auto_increment: false, remark: '修改人id' },
{ name: 'updator', type: 'varchar', length: '100', numScale: '', value: '', notNull: true, pri: false, auto_increment: false, remark: '修改姓名' },
{
name: 'update_time',
type: 'datetime',
length: '',
numScale: '',
value: 'CURRENT_TIMESTAMP',
notNull: true,
pri: false,
auto_increment: false,
remark: '修改时间',
},
];
}
getDefaultIndex(): IndexDefinition {
return {
indexName: '',
columnNames: [],
unique: false,
indexType: 'BTREE',
indexComment: '',
};
}
quoteIdentifier = (name: string) => {
return `\"${name}\"`;
};
genColumnBasicSql(cl: any): string {
let val = cl.value ? (cl.value === 'CURRENT_TIMESTAMP' ? cl.value : `'${cl.value}'`) : '';
let defVal = val ? `DEFAULT ${val}` : '';
let length = cl.length ? `(${cl.length})` : '';
let nullAble = cl.notNull ? 'NOT NULL' : 'NULL';
if (cl.pri) {
return ` ${this.quoteIdentifier(cl.name)} ${cl.type}${length} PRIMARY KEY ${cl.auto_increment ? 'AUTOINCREMENT' : ''} ${nullAble} `;
}
return ` ${this.quoteIdentifier(cl.name)} ${cl.type}${length} ${nullAble} ${defVal} `;
}
getCreateTableSql(data: any): string {
// 创建表结构
let fields: string[] = [];
data.fields.res.forEach((item: any) => {
item.name && fields.push(this.genColumnBasicSql(item));
});
return `CREATE TABLE ${this.quoteIdentifier(data.db)}.${this.quoteIdentifier(data.tableName)}
( ${fields.join(',')} )`;
}
getCreateIndexSql(data: any): string {
// 创建索引
let sql = [] as string[];
data.indexs.res.forEach((a: any) => {
sql.push(
`CREATE ${a.unique ? 'UNIQUE' : ''} INDEX ${this.quoteIdentifier(data.db)}.${this.quoteIdentifier(a.indexName)} ON "${data.tableName}" (${a.columnNames.join(',')})`
);
});
return sql.join(';');
}
getModifyColumnSql(tableData: any, tableName: string, changeData: { del: RowDefinition[]; add: RowDefinition[]; upd: RowDefinition[] }): string {
// sqlite修改表结构需要先删除再创建
// 1.删除旧表索引 DROP INDEX "main"."aa";
let sql = [] as string[];
tableData.indexs.res.forEach((a: any) => {
a.indexName && sql.push(`DROP INDEX ${this.quoteIdentifier(tableData.db)}.${this.quoteIdentifier(a.indexName)}`);
});
// 2.重命名表,备份旧表 ALTER TABLE "main"."t_sys_resource" RENAME TO "_t_sys_resource_old_20240118162712"; new Date().getTime()
let oldTableName = `_${tableName}_old_${new Date().getTime()}`;
sql.push(`ALTER TABLE ${this.quoteIdentifier(tableData.db)}.${this.quoteIdentifier(tableName)} RENAME TO ${this.quoteIdentifier(oldTableName)}`);
// 3.创建新表
sql.push(this.getCreateTableSql(tableData));
// 4.复制数据 INSERT INTO "库名"."新表名" (${insertFields}) SELECT ${queryFields} FROM "库名"."旧表名";
// 查询的字段数据类型和数量应与插入的字段一致
// 判断哪些字段需要查询旧表,哪些字段需要插入新表
// 解析changeData统计需要查询旧表的字段统计需要插入新表的字段
let delFields = changeData.del.map((a) => a.name);
let addFields = changeData.add.map((a) => a.name);
let queryFields = [] as string[];
let insertFields = [] as string[];
tableData.fields.res.forEach((a: any) => {
// 新增、删除的字段不需要查询旧表,不需要插入新表
if (addFields.includes(a.name) || delFields.includes(a.name)) {
return;
}
// 修改的字段需要查询和插入,判断是否修改了字段名,如果修改了字段名,需要查询旧表原名,插入新表新名
// 其余未删除、未修改的字段,需要查询旧表,插入新表
queryFields.push(this.quoteIdentifier(a.name === a.oldName ? a.name : a.oldName));
insertFields.push(this.quoteIdentifier(a.name));
});
// 生成sql
sql.push(
`INSERT INTO ${this.quoteIdentifier(tableData.db)}.${this.quoteIdentifier(tableName)} (${insertFields.join(',')}) SELECT ${queryFields.join(
','
)} FROM ${this.quoteIdentifier(tableData.db)}.${this.quoteIdentifier(oldTableName)}`
);
// 5.创建索引
tableData.indexs.res.forEach((a: any) => {
a.indexName &&
sql.push(
`CREATE ${a.unique ? 'UNIQUE' : ''} INDEX ${this.quoteIdentifier(tableData.db)}.${this.quoteIdentifier(a.indexName)} ON "${tableName}" (${a.columnNames.join(',')})`
);
});
return sql.join(';') + ';';
}
getModifyIndexSql(tableName: string, changeData: { del: any[]; add: any[]; upd: any[] }): string {
// sqlite创建索引需要先删除再创建
// CREATE INDEX "main"."aa1" ON "t_sys_resource" ( "ui_path" );
let sql = [] as string[];
if (changeData.del.length > 0) {
changeData.del.forEach((a) => {
sql.push(`DROP INDEX ${this.quoteIdentifier(a.indexName)}`);
});
}
let indexData = [] as any[];
if (changeData.add.length > 0) {
indexData = indexData.concat(changeData.add);
}
if (changeData.upd.length > 0) {
indexData = indexData.concat(changeData.upd);
}
if (indexData.length > 0) {
indexData.forEach((a) => {
sql.push(`CREATE ${a.unique ? 'UNIQUE' : ''} INDEX ${this.quoteIdentifier(a.indexName)} ON ${tableName} (${a.columnNames.join(',')})`);
});
}
return sql.join(';');
}
getDataType(columnType: string): DataType {
if (DbInst.isNumber(columnType)) {
return DataType.Number;
}
// 日期时间类型
if (/datetime|timestamp/gi.test(columnType)) {
return DataType.DateTime;
}
// 日期类型
if (/date/gi.test(columnType)) {
return DataType.Date;
}
// 时间类型
if (/time/gi.test(columnType)) {
return DataType.Time;
}
return DataType.String;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-unused-vars
wrapStrValue(columnType: string, value: string): string {
return `'${value}'`;
}
}

View File

@@ -41,7 +41,15 @@
<el-input v-model="state.keySeparator" placeholder="分割符" size="small" class="ml5" />
</el-col>
<el-col :span="18">
<el-input @clear="clear" v-model="scanParam.match" placeholder="match 支持*模糊key" clearable size="small" class="ml10" />
<el-input
@clear="clear"
v-model="scanParam.match"
@keyup.enter.native="searchKey()"
placeholder="match 支持*模糊key, 回车搜索"
clearable
size="small"
class="ml10"
/>
</el-col>
<el-col :span="4">
<el-button

View File

@@ -107,10 +107,10 @@ defineExpose({ getContent });
.format-viewer-container .el-textarea textarea {
font-size: 14px;
height: calc(100vh - 546px + v-bind(height));
height: calc(100vh - 550px + v-bind(height));
}
.format-viewer-container .monaco-editor-content {
height: calc(100vh - 560px + v-bind(height)) !important;
height: calc(100vh - 565px + v-bind(height)) !important;
}
</style>

View File

@@ -1,7 +1,7 @@
<template>
<div>
<el-button @click="showEditDialog(null)" icon="plus" size="small" plain type="primary" class="mb10">添加新行</el-button>
<el-table size="small" border :data="hashValues" height="450" min-height="300" stripe>
<el-table size="small" border :data="hashValues" height="500" min-height="300" stripe>
<el-table-column type="index" :label="'ID (Total: ' + total + ')'" sortable width="100"> </el-table-column>
<el-table-column resizable sortable prop="field" label="field" show-overflow-tooltip min-width="100"> </el-table-column>
<el-table-column resizable sortable prop="value" label="value" show-overflow-tooltip min-width="200"> </el-table-column>
@@ -11,7 +11,7 @@
class="key-detail-filter-value"
v-model="state.filterValue"
@keyup.enter="hscan(true, true)"
placeholder="输入关键词回车搜索"
placeholder="关键词回车搜索"
clearable
size="small"
/>
@@ -51,7 +51,7 @@
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, reactive, watch, toRefs } from 'vue';
import { ref, onMounted, reactive, toRefs } from 'vue';
import { redisApi } from './api';
import { ElMessage } from 'element-plus';
import { notBlank } from '@/common/assert';

View File

@@ -142,7 +142,7 @@ const search = async () => {
const changeStatus = async (row: any) => {
let id = row.id;
let status = row.status == -1 ? 1 : -1;
let status = row.status == AccountStatusEnum.Disable.value ? AccountStatusEnum.Enable.value : AccountStatusEnum.Disable.value;
await accountApi.changeStatus.request({
id,
status,

View File

@@ -26,7 +26,7 @@ require (
github.com/pquerna/otp v1.4.0
github.com/redis/go-redis/v9 v9.4.0
github.com/robfig/cron/v3 v3.0.1 //
github.com/sijms/go-ora/v2 v2.8.5
github.com/sijms/go-ora/v2 v2.8.6
github.com/stretchr/testify v1.8.4
go.mongodb.org/mongo-driver v1.13.1 // mongo
golang.org/x/crypto v0.18.0 // ssh
@@ -35,6 +35,7 @@ require (
// gorm
gorm.io/driver/mysql v1.5.2
gorm.io/gorm v1.25.5
)
require (

View File

@@ -1,25 +1,10 @@
package initialize
import (
dbApp "mayfly-go/internal/db/application"
dbInit "mayfly-go/internal/db/init"
)
// 终止服务后的一些操作
// 终止进程服务后的一些操作
func Terminate() {
closeDbTasks()
}
func closeDbTasks() {
restoreApp := dbApp.GetDbRestoreApp()
if restoreApp != nil {
restoreApp.Close()
}
binlogApp := dbApp.GetDbBinlogApp()
if binlogApp != nil {
binlogApp.Close()
}
backupApp := dbApp.GetDbBackupApp()
if backupApp != nil {
backupApp.Close()
}
dbInit.Terminate()
}

View File

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

View File

@@ -5,9 +5,9 @@ type InstanceForm struct {
Name string `binding:"required" json:"name"`
Type string `binding:"required" json:"type"` // 类型mysql oracle等
Host string `binding:"required" json:"host"`
Port int `binding:"required" json:"port"`
Port int `json:"port"`
Sid string `json:"sid"`
Username string `binding:"required" json:"username"`
Username string `json:"username"`
Password string `json:"password"`
Params string `json:"params"`
Remark string `json:"remark"`

View File

@@ -93,8 +93,12 @@ func (d *dbSqlExecAppImpl) Exec(ctx context.Context, execSqlReq *DbSqlExecReq) (
// 如果配置为0则不校验分页参数
maxCount := config.GetDbQueryMaxCount()
if maxCount != 0 {
if !strings.Contains(lowerSql, "limit") {
return nil, errorx.NewBiz("请完善分页信息后执行")
// 兼容oracle rownum分页
if !strings.Contains(lowerSql, "limit") && !strings.Contains(lowerSql, "rownum") {
// 判断是不是count语句
if !strings.Contains(lowerSql, "count(") {
return nil, errorx.NewBiz("请完善分页信息后执行")
}
}
}
}

View File

@@ -73,9 +73,11 @@ func (app *instanceAppImpl) Save(ctx context.Context, instanceEntity *entity.DbI
err := app.GetBy(oldInstance)
if instanceEntity.Id == 0 {
if instanceEntity.Password == "" {
if instanceEntity.Type != string(dbi.DbTypeSqlite) && instanceEntity.Password == "" {
return errorx.NewBiz("密码不能为空")
}
if err == nil {
return errorx.NewBiz("该数据库实例已存在")
}

View File

@@ -16,6 +16,7 @@ const (
DbTypePostgres DbType = "postgres"
DbTypeDM DbType = "dm"
DbTypeOracle DbType = "oracle"
DbTypeSqlite DbType = "sqlite"
)
func ToDbType(dbType string) DbType {
@@ -48,6 +49,17 @@ func (dbType DbType) QuoteIdentifier(name string) string {
}
}
func (dbType DbType) RemoveQuote(name string) string {
switch dbType {
case DbTypeMysql, DbTypeMariadb:
return removeQuote(name, "`")
case DbTypePostgres:
return removeQuote(name, `"`)
default:
return removeQuote(name, `"`)
}
}
func (dbType DbType) QuoteLiteral(literal string) string {
switch dbType {
case DbTypeMysql, DbTypeMariadb:
@@ -93,6 +105,11 @@ func quoteIdentifier(name, quoter string) string {
return quoter + strings.Replace(name, quoter, quoter+quoter, -1) + quoter
}
// 移除相关引号
func removeQuote(name, quoter string) string {
return strings.ReplaceAll(name, quoter, "")
}
func (dbType DbType) StmtSetForeignKeyChecks(check bool) string {
switch dbType {
case DbTypeMysql, DbTypeMariadb:

View File

@@ -75,7 +75,7 @@ type Dialect interface {
GetColumns(tableNames ...string) ([]Column, error)
// 获取表主键字段名,没有主键标识则默认第一个字段
GetPrimaryKey(tablename string) (string, error)
GetPrimaryKey(tableName string) (string, error)
// 获取表索引信息
GetTableIndex(tableName string) ([]Index, error)

View File

@@ -0,0 +1,21 @@
--SQLITE_TABLE_INFO
select tbl_name as tableName,
'' as tableComment,
'' as createTime,
0 as dataLength,
0 as indexLength,
0 as tableRows
FROM sqlite_master
WHERE type = 'table'
and name not like 'sqlite_%'
ORDER BY tbl_name
---------------------------------------
--SQLITE_INDEX_INFO 表索引信息
select name as indexName,
`sql` as indexSql,
'normal' as indexType,
'' as indexComment
FROM sqlite_master
WHERE type = 'index'
and tbl_name = '%s'
ORDER BY name

View File

@@ -8,6 +8,7 @@ import (
"mayfly-go/internal/db/dbm/mysql"
"mayfly-go/internal/db/dbm/oracle"
"mayfly-go/internal/db/dbm/postgres"
"mayfly-go/internal/db/dbm/sqlite"
"mayfly-go/internal/machine/mcm"
"mayfly-go/pkg/cache"
"mayfly-go/pkg/logx"
@@ -48,6 +49,8 @@ func getDbMetaByType(dt dbi.DbType) dbi.Meta {
return dm.GetMeta()
case dbi.DbTypeOracle:
return oracle.GetMeta()
case dbi.DbTypeSqlite:
return sqlite.GetMeta()
default:
panic(fmt.Sprintf("invalid database type: %s", dt))
}

View File

@@ -8,6 +8,7 @@ import (
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/utils/anyx"
"mayfly-go/pkg/utils/collx"
"regexp"
"strings"
"time"
@@ -67,7 +68,7 @@ func (dd *DMDialect) GetTables() ([]dbi.Table, error) {
tables := make([]dbi.Table, 0)
for _, re := range res {
tables = append(tables, dbi.Table{
TableName: re["TABLE_NAME"].(string),
TableName: anyx.ConvString(re["TABLE_NAME"]),
TableComment: anyx.ConvString(re["TABLE_COMMENT"]),
CreateTime: anyx.ConvString(re["CREATE_TIME"]),
TableRows: anyx.ConvInt(re["TABLE_ROWS"]),
@@ -80,13 +81,10 @@ func (dd *DMDialect) GetTables() ([]dbi.Table, error) {
// 获取列元信息, 如列名等
func (dd *DMDialect) GetColumns(tableNames ...string) ([]dbi.Column, error) {
tableName := ""
for i := 0; i < len(tableNames); i++ {
if i != 0 {
tableName = tableName + ", "
}
tableName = tableName + "'" + tableNames[i] + "'"
}
dbType := dd.dc.Info.Type
tableName := strings.Join(collx.ArrayMap[string, string](tableNames, func(val string) string {
return fmt.Sprintf("'%s'", dbType.RemoveQuote(val))
}), ",")
_, res, err := dd.dc.Query(fmt.Sprintf(dbi.GetLocalSql(DM_META_FILE, DM_COLUMN_MA_KEY), tableName))
if err != nil {
@@ -96,8 +94,8 @@ func (dd *DMDialect) GetColumns(tableNames ...string) ([]dbi.Column, error) {
columns := make([]dbi.Column, 0)
for _, re := range res {
columns = append(columns, dbi.Column{
TableName: re["TABLE_NAME"].(string),
ColumnName: re["COLUMN_NAME"].(string),
TableName: anyx.ConvString(re["TABLE_NAME"]),
ColumnName: anyx.ConvString(re["COLUMN_NAME"]),
ColumnType: anyx.ConvString(re["COLUMN_TYPE"]),
ColumnComment: anyx.ConvString(re["COLUMN_COMMENT"]),
Nullable: anyx.ConvString(re["NULLABLE"]),
@@ -136,7 +134,7 @@ func (dd *DMDialect) GetTableIndex(tableName string) ([]dbi.Index, error) {
indexs := make([]dbi.Index, 0)
for _, re := range res {
indexs = append(indexs, dbi.Index{
IndexName: re["INDEX_NAME"].(string),
IndexName: anyx.ConvString(re["INDEX_NAME"]),
ColumnName: anyx.ConvString(re["COLUMN_NAME"]),
IndexType: anyx.ConvString(re["INDEX_TYPE"]),
IndexComment: anyx.ConvString(re["INDEX_COMMENT"]),

View File

@@ -4,6 +4,7 @@ import (
"database/sql"
"fmt"
"mayfly-go/internal/db/dbm/dbi"
"net/url"
"strings"
"sync"
)
@@ -31,10 +32,12 @@ func (md *DmMeta) GetSqlDb(d *dbi.DbInfo) (*sql.DB, error) {
// dm database可以使用db/schema表示方便连接指定schema, 若不存在schema则使用默认schema
ss := strings.Split(db, "/")
if len(ss) > 1 {
dbParam = fmt.Sprintf("%s?schema=%s", ss[0], ss[len(ss)-1])
dbParam = fmt.Sprintf("%s?schema=\"%s\"&escapeProcess=true", ss[0], ss[len(ss)-1])
} else {
dbParam = db
dbParam = db + "?escapeProcess=true"
}
} else {
dbParam = "?escapeProcess=true"
}
err := d.IfUseSshTunnelChangeIpPort()
@@ -42,7 +45,7 @@ func (md *DmMeta) GetSqlDb(d *dbi.DbInfo) (*sql.DB, error) {
return nil, err
}
dsn := fmt.Sprintf("dm://%s:%s@%s:%d/%s", d.Username, d.Password, d.Host, d.Port, dbParam)
dsn := fmt.Sprintf("dm://%s:%s@%s:%d/%s", d.Username, url.PathEscape(d.Password), d.Host, d.Port, dbParam)
return sql.Open(driverName, dsn)
}

View File

@@ -7,6 +7,7 @@ import (
"mayfly-go/internal/db/dbm/dbi"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/utils/anyx"
"mayfly-go/pkg/utils/collx"
"regexp"
"strings"
)
@@ -58,7 +59,7 @@ func (md *MysqlDialect) GetTables() ([]dbi.Table, error) {
tables := make([]dbi.Table, 0)
for _, re := range res {
tables = append(tables, dbi.Table{
TableName: re["tableName"].(string),
TableName: anyx.ConvString(re["tableName"]),
TableComment: anyx.ConvString(re["tableComment"]),
CreateTime: anyx.ConvString(re["createTime"]),
TableRows: anyx.ConvInt(re["tableRows"]),
@@ -71,13 +72,10 @@ func (md *MysqlDialect) GetTables() ([]dbi.Table, error) {
// 获取列元信息, 如列名等
func (md *MysqlDialect) GetColumns(tableNames ...string) ([]dbi.Column, error) {
tableName := ""
for i := 0; i < len(tableNames); i++ {
if i != 0 {
tableName = tableName + ", "
}
tableName = tableName + "'" + tableNames[i] + "'"
}
dbType := md.dc.Info.Type
tableName := strings.Join(collx.ArrayMap[string, string](tableNames, func(val string) string {
return fmt.Sprintf("'%s'", dbType.RemoveQuote(val))
}), ",")
_, res, err := md.dc.Query(fmt.Sprintf(dbi.GetLocalSql(MYSQL_META_FILE, MYSQL_COLUMN_MA_KEY), tableName))
if err != nil {
@@ -87,8 +85,8 @@ func (md *MysqlDialect) GetColumns(tableNames ...string) ([]dbi.Column, error) {
columns := make([]dbi.Column, 0)
for _, re := range res {
columns = append(columns, dbi.Column{
TableName: re["tableName"].(string),
ColumnName: re["columnName"].(string),
TableName: anyx.ConvString(re["tableName"]),
ColumnName: anyx.ConvString(re["columnName"]),
ColumnType: anyx.ConvString(re["columnType"]),
ColumnComment: anyx.ConvString(re["columnComment"]),
Nullable: anyx.ConvString(re["nullable"]),
@@ -129,7 +127,7 @@ func (md *MysqlDialect) GetTableIndex(tableName string) ([]dbi.Index, error) {
indexs := make([]dbi.Index, 0)
for _, re := range res {
indexs = append(indexs, dbi.Index{
IndexName: re["indexName"].(string),
IndexName: anyx.ConvString(re["indexName"]),
ColumnName: anyx.ConvString(re["columnName"]),
IndexType: anyx.ConvString(re["indexType"]),
IndexComment: anyx.ConvString(re["indexComment"]),
@@ -162,7 +160,7 @@ func (md *MysqlDialect) GetTableDDL(tableName string) (string, error) {
if err != nil {
return "", err
}
return res[0]["Create Table"].(string) + ";", nil
return anyx.ConvString(res[0]["Create Table"]) + ";", nil
}
func (md *MysqlDialect) WalkTableRecord(tableName string, walkFn dbi.WalkQueryRowsFunc) error {

View File

@@ -7,6 +7,7 @@ import (
"mayfly-go/internal/db/dbm/dbi"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/utils/anyx"
"mayfly-go/pkg/utils/collx"
"reflect"
"regexp"
"strings"
@@ -68,7 +69,7 @@ func (od *OracleDialect) GetTables() ([]dbi.Table, error) {
tables := make([]dbi.Table, 0)
for _, re := range res {
tables = append(tables, dbi.Table{
TableName: re["TABLE_NAME"].(string),
TableName: anyx.ConvString(re["TABLE_NAME"]),
TableComment: anyx.ConvString(re["TABLE_COMMENT"]),
CreateTime: anyx.ConvString(re["CREATE_TIME"]),
TableRows: anyx.ConvInt(re["TABLE_ROWS"]),
@@ -81,13 +82,10 @@ func (od *OracleDialect) GetTables() ([]dbi.Table, error) {
// 获取列元信息, 如列名等
func (od *OracleDialect) GetColumns(tableNames ...string) ([]dbi.Column, error) {
tableName := ""
for i := 0; i < len(tableNames); i++ {
if i != 0 {
tableName = tableName + ", "
}
tableName = tableName + "'" + tableNames[i] + "'"
}
dbType := od.dc.Info.Type
tableName := strings.Join(collx.ArrayMap[string, string](tableNames, func(val string) string {
return fmt.Sprintf("'%s'", dbType.RemoveQuote(val))
}), ",")
_, res, err := od.dc.Query(fmt.Sprintf(dbi.GetLocalSql(ORACLE_META_FILE, ORACLE_COLUMN_MA_KEY), tableName))
if err != nil {
@@ -102,8 +100,8 @@ func (od *OracleDialect) GetColumns(tableNames ...string) ([]dbi.Column, error)
defaultVal = ""
}
columns = append(columns, dbi.Column{
TableName: re["TABLE_NAME"].(string),
ColumnName: re["COLUMN_NAME"].(string),
TableName: anyx.ConvString(re["TABLE_NAME"]),
ColumnName: anyx.ConvString(re["COLUMN_NAME"]),
ColumnType: anyx.ConvString(re["COLUMN_TYPE"]),
ColumnComment: anyx.ConvString(re["COLUMN_COMMENT"]),
Nullable: anyx.ConvString(re["NULLABLE"]),
@@ -142,7 +140,7 @@ func (od *OracleDialect) GetTableIndex(tableName string) ([]dbi.Index, error) {
indexs := make([]dbi.Index, 0)
for _, re := range res {
indexs = append(indexs, dbi.Index{
IndexName: re["INDEX_NAME"].(string),
IndexName: anyx.ConvString(re["INDEX_NAME"]),
ColumnName: anyx.ConvString(re["COLUMN_NAME"]),
IndexType: anyx.ConvString(re["INDEX_TYPE"]),
IndexComment: anyx.ConvString(re["INDEX_COMMENT"]),
@@ -179,7 +177,7 @@ func (od *OracleDialect) GetTableDDL(tableName string) (string, error) {
// 建表ddl
var builder strings.Builder
for _, re := range res {
builder.WriteString(re["TABLE_DDL"].(string))
builder.WriteString(anyx.ConvString(re["TABLE_DDL"]))
}
// 表注释
@@ -230,7 +228,7 @@ func (od *OracleDialect) GetTableDDL(tableName string) (string, error) {
return "", err
}
for _, re := range res {
builder.WriteString("\n\n" + re["INDEX_DEF"].(string))
builder.WriteString("\n\n" + anyx.ConvString(re["INDEX_DEF"]))
}
return builder.String(), nil

View File

@@ -3,10 +3,11 @@ package oracle
import (
"database/sql"
"fmt"
go_ora "github.com/sijms/go-ora/v2"
"mayfly-go/internal/db/dbm/dbi"
"strings"
"sync"
go_ora "github.com/sijms/go-ora/v2"
)
var (
@@ -44,9 +45,21 @@ func (md *OraMeta) GetSqlDb(d *dbi.DbInfo) (*sql.DB, error) {
schema = ss[1]
}
}
urlOptions["TIMEOUT"] = "60"
urlOptions["client charset"] = "UTF8"
// 解析参数
if d.Params != "" {
paramArr := strings.Split(d.Params, "&")
for _, param := range paramArr {
ps := strings.Split(param, "=")
if len(ps) > 1 {
if ps[0] == "clientCharset" {
urlOptions["client charset"] = ps[1]
} else {
urlOptions[ps[0]] = ps[1]
}
}
}
}
urlOptions["TIMEOUT"] = "10"
connStr := go_ora.BuildUrl(d.Host, d.Port, d.Sid, d.Username, d.Password, urlOptions)
conn, err := sql.Open(driverName, connStr)
if err != nil {

View File

@@ -7,6 +7,7 @@ import (
"mayfly-go/internal/db/dbm/dbi"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/utils/anyx"
"mayfly-go/pkg/utils/collx"
"regexp"
"strings"
"time"
@@ -73,13 +74,10 @@ func (pd *PgsqlDialect) GetTables() ([]dbi.Table, error) {
// 获取列元信息, 如列名等
func (pd *PgsqlDialect) GetColumns(tableNames ...string) ([]dbi.Column, error) {
tableName := ""
for i := 0; i < len(tableNames); i++ {
if i != 0 {
tableName = tableName + ", "
}
tableName = tableName + "'" + tableNames[i] + "'"
}
dbType := pd.dc.Info.Type
tableName := strings.Join(collx.ArrayMap[string, string](tableNames, func(val string) string {
return fmt.Sprintf("'%s'", dbType.RemoveQuote(val))
}), ",")
_, res, err := pd.dc.Query(fmt.Sprintf(dbi.GetLocalSql(PGSQL_META_FILE, PGSQL_COLUMN_MA_KEY), tableName))
if err != nil {
@@ -89,8 +87,8 @@ func (pd *PgsqlDialect) GetColumns(tableNames ...string) ([]dbi.Column, error) {
columns := make([]dbi.Column, 0)
for _, re := range res {
columns = append(columns, dbi.Column{
TableName: re["tableName"].(string),
ColumnName: re["columnName"].(string),
TableName: anyx.ConvString(re["tableName"]),
ColumnName: anyx.ConvString(re["columnName"]),
ColumnType: anyx.ConvString(re["columnType"]),
ColumnComment: anyx.ConvString(re["columnComment"]),
Nullable: anyx.ConvString(re["nullable"]),
@@ -129,7 +127,7 @@ func (pd *PgsqlDialect) GetTableIndex(tableName string) ([]dbi.Index, error) {
indexs := make([]dbi.Index, 0)
for _, re := range res {
indexs = append(indexs, dbi.Index{
IndexName: re["indexName"].(string),
IndexName: anyx.ConvString(re["indexName"]),
ColumnName: anyx.ConvString(re["columnName"]),
IndexType: anyx.ConvString(re["IndexType"]),
IndexComment: anyx.ConvString(re["indexComment"]),

View File

@@ -0,0 +1,247 @@
package sqlite
import (
"context"
"database/sql"
"errors"
"fmt"
"mayfly-go/internal/db/dbm/dbi"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/utils/anyx"
"regexp"
"strings"
"time"
)
const (
SQLITE_META_FILE = "metasql/sqlite_meta.sql"
SQLITE_TABLE_INFO_KEY = "SQLITE_TABLE_INFO"
SQLITE_INDEX_INFO_KEY = "SQLITE_INDEX_INFO"
)
type SqliteDialect struct {
dc *dbi.DbConn
}
func (sd *SqliteDialect) GetDbServer() (*dbi.DbServer, error) {
_, res, err := sd.dc.Query("SELECT SQLITE_VERSION() as version")
if err != nil {
return nil, err
}
ds := &dbi.DbServer{
Version: anyx.ConvString(res[0]["version"]),
}
return ds, nil
}
func (sd *SqliteDialect) GetDbNames() ([]string, error) {
databases := make([]string, 0)
_, res, err := sd.dc.Query("PRAGMA database_list")
if err != nil {
return nil, err
}
for _, re := range res {
databases = append(databases, anyx.ConvString(re["name"]))
}
return databases, nil
}
// 获取表基础元信息, 如表名等
func (sd *SqliteDialect) GetTables() ([]dbi.Table, error) {
_, res, err := sd.dc.Query(dbi.GetLocalSql(SQLITE_META_FILE, SQLITE_TABLE_INFO_KEY))
//cols, res, err := sd.dc.Query("SELECT datetime(1092941466, 'unixepoch')")
if err != nil {
return nil, err
}
tables := make([]dbi.Table, 0)
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"]),
})
}
return tables, nil
}
// 获取列元信息, 如列名等
func (sd *SqliteDialect) GetColumns(tableNames ...string) ([]dbi.Column, error) {
columns := make([]dbi.Column, 0)
for i := 0; i < len(tableNames); i++ {
tableName := tableNames[i]
_, res, err := sd.dc.Query(fmt.Sprintf("PRAGMA table_info(%s)", tableName))
if err != nil {
logx.Error("获取数据库表字段结构出错", err.Error())
continue
}
for _, re := range res {
nullable := "YES"
if anyx.ConvInt(re["notnull"]) == 1 {
nullable = "NO"
}
// 去掉默认值的引号
defaultValue := anyx.ConvString(re["dflt_value"])
if strings.Contains(defaultValue, "'") {
defaultValue = strings.ReplaceAll(defaultValue, "'", "")
}
columnKey := ""
if anyx.ConvInt(re["pk"]) == 1 {
columnKey = "PRI"
}
columns = append(columns, dbi.Column{
TableName: tableName,
ColumnName: re["name"].(string),
ColumnType: strings.ToLower(anyx.ConvString(re["type"])),
ColumnComment: "",
Nullable: nullable,
ColumnKey: columnKey,
ColumnDefault: defaultValue,
NumScale: "0",
})
}
}
return columns, nil
}
func (sd *SqliteDialect) GetPrimaryKey(tableName string) (string, error) {
_, res, err := sd.dc.Query(fmt.Sprintf("PRAGMA table_info(%s)", tableName))
if err != nil {
return "", err
}
for _, re := range res {
if anyx.ConvInt(re["pk"]) == 1 {
return re["name"].(string), nil
}
}
return "", errors.New("不存在主键")
}
// 解析索引创建语句以获取字段信息
func extractIndexFields(indexSQL string) string {
// 使用正则表达式提取字段信息
re := regexp.MustCompile(`\((.*?)\)`)
match := re.FindStringSubmatch(indexSQL)
if len(match) > 1 {
fields := strings.Split(match[1], ",")
for i, field := range fields {
// 去除空格
fields[i] = strings.TrimSpace(field)
}
return strings.Join(fields, ",")
}
return ""
}
// 获取表索引信息
func (sd *SqliteDialect) GetTableIndex(tableName string) ([]dbi.Index, error) {
_, res, err := sd.dc.Query(fmt.Sprintf(dbi.GetLocalSql(SQLITE_META_FILE, SQLITE_INDEX_INFO_KEY), tableName))
if err != nil {
return nil, err
}
indexs := make([]dbi.Index, 0)
for _, re := range res {
indexSql := re["indexSql"].(string)
isUnique := strings.Contains(indexSql, "CREATE UNIQUE INDEX")
nonUnique := 1
if isUnique {
nonUnique = 0
}
indexs = append(indexs, dbi.Index{
IndexName: re["indexName"].(string),
ColumnName: extractIndexFields(indexSql),
IndexType: anyx.ConvString(re["indexType"]),
IndexComment: anyx.ConvString(re["indexComment"]),
NonUnique: nonUnique,
SeqInIndex: 1,
})
}
// 把查询结果以索引名分组,索引字段以逗号连接
return indexs, nil
}
// 获取建表ddl
func (sd *SqliteDialect) GetTableDDL(tableName string) (string, error) {
_, res, err := sd.dc.Query("select sql from sqlite_master WHERE name=? order by type desc", tableName)
if err != nil {
return "", err
}
var builder strings.Builder
for _, re := range res {
builder.WriteString(re["sql"].(string))
}
return builder.String(), nil
}
func (sd *SqliteDialect) WalkTableRecord(tableName string, walkFn dbi.WalkQueryRowsFunc) error {
return sd.dc.WalkQueryRows(context.Background(), fmt.Sprintf("SELECT * FROM %s", tableName), walkFn)
}
func (sd *SqliteDialect) GetSchemas() ([]string, error) {
return nil, nil
}
// GetDbProgram 获取数据库程序模块,用于数据库备份与恢复
func (sd *SqliteDialect) GetDbProgram() dbi.DbProgram {
panic("implement me")
}
func (sd *SqliteDialect) GetDataType(dbColumnType string) dbi.DataType {
if regexp.MustCompile(`(?i)int`).MatchString(dbColumnType) {
return dbi.DataTypeNumber
}
if regexp.MustCompile(`(?i)datetime`).MatchString(dbColumnType) {
return dbi.DataTypeDateTime
}
return dbi.DataTypeString
}
func (sd *SqliteDialect) BatchInsert(tx *sql.Tx, tableName string, columns []string, values [][]any) (int64, error) {
// 执行批量insert sql跟mysql一样 支持批量insert语法
// 生成占位符字符串:如:(?,?)
// 重复字符串并用逗号连接
repeated := strings.Repeat("?,", len(columns))
// 去除最后一个逗号,占位符由括号包裹
placeholder := fmt.Sprintf("(%s)", strings.TrimSuffix(repeated, ","))
// 重复占位符字符串n遍
repeated = strings.Repeat(placeholder+",", len(values))
// 去除最后一个逗号
placeholder = strings.TrimSuffix(repeated, ",")
sqlStr := fmt.Sprintf("insert into %s (%s) values %s", sd.dc.Info.Type.QuoteIdentifier(tableName), strings.Join(columns, ","), placeholder)
// 把二维数组转为一维数组
var args []any
for _, v := range values {
args = append(args, v...)
}
// 执行批量insert sql
return sd.dc.TxExec(tx, sqlStr, args...)
}
func (sd *SqliteDialect) FormatStrData(dbColumnValue string, dataType dbi.DataType) string {
switch dataType {
case dbi.DataTypeDateTime: // "2024-01-02T22:08:22.275697+08:00"
res, _ := time.Parse(time.RFC3339, dbColumnValue)
return res.Format(time.DateTime)
case dbi.DataTypeDate: // "2024-01-02T00:00:00+08:00"
res, _ := time.Parse(time.RFC3339, dbColumnValue)
return res.Format(time.DateOnly)
case dbi.DataTypeTime: // "0000-01-01T22:08:22.275688+08:00"
res, _ := time.Parse(time.RFC3339, dbColumnValue)
return res.Format(time.TimeOnly)
}
return dbColumnValue
}

View File

@@ -0,0 +1,37 @@
package sqlite
import (
"database/sql"
"errors"
"mayfly-go/internal/db/dbm/dbi"
"os"
"sync"
)
var (
meta dbi.Meta
once sync.Once
)
func GetMeta() dbi.Meta {
once.Do(func() {
meta = new(SqliteMeta)
})
return meta
}
type SqliteMeta struct {
}
func (md *SqliteMeta) GetSqlDb(d *dbi.DbInfo) (*sql.DB, error) {
// 用host字段来存sqlite的文件路径
// 检查文件是否存在,否则报错基于sqlite会自动创建文件为了服务器文件安全所以先确定文件存在再连接不自动创建
if _, err := os.Stat(d.Host); err != nil {
return nil, errors.New("数据库文件不存在")
}
return sql.Open("sqlite", d.Host)
}
func (md *SqliteMeta) GetDialect(conn *dbi.DbConn) dbi.Dialect {
return &SqliteDialect{conn}
}

View File

@@ -24,9 +24,11 @@ func (b *DbBackup) GetDbName() string {
}
func (b *DbBackup) Schedule() (time.Time, error) {
var deadline time.Time
if b.IsFinished() || !b.Enabled {
return deadline, runner.ErrFinished
if b.IsFinished() {
return time.Time{}, runner.ErrJobFinished
}
if !b.Enabled {
return time.Time{}, runner.ErrJobDisabled
}
switch b.LastStatus {
case DbJobSuccess:
@@ -34,13 +36,12 @@ func (b *DbBackup) Schedule() (time.Time, error) {
if lastTime.Before(b.StartTime) {
lastTime = b.StartTime.Add(-b.Interval)
}
deadline = lastTime.Add(b.Interval - lastTime.Sub(b.StartTime)%b.Interval)
return lastTime.Add(b.Interval - lastTime.Sub(b.StartTime)%b.Interval), nil
case DbJobFailed:
deadline = time.Now().Add(time.Minute)
return time.Now().Add(time.Minute), nil
default:
deadline = b.StartTime
return b.StartTime, nil
}
return deadline, nil
}
func (b *DbBackup) IsFinished() bool {

View File

@@ -43,9 +43,8 @@ func (b *DbBinlog) GetDbName() string {
func (b *DbBinlog) Schedule() (time.Time, error) {
switch b.GetJobBase().LastStatus {
case DbJobSuccess:
return time.Time{}, runner.ErrFinished
return time.Time{}, runner.ErrJobFinished
case DbJobFailed:
return time.Now().Add(BinlogDownloadInterval), nil
default:
return time.Now(), nil

View File

@@ -28,23 +28,18 @@ func (r *DbRestore) GetDbName() string {
}
func (r *DbRestore) Schedule() (time.Time, error) {
var deadline time.Time
if r.IsFinished() || !r.Enabled {
return deadline, runner.ErrFinished
if !r.Enabled {
return time.Time{}, runner.ErrJobDisabled
}
switch r.LastStatus {
case DbJobSuccess:
lastTime := r.LastTime.Time
if lastTime.Before(r.StartTime) {
lastTime = r.StartTime.Add(-r.Interval)
}
deadline = lastTime.Add(r.Interval - lastTime.Sub(r.StartTime)%r.Interval)
case DbJobFailed:
deadline = time.Now().Add(time.Minute)
case DbJobSuccess, DbJobFailed:
return time.Time{}, runner.ErrJobFinished
default:
deadline = r.StartTime
if time.Now().Sub(r.StartTime) > time.Hour {
return time.Time{}, runner.ErrJobTimeout
}
return r.StartTime, nil
}
return deadline, nil
}
func (r *DbRestore) IsEnabled() bool {

View File

@@ -22,11 +22,13 @@ func NewDbBackupRepo() repository.DbBackup {
func (d *dbBackupRepoImpl) GetDbNamesWithoutBackup(instanceId uint64, dbNames []string) ([]string, error) {
var dbNamesWithBackup []string
query := gormx.NewQuery(d.GetModel()).
Eq("db_instance_id", instanceId).
Eq("repeated", true).
Undeleted()
if err := query.GenGdb().Pluck("db_name", &dbNamesWithBackup).Error; err != nil {
err := global.Db.Model(d.GetModel()).
Where("db_instance_id = ?", instanceId).
Where("repeated = ?", true).
Scopes(gormx.UndeleteScope).
Pluck("db_name", &dbNamesWithBackup).
Error
if err != nil {
return nil, err
}
result := make([]string, 0, len(dbNames))
@@ -39,11 +41,13 @@ func (d *dbBackupRepoImpl) GetDbNamesWithoutBackup(instanceId uint64, dbNames []
}
func (d *dbBackupRepoImpl) ListDbInstances(enabled bool, repeated bool, instanceIds *[]uint64) error {
query := gormx.NewQuery(d.GetModel()).
Eq0("enabled", enabled).
Eq0("repeated", repeated).
Undeleted()
return query.GenGdb().Distinct().Pluck("db_instance_id", &instanceIds).Error
return global.Db.Model(d.GetModel()).
Where("enabled = ?", enabled).
Where("repeated = ?", repeated).
Scopes(gormx.UndeleteScope).
Distinct().
Pluck("db_instance_id", &instanceIds).
Error
}
func (d *dbBackupRepoImpl) ListToDo(jobs any) error {

View File

@@ -22,13 +22,16 @@ func NewDbRestoreRepo() repository.DbRestore {
func (d *dbRestoreRepoImpl) GetDbNamesWithoutRestore(instanceId uint64, dbNames []string) ([]string, error) {
var dbNamesWithRestore []string
query := gormx.NewQuery(d.GetModel()).
Eq("db_instance_id", instanceId).
Eq("repeated", true).
Undeleted()
if err := query.GenGdb().Pluck("db_name", &dbNamesWithRestore).Error; err != nil {
err := global.Db.Model(d.GetModel()).
Where("db_instance_id = ?", instanceId).
Where("repeated = ?", true).
Scopes(gormx.UndeleteScope).
Pluck("db_name", &dbNamesWithRestore).
Error
if err != nil {
return nil, err
}
result := make([]string, 0, len(dbNames))
for _, name := range dbNames {
if !slices.Contains(dbNamesWithRestore, name) {

View File

@@ -0,0 +1,23 @@
package init
import "mayfly-go/internal/db/application"
// 终止进程时的处理函数
func Terminate() {
closeDbTasks()
}
func closeDbTasks() {
restoreApp := application.GetDbRestoreApp()
if restoreApp != nil {
restoreApp.Close()
}
binlogApp := application.GetDbBinlogApp()
if binlogApp != nil {
binlogApp.Close()
}
backupApp := application.GetDbBackupApp()
if backupApp != nil {
backupApp.Close()
}
}

View File

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

View File

@@ -154,7 +154,11 @@ func (a *Account) ChangeStatus(rc *req.Ctx) {
account := &entity.Account{}
account.Id = uint64(ginx.PathParamInt(g, "id"))
account.Status = int8(ginx.PathParamInt(g, "status"))
status := entity.AccountStatus(int8(ginx.PathParamInt(g, "status")))
biz.ErrIsNil(entity.AccountStatusEnum.Valid(status))
account.Status = status
rc.ReqParam = collx.Kvs("accountId", account.Id, "status", account.Status)
biz.ErrIsNil(a.AccountApp.Update(rc.MetaCtx, account))
}

View File

@@ -1,31 +1,32 @@
package vo
import (
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/pkg/model"
"time"
)
type AccountManageVO struct {
model.Model
Name string `json:"name"`
Username string `json:"username"`
Status int `json:"status"`
LastLoginTime *time.Time `json:"lastLoginTime"`
OtpSecret string `json:"otpSecret"`
Name string `json:"name"`
Username string `json:"username"`
Status entity.AccountStatus `json:"status"`
LastLoginTime *time.Time `json:"lastLoginTime"`
OtpSecret string `json:"otpSecret"`
}
// 账号角色信息
type AccountRoleVO struct {
RoleId uint64 `json:"roleId"`
RoleName string `json:"roleName"`
Code string `json:"code"`
Status int `json:"status"`
AccountId uint64 `json:"accountId" gorm:"column:accountId"`
AccountName string `json:"accountName" gorm:"column:accountName"`
Username string `json:"username"`
AccountStatus int `json:"accountStatus" gorm:"column:accountStatus"`
CreateTime *time.Time `json:"createTime"`
Creator string `json:"creator"`
RoleId uint64 `json:"roleId"`
RoleName string `json:"roleName"`
Code string `json:"code"`
Status int `json:"status"`
AccountId uint64 `json:"accountId" gorm:"column:accountId"`
AccountName string `json:"accountName" gorm:"column:accountName"`
Username string `json:"username"`
AccountStatus entity.AccountStatus `json:"accountStatus" gorm:"column:accountStatus"`
CreateTime *time.Time `json:"createTime"`
Creator string `json:"creator"`
}
// 账号个人信息

View File

@@ -43,7 +43,7 @@ func (a *accountAppImpl) Create(ctx context.Context, account *entity.Account) er
}
// 默认密码为账号用户名
account.Password = cryptox.PwdHash(account.Username)
account.Status = entity.AccountEnableStatus
account.Status = entity.AccountEnable
return a.Insert(ctx, account)
}

View File

@@ -3,6 +3,7 @@ package entity
import (
"errors"
"mayfly-go/internal/common/utils"
"mayfly-go/pkg/enumx"
"mayfly-go/pkg/model"
"time"
)
@@ -10,13 +11,13 @@ import (
type Account struct {
model.Model
Name string `json:"name"`
Username string `json:"username"`
Password string `json:"-"`
Status int8 `json:"status"`
LastLoginTime *time.Time `json:"lastLoginTime"`
LastLoginIp string `json:"lastLoginIp"`
OtpSecret string `json:"-"`
Name string `json:"name"`
Username string `json:"username"`
Password string `json:"-"`
Status AccountStatus `json:"status"`
LastLoginTime *time.Time `json:"lastLoginTime"`
LastLoginIp string `json:"lastLoginIp"`
OtpSecret string `json:"-"`
}
func (a *Account) TableName() string {
@@ -25,7 +26,7 @@ func (a *Account) TableName() string {
// 是否可用
func (a *Account) IsEnable() bool {
return a.Status == AccountEnableStatus
return a.Status == AccountEnable
}
func (a *Account) OtpSecretEncrypt() error {
@@ -49,7 +50,13 @@ func (a *Account) OtpSecretDecrypt() error {
return nil
}
type AccountStatus int8
const (
AccountEnableStatus int8 = 1 // 启用状态
AccountDisableStatus int8 = -1 // 禁用状态
AccountEnable AccountStatus = 1 // 启用状态
AccountDisable AccountStatus = -1 // 禁用状态
)
var AccountStatusEnum = enumx.NewEnum[AccountStatus]("账号状态").
Add(AccountEnable, "启用").
Add(AccountDisable, "禁用")

View File

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

50
server/pkg/enumx/enumx.go Normal file
View File

@@ -0,0 +1,50 @@
package enumx
import (
"fmt"
"mayfly-go/pkg/errorx"
)
type Enum[T comparable] struct {
name string // 枚举值名称
values map[T]string // 所有枚举值。枚举值 -> desc(描述)
}
// 新建枚举
func NewEnum[T comparable](name string) *Enum[T] {
return &Enum[T]{
name: name,
values: make(map[T]string),
}
}
// 添加枚举值
func (e *Enum[T]) Add(value T, desc string) *Enum[T] {
e.values[value] = desc
return e
}
// 校验枚举值是否合法
func (e *Enum[T]) Valid(value T) error {
_, ok := e.values[value]
if ok {
return nil
}
errMsg := fmt.Sprintf("%s可选值为: ", e.name)
for val, desc := range e.values {
errMsg = fmt.Sprintf("%s [%v->%s]", errMsg, val, desc)
}
return errorx.NewBiz(errMsg)
}
// 根据枚举值获取描述
func (e *Enum[T]) GetDesc(value T) string {
desc, ok := e.values[value]
if ok {
return desc
}
return ""
}

View File

@@ -11,9 +11,11 @@ import (
)
var (
ErrNotFound = errors.New("job not found")
ErrExist = errors.New("job already exists")
ErrFinished = errors.New("job already finished")
ErrJobNotFound = errors.New("job not found")
ErrJobExist = errors.New("job already exists")
ErrJobFinished = errors.New("job already finished")
ErrJobDisabled = errors.New("job has been disabled")
ErrJobTimeout = errors.New("job has timed out")
)
type JobKey = string
@@ -236,7 +238,7 @@ func (r *Runner[T]) afterRun(wrap *wrapper[T]) {
func (r *Runner[T]) doScheduleJob(job T, finished bool) (time.Time, error) {
if r.scheduleJob == nil {
if finished {
return time.Time{}, ErrFinished
return time.Time{}, ErrJobFinished
}
return time.Now(), nil
}
@@ -293,7 +295,7 @@ func (r *Runner[T]) Add(ctx context.Context, job T) error {
defer r.mutex.Unlock()
if _, ok := r.all[job.GetKey()]; ok {
return ErrExist
return ErrJobExist
}
deadline, err := r.doScheduleJob(job, false)
if err != nil {
@@ -358,7 +360,7 @@ func (r *Runner[T]) Remove(ctx context.Context, key JobKey) error {
wrap, ok := r.all[key]
if !ok {
return ErrNotFound
return ErrJobNotFound
}
switch wrap.status {
case JobDelaying:

View File

@@ -75,7 +75,7 @@ func TestRunner_AddJob(t *testing.T) {
{
name: "repetitive job",
job: newTestJob("dual"),
want: ErrExist,
want: ErrJobExist,
},
}
runner := NewRunner[*testJob](1, func(ctx context.Context, job *testJob) {

View File

@@ -1,15 +1,17 @@
package stringx
package conv
import (
"mayfly-go/pkg/logx"
"strconv"
)
// 将字符串值转为int值, 若value为空或者转换失败则返回默认值
func ConvInt(value string, defaultValue int) int {
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

View File

@@ -0,0 +1,993 @@
--
-- Text encoding used: UTF-8
--
PRAGMA foreign_keys = off;
BEGIN TRANSACTION;
-- Table: t_auth_cert
CREATE TABLE IF NOT EXISTS "t_auth_cert" (
"id" integer NOT NULL,
"name" text(32),
"auth_method" integer(4) NOT NULL,
"password" text(4200),
"passphrase" text(32),
"remark" text(255),
"create_time" datetime NOT NULL,
"creator" text(16) NOT NULL,
"creator_id" integer(20) NOT NULL,
"update_time" datetime NOT NULL,
"modifier" text(12) NOT NULL,
"modifier_id" integer(20) NOT NULL,
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_db
CREATE TABLE IF NOT EXISTS "t_db" (
"id" integer NOT NULL,
"code" text(32),
"name" text(32),
"database" text(1000),
"remark" text(125),
"instance_id" integer(20) NOT NULL,
"create_time" datetime,
"creator_id" integer(20),
"creator" text(32),
"update_time" datetime,
"modifier_id" integer(20),
"modifier" text(32),
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_db_backup
CREATE TABLE IF NOT EXISTS "t_db_backup" (
"id" integer NOT NULL,
"name" text(32) NOT NULL,
"db_instance_id" integer(20) NOT NULL,
"db_name" text(64) NOT NULL,
"repeated" integer(1),
"interval" integer(20),
"start_time" datetime,
"enabled" integer(1),
"last_status" integer(4),
"last_result" text(256),
"last_time" datetime,
"create_time" datetime,
"creator_id" integer(20),
"creator" text(32),
"update_time" datetime,
"modifier_id" integer(20),
"modifier" text(32),
"is_deleted" integer(1) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_db_backup_history
CREATE TABLE IF NOT EXISTS "t_db_backup_history" (
"id" integer NOT NULL,
"name" text(64) NOT NULL,
"db_backup_id" integer(20) NOT NULL,
"db_instance_id" integer(20) NOT NULL,
"db_name" text(64) NOT NULL,
"uuid" text(36) NOT NULL,
"binlog_file_name" text(32),
"binlog_sequence" integer(20),
"binlog_position" integer(20),
"create_time" datetime,
"is_deleted" integer(1) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_db_binlog
CREATE TABLE IF NOT EXISTS "t_db_binlog" (
"id" integer NOT NULL,
"db_instance_id" integer(20) NOT NULL,
"last_status" integer(20),
"last_result" text(256),
"last_time" datetime,
"create_time" datetime,
"creator_id" integer(20),
"creator" text(32),
"update_time" datetime,
"modifier_id" integer(20),
"modifier" text(32),
"is_deleted" integer(1) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_db_binlog_history
CREATE TABLE IF NOT EXISTS "t_db_binlog_history" (
"id" integer NOT NULL,
"db_instance_id" integer(20) NOT NULL,
"file_name" text(32),
"file_size" integer(20),
"sequence" integer(20),
"first_event_time" datetime,
"create_time" datetime,
"is_deleted" integer(4) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_db_data_sync_log
CREATE TABLE IF NOT EXISTS "t_db_data_sync_log" (
"id" integer NOT NULL,
"task_id" integer(20) NOT NULL,
"create_time" datetime NOT NULL,
"data_sql_full" text NOT NULL,
"res_num" integer(11),
"err_text" text,
"status" integer(4) NOT NULL,
"is_deleted" integer(1) NOT NULL,
PRIMARY KEY ("id")
);
-- Table: t_db_data_sync_task
CREATE TABLE IF NOT EXISTS "t_db_data_sync_task" (
"id" integer NOT NULL,
"creator_id" integer(20) NOT NULL,
"creator" text(100) NOT NULL,
"create_time" datetime NOT NULL,
"update_time" datetime NOT NULL,
"modifier" text(100) NOT NULL,
"modifier_id" integer(20) NOT NULL,
"task_name" text(500) NOT NULL,
"task_cron" text(50) NOT NULL,
"src_db_id" integer(20) NOT NULL,
"src_db_name" text(100),
"src_tag_path" text(200),
"target_db_id" integer(20) NOT NULL,
"target_db_name" text(100),
"target_tag_path" text(200),
"target_table_name" text(100),
"data_sql" text NOT NULL,
"page_size" integer(11) NOT NULL,
"upd_field" text(100) NOT NULL,
"upd_field_val" text(100),
"id_rule" integer(2) NOT NULL,
"pk_field" text(100),
"field_map" text,
"is_deleted" integer(8),
"delete_time" datetime,
"status" integer(1) NOT NULL,
"recent_state" integer(1) NOT NULL,
"task_key" text(100),
"running_state" integer(1),
PRIMARY KEY ("id")
);
-- Table: t_db_instance
CREATE TABLE IF NOT EXISTS "t_db_instance" (
"id" integer NOT NULL,
"name" text(32),
"host" text(100) NOT NULL,
"port" integer(8) NOT NULL,
"sid" text(255) NOT NULL,
"username" text(255) NOT NULL,
"password" text(255),
"type" text(20) NOT NULL,
"params" text(125),
"network" text(20),
"ssh_tunnel_machine_id" integer(20),
"remark" text(125),
"create_time" datetime,
"creator_id" integer(20),
"creator" text(32),
"update_time" datetime,
"modifier_id" integer(20),
"modifier" text(32),
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_db_restore
CREATE TABLE IF NOT EXISTS "t_db_restore" (
"id" integer NOT NULL,
"db_instance_id" integer(20) NOT NULL,
"db_name" text(64) NOT NULL,
"repeated" integer(1),
"interval" integer(20),
"start_time" datetime,
"enabled" integer(1),
"last_status" integer(4),
"last_result" text(256),
"last_time" datetime,
"point_in_time" datetime,
"db_backup_id" integer(20),
"db_backup_history_id" integer(20),
"db_backup_history_name" text(64),
"create_time" datetime,
"creator_id" integer(20),
"creator" text(32),
"update_time" datetime,
"modifier_id" integer(20),
"modifier" text(32),
"is_deleted" integer(1) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_db_restore_history
CREATE TABLE IF NOT EXISTS "t_db_restore_history" (
"id" integer NOT NULL,
"db_restore_id" integer(20) NOT NULL,
"create_time" datetime,
"is_deleted" integer(4) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_db_sql
CREATE TABLE IF NOT EXISTS "t_db_sql" (
"id" integer NOT NULL,
"db_id" integer(20) NOT NULL,
"db" text(125) NOT NULL,
"name" text(60),
"sql" text,
"type" integer(8) NOT NULL,
"creator_id" integer(20) NOT NULL,
"creator" text(32),
"create_time" datetime NOT NULL,
"update_time" datetime NOT NULL,
"modifier_id" integer(20),
"modifier" text(255),
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_db_sql_exec
CREATE TABLE IF NOT EXISTS "t_db_sql_exec" (
"id" integer NOT NULL,
"db_id" integer(20) NOT NULL,
"db" text(128) NOT NULL,
"table" text(128) NOT NULL,
"type" text(255) NOT NULL,
"sql" text(5000) NOT NULL,
"old_value" text(5000),
"remark" text(128),
"create_time" datetime NOT NULL,
"creator" text(36) NOT NULL,
"creator_id" integer(20) NOT NULL,
"update_time" datetime NOT NULL,
"modifier" text(36) NOT NULL,
"modifier_id" integer(20) NOT NULL,
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_machine
CREATE TABLE IF NOT EXISTS "t_machine" (
"id" integer NOT NULL,
"code" text(32),
"name" text(32),
"ip" text(50) NOT NULL,
"port" integer(12) NOT NULL,
"username" text(12) NOT NULL,
"auth_method" integer(2),
"password" text(100),
"auth_cert_id" integer(20),
"ssh_tunnel_machine_id" integer(20),
"enable_recorder" integer(2),
"status" integer(2) NOT NULL,
"remark" text(255),
"need_monitor" integer(2),
"create_time" datetime NOT NULL,
"creator" text(16),
"creator_id" integer(32),
"update_time" datetime NOT NULL,
"modifier" text(12),
"modifier_id" integer(32),
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_machine_cron_job
CREATE TABLE IF NOT EXISTS "t_machine_cron_job" (
"id" integer NOT NULL,
"key" text(32) NOT NULL,
"name" text(255) NOT NULL,
"cron" text(255) NOT NULL,
"script" text,
"remark" text(255),
"status" integer(4),
"save_exec_res_type" integer(4),
"last_exec_time" datetime,
"creator_id" integer(20),
"creator" text(32),
"modifier_id" integer(20),
"modifier" text(255),
"create_time" datetime,
"update_time" datetime,
"is_deleted" integer(4) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_machine_cron_job_exec
CREATE TABLE IF NOT EXISTS "t_machine_cron_job_exec" (
"id" integer NOT NULL,
"cron_job_id" integer(20),
"machine_id" integer(20),
"status" integer(4),
"res" text(1000),
"exec_time" datetime,
"is_deleted" integer(4) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_machine_cron_job_relate
CREATE TABLE IF NOT EXISTS "t_machine_cron_job_relate" (
"id" integer NOT NULL,
"cron_job_id" integer(20),
"machine_id" integer(20),
"creator_id" integer(20),
"creator" text(32),
"create_time" datetime,
"is_deleted" integer(4) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_machine_file
CREATE TABLE IF NOT EXISTS "t_machine_file" (
"id" integer NOT NULL,
"machine_id" integer(20) NOT NULL,
"name" text(45) NOT NULL,
"path" text(45) NOT NULL,
"type" text(45) NOT NULL,
"creator_id" integer(20),
"creator" text(45),
"modifier_id" integer(20),
"modifier" text(45),
"create_time" datetime NOT NULL,
"update_time" datetime,
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_machine_monitor
CREATE TABLE IF NOT EXISTS "t_machine_monitor" (
"id" integer NOT NULL,
"machine_id" integer(20) NOT NULL,
"cpu_rate" real(255,2),
"mem_rate" real(255,2),
"sys_load" text(32),
"create_time" datetime NOT NULL,
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_machine_script
CREATE TABLE IF NOT EXISTS "t_machine_script" (
"id" integer NOT NULL,
"name" text(255) NOT NULL,
"machine_id" integer(64) NOT NULL,
"script" text,
"params" text(512),
"description" text(255),
"type" integer(8),
"creator_id" integer(20),
"creator" text(32),
"modifier_id" integer(20),
"modifier" text(255),
"create_time" datetime,
"update_time" datetime,
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
INSERT INTO t_machine_script (id, name, machine_id, script, params, description, type, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (1, 'sys_info', 9999999, '# 获取系统cpu信息
function get_cpu_info() {
Physical_CPUs=$(grep "physical id" /proc/cpuinfo | sort | uniq | wc -l)
Virt_CPUs=$(grep "processor" /proc/cpuinfo | wc -l)
CPU_Kernels=$(grep "cores" /proc/cpuinfo | uniq | awk -F '': '' ''{print $2}'')
CPU_Type=$(grep "model name" /proc/cpuinfo | awk -F '': '' ''{print $2}'' | sort | uniq)
CPU_Arch=$(uname -m)
echo -e ''\n-------------------------- CPU信息 --------------------------''
cat <<EOF | column -t
物理CPU个数: $Physical_CPUs
逻辑CPU个数: $Virt_CPUs
每CPU核心数: $CPU_Kernels
CPU型号: $CPU_Type
CPU架构: $CPU_Arch
EOF
}
# 获取系统信息
function get_systatus_info() {
sys_os=$(uname -o)
sys_release=$(cat /etc/redhat-release)
sys_kernel=$(uname -r)
sys_hostname=$(hostname)
sys_selinux=$(getenforce)
sys_lang=$(echo $LANG)
sys_lastreboot=$(who -b | awk ''{print $3,$4}'')
echo -e ''-------------------------- 系统信息 --------------------------''
cat <<EOF | column -t
系统: ${sys_os}
发行版本: ${sys_release}
系统内核: ${sys_kernel}
主机名: ${sys_hostname}
selinux状态: ${sys_selinux}
系统语言: ${sys_lang}
系统最后重启时间: ${sys_lastreboot}
EOF
}
get_systatus_info
#echo -e "\n"
get_cpu_info', NULL, '获取系统信息', 1, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL);
INSERT INTO t_machine_script (id, name, machine_id, script, params, description, type, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (2, 'get_process_by_name', 9999999, '#! /bin/bash
# Function: 根据输入的程序的名字过滤出所对应的PID并显示出详细信息如果有几个PID则全部显示
NAME={{.processName}}
N=`ps -aux | grep $NAME | grep -v grep | wc -l` ##统计进程总数
if [ $N -le 0 ];then
echo "无该进程!"
fi
i=1
while [ $N -gt 0 ]
do
echo "进程PID: `ps -aux | grep $NAME | grep -v grep | awk ''NR==''$i''{print $0}''| awk ''{print $2}''`"
echo "进程命令:`ps -aux | grep $NAME | grep -v grep | awk ''NR==''$i''{print $0}''| awk ''{print $11}''`"
echo "进程所属用户: `ps -aux | grep $NAME | grep -v grep | awk ''NR==''$i''{print $0}''| awk ''{print $1}''`"
echo "CPU占用率`ps -aux | grep $NAME | grep -v grep | awk ''NR==''$i''{print $0}''| awk ''{print $3}''`%"
echo "内存占用率:`ps -aux | grep $NAME | grep -v grep | awk ''NR==''$i''{print $0}''| awk ''{print $4}''`%"
echo "进程开始运行的时刻:`ps -aux | grep $NAME | grep -v grep | awk ''NR==''$i''{print $0}''| awk ''{print $9}''`"
echo "进程运行的时间:` ps -aux | grep $NAME | grep -v grep | awk ''NR==''$i''{print $0}''| awk ''{print $11}''`"
echo "进程状态:`ps -aux | grep $NAME | grep -v grep | awk ''NR==''$i''{print $0}''| awk ''{print $8}''`"
echo "进程虚拟内存:`ps -aux | grep $NAME | grep -v grep | awk ''NR==''$i''{print $0}''| awk ''{print $5}''`"
echo "进程共享内存:`ps -aux | grep $NAME | grep -v grep | awk ''NR==''$i''{print $0}''| awk ''{print $6}''`"
echo "***************************************************************"
let N-- i++
done', '[{"name": "进程名","model": "processName", "placeholder": "请输入进程名"}]', '获取进程运行状态', 1, NULL, NULL, 1, 'admin', NULL, '2021-07-12 15:33:41', 0, NULL);
INSERT INTO t_machine_script (id, name, machine_id, script, params, description, type, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (3, 'sys_run_info', 9999999, '#!/bin/bash
# 获取要监控的本地服务器IP地址
IP=`ifconfig | grep inet | grep -vE ''inet6|127.0.0.1'' | awk ''{print $2}''`
echo "IP地址"$IP
# 获取cpu总核数
cpu_num=`grep -c "model name" /proc/cpuinfo`
echo "cpu总核数"$cpu_num
# 1、获取CPU利用率
################################################
#us 用户空间占用CPU百分比
#sy 内核空间占用CPU百分比
#ni 用户进程空间内改变过优先级的进程占用CPU百分比
#id 空闲CPU百分比
#wa 等待输入输出的CPU时间百分比
#hi 硬件中断
#si 软件中断
#################################################
# 获取用户空间占用CPU百分比
cpu_user=`top -b -n 1 | grep Cpu | awk ''{print $2}'' | cut -f 1 -d "%"`
echo "用户空间占用CPU百分比"$cpu_user
# 获取内核空间占用CPU百分比
cpu_system=`top -b -n 1 | grep Cpu | awk ''{print $4}'' | cut -f 1 -d "%"`
echo "内核空间占用CPU百分比"$cpu_system
# 获取空闲CPU百分比
cpu_idle=`top -b -n 1 | grep Cpu | awk ''{print $8}'' | cut -f 1 -d "%"`
echo "空闲CPU百分比"$cpu_idle
# 获取等待输入输出占CPU百分比
cpu_iowait=`top -b -n 1 | grep Cpu | awk ''{print $10}'' | cut -f 1 -d "%"`
echo "等待输入输出占CPU百分比"$cpu_iowait
#2、获取CPU上下文切换和中断次数
# 获取CPU中断次数
cpu_interrupt=`vmstat -n 1 1 | sed -n 3p | awk ''{print $11}''`
echo "CPU中断次数"$cpu_interrupt
# 获取CPU上下文切换次数
cpu_context_switch=`vmstat -n 1 1 | sed -n 3p | awk ''{print $12}''`
echo "CPU上下文切换次数"$cpu_context_switch
#3、获取CPU负载信息
# 获取CPU15分钟前到现在的负载平均值
cpu_load_15min=`uptime | awk ''{print $11}'' | cut -f 1 -d '',''`
echo "CPU 15分钟前到现在的负载平均值"$cpu_load_15min
# 获取CPU5分钟前到现在的负载平均值
cpu_load_5min=`uptime | awk ''{print $10}'' | cut -f 1 -d '',''`
echo "CPU 5分钟前到现在的负载平均值"$cpu_load_5min
# 获取CPU1分钟前到现在的负载平均值
cpu_load_1min=`uptime | awk ''{print $9}'' | cut -f 1 -d '',''`
echo "CPU 1分钟前到现在的负载平均值"$cpu_load_1min
# 获取任务队列(就绪状态等待的进程数)
cpu_task_length=`vmstat -n 1 1 | sed -n 3p | awk ''{print $1}''`
echo "CPU任务队列长度"$cpu_task_length
#4、获取内存信息
# 获取物理内存总量
mem_total=`free -h | grep Mem | awk ''{print $2}''`
echo "物理内存总量:"$mem_total
# 获取操作系统已使用内存总量
mem_sys_used=`free -h | grep Mem | awk ''{print $3}''`
echo "已使用内存总量(操作系统)"$mem_sys_used
# 获取操作系统未使用内存总量
mem_sys_free=`free -h | grep Mem | awk ''{print $4}''`
echo "剩余内存总量(操作系统)"$mem_sys_free
# 获取应用程序已使用的内存总量
mem_user_used=`free | sed -n 3p | awk ''{print $3}''`
echo "已使用内存总量(应用程序)"$mem_user_used
# 获取应用程序未使用内存总量
mem_user_free=`free | sed -n 3p | awk ''{print $4}''`
echo "剩余内存总量(应用程序)"$mem_user_free
# 获取交换分区总大小
mem_swap_total=`free | grep Swap | awk ''{print $2}''`
echo "交换分区总大小:"$mem_swap_total
# 获取已使用交换分区大小
mem_swap_used=`free | grep Swap | awk ''{print $3}''`
echo "已使用交换分区大小:"$mem_swap_used
# 获取剩余交换分区大小
mem_swap_free=`free | grep Swap | awk ''{print $4}''`
echo "剩余交换分区大小:"$mem_swap_free', NULL, '获取cpu、内存等系统运行状态', 1, NULL, NULL, NULL, NULL, NULL, '2021-04-25 15:07:16', 0, NULL);
INSERT INTO t_machine_script (id, name, machine_id, script, params, description, type, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (4, 'top', 9999999, 'top', NULL, '实时获取系统运行状态', 3, NULL, NULL, 1, 'admin', NULL, '2021-05-24 15:58:20', 0, NULL);
INSERT INTO t_machine_script (id, name, machine_id, script, params, description, type, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (18, 'disk-mem', 9999999, 'df -h', '', '磁盘空间查看', 1, 1, 'admin', 1, 'admin', '2021-07-16 10:49:53', '2021-07-16 10:49:53', 0, NULL);
-- Table: t_machine_term_op
CREATE TABLE IF NOT EXISTS "t_machine_term_op" (
"id" integer NOT NULL,
"machine_id" integer(20) NOT NULL,
"username" text(60),
"record_file_path" text(191),
"creator_id" integer(20),
"creator" text(191),
"create_time" datetime NOT NULL,
"end_time" datetime,
"is_deleted" integer(4),
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_mongo
CREATE TABLE IF NOT EXISTS "t_mongo" (
"id" integer NOT NULL,
"code" text(32),
"name" text(36) NOT NULL,
"uri" text(255) NOT NULL,
"ssh_tunnel_machine_id" integer(20),
"create_time" datetime NOT NULL,
"creator_id" integer(20),
"creator" text(36),
"update_time" datetime,
"modifier_id" integer(20),
"modifier" text(36),
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_oauth2_account
CREATE TABLE IF NOT EXISTS "t_oauth2_account" (
"id" integer NOT NULL,
"account_id" integer(20) NOT NULL,
"identity" text(64),
"create_time" datetime NOT NULL,
"update_time" datetime NOT NULL,
"is_deleted" integer(4),
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_redis
CREATE TABLE IF NOT EXISTS "t_redis" (
"id" integer NOT NULL,
"code" text(32),
"name" text(255),
"host" text(255) NOT NULL,
"username" text(32),
"password" text(100),
"db" text(64),
"mode" text(32),
"ssh_tunnel_machine_id" integer(20),
"remark" text(125),
"creator" text(32),
"creator_id" integer(32),
"create_time" datetime,
"modifier" text(32),
"modifier_id" integer(20),
"update_time" datetime,
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_sys_account
CREATE TABLE IF NOT EXISTS "t_sys_account" (
"id" integer NOT NULL,
"name" text(30) NOT NULL,
"username" text(30) NOT NULL,
"password" text(64) NOT NULL,
"status" integer(4),
"otp_secret" text(100),
"last_login_time" datetime,
"last_login_ip" text(50),
"create_time" datetime NOT NULL,
"creator_id" integer(255) NOT NULL,
"creator" text(12) NOT NULL,
"update_time" datetime NOT NULL,
"modifier_id" integer(255) NOT NULL,
"modifier" text(12) NOT NULL,
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
INSERT INTO t_sys_account (id, name, username, password, status, otp_secret, last_login_time, last_login_ip, create_time, creator_id, creator, update_time, modifier_id, modifier, is_deleted, delete_time) VALUES (1, '管理员', 'admin', '$2a$10$w3Wky2U.tinvR7c/s0aKPuwZsIu6pM1/DMJalwBDMbE6niHIxVrrm', 1, '', '2022-10-26 20:03:48', '::1', '2020-01-01 19:00:00', 1, 'admin', '2020-01-01 19:00:00', 1, 'admin', 0, NULL);
-- Table: t_sys_account_role
CREATE TABLE IF NOT EXISTS "t_sys_account_role" (
"id" integer NOT NULL,
"account_id" integer(20) NOT NULL,
"role_id" integer(20) NOT NULL,
"creator" text(45),
"creator_id" integer(20),
"create_time" datetime NOT NULL,
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_sys_config
CREATE TABLE IF NOT EXISTS "t_sys_config" (
"id" integer NOT NULL,
"name" text(60) NOT NULL,
"key" text(120) NOT NULL,
"params" text(1500),
"value" text(1500),
"remark" text(255),
"permission" text(255),
"create_time" datetime NOT NULL,
"creator_id" integer(20) NOT NULL,
"creator" text(36) NOT NULL,
"update_time" datetime NOT NULL,
"modifier_id" integer(20) NOT NULL,
"modifier" text(36) NOT NULL,
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
INSERT INTO t_sys_config (id, name, key, params, value, remark, permission, create_time, creator_id, creator, update_time, modifier_id, modifier, is_deleted, delete_time) VALUES (3, '账号登录安全设置', 'AccountLoginSecurity', '[{"name":"登录验证码","model":"useCaptcha","placeholder":"是否启用登录验证码","options":"true,false"},{"name":"双因素校验(OTP)","model":"useOtp","placeholder":"是否启用双因素(OTP)校验","options":"true,false"},{"name":"OTP签发人","model":"otpIssuer","placeholder":"otp签发人"},{"name":"允许失败次数","model":"loginFailCount","placeholder":"登录失败n次后禁止登录"},{"name":"禁止登录时间","model":"loginFailMin","placeholder":"登录失败指定次数后禁止m分钟内再次登录"}]', '{"useCaptcha":"true","useOtp":"false","loginFailCount":"5","loginFailMin":"10","otpIssuer":"mayfly-go"}', '系统账号登录相关安全设置', 'all', '2023-06-17 11:02:11', 1, 'admin', '2023-06-17 14:18:07', 1, 'admin', 0, NULL);
INSERT INTO t_sys_config (id, name, key, params, value, remark, permission, create_time, creator_id, creator, update_time, modifier_id, modifier, is_deleted, delete_time) VALUES (4, 'oauth2登录配置', 'Oauth2Login', '[{"name":"是否启用","model":"enable","placeholder":"是否启用oauth2登录","options":"true,false"},{"name":"名称","model":"name","placeholder":"oauth2名称"},{"name":"Client ID","model":"clientId","placeholder":"Client ID"},{"name":"Client Secret","model":"clientSecret","placeholder":"Client Secret"},{"name":"Authorization URL","model":"authorizationURL","placeholder":"Authorization URL"},{"name":"AccessToken URL","model":"accessTokenURL","placeholder":"AccessToken URL"},{"name":"Redirect URL","model":"redirectURL","placeholder":"本系统地址"},{"name":"Scopes","model":"scopes","placeholder":"Scopes"},{"name":"Resource URL","model":"resourceURL","placeholder":"获取用户信息资源地址"},{"name":"UserIdentifier","model":"userIdentifier","placeholder":"用户唯一标识字段;格式为type:fieldPath(string:username)"},{"name":"是否自动注册","model":"autoRegister","placeholder":"","options":"true,false"}]', '', 'oauth2登录相关配置信息', 'admin,', '2023-07-22 13:58:51', 1, 'admin', '2023-07-22 19:34:37', 1, 'admin', 0, NULL);
INSERT INTO t_sys_config (id, name, key, params, value, remark, permission, create_time, creator_id, creator, update_time, modifier_id, modifier, is_deleted, delete_time) VALUES (5, 'ldap登录配置', 'LdapLogin', '[{"name":"是否启用","model":"enable","placeholder":"是否启用","options":"true,false"},{"name":"host","model":"host","placeholder":"host"},{"name":"port","model":"port","placeholder":"port"},{"name":"bindDN","model":"bindDN","placeholder":"LDAP 服务的管理员账号,如: \"cn=admin,dc=example,dc=com\""},{"name":"bindPwd","model":"bindPwd","placeholder":"LDAP 服务的管理员密码"},{"name":"baseDN","model":"baseDN","placeholder":"用户所在的 base DN, 如: \"ou=users,dc=example,dc=com\""},{"name":"userFilter","model":"userFilter","placeholder":"过滤用户的方式, 如: \"(uid=%s)、(&(objectClass=organizationalPerson)(uid=%s))\""},{"name":"uidMap","model":"uidMap","placeholder":"用户id和 LDAP 字段名之间的映射关系,如: cn"},{"name":"udnMap","model":"udnMap","placeholder":"用户姓名(dispalyName)和 LDAP 字段名之间的映射关系,如: displayName"},{"name":"emailMap","model":"emailMap","placeholder":"用户email和 LDAP 字段名之间的映射关系"},{"name":"skipTLSVerify","model":"skipTLSVerify","placeholder":"客户端是否跳过 TLS 证书验证","options":"true,false"},{"name":"安全协议","model":"securityProtocol","placeholder":"安全协议为Null不使用安全协议如: StartTLS, LDAPS","options":"Null,StartTLS,LDAPS"}]', '', 'ldap登录相关配置', 'admin,', '2023-08-25 21:47:20', 1, 'admin', '2023-08-25 22:56:07', 1, 'admin', 0, NULL);
INSERT INTO t_sys_config (id, name, key, params, value, remark, permission, create_time, creator_id, creator, update_time, modifier_id, modifier, is_deleted, delete_time) VALUES (6, '系统全局样式设置', 'SysStyleConfig', '[{"model":"logoIcon","name":"logo图标","placeholder":"系统logo图标base64编码, 建议svg格式不超过10k","required":false},{"model":"title","name":"菜单栏标题","placeholder":"系统菜单栏标题展示","required":false},{"model":"viceTitle","name":"登录页标题","placeholder":"登录页标题展示","required":false},{"model":"useWatermark","name":"是否启用水印","placeholder":"是否启用系统水印","options":"true,false","required":false},{"model":"watermarkContent","name":"水印补充信息","placeholder":"额外水印信息","required":false}]', '{"title":"mayfly-go","viceTitle":"mayfly-go","logoIcon":"","useWatermark":"true","watermarkContent":""}', '系统icon、标题、水印信息等配置', 'all', '2024-01-04 15:17:18', 1, 'admin', '2024-01-05 09:40:44', 1, 'admin', 0, NULL);
INSERT INTO t_sys_config (id, name, key, params, value, remark, permission, create_time, creator_id, creator, update_time, modifier_id, modifier, is_deleted, delete_time) VALUES (7, '数据库查询最大结果集', 'DbQueryMaxCount', '[]', '200', '允许sql查询的最大结果集数。注: 0=不限制', 'all', '2023-02-11 14:29:03', 1, 'admin', '2023-02-11 14:40:56', 1, 'admin', 0, NULL);
INSERT INTO t_sys_config (id, name, key, params, value, remark, permission, create_time, creator_id, creator, update_time, modifier_id, modifier, is_deleted, delete_time) VALUES (8, '数据库是否记录查询SQL', 'DbSaveQuerySQL', '[]', '0', '1: 记录、0:不记录', 'all', '2023-02-11 16:07:14', 1, 'admin', '2023-02-11 16:44:17', 1, 'admin', 0, NULL);
INSERT INTO t_sys_config (id, name, key, params, value, remark, permission, create_time, creator_id, creator, update_time, modifier_id, modifier, is_deleted, delete_time) VALUES (9, '机器相关配置', 'MachineConfig', '[{"name":"终端回放存储路径","model":"terminalRecPath","placeholder":"终端回放存储路径"},{"name":"uploadMaxFileSize","model":"uploadMaxFileSize","placeholder":"允许上传的最大文件大小(1MB\\2GB等)"}]', '{"terminalRecPath":"./rec","uploadMaxFileSize":"1GB"}', '机器相关配置,如终端回放路径等', 'admin,', '2023-07-13 16:26:44', 1, 'admin', '2023-11-09 22:01:31', 1, 'admin', 0, NULL);
INSERT INTO t_sys_config (id, name, key, params, value, remark, permission, create_time, creator_id, creator, update_time, modifier_id, modifier, is_deleted, delete_time) VALUES (10, '数据库备份恢复', 'DbBackupRestore', '[{"model":"backupPath","name":"备份路径","placeholder":"备份文件存储路径"}]', '{"backupPath":"./db/backup"}', '', 'admin,', '2023-12-29 09:55:26', 1, 'admin', '2023-12-29 15:45:24', 1, 'admin', 0, NULL);
INSERT INTO t_sys_config (id, name, key, params, value, remark, permission, create_time, creator_id, creator, update_time, modifier_id, modifier, is_deleted, delete_time) VALUES (11, 'Mysql可执行文件', 'MysqlBin', '[{"model":"path","name":"路径","placeholder":"可执行文件路径","required":true},{"model":"mysql","name":"mysql","placeholder":"mysql命令路径(空则为 路径/mysql)","required":false},{"model":"mysqldump","name":"mysqldump","placeholder":"mysqldump命令路径(空则为 路径/mysqldump)","required":false},{"model":"mysqlbinlog","name":"mysqlbinlog","placeholder":"mysqlbinlog命令路径(空则为 路径/mysqlbinlog)","required":false}]', '{"mysql":"","mysqldump":"","mysqlbinlog":"","path":"./db/mysql/bin"}', '', 'admin,', '2023-12-29 10:01:33', 1, 'admin', '2023-12-29 13:34:40', 1, 'admin', 0, NULL);
INSERT INTO t_sys_config (id, name, key, params, value, remark, permission, create_time, creator_id, creator, update_time, modifier_id, modifier, is_deleted, delete_time) VALUES (12, 'MariaDB可执行文件', 'MariadbBin', '[{"model":"path","name":"路径","placeholder":"可执行文件路径","required":true},{"model":"mysql","name":"mysql","placeholder":"mysql命令路径(空则为 路径/mysql)","required":false},{"model":"mysqldump","name":"mysqldump","placeholder":"mysqldump命令路径(空则为 路径/mysqldump)","required":false},{"model":"mysqlbinlog","name":"mysqlbinlog","placeholder":"mysqlbinlog命令路径(空则为 路径/mysqlbinlog)","required":false}]', '{"mysql":"","mysqldump":"","mysqlbinlog":"","path":"./db/mariadb/bin"}', '', 'admin,', '2023-12-29 10:01:33', 1, 'admin', '2023-12-29 13:34:40', 1, 'admin', 0, NULL);
-- Table: t_sys_log
CREATE TABLE IF NOT EXISTS "t_sys_log" (
"id" integer NOT NULL,
"type" integer(4) NOT NULL,
"description" text(255),
"req_param" text(2000),
"resp" text(1000),
"creator" text(36) NOT NULL,
"creator_id" integer(20) NOT NULL,
"create_time" datetime NOT NULL,
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_sys_msg
CREATE TABLE IF NOT EXISTS "t_sys_msg" (
"id" integer NOT NULL,
"type" integer(255),
"msg" text(2000) NOT NULL,
"recipient_id" integer(20),
"creator_id" integer(20),
"creator" text(36),
"create_time" datetime NOT NULL,
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_sys_resource
CREATE TABLE IF NOT EXISTS "t_sys_resource" (
"id" integer NOT NULL,
"pid" integer(11) NOT NULL,
"ui_path" text(200),
"type" integer(4) NOT NULL,
"status" integer(11) NOT NULL,
"name" text(255) NOT NULL,
"code" text(255),
"weight" integer(11),
"meta" text(455),
"creator_id" integer(20) NOT NULL,
"creator" text(255) NOT NULL,
"modifier_id" integer(20) NOT NULL,
"modifier" text(255) NOT NULL,
"create_time" datetime NOT NULL,
"update_time" datetime NOT NULL,
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (1, 0, 'Aexqq77l/', 1, 1, '首页', '/home', 10000000, '{"component":"home/Home","icon":"HomeFilled","isAffix":true,"isKeepAlive":true,"routeName":"Home"}', 1, 'admin', 1, 'admin', '2021-05-25 16:44:41', '2023-03-14 14:27:07', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (2, 0, '12sSjal1/', 1, 1, '机器管理', '/machine', 49999998, '{"icon":"Monitor","isKeepAlive":true,"redirect":"machine/list","routeName":"Machine"}', 1, 'admin', 1, 'admin', '2021-05-25 16:48:16', '2022-10-06 14:58:49', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (3, 2, '12sSjal1/lskeiql1/', 1, 1, '机器列表', 'machines', 20000000, '{"component":"ops/machine/MachineList","icon":"Monitor","isKeepAlive":true,"routeName":"MachineList"}', 2, 'admin', 1, 'admin', '2021-05-25 16:50:04', '2023-03-15 17:14:44', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (4, 0, 'Xlqig32x/', 1, 1, '系统管理', '/sys', 60000001, '{"icon":"Setting","isKeepAlive":true,"redirect":"/sys/resources","routeName":"sys"}', 1, 'admin', 1, 'admin', '2021-05-26 15:20:20', '2022-10-06 14:59:53', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (5, 4, 'Xlqig32x/UGxla231/', 1, 1, '资源管理', 'resources', 9999999, '{"component":"system/resource/ResourceList","icon":"Menu","isKeepAlive":true,"routeName":"ResourceList"}', 1, 'admin', 1, 'admin', '2021-05-26 15:23:07', '2023-03-14 15:44:34', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (11, 4, 'Xlqig32x/lxqSiae1/', 1, 1, '角色管理', 'roles', 10000001, '{"component":"system/role/RoleList","icon":"Menu","isKeepAlive":true,"routeName":"RoleList"}', 1, 'admin', 1, 'admin', '2021-05-27 11:15:35', '2023-03-14 15:44:22', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (12, 3, '12sSjal1/lskeiql1/Alw1Xkq3/', 2, 1, '机器终端按钮', 'machine:terminal', 40000000, '', 1, 'admin', 1, 'admin', '2021-05-28 14:06:02', '2021-05-31 17:47:59', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (14, 4, 'Xlqig32x/sfslfel/', 1, 1, '账号管理', 'accounts', 9999999, '{"component":"system/account/AccountList","icon":"Menu","isKeepAlive":true,"routeName":"AccountList"}', 1, 'admin', 1, 'admin', '2021-05-28 14:56:25', '2023-03-14 15:44:10', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (15, 3, '12sSjal1/lskeiql1/Lsew24Kx/', 2, 1, '文件管理按钮', 'machine:file', 50000000, NULL, 1, 'admin', 1, 'admin', '2021-05-31 17:44:37', '2021-05-31 17:48:07', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (16, 3, '12sSjal1/lskeiql1/exIsqL31/', 2, 1, '机器添加按钮', 'machine:add', 10000000, NULL, 1, 'admin', 1, 'admin', '2021-05-31 17:46:11', '2021-05-31 19:34:15', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (17, 3, '12sSjal1/lskeiql1/Liwakg2x/', 2, 1, '机器编辑按钮', 'machine:update', 20000000, NULL, 1, 'admin', 1, 'admin', '2021-05-31 17:46:23', '2021-05-31 19:34:18', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (18, 3, '12sSjal1/lskeiql1/Lieakenx/', 2, 1, '机器删除按钮', 'machine:del', 30000000, NULL, 1, 'admin', 1, 'admin', '2021-05-31 17:46:36', '2021-05-31 19:34:17', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (19, 14, 'Xlqig32x/sfslfel/UUiex2xA/', 2, 1, '角色分配按钮', 'account:saveRoles', 10000000, NULL, 1, 'admin', 1, 'admin', '2021-05-31 17:50:51', '2021-05-31 19:19:30', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (20, 11, 'Xlqig32x/lxqSiae1/EMq2Kxq3/', 2, 1, '分配菜单&权限按钮', 'role:saveResources', 10000000, NULL, 1, 'admin', 1, 'admin', '2021-05-31 17:51:41', '2021-05-31 19:33:37', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (21, 14, 'Xlqig32x/sfslfel/Uexax2xA/', 2, 1, '账号删除按钮', 'account:del', 20000000, 'null', 1, 'admin', 1, 'admin', '2021-05-31 18:02:01', '2021-06-10 17:12:17', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (22, 11, 'Xlqig32x/lxqSiae1/Elxq2Kxq3/', 2, 1, '角色删除按钮', 'role:del', 20000000, NULL, 1, 'admin', 1, 'admin', '2021-05-31 18:02:29', '2021-05-31 19:33:38', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (23, 11, 'Xlqig32x/lxqSiae1/342xKxq3/', 2, 1, '角色新增按钮', 'role:add', 30000000, NULL, 1, 'admin', 1, 'admin', '2021-05-31 18:02:44', '2021-05-31 19:33:39', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (24, 11, 'Xlqig32x/lxqSiae1/LexqKxq3/', 2, 1, '角色编辑按钮', 'role:update', 40000000, NULL, 1, 'admin', 1, 'admin', '2021-05-31 18:02:57', '2021-05-31 19:33:40', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (25, 5, 'Xlqig32x/UGxla231/Elxq23XK/', 2, 1, '资源新增按钮', 'resource:add', 10000000, NULL, 1, 'admin', 1, 'admin', '2021-05-31 18:03:33', '2021-05-31 19:31:47', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (26, 5, 'Xlqig32x/UGxla231/eloq23XK/', 2, 1, '资源删除按钮', 'resource:delete', 20000000, NULL, 1, 'admin', 1, 'admin', '2021-05-31 18:03:47', '2021-05-31 19:29:40', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (27, 5, 'Xlqig32x/UGxla231/JExq23XK/', 2, 1, '资源编辑按钮', 'resource:update', 30000000, NULL, 1, 'admin', 1, 'admin', '2021-05-31 18:04:03', '2021-05-31 19:29:40', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (28, 5, 'Xlqig32x/UGxla231/Elex13XK/', 2, 1, '资源禁用启用按钮', 'resource:changeStatus', 40000000, NULL, 1, 'admin', 1, 'admin', '2021-05-31 18:04:33', '2021-05-31 18:04:33', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (29, 14, 'Xlqig32x/sfslfel/xlawx2xA/', 2, 1, '账号添加按钮', 'account:add', 30000000, NULL, 1, 'admin', 1, 'admin', '2021-05-31 19:23:42', '2021-05-31 19:23:42', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (30, 14, 'Xlqig32x/sfslfel/32xax2xA/', 2, 1, '账号编辑修改按钮', 'account:update', 40000000, NULL, 1, 'admin', 1, 'admin', '2021-05-31 19:23:58', '2021-05-31 19:23:58', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (31, 14, 'Xlqig32x/sfslfel/eubale13/', 2, 1, '账号管理基本权限', 'account', 10000000, 'null', 1, 'admin', 1, 'admin', '2021-05-31 21:25:06', '2021-06-22 11:20:34', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (32, 5, 'Xlqig32x/UGxla231/321q23XK/', 2, 1, '资源管理基本权限', 'resource', 10000000, NULL, 1, 'admin', 1, 'admin', '2021-05-31 21:25:25', '2021-05-31 21:25:25', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (33, 11, 'Xlqig32x/lxqSiae1/908xKxq3/', 2, 1, '角色管理基本权限', 'role', 10000000, NULL, 1, 'admin', 1, 'admin', '2021-05-31 21:25:40', '2021-05-31 21:25:40', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (34, 14, 'Xlqig32x/sfslfel/32alx2xA/', 2, 1, '账号启用禁用按钮', 'account:changeStatus', 50000000, NULL, 1, 'admin', 1, 'admin', '2021-05-31 21:29:48', '2021-05-31 21:29:48', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (36, 0, 'dbms23ax/', 1, 1, 'DBMS', '/dbms', 49999999, '{"icon":"Coin","isKeepAlive":true,"routeName":"DBMS"}', 1, 'admin', 1, 'admin', '2021-06-01 14:01:33', '2023-03-15 17:31:08', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (37, 3, '12sSjal1/lskeiql1/Keiqkx4L/', 2, 1, '添加文件配置', 'machine:addFile', 60000000, 'null', 1, 'admin', 1, 'admin', '2021-06-01 19:54:23', '2021-06-01 19:54:23', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (38, 36, 'dbms23ax/exaeca2x/', 1, 1, '数据操作', 'sql-exec', 10000000, '{"component":"ops/db/SqlExec","icon":"Coin","isKeepAlive":true,"routeName":"SqlExec"}', 1, 'admin', 1, 'admin', '2021-06-03 09:09:29', '2023-03-15 17:31:21', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (39, 0, 'sl3as23x/', 1, 1, '个人中心', '/personal', 19999999, '{"component":"personal/index","icon":"UserFilled","isHide":true,"isKeepAlive":true,"routeName":"Personal"}', 1, 'admin', 1, 'admin', '2021-06-03 14:25:35', '2023-03-14 14:28:36', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (40, 3, '12sSjal1/lskeiql1/Keal2Xke/', 2, 1, '文件管理-新增按钮', 'machine:file:add', 70000000, 'null', 1, 'admin', 1, 'admin', '2021-06-08 11:06:26', '2021-06-08 11:12:28', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (41, 3, '12sSjal1/lskeiql1/Ihfs2xaw/', 2, 1, '文件管理-删除按钮', 'machine:file:del', 80000000, 'null', 1, 'admin', 1, 'admin', '2021-06-08 11:06:49', '2021-06-08 11:06:49', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (42, 3, '12sSjal1/lskeiql1/3ldkxJDx/', 2, 1, '文件管理-写入or下载文件权限', 'machine:file:write', 90000000, 'null', 1, 'admin', 1, 'admin', '2021-06-08 11:07:27', '2021-06-08 11:07:27', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (43, 3, '12sSjal1/lskeiql1/Ljewix43/', 2, 1, '文件管理-文件上传按钮', 'machine:file:upload', 100000000, 'null', 1, 'admin', 1, 'admin', '2021-06-08 11:07:42', '2021-06-08 11:07:42', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (44, 3, '12sSjal1/lskeiql1/L12wix43/', 2, 1, '文件管理-删除文件按钮', 'machine:file:rm', 110000000, 'null', 1, 'admin', 1, 'admin', '2021-06-08 11:08:12', '2021-06-08 11:08:12', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (45, 3, '12sSjal1/lskeiql1/Ljewisd3/', 2, 1, '脚本管理-保存脚本按钮', 'machine:script:save', 120000000, 'null', 1, 'admin', 1, 'admin', '2021-06-08 11:09:01', '2021-06-08 11:09:01', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (46, 3, '12sSjal1/lskeiql1/Ljeew43/', 2, 1, '脚本管理-删除按钮', 'machine:script:del', 130000000, 'null', 1, 'admin', 1, 'admin', '2021-06-08 11:09:27', '2021-06-08 11:09:27', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (47, 3, '12sSjal1/lskeiql1/ODewix43/', 2, 1, '脚本管理-执行按钮', 'machine:script:run', 140000000, 'null', 1, 'admin', 1, 'admin', '2021-06-08 11:09:50', '2021-06-08 11:09:50', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (49, 36, 'dbms23ax/xleaiec2/', 1, 1, '数据库管理', 'dbs', 20000000, '{"component":"ops/db/DbList","icon":"Coin","isKeepAlive":true,"routeName":"DbList"}', 1, 'admin', 1, 'admin', '2021-07-07 15:13:55', '2023-03-15 17:31:28', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (54, 49, 'dbms23ax/xleaiec2/leix3Axl/', 2, 1, '数据库保存', 'db:save', 10000000, 'null', 1, 'admin', 1, 'admin', '2021-07-08 17:30:36', '2021-07-08 17:31:05', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (55, 49, 'dbms23ax/xleaiec2/ygjL3sxA/', 2, 1, '数据库删除', 'db:del', 20000000, 'null', 1, 'admin', 1, 'admin', '2021-07-08 17:30:48', '2021-07-08 17:30:48', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (57, 3, '12sSjal1/lskeiql1/OJewex43/', 2, 1, '基本权限', 'machine', 10000000, 'null', 1, 'admin', 1, 'admin', '2021-07-09 10:48:02', '2021-07-09 10:48:02', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (58, 49, 'dbms23ax/xleaiec2/AceXe321/', 2, 1, '基本权限', 'db', 10000000, 'null', 1, 'admin', 1, 'admin', '2021-07-09 10:48:22', '2021-07-09 10:48:22', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (59, 38, 'dbms23ax/exaeca2x/ealcia23/', 2, 1, '基本权限', 'db:exec', 10000000, 'null', 1, 'admin', 1, 'admin', '2021-07-09 10:50:13', '2021-07-09 10:50:13', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (60, 0, 'RedisXq4/', 1, 1, 'Redis', '/redis', 50000001, '{"icon":"iconfont icon-redis","isKeepAlive":true,"routeName":"RDS"}', 1, 'admin', 1, 'admin', '2021-07-19 20:15:41', '2023-03-15 16:44:59', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (61, 60, 'RedisXq4/Exitx4al/', 1, 1, '数据操作', 'data-operation', 10000000, '{"component":"ops/redis/DataOperation","icon":"iconfont icon-redis","isKeepAlive":true,"routeName":"DataOperation"}', 1, 'admin', 1, 'admin', '2021-07-19 20:17:29', '2023-03-15 16:37:50', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (62, 61, 'RedisXq4/Exitx4al/LSjie321/', 2, 1, '基本权限', 'redis:data', 10000000, 'null', 1, 'admin', 1, 'admin', '2021-07-19 20:18:54', '2021-07-19 20:18:54', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (63, 60, 'RedisXq4/Eoaljc12/', 1, 1, 'redis管理', 'manage', 20000000, '{"component":"ops/redis/RedisList","icon":"iconfont icon-redis","isKeepAlive":true,"routeName":"RedisList"}', 1, 'admin', 1, 'admin', '2021-07-20 10:48:04', '2023-03-15 16:38:00', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (64, 63, 'RedisXq4/Eoaljc12/IoxqAd31/', 2, 1, '基本权限', 'redis:manage', 10000000, 'null', 1, 'admin', 1, 'admin', '2021-07-20 10:48:26', '2021-07-20 10:48:26', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (71, 61, 'RedisXq4/Exitx4al/IUlxia23/', 2, 1, '数据保存', 'redis:data:save', 60000000, 'null', 1, 'admin', 1, 'admin', '2021-08-17 11:20:37', '2021-08-17 11:20:37', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (72, 3, '12sSjal1/lskeiql1/LIEwix43/', 2, 1, '终止进程', 'machine:killprocess', 60000000, 'null', 1, 'admin', 1, 'admin', '2021-08-17 11:20:37', '2021-08-17 11:20:37', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (79, 0, 'Mongo452/', 1, 1, 'Mongo', '/mongo', 50000002, '{"icon":"iconfont icon-mongo","isKeepAlive":true,"routeName":"Mongo"}', 1, 'admin', 1, 'admin', '2022-05-13 14:00:41', '2023-03-16 14:23:22', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (80, 79, 'Mongo452/eggago31/', 1, 1, '数据操作', 'mongo-data-operation', 10000000, '{"component":"ops/mongo/MongoDataOp","icon":"iconfont icon-mongo","isKeepAlive":true,"routeName":"MongoDataOp"}', 1, 'admin', 1, 'admin', '2022-05-13 14:03:58', '2023-03-15 17:15:02', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (81, 80, 'Mongo452/eggago31/egjglal3/', 2, 1, '基本权限', 'mongo:base', 10000000, 'null', 1, 'admin', 1, 'admin', '2022-05-13 14:04:16', '2022-05-13 14:04:16', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (82, 79, 'Mongo452/ghxagl43/', 1, 1, 'Mongo管理', 'mongo-manage', 20000000, '{"component":"ops/mongo/MongoList","icon":"iconfont icon-mongo","isKeepAlive":true,"routeName":"MongoList"}', 1, 'admin', 1, 'admin', '2022-05-16 18:13:06', '2023-03-15 17:26:55', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (83, 82, 'Mongo452/ghxagl43/egljbla3/', 2, 1, '基本权限', 'mongo:manage:base', 10000000, 'null', 1, 'admin', 1, 'admin', '2022-05-16 18:13:25', '2022-05-16 18:13:25', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (84, 4, 'Xlqig32x/exlaeAlx/', 1, 1, '操作日志', 'syslogs', 20000000, '{"component":"system/syslog/SyslogList","icon":"Tickets","routeName":"SyslogList"}', 1, 'admin', 1, 'admin', '2022-07-13 19:57:07', '2023-03-14 15:44:45', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (85, 84, 'Xlqig32x/exlaeAlx/3xlqeXql/', 2, 1, '操作日志基本权限', 'syslog', 10000000, 'null', 1, 'admin', 1, 'admin', '2022-07-13 19:57:55', '2022-07-13 19:57:55', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (87, 4, 'Xlqig32x/Ulxaee23/', 1, 1, '系统配置', 'configs', 10000002, '{"component":"system/config/ConfigList","icon":"Setting","isKeepAlive":true,"routeName":"ConfigList"}', 1, 'admin', 1, 'admin', '2022-08-25 22:18:55', '2023-03-15 11:06:07', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (88, 87, 'Xlqig32x/Ulxaee23/exlqguA3/', 2, 1, '基本权限', 'config:base', 10000000, 'null', 1, 'admin', 1, 'admin', '2022-08-25 22:19:35', '2022-08-25 22:19:35', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (93, 0, 'Tag3fhad/', 1, 1, '标签管理', '/tag', 20000001, '{"icon":"CollectionTag","isKeepAlive":true,"routeName":"Tag"}', 1, 'admin', 1, 'admin', '2022-10-24 15:18:40', '2022-10-24 15:24:29', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (94, 93, 'Tag3fhad/glxajg23/', 1, 1, '标签树', 'tag-trees', 10000000, '{"component":"ops/tag/TagTreeList","icon":"CollectionTag","isKeepAlive":true,"routeName":"TagTreeList"}', 1, 'admin', 1, 'admin', '2022-10-24 15:19:40', '2023-03-14 14:30:51', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (95, 93, 'Tag3fhad/Bjlag32x/', 1, 1, '团队管理', 'teams', 20000000, '{"component":"ops/tag/TeamList","icon":"UserFilled","isKeepAlive":true,"routeName":"TeamList"}', 1, 'admin', 1, 'admin', '2022-10-24 15:20:09', '2023-03-14 14:31:03', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (96, 94, 'Tag3fhad/glxajg23/gkxagt23/', 2, 1, '保存标签', 'tag:save', 10000000, 'null', 1, 'admin', 1, 'admin', '2022-10-24 15:20:40', '2022-10-26 13:58:36', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (97, 95, 'Tag3fhad/Bjlag32x/GJslag32/', 2, 1, '保存团队', 'team:save', 10000000, 'null', 1, 'admin', 1, 'admin', '2022-10-24 15:20:57', '2022-10-26 13:58:56', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (98, 94, 'Tag3fhad/glxajg23/xjgalte2/', 2, 1, '删除标签', 'tag:del', 20000000, 'null', 1, 'admin', 1, 'admin', '2022-10-26 13:58:47', '2022-10-26 13:58:47', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (99, 95, 'Tag3fhad/Bjlag32x/Gguca23x/', 2, 1, '删除团队', 'team:del', 20000000, 'null', 1, 'admin', 1, 'admin', '2022-10-26 13:59:06', '2022-10-26 13:59:06', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (100, 95, 'Tag3fhad/Bjlag32x/Lgidsq32/', 2, 1, '新增团队成员', 'team:member:save', 30000000, 'null', 1, 'admin', 1, 'admin', '2022-10-26 13:59:27', '2022-10-26 13:59:27', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (101, 95, 'Tag3fhad/Bjlag32x/Lixaue3G/', 2, 1, '移除团队成员', 'team:member:del', 40000000, 'null', 1, 'admin', 1, 'admin', '2022-10-26 13:59:43', '2022-10-26 13:59:43', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (102, 95, 'Tag3fhad/Bjlag32x/Oygsq3xg/', 2, 1, '保存团队标签', 'team:tag:save', 50000000, 'null', 1, 'admin', 1, 'admin', '2022-10-26 13:59:57', '2022-10-26 13:59:57', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (103, 2, '12sSjal1/exahgl32/', 1, 1, '授权凭证', 'authcerts', 60000000, '{"component":"ops/machine/authcert/AuthCertList","icon":"Unlock","isKeepAlive":true,"routeName":"AuthCertList"}', 1, 'admin', 1, 'admin', '2023-02-23 11:36:26', '2023-03-14 14:33:28', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (104, 103, '12sSjal1/exahgl32/egxahg24/', 2, 1, '基本权限', 'authcert', 10000000, 'null', 1, 'admin', 1, 'admin', '2023-02-23 11:37:24', '2023-02-23 11:37:24', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (105, 103, '12sSjal1/exahgl32/yglxahg2/', 2, 1, '保存权限', 'authcert:save', 20000000, 'null', 1, 'admin', 1, 'admin', '2023-02-23 11:37:54', '2023-02-23 11:37:54', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (106, 103, '12sSjal1/exahgl32/Glxag234/', 2, 1, '删除权限', 'authcert:del', 30000000, 'null', 1, 'admin', 1, 'admin', '2023-02-23 11:38:09', '2023-02-23 11:38:09', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (108, 61, 'RedisXq4/Exitx4al/Gxlagheg/', 2, 1, '数据删除', 'redis:data:del', 30000000, 'null', 1, 'admin', 1, 'admin', '2023-03-14 17:20:00', '2023-03-14 17:20:00', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (109, 3, '12sSjal1/lskeiql1/KMdsix43/', 2, 1, '关闭连接', 'machine:close-cli', 60000000, 'null', 1, 'admin', 1, 'admin', '2023-03-16 16:11:04', '2023-03-16 16:11:04', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (128, 87, 'Xlqig32x/Ulxaee23/MoOWr2N0/', 2, 1, '配置保存', 'config:save', 1687315135, 'null', 1, 'admin', 1, 'admin', '2023-06-21 10:38:55', '2023-06-21 10:38:55', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (130, 2, '12sSjal1/W9XKiabq/', 1, 1, '计划任务', '/machine/cron-job', 1689646396, '{"component":"ops/machine/cronjob/CronJobList","icon":"AlarmClock","isKeepAlive":true,"routeName":"CronJobList"}', 1, 'admin', 1, 'admin', '2023-07-18 10:13:16', '2023-07-18 10:14:06', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (131, 130, '12sSjal1/W9XKiabq/gEOqr2pD/', 2, 1, '保存计划任务', 'machine:cronjob:save', 1689860087, 'null', 1, 'admin', 1, 'admin', '2023-07-20 21:34:47', '2023-07-20 21:34:47', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (132, 130, '12sSjal1/W9XKiabq/zxXM23i0/', 2, 1, '删除计划任务', 'machine:cronjob:del', 1689860102, 'null', 1, 'admin', 1, 'admin', '2023-07-20 21:35:02', '2023-07-20 21:35:02', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (133, 80, 'Mongo452/eggago31/xvpKk36u/', 2, 1, '保存数据', 'mongo:data:save', 1692674943, 'null', 1, 'admin', 1, 'admin', '2023-08-22 11:29:04', '2023-08-22 11:29:11', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (134, 80, 'Mongo452/eggago31/3sblw1Wb/', 2, 1, '删除数据', 'mongo:data:del', 1692674964, 'null', 1, 'admin', 1, 'admin', '2023-08-22 11:29:24', '2023-08-22 11:29:24', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (135, 36, 'dbms23ax/X0f4BxT0/', 1, 1, '数据库实例', 'instances', 1693040706, '{"component":"ops/db/InstanceList","icon":"Coin","isKeepAlive":true,"routeName":"InstanceList"}', 1, 'admin', 1, 'admin', '2023-08-26 09:05:07', '2023-08-29 22:35:11', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (136, 135, 'dbms23ax/X0f4BxT0/D23fUiBr/', 2, 1, '实例保存', 'db:instance:save', 1693041001, 'null', 1, 'admin', 1, 'admin', '2023-08-26 09:10:02', '2023-08-26 09:10:02', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (137, 135, 'dbms23ax/X0f4BxT0/mJlBeTCs/', 2, 1, '基本权限', 'db:instance', 1693041055, 'null', 1, 'admin', 1, 'admin', '2023-08-26 09:10:55', '2023-08-26 09:10:55', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (138, 135, 'dbms23ax/X0f4BxT0/Sgg8uPwz/', 2, 1, '实例删除', 'db:instance:del', 1693041084, 'null', 1, 'admin', 1, 'admin', '2023-08-26 09:11:24', '2023-08-26 09:11:24', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (150, 36, 'Jra0n7De/', 1, 1, '数据同步', 'sync', 1693040707, '{"component":"ops/db/SyncTaskList","icon":"Coin","isKeepAlive":true,"routeName":"SyncTaskList"}', 12, 'liuzongyang', 12, 'liuzongyang', '2023-12-22 09:51:34', '2023-12-27 10:16:57', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (151, 150, 'Jra0n7De/uAnHZxEV/', 2, 1, '基本权限', 'db:sync', 1703641202, 'null', 12, 'liuzongyang', 12, 'liuzongyang', '2023-12-27 09:40:02', '2023-12-27 09:40:02', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (152, 150, 'Jra0n7De/zvAMo2vk/', 2, 1, '编辑', 'db:sync:save', 1703641320, 'null', 12, 'liuzongyang', 12, 'liuzongyang', '2023-12-27 09:42:00', '2023-12-27 09:42:12', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (153, 150, 'Jra0n7De/pLOA2UYz/', 2, 1, '删除', 'db:sync:del', 1703641342, 'null', 12, 'liuzongyang', 12, 'liuzongyang', '2023-12-27 09:42:22', '2023-12-27 09:42:22', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (154, 150, 'Jra0n7De/VBt68CDx/', 2, 1, '启停', 'db:sync:status', 1703641364, 'null', 12, 'liuzongyang', 12, 'liuzongyang', '2023-12-27 09:42:45', '2023-12-27 09:42:45', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (155, 150, 'Jra0n7De/PigmSGVg/', 2, 1, '日志', 'db:sync:log', 1704266866, 'null', 12, 'liuzongyang', 12, 'liuzongyang', '2024-01-03 15:27:47', '2024-01-03 15:27:47', 0, NULL);
-- Table: t_sys_role
CREATE TABLE IF NOT EXISTS "t_sys_role" (
"id" integer NOT NULL,
"name" text(16) NOT NULL,
"code" text(64) NOT NULL,
"status" integer(255),
"remark" text(255),
"type" integer(2) NOT NULL,
"create_time" datetime,
"creator_id" integer(20),
"creator" text(16),
"update_time" datetime,
"modifier_id" integer(20),
"modifier" text(16),
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
INSERT INTO t_sys_role (id, name, code, status, remark, type, create_time, creator_id, creator, update_time, modifier_id, modifier, is_deleted, delete_time) VALUES (7, '公共角色', 'COMMON', 1, '所有账号基础角色', 1, '2021-07-06 15:05:47', 1, 'admin', '2021-07-06 15:05:47', 1, 'admin', 0, NULL);
INSERT INTO t_sys_role (id, name, code, status, remark, type, create_time, creator_id, creator, update_time, modifier_id, modifier, is_deleted, delete_time) VALUES (8, '开发', 'DEV', 1, '研发人员', 0, '2021-07-09 10:46:10', 1, 'admin', '2021-07-09 10:46:10', 1, 'admin', 0, NULL);
-- Table: t_sys_role_resource
CREATE TABLE IF NOT EXISTS "t_sys_role_resource" (
"id" integer NOT NULL,
"role_id" integer(20) NOT NULL,
"resource_id" integer(20) NOT NULL,
"creator_id" integer(20),
"creator" text(45),
"create_time" datetime,
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
INSERT INTO t_sys_role_resource (id, role_id, resource_id, creator_id, creator, create_time, is_deleted, delete_time) VALUES (526, 7, 1, 1, 'admin', '2021-07-06 15:07:09', 0, NULL);
INSERT INTO t_sys_role_resource (id, role_id, resource_id, creator_id, creator, create_time, is_deleted, delete_time) VALUES (527, 8, 57, 1, 'admin', '2021-07-09 10:49:46', 0, NULL);
INSERT INTO t_sys_role_resource (id, role_id, resource_id, creator_id, creator, create_time, is_deleted, delete_time) VALUES (528, 8, 12, 1, 'admin', '2021-07-09 10:49:46', 0, NULL);
INSERT INTO t_sys_role_resource (id, role_id, resource_id, creator_id, creator, create_time, is_deleted, delete_time) VALUES (529, 8, 15, 1, 'admin', '2021-07-09 10:49:46', 0, NULL);
INSERT INTO t_sys_role_resource (id, role_id, resource_id, creator_id, creator, create_time, is_deleted, delete_time) VALUES (530, 8, 38, 1, 'admin', '2021-07-09 10:49:46', 0, NULL);
INSERT INTO t_sys_role_resource (id, role_id, resource_id, creator_id, creator, create_time, is_deleted, delete_time) VALUES (531, 8, 2, 1, 'admin', '2021-07-09 10:49:46', 0, NULL);
INSERT INTO t_sys_role_resource (id, role_id, resource_id, creator_id, creator, create_time, is_deleted, delete_time) VALUES (532, 8, 3, 1, 'admin', '2021-07-09 10:49:46', 0, NULL);
INSERT INTO t_sys_role_resource (id, role_id, resource_id, creator_id, creator, create_time, is_deleted, delete_time) VALUES (533, 8, 36, 1, 'admin', '2021-07-09 10:49:46', 0, NULL);
INSERT INTO t_sys_role_resource (id, role_id, resource_id, creator_id, creator, create_time, is_deleted, delete_time) VALUES (534, 8, 59, 1, 'admin', '2021-07-09 10:50:32', 0, NULL);
INSERT INTO t_sys_role_resource (id, role_id, resource_id, creator_id, creator, create_time, is_deleted, delete_time) VALUES (535, 7, 39, 1, 'admin', '2021-09-09 10:10:30', 0, NULL);
INSERT INTO t_sys_role_resource (id, role_id, resource_id, creator_id, creator, create_time, is_deleted, delete_time) VALUES (536, 8, 42, 1, 'admin', '2021-11-05 15:59:16', 0, NULL);
INSERT INTO t_sys_role_resource (id, role_id, resource_id, creator_id, creator, create_time, is_deleted, delete_time) VALUES (537, 8, 43, 1, 'admin', '2021-11-05 15:59:16', 0, NULL);
INSERT INTO t_sys_role_resource (id, role_id, resource_id, creator_id, creator, create_time, is_deleted, delete_time) VALUES (538, 8, 47, 1, 'admin', '2021-11-05 15:59:16', 0, NULL);
INSERT INTO t_sys_role_resource (id, role_id, resource_id, creator_id, creator, create_time, is_deleted, delete_time) VALUES (539, 8, 60, 1, 'admin', '2021-11-05 15:59:16', 0, NULL);
INSERT INTO t_sys_role_resource (id, role_id, resource_id, creator_id, creator, create_time, is_deleted, delete_time) VALUES (540, 8, 61, 1, 'admin', '2021-11-05 15:59:16', 0, NULL);
INSERT INTO t_sys_role_resource (id, role_id, resource_id, creator_id, creator, create_time, is_deleted, delete_time) VALUES (541, 8, 62, 1, 'admin', '2021-11-05 15:59:16', 0, NULL);
INSERT INTO t_sys_role_resource (id, role_id, resource_id, creator_id, creator, create_time, is_deleted, delete_time) VALUES (542, 8, 80, 1, 'admin', '2022-10-08 10:54:34', 0, NULL);
INSERT INTO t_sys_role_resource (id, role_id, resource_id, creator_id, creator, create_time, is_deleted, delete_time) VALUES (543, 8, 81, 1, 'admin', '2022-10-08 10:54:34', 0, NULL);
INSERT INTO t_sys_role_resource (id, role_id, resource_id, creator_id, creator, create_time, is_deleted, delete_time) VALUES (544, 8, 79, 1, 'admin', '2022-10-08 10:54:34', 0, NULL);
-- Table: t_tag_resource
CREATE TABLE IF NOT EXISTS "t_tag_resource" (
"id" integer NOT NULL,
"tag_id" integer(20) NOT NULL,
"tag_path" text(255) NOT NULL,
"resource_code" text(36),
"resource_type" integer(4) NOT NULL,
"create_time" datetime NOT NULL,
"creator_id" integer(20) NOT NULL,
"creator" text(36) NOT NULL,
"update_time" datetime NOT NULL,
"modifier_id" integer(20) NOT NULL,
"modifier" text(36) NOT NULL,
"is_deleted" integer(4),
"delete_time" datetime,
PRIMARY KEY ("id")
);
-- Table: t_tag_tree
CREATE TABLE IF NOT EXISTS "t_tag_tree" (
"id" integer NOT NULL,
"pid" integer(20) NOT NULL,
"code" text(36) NOT NULL,
"code_path" text(255) NOT NULL,
"name" text(36),
"remark" text(255),
"create_time" datetime NOT NULL,
"creator_id" integer(20) NOT NULL,
"creator" text(36) NOT NULL,
"update_time" datetime NOT NULL,
"modifier_id" integer(20) NOT NULL,
"modifier" text(36) NOT NULL,
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
INSERT INTO t_tag_tree (id, pid, code, code_path, name, remark, create_time, creator_id, creator, update_time, modifier_id, modifier, is_deleted, delete_time) VALUES (33, 0, 'default', 'default/', '默认', '默认标签', '2022-10-26 20:04:19', 1, 'admin', '2022-10-26 20:04:19', 1, 'admin', 0, NULL);
-- Table: t_tag_tree_team
CREATE TABLE IF NOT EXISTS "t_tag_tree_team" (
"id" integer NOT NULL,
"tag_id" integer(20) NOT NULL,
"tag_path" text(255),
"team_id" integer(20) NOT NULL,
"create_time" datetime NOT NULL,
"creator_id" integer(20) NOT NULL,
"creator" text(36) NOT NULL,
"update_time" datetime NOT NULL,
"modifier_id" integer(20) NOT NULL,
"modifier" text(36) NOT NULL,
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
INSERT INTO t_tag_tree_team (id, tag_id, tag_path, team_id, create_time, creator_id, creator, update_time, modifier_id, modifier, is_deleted, delete_time) VALUES (31, 33, 'default/', 3, '2022-10-26 20:04:45', 1, 'admin', '2022-10-26 20:04:45', 1, 'admin', 0, NULL);
-- Table: t_team
CREATE TABLE IF NOT EXISTS "t_team" (
"id" integer NOT NULL,
"name" text(36) NOT NULL,
"remark" text(255),
"create_time" datetime NOT NULL,
"creator_id" integer(20) NOT NULL,
"creator" text(36),
"update_time" datetime,
"modifier_id" integer(20),
"modifier" text(36),
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
INSERT INTO t_team (id, name, remark, create_time, creator_id, creator, update_time, modifier_id, modifier, is_deleted, delete_time) VALUES (3, '默认团队', '默认团队', '2022-10-26 20:04:36', 1, 'admin', '2022-10-26 20:04:36', 1, 'admin', 0, NULL);
-- Table: t_team_member
CREATE TABLE IF NOT EXISTS "t_team_member" (
"id" integer NOT NULL,
"team_id" integer(20) NOT NULL,
"account_id" integer(20) NOT NULL,
"username" text(36) NOT NULL,
"create_time" datetime NOT NULL,
"creator_id" integer(20) NOT NULL,
"creator" text(36) NOT NULL,
"update_time" datetime NOT NULL,
"modifier_id" integer(20) NOT NULL,
"modifier" text(36) NOT NULL,
"is_deleted" integer(8) NOT NULL,
"delete_time" datetime,
PRIMARY KEY ("id")
);
INSERT INTO t_team_member (id, team_id, account_id, username, create_time, creator_id, creator, update_time, modifier_id, modifier, is_deleted, delete_time) VALUES (7, 3, 1, 'admin', '2022-10-26 20:04:36', 1, 'admin', '2022-10-26 20:04:36', 1, 'admin', 0, NULL);
-- Index: idx_db_backup_id
CREATE INDEX IF NOT EXISTS "idx_db_backup_id"
ON "t_db_backup_history" (
"db_backup_id" ASC
);
-- Index: idx_db_instance_id
CREATE INDEX IF NOT EXISTS "idx_db_instance_id"
ON "t_db_backup" (
"db_instance_id" ASC
);
-- Index: idx_db_name
CREATE INDEX IF NOT EXISTS "idx_db_name"
ON "t_db_backup" (
"db_name" ASC
);
COMMIT TRANSACTION;
PRAGMA foreign_keys = on;

View File

@@ -9,9 +9,9 @@ CREATE TABLE `t_db_instance` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '数据库实例名称',
`host` varchar(100) COLLATE utf8mb4_bin NOT NULL,
`port` int(8) NOT NULL,
`port` int(8) NULL,
`sid` varchar(255) NULL COMMENT 'oracle数据库需要sid',
`username` varchar(255) COLLATE utf8mb4_bin NOT NULL,
`username` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
`password` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
`type` varchar(20) COLLATE utf8mb4_bin NOT NULL COMMENT '数据库实例类型(mysql...)',
`params` varchar(125) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '其他连接参数',

View File

@@ -0,0 +1,3 @@
ALTER TABLE `t_db_instance`
MODIFY `port` int (8) NULL comment '数据库端口',
MODIFY `username` varchar (255) NULL comment '数据库用户名';