mirror of
				https://gitee.com/dromara/mayfly-go
				synced 2025-11-04 08:20:25 +08:00 
			
		
		
		
	!60 feat: 支持pgsql编辑表、索引
Merge pull request !60 from zongyangleo/dev_1126
This commit is contained in:
		@@ -1,18 +1,6 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
    <div class="db-list">
 | 
					    <div class="db-list">
 | 
				
			||||||
        <page-table
 | 
					        <page-table ref="pageTableRef" :query="queryConfig" v-model:query-form="query" :show-selection="true" v-model:selection-data="state.selectionData" :data="datas" :columns="columns" :total="total" v-model:page-size="query.pageSize" v-model:page-num="query.pageNum" @pageChange="search()">
 | 
				
			||||||
            ref="pageTableRef"
 | 
					 | 
				
			||||||
            :query="queryConfig"
 | 
					 | 
				
			||||||
            v-model:query-form="query"
 | 
					 | 
				
			||||||
            :show-selection="true"
 | 
					 | 
				
			||||||
            v-model:selection-data="state.selectionData"
 | 
					 | 
				
			||||||
            :data="datas"
 | 
					 | 
				
			||||||
            :columns="columns"
 | 
					 | 
				
			||||||
            :total="total"
 | 
					 | 
				
			||||||
            v-model:page-size="query.pageSize"
 | 
					 | 
				
			||||||
            v-model:page-num="query.pageNum"
 | 
					 | 
				
			||||||
            @pageChange="search()"
 | 
					 | 
				
			||||||
        >
 | 
					 | 
				
			||||||
            <template #tagPathSelect>
 | 
					            <template #tagPathSelect>
 | 
				
			||||||
                <el-select @focus="getTags" v-model="query.tagPath" placeholder="请选择标签" filterable clearable style="width: 200px">
 | 
					                <el-select @focus="getTags" v-model="query.tagPath" placeholder="请选择标签" filterable clearable style="width: 200px">
 | 
				
			||||||
                    <el-option v-for="item in tags" :key="item" :label="item" :value="item"> </el-option>
 | 
					                    <el-option v-for="item in tags" :key="item" :label="item" :value="item"> </el-option>
 | 
				
			||||||
@@ -20,15 +8,7 @@
 | 
				
			|||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <template #instanceSelect>
 | 
					            <template #instanceSelect>
 | 
				
			||||||
                <el-select
 | 
					                <el-select remote :remote-method="getInstances" v-model="query.instanceId" placeholder="输入并选择实例" filterable clearable style="width: 200px">
 | 
				
			||||||
                    remote
 | 
					 | 
				
			||||||
                    :remote-method="getInstances"
 | 
					 | 
				
			||||||
                    v-model="query.instanceId"
 | 
					 | 
				
			||||||
                    placeholder="输入并选择实例"
 | 
					 | 
				
			||||||
                    filterable
 | 
					 | 
				
			||||||
                    clearable
 | 
					 | 
				
			||||||
                    style="width: 200px"
 | 
					 | 
				
			||||||
                >
 | 
					 | 
				
			||||||
                    <el-option v-for="item in state.instances" :key="item.id" :label="`${item.name}`" :value="item.id">
 | 
					                    <el-option v-for="item in state.instances" :key="item.id" :label="`${item.name}`" :value="item.id">
 | 
				
			||||||
                        {{ item.name }}
 | 
					                        {{ item.name }}
 | 
				
			||||||
                        <el-divider direction="vertical" border-style="dashed" />
 | 
					                        <el-divider direction="vertical" border-style="dashed" />
 | 
				
			||||||
@@ -78,7 +58,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                            <!-- <el-dropdown-item :command="{ type: 'edit', data }" v-if="actionBtns[perms.saveDb]"> 编辑 </el-dropdown-item> -->
 | 
					                            <!-- <el-dropdown-item :command="{ type: 'edit', data }" v-if="actionBtns[perms.saveDb]"> 编辑 </el-dropdown-item> -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            <el-dropdown-item :command="{ type: 'dumpDb', data }" v-if="data.type == 'mysql'"> 导出 </el-dropdown-item>
 | 
					                            <el-dropdown-item :command="{ type: 'dumpDb', data }" v-if="data.type == DbType.mysql"> 导出 </el-dropdown-item>
 | 
				
			||||||
                        </el-dropdown-menu>
 | 
					                        </el-dropdown-menu>
 | 
				
			||||||
                    </template>
 | 
					                    </template>
 | 
				
			||||||
                </el-dropdown>
 | 
					                </el-dropdown>
 | 
				
			||||||
@@ -106,15 +86,7 @@
 | 
				
			|||||||
            </el-row>
 | 
					            </el-row>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <el-form-item>
 | 
					            <el-form-item>
 | 
				
			||||||
                <el-transfer
 | 
					                <el-transfer v-model="exportDialog.value" filterable filter-placeholder="按数据库名称筛选" :titles="['全部数据库', '导出数据库']" :data="exportDialog.data" max-height="300" size="small" />
 | 
				
			||||||
                    v-model="exportDialog.value"
 | 
					 | 
				
			||||||
                    filterable
 | 
					 | 
				
			||||||
                    filter-placeholder="按数据库名称筛选"
 | 
					 | 
				
			||||||
                    :titles="['全部数据库', '导出数据库']"
 | 
					 | 
				
			||||||
                    :data="exportDialog.data"
 | 
					 | 
				
			||||||
                    max-height="300"
 | 
					 | 
				
			||||||
                    size="small"
 | 
					 | 
				
			||||||
                />
 | 
					 | 
				
			||||||
            </el-form-item>
 | 
					            </el-form-item>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <template #footer>
 | 
					            <template #footer>
 | 
				
			||||||
@@ -125,13 +97,7 @@
 | 
				
			|||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
        </el-dialog>
 | 
					        </el-dialog>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <el-dialog
 | 
					        <el-dialog width="90%" :title="`${sqlExecLogDialog.title} - SQL执行记录`" :before-close="onBeforeCloseSqlExecDialog" :close-on-click-modal="false" v-model="sqlExecLogDialog.visible">
 | 
				
			||||||
            width="90%"
 | 
					 | 
				
			||||||
            :title="`${sqlExecLogDialog.title} - SQL执行记录`"
 | 
					 | 
				
			||||||
            :before-close="onBeforeCloseSqlExecDialog"
 | 
					 | 
				
			||||||
            :close-on-click-modal="false"
 | 
					 | 
				
			||||||
            v-model="sqlExecLogDialog.visible"
 | 
					 | 
				
			||||||
        >
 | 
					 | 
				
			||||||
            <db-sql-exec-log :db-id="sqlExecLogDialog.dbId" :dbs="sqlExecLogDialog.dbs" />
 | 
					            <db-sql-exec-log :db-id="sqlExecLogDialog.dbId" :dbs="sqlExecLogDialog.dbs" />
 | 
				
			||||||
        </el-dialog>
 | 
					        </el-dialog>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -172,6 +138,7 @@ import PageTable from '@/components/pagetable/PageTable.vue';
 | 
				
			|||||||
import { TableColumn, TableQuery } from '@/components/pagetable';
 | 
					import { TableColumn, TableQuery } from '@/components/pagetable';
 | 
				
			||||||
import { hasPerms } from '@/components/auth/auth';
 | 
					import { hasPerms } from '@/components/auth/auth';
 | 
				
			||||||
import DbSqlExecLog from './DbSqlExecLog.vue';
 | 
					import DbSqlExecLog from './DbSqlExecLog.vue';
 | 
				
			||||||
 | 
					import { DbType } from '@/views/ops/db/component/table/dbs/db-option';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const DbEdit = defineAsyncComponent(() => import('./DbEdit.vue'));
 | 
					const DbEdit = defineAsyncComponent(() => import('./DbEdit.vue'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -402,12 +369,7 @@ const dumpDbs = () => {
 | 
				
			|||||||
            type += 2;
 | 
					            type += 2;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    a.setAttribute(
 | 
					    a.setAttribute('href', `${config.baseApiUrl}/dbs/${state.exportDialog.dbId}/dump?db=${state.exportDialog.value.join(',')}&type=${type}&extName=${state.exportDialog.extName}&${joinClientParams()}`);
 | 
				
			||||||
        'href',
 | 
					 | 
				
			||||||
        `${config.baseApiUrl}/dbs/${state.exportDialog.dbId}/dump?db=${state.exportDialog.value.join(',')}&type=${type}&extName=${
 | 
					 | 
				
			||||||
            state.exportDialog.extName
 | 
					 | 
				
			||||||
        }&${joinClientParams()}`
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
    a.click();
 | 
					    a.click();
 | 
				
			||||||
    state.exportDialog.visible = false;
 | 
					    state.exportDialog.visible = false;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,26 +13,6 @@
 | 
				
			|||||||
                            <el-input style="width: 80%" v-model="tableData.tableComment" size="small"></el-input>
 | 
					                            <el-input style="width: 80%" v-model="tableData.tableComment" size="small"></el-input>
 | 
				
			||||||
                        </el-form-item>
 | 
					                        </el-form-item>
 | 
				
			||||||
                    </el-col>
 | 
					                    </el-col>
 | 
				
			||||||
                    <el-col :span="12">
 | 
					 | 
				
			||||||
                        <el-form-item prop="characterSet" label="charset">
 | 
					 | 
				
			||||||
                            <el-select filterable style="width: 80%" v-model="tableData.characterSet" size="small">
 | 
					 | 
				
			||||||
                                <el-option v-for="item in characterSetNameList" :key="item" :label="item" :value="item"> </el-option>
 | 
					 | 
				
			||||||
                            </el-select>
 | 
					 | 
				
			||||||
                        </el-form-item>
 | 
					 | 
				
			||||||
                    </el-col>
 | 
					 | 
				
			||||||
                    <el-col :span="12">
 | 
					 | 
				
			||||||
                        <el-form-item prop="characterSet" label="collation">
 | 
					 | 
				
			||||||
                            <el-select filterable style="width: 80%" v-model="tableData.collation" size="small">
 | 
					 | 
				
			||||||
                                <el-option
 | 
					 | 
				
			||||||
                                    v-for="item in collationNameList"
 | 
					 | 
				
			||||||
                                    :key="item"
 | 
					 | 
				
			||||||
                                    :label="tableData.characterSet + '_' + item"
 | 
					 | 
				
			||||||
                                    :value="tableData.characterSet + '_' + item"
 | 
					 | 
				
			||||||
                                >
 | 
					 | 
				
			||||||
                                </el-option>
 | 
					 | 
				
			||||||
                            </el-select>
 | 
					 | 
				
			||||||
                        </el-form-item>
 | 
					 | 
				
			||||||
                    </el-col>
 | 
					 | 
				
			||||||
                </el-row>
 | 
					                </el-row>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <el-tabs v-model="activeName">
 | 
					                <el-tabs v-model="activeName">
 | 
				
			||||||
@@ -42,31 +22,28 @@
 | 
				
			|||||||
                                <template #default="scope">
 | 
					                                <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-input>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                    <el-select v-if="item.prop === 'type'" filterable size="small" v-model="scope.row.type">
 | 
					                                    <el-select v-else-if="item.prop === 'type'" filterable size="small" v-model="scope.row.type">
 | 
				
			||||||
                                        <el-option v-for="typeValue in columnTypeList" :key="typeValue" :value="typeValue">{{ typeValue }}</el-option>
 | 
					                                        <el-option v-for="pgsqlType in state.columnTypeList" :key="pgsqlType.dataType" :value="pgsqlType.udtName" :label="pgsqlType.dataType">
 | 
				
			||||||
 | 
					                                            <span v-if="pgsqlType.dataType === pgsqlType.udtName">{{ pgsqlType.dataType }}{{ pgsqlType.desc && ':' + pgsqlType.desc }}</span>
 | 
				
			||||||
 | 
					                                            <span v-else>{{ pgsqlType.dataType }},别名:{{ pgsqlType.udtName }} {{ pgsqlType.desc }}</span>
 | 
				
			||||||
 | 
					                                        </el-option>
 | 
				
			||||||
                                    </el-select>
 | 
					                                    </el-select>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                    <el-input v-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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                    <el-input v-if="item.prop === 'length'" size="small" v-model="scope.row.length"> </el-input>
 | 
					                                    <el-input v-else-if="item.prop === 'length'" size="small" v-model="scope.row.length"> </el-input>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                    <el-checkbox v-if="item.prop === 'notNull'" size="small" v-model="scope.row.notNull"> </el-checkbox>
 | 
					                                    <el-input v-else-if="item.prop === 'numScale'" size="small" v-model="scope.row.numScale"> </el-input>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                    <el-checkbox v-if="item.prop === 'pri'" size="small" v-model="scope.row.pri"> </el-checkbox>
 | 
					                                    <el-checkbox v-else-if="item.prop === 'notNull'" size="small" v-model="scope.row.notNull"> </el-checkbox>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                    <el-checkbox v-if="item.prop === 'auto_increment'" size="small" v-model="scope.row.auto_increment"> </el-checkbox>
 | 
					                                    <el-checkbox v-else-if="item.prop === 'pri'" size="small" v-model="scope.row.pri"> </el-checkbox>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                    <el-input v-if="item.prop === 'remark'" size="small" v-model="scope.row.remark"> </el-input>
 | 
					                                    <el-checkbox v-else-if="item.prop === 'auto_increment'" size="small" v-model="scope.row.auto_increment" :disabled="dbType === DbType.postgresql"> </el-checkbox>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                    <el-link
 | 
					                                    <el-input v-else-if="item.prop === 'remark'" size="small" v-model="scope.row.remark"> </el-input>
 | 
				
			||||||
                                        v-if="item.prop === 'action'"
 | 
					
 | 
				
			||||||
                                        type="danger"
 | 
					                                    <el-link v-else-if="item.prop === 'action'" type="danger" plain size="small" :underline="false" @click.prevent="deleteRow(scope.$index)">删除</el-link>
 | 
				
			||||||
                                        plain
 | 
					 | 
				
			||||||
                                        size="small"
 | 
					 | 
				
			||||||
                                        :underline="false"
 | 
					 | 
				
			||||||
                                        @click.prevent="deleteRow(scope.$index)"
 | 
					 | 
				
			||||||
                                        >删除</el-link
 | 
					 | 
				
			||||||
                                    >
 | 
					 | 
				
			||||||
                                </template>
 | 
					                                </template>
 | 
				
			||||||
                            </el-table-column>
 | 
					                            </el-table-column>
 | 
				
			||||||
                        </el-table>
 | 
					                        </el-table>
 | 
				
			||||||
@@ -81,24 +58,13 @@
 | 
				
			|||||||
                                <template #default="scope">
 | 
					                                <template #default="scope">
 | 
				
			||||||
                                    <el-input v-if="item.prop === 'indexName'" size="small" disabled v-model="scope.row.indexName"></el-input>
 | 
					                                    <el-input v-if="item.prop === 'indexName'" size="small" disabled v-model="scope.row.indexName"></el-input>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                    <el-select
 | 
					                                    <el-select v-if="item.prop === 'columnNames'" v-model="scope.row.columnNames" multiple collapse-tags collapse-tags-tooltip filterable placeholder="请选择字段" @change="indexChanges(scope.row)" style="width: 100%">
 | 
				
			||||||
                                        v-if="item.prop === 'columnNames'"
 | 
					 | 
				
			||||||
                                        v-model="scope.row.columnNames"
 | 
					 | 
				
			||||||
                                        multiple
 | 
					 | 
				
			||||||
                                        collapse-tags
 | 
					 | 
				
			||||||
                                        collapse-tags-tooltip
 | 
					 | 
				
			||||||
                                        filterable
 | 
					 | 
				
			||||||
                                        placeholder="请选择字段"
 | 
					 | 
				
			||||||
                                        @change="indexChanges(scope.row)"
 | 
					 | 
				
			||||||
                                        style="width: 100%"
 | 
					 | 
				
			||||||
                                    >
 | 
					 | 
				
			||||||
                                        <el-option v-for="cl in tableData.indexs.columns" :key="cl.name" :label="cl.name" :value="cl.name">
 | 
					                                        <el-option v-for="cl in tableData.indexs.columns" :key="cl.name" :label="cl.name" :value="cl.name">
 | 
				
			||||||
                                            {{ cl.name + ' - ' + (cl.remark || '') }}
 | 
					                                            {{ cl.name + ' - ' + (cl.remark || '') }}
 | 
				
			||||||
                                        </el-option>
 | 
					                                        </el-option>
 | 
				
			||||||
                                    </el-select>
 | 
					                                    </el-select>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                    <el-checkbox v-if="item.prop === 'unique'" size="small" v-model="scope.row.unique" @change="indexChanges(scope.row)">
 | 
					                                    <el-checkbox v-if="item.prop === 'unique'" size="small" v-model="scope.row.unique" @change="indexChanges(scope.row)"> </el-checkbox>
 | 
				
			||||||
                                    </el-checkbox>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                    <el-select v-if="item.prop === 'indexType'" filterable size="small" v-model="scope.row.indexType">
 | 
					                                    <el-select v-if="item.prop === 'indexType'" filterable size="small" v-model="scope.row.indexType">
 | 
				
			||||||
                                        <el-option v-for="typeValue in indexTypeList" :key="typeValue" :value="typeValue">{{ typeValue }}</el-option>
 | 
					                                        <el-option v-for="typeValue in indexTypeList" :key="typeValue" :value="typeValue">{{ typeValue }}</el-option>
 | 
				
			||||||
@@ -106,15 +72,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                                    <el-input v-if="item.prop === 'indexComment'" size="small" v-model="scope.row.indexComment"> </el-input>
 | 
					                                    <el-input v-if="item.prop === 'indexComment'" size="small" v-model="scope.row.indexComment"> </el-input>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                    <el-link
 | 
					                                    <el-link v-if="item.prop === 'action'" type="danger" plain size="small" :underline="false" @click.prevent="deleteIndex(scope.$index)">删除</el-link>
 | 
				
			||||||
                                        v-if="item.prop === 'action'"
 | 
					 | 
				
			||||||
                                        type="danger"
 | 
					 | 
				
			||||||
                                        plain
 | 
					 | 
				
			||||||
                                        size="small"
 | 
					 | 
				
			||||||
                                        :underline="false"
 | 
					 | 
				
			||||||
                                        @click.prevent="deleteIndex(scope.$index)"
 | 
					 | 
				
			||||||
                                        >删除</el-link
 | 
					 | 
				
			||||||
                                    >
 | 
					 | 
				
			||||||
                                </template>
 | 
					                                </template>
 | 
				
			||||||
                            </el-table-column>
 | 
					                            </el-table-column>
 | 
				
			||||||
                        </el-table>
 | 
					                        </el-table>
 | 
				
			||||||
@@ -133,10 +91,11 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { watch, toRefs, reactive, ref } from 'vue';
 | 
					import { reactive, ref, toRefs, watch } from 'vue';
 | 
				
			||||||
import { TYPE_LIST, CHARACTER_SET_NAME_LIST, COLLATION_SUFFIX_LIST } from './service';
 | 
					import { getDbOption } from './service';
 | 
				
			||||||
import { ElMessage } from 'element-plus';
 | 
					import { ElMessage } from 'element-plus';
 | 
				
			||||||
import SqlExecBox from '../sqleditor/SqlExecBox';
 | 
					import SqlExecBox from '../sqleditor/SqlExecBox';
 | 
				
			||||||
 | 
					import { DbType } from '@/views/ops/db/component/table/dbs/db-option';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const props = defineProps({
 | 
					const props = defineProps({
 | 
				
			||||||
    visible: {
 | 
					    visible: {
 | 
				
			||||||
@@ -154,20 +113,23 @@ const props = defineProps({
 | 
				
			|||||||
    db: {
 | 
					    db: {
 | 
				
			||||||
        type: String,
 | 
					        type: String,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    dbType: {
 | 
				
			||||||
 | 
					        type: String,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//定义事件
 | 
					//定义事件
 | 
				
			||||||
const emit = defineEmits(['update:visible', 'cancel', 'val-change', 'submit-sql']);
 | 
					const emit = defineEmits(['update:visible', 'cancel', 'val-change', 'submit-sql']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const dbOption = getDbOption(props.dbType);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const formRef: any = ref();
 | 
					const formRef: any = ref();
 | 
				
			||||||
const state = reactive({
 | 
					const state = reactive({
 | 
				
			||||||
    dialogVisible: false,
 | 
					    dialogVisible: false,
 | 
				
			||||||
    btnloading: false,
 | 
					    btnloading: false,
 | 
				
			||||||
    activeName: '1',
 | 
					    activeName: '1',
 | 
				
			||||||
    columnTypeList: TYPE_LIST,
 | 
					    columnTypeList: dbOption.getTypeList(),
 | 
				
			||||||
    indexTypeList: ['BTREE'], // mysql索引类型详解 http://c.biancheng.net/view/7897.html
 | 
					    indexTypeList: ['BTREE'], // mysql索引类型详解 http://c.biancheng.net/view/7897.html
 | 
				
			||||||
    characterSetNameList: CHARACTER_SET_NAME_LIST,
 | 
					 | 
				
			||||||
    collationNameList: COLLATION_SUFFIX_LIST,
 | 
					 | 
				
			||||||
    tableData: {
 | 
					    tableData: {
 | 
				
			||||||
        fields: {
 | 
					        fields: {
 | 
				
			||||||
            colNames: [
 | 
					            colNames: [
 | 
				
			||||||
@@ -183,6 +145,10 @@ const state = reactive({
 | 
				
			|||||||
                    prop: 'length',
 | 
					                    prop: 'length',
 | 
				
			||||||
                    label: '长度',
 | 
					                    label: '长度',
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    prop: 'numScale',
 | 
				
			||||||
 | 
					                    label: '小数点',
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    prop: 'value',
 | 
					                    prop: 'value',
 | 
				
			||||||
                    label: '默认值',
 | 
					                    label: '默认值',
 | 
				
			||||||
@@ -209,18 +175,17 @@ const state = reactive({
 | 
				
			|||||||
                    label: '操作',
 | 
					                    label: '操作',
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            res: [
 | 
					            res: [] as {
 | 
				
			||||||
                {
 | 
					                name: string;
 | 
				
			||||||
                    name: '',
 | 
					                type: string;
 | 
				
			||||||
                    type: '',
 | 
					                value: string;
 | 
				
			||||||
                    value: '',
 | 
					                length: string;
 | 
				
			||||||
                    length: '',
 | 
					                numScale: string;
 | 
				
			||||||
                    notNull: false,
 | 
					                notNull: boolean;
 | 
				
			||||||
                    pri: false,
 | 
					                pri: boolean;
 | 
				
			||||||
                    auto_increment: false,
 | 
					                auto_increment: boolean;
 | 
				
			||||||
                    remark: '',
 | 
					                remark: string;
 | 
				
			||||||
                },
 | 
					            }[],
 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        indexs: {
 | 
					        indexs: {
 | 
				
			||||||
            colNames: [
 | 
					            colNames: [
 | 
				
			||||||
@@ -250,25 +215,21 @@ const state = reactive({
 | 
				
			|||||||
                },
 | 
					                },
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            columns: [{ name: '', remark: '' }],
 | 
					            columns: [{ name: '', remark: '' }],
 | 
				
			||||||
            res: [
 | 
					            res: [] as {
 | 
				
			||||||
                {
 | 
					                indexName: string;
 | 
				
			||||||
                    indexName: '',
 | 
					                columnNames: string[];
 | 
				
			||||||
                    columnNames: [],
 | 
					                unique: boolean;
 | 
				
			||||||
                    unique: false,
 | 
					                indexType: 'BTREE';
 | 
				
			||||||
                    indexType: 'BTREE',
 | 
					                indexComment: string;
 | 
				
			||||||
                    indexComment: '',
 | 
					            }[],
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        characterSet: 'utf8mb4',
 | 
					 | 
				
			||||||
        collation: 'utf8mb4_general_ci',
 | 
					 | 
				
			||||||
        tableName: '',
 | 
					        tableName: '',
 | 
				
			||||||
        tableComment: '',
 | 
					        tableComment: '',
 | 
				
			||||||
        height: 550,
 | 
					        height: 550,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { dialogVisible, btnloading, activeName, columnTypeList, indexTypeList, characterSetNameList, collationNameList, tableData } = toRefs(state);
 | 
					const { dialogVisible, btnloading, activeName, indexTypeList, tableData } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(props, async (newValue) => {
 | 
					watch(props, async (newValue) => {
 | 
				
			||||||
    state.dialogVisible = newValue.visible;
 | 
					    state.dialogVisible = newValue.visible;
 | 
				
			||||||
@@ -285,6 +246,7 @@ const addRow = () => {
 | 
				
			|||||||
        type: '',
 | 
					        type: '',
 | 
				
			||||||
        value: '',
 | 
					        value: '',
 | 
				
			||||||
        length: '',
 | 
					        length: '',
 | 
				
			||||||
 | 
					        numScale: '',
 | 
				
			||||||
        notNull: false,
 | 
					        notNull: false,
 | 
				
			||||||
        pri: false,
 | 
					        pri: false,
 | 
				
			||||||
        auto_increment: false,
 | 
					        auto_increment: false,
 | 
				
			||||||
@@ -303,15 +265,27 @@ const addIndex = () => {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const addDefaultRows = () => {
 | 
					const addDefaultRows = () => {
 | 
				
			||||||
 | 
					    if (props.dbType === DbType.mysql) {
 | 
				
			||||||
        state.tableData.fields.res.push(
 | 
					        state.tableData.fields.res.push(
 | 
				
			||||||
        { name: 'id', type: 'bigint', length: '20', value: '', notNull: true, pri: true, auto_increment: true, remark: '主键ID' },
 | 
					            { name: 'id', type: 'bigint', length: '20', numScale: '', value: '', notNull: true, pri: true, auto_increment: true, remark: '主键ID' },
 | 
				
			||||||
        { name: 'creator_id', type: 'bigint', length: '20', value: '', notNull: true, pri: false, auto_increment: false, 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', value: '', notNull: true, pri: false, auto_increment: false, remark: '创建人姓名' },
 | 
					            { name: 'creator', type: 'varchar', length: '100', numScale: '', value: '', notNull: true, pri: false, auto_increment: false, remark: '创建人姓名' },
 | 
				
			||||||
        { name: 'create_time', type: 'datetime', length: '', value: 'CURRENT_TIMESTAMP', 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', value: '', notNull: true, pri: false, auto_increment: false, remark: '修改人id' },
 | 
					            { name: 'updator_id', type: 'bigint', length: '20', numScale: '', value: '', notNull: true, pri: false, auto_increment: false, remark: '修改人id' },
 | 
				
			||||||
        { name: 'updator', type: 'varchar', length: '100', value: '', notNull: true, pri: false, auto_increment: false, remark: '修改人姓名' },
 | 
					            { name: 'updator', type: 'varchar', length: '100', numScale: '', value: '', notNull: true, pri: false, auto_increment: false, remark: '修改人姓名' },
 | 
				
			||||||
        { name: 'update_time', type: 'datetime', length: '', value: 'CURRENT_TIMESTAMP', 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: '修改时间' }
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					    } else if (props.dbType === DbType.postgresql) {
 | 
				
			||||||
 | 
					        state.tableData.fields.res.push(
 | 
				
			||||||
 | 
					            { name: 'id', type: 'bigserial', length: '', numScale: '', value: '', notNull: true, pri: true, auto_increment: true, remark: '主键ID' },
 | 
				
			||||||
 | 
					            { name: 'creator_id', type: 'int8', length: '', 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: 'timestamp', length: '', numScale: '', value: 'CURRENT_TIMESTAMP', notNull: true, pri: false, auto_increment: false, remark: '创建时间' },
 | 
				
			||||||
 | 
					            { name: 'updator_id', type: 'int8', length: '', 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: 'timestamp', length: '', numScale: '', value: 'CURRENT_TIMESTAMP', notNull: true, pri: false, auto_increment: false, remark: '修改时间' }
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const deleteRow = (index: any) => {
 | 
					const deleteRow = (index: any) => {
 | 
				
			||||||
@@ -399,129 +373,24 @@ const filterChangedData = (oldArr: object[], nowArr: object[], key: string): { d
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const genSql = () => {
 | 
					const genSql = () => {
 | 
				
			||||||
    const genColumnBasicSql = (cl: any) => {
 | 
					 | 
				
			||||||
        let val = cl.value ? (cl.value === 'CURRENT_TIMESTAMP' ? cl.value : "'" + cl.value + "'") : '';
 | 
					 | 
				
			||||||
        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'} ${
 | 
					 | 
				
			||||||
            cl.auto_increment ? 'AUTO_INCREMENT' : ''
 | 
					 | 
				
			||||||
        } ${defVal} ${onUpdate} comment '${cl.remark || ''}' `;
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let data = state.tableData;
 | 
					    let data = state.tableData;
 | 
				
			||||||
    // 创建表
 | 
					    // 创建表
 | 
				
			||||||
    if (!props.data?.edit) {
 | 
					    if (!props.data?.edit) {
 | 
				
			||||||
        if (state.activeName === '1') {
 | 
					        if (state.activeName === '1') {
 | 
				
			||||||
            // 创建表结构
 | 
					            return dbOption.getCreateTableSql(data);
 | 
				
			||||||
            let primary_key = '';
 | 
					 | 
				
			||||||
            let fields: string[] = [];
 | 
					 | 
				
			||||||
            data.fields.res.forEach((item) => {
 | 
					 | 
				
			||||||
                item.name && fields.push(genColumnBasicSql(item));
 | 
					 | 
				
			||||||
                if (item.pri) {
 | 
					 | 
				
			||||||
                    primary_key += `${item.name},`;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return `CREATE TABLE ${data.tableName}
 | 
					 | 
				
			||||||
                  ( ${fields.join(',')}
 | 
					 | 
				
			||||||
                      ${primary_key ? `, PRIMARY KEY (${primary_key.slice(0, -1)})` : ''}
 | 
					 | 
				
			||||||
                  ) ENGINE=InnoDB DEFAULT CHARSET=${data.characterSet} COLLATE =${data.collation} COMMENT='${data.tableComment}';`;
 | 
					 | 
				
			||||||
        } else if (state.activeName === '2' && data.indexs.res.length > 0) {
 | 
					        } else if (state.activeName === '2' && data.indexs.res.length > 0) {
 | 
				
			||||||
            // 创建索引
 | 
					            return dbOption.getCreateIndexSql(data);
 | 
				
			||||||
            let sql = `ALTER TABLE ${data.tableName}`;
 | 
					 | 
				
			||||||
            state.tableData.indexs.res.forEach((a) => {
 | 
					 | 
				
			||||||
                sql += ` ADD ${a.unique ? 'UNIQUE' : ''} INDEX ${a.indexName}(${a.columnNames.join(',')}) USING ${a.indexType} COMMENT '${a.indexComment}',`;
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
            return sql.substring(0, sql.length - 1) + ';';
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        // 修改
 | 
					        // 修改
 | 
				
			||||||
        let addSql = '',
 | 
					 | 
				
			||||||
            updSql = '',
 | 
					 | 
				
			||||||
            delSql = '';
 | 
					 | 
				
			||||||
        if (state.activeName === '1') {
 | 
					        if (state.activeName === '1') {
 | 
				
			||||||
            // 修改列
 | 
					            // 修改列
 | 
				
			||||||
            let changeData = filterChangedData(oldData.fields, state.tableData.fields.res, 'name');
 | 
					            let changeData = filterChangedData(oldData.fields, state.tableData.fields.res, 'name');
 | 
				
			||||||
            if (changeData.add.length > 0) {
 | 
					            return dbOption.getModifyColumnSql(data.tableName, changeData);
 | 
				
			||||||
                addSql = `ALTER TABLE ${data.tableName}`;
 | 
					 | 
				
			||||||
                changeData.add.forEach((a) => {
 | 
					 | 
				
			||||||
                    addSql += ` ADD ${genColumnBasicSql(a)},`;
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
                addSql = addSql.substring(0, addSql.length - 1);
 | 
					 | 
				
			||||||
                addSql += ';';
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (changeData.upd.length > 0) {
 | 
					 | 
				
			||||||
                updSql = `ALTER TABLE ${data.tableName}`;
 | 
					 | 
				
			||||||
                changeData.upd.forEach((a) => {
 | 
					 | 
				
			||||||
                    updSql += ` MODIFY ${genColumnBasicSql(a)},`;
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
                updSql = updSql.substring(0, updSql.length - 1);
 | 
					 | 
				
			||||||
                updSql += ';';
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (changeData.del.length > 0) {
 | 
					 | 
				
			||||||
                changeData.del.forEach((a) => {
 | 
					 | 
				
			||||||
                    delSql += ` ALTER TABLE ${data.tableName} DROP COLUMN ${a.name}; `;
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return addSql + updSql + delSql;
 | 
					 | 
				
			||||||
        } else if (state.activeName === '2') {
 | 
					        } else if (state.activeName === '2') {
 | 
				
			||||||
            // 修改索引
 | 
					            // 修改索引
 | 
				
			||||||
            let changeData = filterChangedData(oldData.indexs, state.tableData.indexs.res, 'indexName');
 | 
					            let changeData = filterChangedData(oldData.indexs, state.tableData.indexs.res, 'indexName');
 | 
				
			||||||
            // 搜集修改和删除的索引,添加到drop index xx
 | 
					            return dbOption.getModifyIndexSql(data.tableName, changeData);
 | 
				
			||||||
            // 收集新增和修改的索引,添加到ADD xx
 | 
					 | 
				
			||||||
            // ALTER TABLE `test1`
 | 
					 | 
				
			||||||
            // DROP INDEX `test1_name_uindex`,
 | 
					 | 
				
			||||||
            // DROP INDEX `test1_column_name4_index`,
 | 
					 | 
				
			||||||
            // ADD UNIQUE INDEX `test1_name_uindex`(`id`) USING BTREE COMMENT 'ASDASD',
 | 
					 | 
				
			||||||
            // ADD INDEX `111`(`column_name4`) USING BTREE COMMENT 'zasf';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            let dropIndexNames: string[] = [];
 | 
					 | 
				
			||||||
            let addIndexs: any[] = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (changeData.upd.length > 0) {
 | 
					 | 
				
			||||||
                changeData.upd.forEach((a) => {
 | 
					 | 
				
			||||||
                    dropIndexNames.push(a.indexName);
 | 
					 | 
				
			||||||
                    addIndexs.push(a);
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (changeData.del.length > 0) {
 | 
					 | 
				
			||||||
                changeData.del.forEach((a) => {
 | 
					 | 
				
			||||||
                    dropIndexNames.push(a.indexName);
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (changeData.add.length > 0) {
 | 
					 | 
				
			||||||
                changeData.add.forEach((a) => {
 | 
					 | 
				
			||||||
                    addIndexs.push(a);
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (dropIndexNames.length > 0 || addIndexs.length > 0) {
 | 
					 | 
				
			||||||
                let sql = `ALTER TABLE ${data.tableName} `;
 | 
					 | 
				
			||||||
                if (dropIndexNames.length > 0) {
 | 
					 | 
				
			||||||
                    dropIndexNames.forEach((a) => {
 | 
					 | 
				
			||||||
                        sql += `DROP INDEX ${a},`;
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
                    sql = sql.substring(0, sql.length - 1);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (addIndexs.length > 0) {
 | 
					 | 
				
			||||||
                    if (dropIndexNames.length > 0) {
 | 
					 | 
				
			||||||
                        sql += ',';
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    addIndexs.forEach((a) => {
 | 
					 | 
				
			||||||
                        sql += ` ADD ${a.unique ? 'UNIQUE' : ''} INDEX ${a.indexName}(${a.columnNames.join(',')}) USING ${a.indexType} COMMENT '${
 | 
					 | 
				
			||||||
                            a.indexComment
 | 
					 | 
				
			||||||
                        }',`;
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
                    sql = sql.substring(0, sql.length - 1);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                return sql;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -537,6 +406,7 @@ const reset = () => {
 | 
				
			|||||||
            type: '',
 | 
					            type: '',
 | 
				
			||||||
            value: '',
 | 
					            value: '',
 | 
				
			||||||
            length: '',
 | 
					            length: '',
 | 
				
			||||||
 | 
					            numScale: '',
 | 
				
			||||||
            notNull: false,
 | 
					            notNull: false,
 | 
				
			||||||
            pri: false,
 | 
					            pri: false,
 | 
				
			||||||
            auto_increment: false,
 | 
					            auto_increment: false,
 | 
				
			||||||
@@ -568,7 +438,7 @@ const indexChanges = (row: any) => {
 | 
				
			|||||||
    let suffix = row.unique ? 'udx' : 'idx';
 | 
					    let suffix = row.unique ? 'udx' : 'idx';
 | 
				
			||||||
    let commentSuffix = row.unique ? '唯一索引' : '普通索引';
 | 
					    let commentSuffix = row.unique ? '唯一索引' : '普通索引';
 | 
				
			||||||
    // 以表名为前缀
 | 
					    // 以表名为前缀
 | 
				
			||||||
    row.indexName = `${tableData.value.tableName}-${name}-${suffix}`;
 | 
					    row.indexName = `${tableData.value.tableName}_${name}_${suffix}`.replaceAll(' ', '');
 | 
				
			||||||
    row.indexComment = `${tableData.value.tableName}表(${name.replaceAll('_', ',')})${commentSuffix}`;
 | 
					    row.indexComment = `${tableData.value.tableName}表(${name.replaceAll('_', ',')})${commentSuffix}`;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -595,6 +465,7 @@ watch(
 | 
				
			|||||||
                    type,
 | 
					                    type,
 | 
				
			||||||
                    value: a.columnDefault || '',
 | 
					                    value: a.columnDefault || '',
 | 
				
			||||||
                    length,
 | 
					                    length,
 | 
				
			||||||
 | 
					                    numScale: a.numScale,
 | 
				
			||||||
                    notNull: a.nullable !== 'YES',
 | 
					                    notNull: a.nullable !== 'YES',
 | 
				
			||||||
                    pri: a.columnKey === 'PRI',
 | 
					                    pri: a.columnKey === 'PRI',
 | 
				
			||||||
                    auto_increment: a.columnKey === 'PRI' /*a.extra?.indexOf('auto_increment') > -1*/,
 | 
					                    auto_increment: a.columnKey === 'PRI' /*a.extra?.indexOf('auto_increment') > -1*/,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,36 +41,23 @@
 | 
				
			|||||||
                    <el-input v-model="tableCommentSearch" size="small" placeholder="备注: 输入可过滤" clearable />
 | 
					                    <el-input v-model="tableCommentSearch" size="small" placeholder="备注: 输入可过滤" clearable />
 | 
				
			||||||
                </template>
 | 
					                </template>
 | 
				
			||||||
            </el-table-column>
 | 
					            </el-table-column>
 | 
				
			||||||
            <el-table-column
 | 
					            <el-table-column prop="tableRows" label="Rows" min-width="70" sortable :sort-method="(a: any, b: any) => parseInt(a.tableRows) - parseInt(b.tableRows)"></el-table-column>
 | 
				
			||||||
                prop="tableRows"
 | 
					 | 
				
			||||||
                label="Rows"
 | 
					 | 
				
			||||||
                min-width="70"
 | 
					 | 
				
			||||||
                sortable
 | 
					 | 
				
			||||||
                :sort-method="(a: any, b: any) => parseInt(a.tableRows) - parseInt(b.tableRows)"
 | 
					 | 
				
			||||||
            ></el-table-column>
 | 
					 | 
				
			||||||
            <el-table-column property="dataLength" label="数据大小" sortable :sort-method="(a: any, b: any) => parseInt(a.dataLength) - parseInt(b.dataLength)">
 | 
					            <el-table-column property="dataLength" label="数据大小" sortable :sort-method="(a: any, b: any) => parseInt(a.dataLength) - parseInt(b.dataLength)">
 | 
				
			||||||
                <template #default="scope">
 | 
					                <template #default="scope">
 | 
				
			||||||
                    {{ formatByteSize(scope.row.dataLength) }}
 | 
					                    {{ formatByteSize(scope.row.dataLength) }}
 | 
				
			||||||
                </template>
 | 
					                </template>
 | 
				
			||||||
            </el-table-column>
 | 
					            </el-table-column>
 | 
				
			||||||
            <el-table-column
 | 
					            <el-table-column property="indexLength" label="索引大小" sortable :sort-method="(a: any, b: any) => parseInt(a.indexLength) - parseInt(b.indexLength)">
 | 
				
			||||||
                property="indexLength"
 | 
					 | 
				
			||||||
                label="索引大小"
 | 
					 | 
				
			||||||
                sortable
 | 
					 | 
				
			||||||
                :sort-method="(a: any, b: any) => parseInt(a.indexLength) - parseInt(b.indexLength)"
 | 
					 | 
				
			||||||
            >
 | 
					 | 
				
			||||||
                <template #default="scope">
 | 
					                <template #default="scope">
 | 
				
			||||||
                    {{ formatByteSize(scope.row.indexLength) }}
 | 
					                    {{ formatByteSize(scope.row.indexLength) }}
 | 
				
			||||||
                </template>
 | 
					                </template>
 | 
				
			||||||
            </el-table-column>
 | 
					            </el-table-column>
 | 
				
			||||||
            <el-table-column property="createTime" label="创建时间" min-width="150"> </el-table-column>
 | 
					            <el-table-column v-if="dbType===DbType.mysql" property="createTime" label="创建时间" min-width="150"> </el-table-column>
 | 
				
			||||||
            <el-table-column label="更多信息" min-width="160">
 | 
					            <el-table-column label="更多信息" min-width="160">
 | 
				
			||||||
                <template #default="scope">
 | 
					                <template #default="scope">
 | 
				
			||||||
                    <el-link @click.prevent="showColumns(scope.row)" type="primary">字段</el-link>
 | 
					                    <el-link @click.prevent="showColumns(scope.row)" type="primary">字段</el-link>
 | 
				
			||||||
                    <el-link class="ml5" @click.prevent="showTableIndex(scope.row)" type="success">索引</el-link>
 | 
					                    <el-link class="ml5" @click.prevent="showTableIndex(scope.row)" type="success">索引</el-link>
 | 
				
			||||||
                    <el-link class="ml5" v-if="tableCreateDialog.enableEditTypes.indexOf(dbType) > -1" @click.prevent="openEditTable(scope.row)" type="warning"
 | 
					                    <el-link class="ml5" v-if="tableCreateDialog.enableEditTypes.indexOf(dbType) > -1" @click.prevent="openEditTable(scope.row)" type="warning">编辑表</el-link>
 | 
				
			||||||
                        >编辑表</el-link
 | 
					 | 
				
			||||||
                    >
 | 
					 | 
				
			||||||
                    <el-link class="ml5" @click.prevent="showCreateDdl(scope.row)" type="info">DDL</el-link>
 | 
					                    <el-link class="ml5" @click.prevent="showCreateDdl(scope.row)" type="info">DDL</el-link>
 | 
				
			||||||
                </template>
 | 
					                </template>
 | 
				
			||||||
            </el-table-column>
 | 
					            </el-table-column>
 | 
				
			||||||
@@ -104,21 +91,12 @@
 | 
				
			|||||||
            <el-input disabled type="textarea" :autosize="{ minRows: 15, maxRows: 30 }" v-model="ddlDialog.ddl" size="small"> </el-input>
 | 
					            <el-input disabled type="textarea" :autosize="{ minRows: 15, maxRows: 30 }" v-model="ddlDialog.ddl" size="small"> </el-input>
 | 
				
			||||||
        </el-dialog>
 | 
					        </el-dialog>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <db-table-op
 | 
					        <db-table-op :title="tableCreateDialog.title" :active-name="tableCreateDialog.activeName" :dbId="dbId" :db="db" :dbType="dbType" :data="tableCreateDialog.data" v-model:visible="tableCreateDialog.visible" @submit-sql="onSubmitSql"> </db-table-op>
 | 
				
			||||||
            :title="tableCreateDialog.title"
 | 
					 | 
				
			||||||
            :active-name="tableCreateDialog.activeName"
 | 
					 | 
				
			||||||
            :dbId="dbId"
 | 
					 | 
				
			||||||
            :db="db"
 | 
					 | 
				
			||||||
            :data="tableCreateDialog.data"
 | 
					 | 
				
			||||||
            v-model:visible="tableCreateDialog.visible"
 | 
					 | 
				
			||||||
            @submit-sql="onSubmitSql"
 | 
					 | 
				
			||||||
        >
 | 
					 | 
				
			||||||
        </db-table-op>
 | 
					 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { toRefs, reactive, watch, computed, onMounted, defineAsyncComponent } from 'vue';
 | 
					import { computed, defineAsyncComponent, onMounted, reactive, toRefs, watch } from 'vue';
 | 
				
			||||||
import { ElMessageBox } from 'element-plus';
 | 
					import { ElMessageBox } from 'element-plus';
 | 
				
			||||||
import { formatByteSize } from '@/common/utils/format';
 | 
					import { formatByteSize } from '@/common/utils/format';
 | 
				
			||||||
import { dbApi } from '@/views/ops/db/api';
 | 
					import { dbApi } from '@/views/ops/db/api';
 | 
				
			||||||
@@ -126,6 +104,7 @@ import SqlExecBox from '../sqleditor/SqlExecBox';
 | 
				
			|||||||
import config from '@/common/config';
 | 
					import config from '@/common/config';
 | 
				
			||||||
import { joinClientParams } from '@/common/request';
 | 
					import { joinClientParams } from '@/common/request';
 | 
				
			||||||
import { isTrue } from '@/common/assert';
 | 
					import { isTrue } from '@/common/assert';
 | 
				
			||||||
 | 
					import { DbType } from '@/views/ops/db/component/table/dbs/db-option';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const DbTableOp = defineAsyncComponent(() => import('./DbTableOp.vue'));
 | 
					const DbTableOp = defineAsyncComponent(() => import('./DbTableOp.vue'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -179,7 +158,7 @@ const state = reactive({
 | 
				
			|||||||
        visible: false,
 | 
					        visible: false,
 | 
				
			||||||
        activeName: '1',
 | 
					        activeName: '1',
 | 
				
			||||||
        type: '',
 | 
					        type: '',
 | 
				
			||||||
        enableEditTypes: ['mysql'], // 支持"编辑表"的数据库类型
 | 
					        enableEditTypes: [DbType.mysql, DbType.postgresql], // 支持"编辑表"的数据库类型
 | 
				
			||||||
        data: {
 | 
					        data: {
 | 
				
			||||||
            // 修改表时,传递修改数据
 | 
					            // 修改表时,传递修改数据
 | 
				
			||||||
            edit: false,
 | 
					            edit: false,
 | 
				
			||||||
@@ -195,19 +174,7 @@ const state = reactive({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const {
 | 
					const { loading, tables, tableNameSearch, tableCommentSearch, showDumpInfo, dumpInfo, chooseTableName, columnDialog, indexDialog, ddlDialog, tableCreateDialog } = toRefs(state);
 | 
				
			||||||
    loading,
 | 
					 | 
				
			||||||
    tables,
 | 
					 | 
				
			||||||
    tableNameSearch,
 | 
					 | 
				
			||||||
    tableCommentSearch,
 | 
					 | 
				
			||||||
    showDumpInfo,
 | 
					 | 
				
			||||||
    dumpInfo,
 | 
					 | 
				
			||||||
    chooseTableName,
 | 
					 | 
				
			||||||
    columnDialog,
 | 
					 | 
				
			||||||
    indexDialog,
 | 
					 | 
				
			||||||
    ddlDialog,
 | 
					 | 
				
			||||||
    tableCreateDialog,
 | 
					 | 
				
			||||||
} = toRefs(state);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
onMounted(async () => {
 | 
					onMounted(async () => {
 | 
				
			||||||
    getTables();
 | 
					    getTables();
 | 
				
			||||||
@@ -262,10 +229,7 @@ const handleDumpTableSelectionChange = (vals: any) => {
 | 
				
			|||||||
const dump = (db: string) => {
 | 
					const dump = (db: string) => {
 | 
				
			||||||
    isTrue(state.dumpInfo.tables.length > 0, '请选择要导出的表');
 | 
					    isTrue(state.dumpInfo.tables.length > 0, '请选择要导出的表');
 | 
				
			||||||
    const a = document.createElement('a');
 | 
					    const a = document.createElement('a');
 | 
				
			||||||
    a.setAttribute(
 | 
					    a.setAttribute('href', `${config.baseApiUrl}/dbs/${props.dbId}/dump?db=${db}&type=${state.dumpInfo.type}&tables=${state.dumpInfo.tables.join(',')}&${joinClientParams()}`);
 | 
				
			||||||
        'href',
 | 
					 | 
				
			||||||
        `${config.baseApiUrl}/dbs/${props.dbId}/dump?db=${db}&type=${state.dumpInfo.type}&tables=${state.dumpInfo.tables.join(',')}&${joinClientParams()}`
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
    a.click();
 | 
					    a.click();
 | 
				
			||||||
    state.showDumpInfo = false;
 | 
					    state.showDumpInfo = false;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					export interface sqlType {
 | 
				
			||||||
 | 
					    udtName: string;
 | 
				
			||||||
 | 
					    dataType: string;
 | 
				
			||||||
 | 
					    desc: string;
 | 
				
			||||||
 | 
					    space: string;
 | 
				
			||||||
 | 
					    range?: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface DbOption {
 | 
				
			||||||
 | 
					    /** 生成字段类型列表 */
 | 
				
			||||||
 | 
					    getTypeList(): sqlType[];
 | 
				
			||||||
 | 
					    /** 生成创建表sql */
 | 
				
			||||||
 | 
					    getCreateTableSql(tableData: any): string;
 | 
				
			||||||
 | 
					    /** 生成创建索引sql */
 | 
				
			||||||
 | 
					    getCreateIndexSql(tableData: any): string;
 | 
				
			||||||
 | 
					    /** 生成编辑列sql */
 | 
				
			||||||
 | 
					    getModifyColumnSql(tableName: string, changeData: { del: any[]; add: any[]; upd: any[] }): string;
 | 
				
			||||||
 | 
					    /** 生成编辑索引sql */
 | 
				
			||||||
 | 
					    getModifyIndexSql(tableName: string, changeData: { del: any[]; add: any[]; upd: any[] }): string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const DbType = {
 | 
				
			||||||
 | 
					    mysql: 'mysql',
 | 
				
			||||||
 | 
					    postgresql: 'postgres',
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -0,0 +1,126 @@
 | 
				
			|||||||
 | 
					import { DbOption, sqlType } from '@/views/ops/db/component/table/dbs/db-option';
 | 
				
			||||||
 | 
					import { MYSQL_TYPE_LIST } from '@/views/ops/db/component/table/service';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class MysqlOption implements DbOption {
 | 
				
			||||||
 | 
					    getTypeList(): sqlType[] {
 | 
				
			||||||
 | 
					        return MYSQL_TYPE_LIST.map((a) => ({ udtName: a, dataType: a, desc: '', space: '' }));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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 onUpdate = 'update_time' === cl.name ? ' ON UPDATE CURRENT_TIMESTAMP ' : '';
 | 
				
			||||||
 | 
					        return ` ${cl.name} ${cl.type}${length} ${cl.notNull ? 'NOT NULL' : 'NULL'} ${cl.auto_increment ? 'AUTO_INCREMENT' : ''} ${defVal} ${onUpdate} comment '${cl.remark || ''}' `;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    getCreateTableSql(data: any): string {
 | 
				
			||||||
 | 
					        // 创建表结构
 | 
				
			||||||
 | 
					        let pks = [] as string[];
 | 
				
			||||||
 | 
					        let fields: string[] = [];
 | 
				
			||||||
 | 
					        data.fields.res.forEach((item: any) => {
 | 
				
			||||||
 | 
					            item.name && fields.push(this.genColumnBasicSql(item));
 | 
				
			||||||
 | 
					            if (item.pri) {
 | 
				
			||||||
 | 
					                pks.push(item.name);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return `CREATE TABLE ${data.tableName}
 | 
				
			||||||
 | 
					                  ( ${fields.join(',')}
 | 
				
			||||||
 | 
					                      ${pks ? `, PRIMARY KEY (${pks.join(',')})` : ''}
 | 
				
			||||||
 | 
					                  ) COMMENT='${data.tableComment}';`;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getCreateIndexSql(data: any): string {
 | 
				
			||||||
 | 
					        // 创建索引
 | 
				
			||||||
 | 
					        let sql = `ALTER TABLE ${data.tableName}`;
 | 
				
			||||||
 | 
					        data.indexs.res.forEach((a: any) => {
 | 
				
			||||||
 | 
					            sql += ` ADD ${a.unique ? 'UNIQUE' : ''} INDEX ${a.indexName}(${a.columnNames.join(',')}) USING ${a.indexType} COMMENT '${a.indexComment}',`;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        return sql.substring(0, sql.length - 1) + ';';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getModifyColumnSql(tableName: string, changeData: { del: any[]; add: any[]; upd: any[] }): string {
 | 
				
			||||||
 | 
					        let addSql = '',
 | 
				
			||||||
 | 
					            updSql = '',
 | 
				
			||||||
 | 
					            delSql = '';
 | 
				
			||||||
 | 
					        if (changeData.add.length > 0) {
 | 
				
			||||||
 | 
					            addSql = `ALTER TABLE ${tableName}`;
 | 
				
			||||||
 | 
					            changeData.add.forEach((a) => {
 | 
				
			||||||
 | 
					                addSql += ` ADD ${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)}`);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getModifyIndexSql(tableName: string, changeData: { del: any[]; add: any[]; upd: any[] }): string {
 | 
				
			||||||
 | 
					        // 搜集修改和删除的索引,添加到drop index xx
 | 
				
			||||||
 | 
					        // 收集新增和修改的索引,添加到ADD xx
 | 
				
			||||||
 | 
					        // ALTER TABLE `test1`
 | 
				
			||||||
 | 
					        // DROP INDEX `test1_name_uindex`,
 | 
				
			||||||
 | 
					        // DROP INDEX `test1_column_name4_index`,
 | 
				
			||||||
 | 
					        // ADD UNIQUE INDEX `test1_name_uindex`(`id`) USING BTREE COMMENT 'ASDASD',
 | 
				
			||||||
 | 
					        // ADD INDEX `111`(`column_name4`) USING BTREE COMMENT 'zasf';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let dropIndexNames: string[] = [];
 | 
				
			||||||
 | 
					        let addIndexs: any[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (changeData.upd.length > 0) {
 | 
				
			||||||
 | 
					            changeData.upd.forEach((a) => {
 | 
				
			||||||
 | 
					                dropIndexNames.push(a.indexName);
 | 
				
			||||||
 | 
					                addIndexs.push(a);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (changeData.del.length > 0) {
 | 
				
			||||||
 | 
					            changeData.del.forEach((a) => {
 | 
				
			||||||
 | 
					                dropIndexNames.push(a.indexName);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (changeData.add.length > 0) {
 | 
				
			||||||
 | 
					            changeData.add.forEach((a) => {
 | 
				
			||||||
 | 
					                addIndexs.push(a);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (dropIndexNames.length > 0 || addIndexs.length > 0) {
 | 
				
			||||||
 | 
					            let sql = `ALTER TABLE ${tableName} `;
 | 
				
			||||||
 | 
					            if (dropIndexNames.length > 0) {
 | 
				
			||||||
 | 
					                dropIndexNames.forEach((a) => {
 | 
				
			||||||
 | 
					                    sql += `DROP INDEX ${a},`;
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					                sql = sql.substring(0, sql.length - 1);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (addIndexs.length > 0) {
 | 
				
			||||||
 | 
					                if (dropIndexNames.length > 0) {
 | 
				
			||||||
 | 
					                    sql += ',';
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                addIndexs.forEach((a) => {
 | 
				
			||||||
 | 
					                    sql += ` ADD ${a.unique ? 'UNIQUE' : ''} INDEX ${a.indexName}(${a.columnNames.join(',')}) USING ${a.indexType} COMMENT '${a.indexComment}',`;
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					                sql = sql.substring(0, sql.length - 1);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return sql;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return '';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,177 @@
 | 
				
			|||||||
 | 
					import { DbOption, sqlType } from '@/views/ops/db/component/table/dbs/db-option';
 | 
				
			||||||
 | 
					import { GAUSS_TYPE_LIST } from '@/views/ops/db/component/table/service';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class PostgresqlOption implements DbOption {
 | 
				
			||||||
 | 
					    getTypeList(): sqlType[] {
 | 
				
			||||||
 | 
					        return GAUSS_TYPE_LIST.sort((a, b) => a.udtName.localeCompare(b.udtName));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    matchType(text: string, arr: string[]): boolean {
 | 
				
			||||||
 | 
					        if (!text || !arr || arr.length === 0) {
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        for (let i = 0; i < arr.length; i++) {
 | 
				
			||||||
 | 
					            if (text.indexOf(arr[i]) > -1) {
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getDefaultValueSql(cl: any): string {
 | 
				
			||||||
 | 
					        if (cl.value && cl.value.length > 0) {
 | 
				
			||||||
 | 
					            // 哪些字段默认值需要加引号
 | 
				
			||||||
 | 
					            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'])) {
 | 
				
			||||||
 | 
					                    marks = false;
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    marks = true;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return ` DEFAULT ${marks ? "'" : ''}${cl.value}${marks ? "'" : ''}`;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return '';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getTypeLengthSql(cl: any) {
 | 
				
			||||||
 | 
					        // 哪些字段可以指定长度
 | 
				
			||||||
 | 
					        if (cl.length && this.matchType(cl.type, ['char', 'time', 'bit', 'num', 'decimal'])) {
 | 
				
			||||||
 | 
					            // 哪些字段类型可以指定小数点
 | 
				
			||||||
 | 
					            if (cl.numScale && this.matchType(cl.type, ['num', 'decimal'])) {
 | 
				
			||||||
 | 
					                return `(${cl.length}, ${cl.numScale})`;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                return `(${cl.length})`;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return '';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    genColumnBasicSql(cl: any): string {
 | 
				
			||||||
 | 
					        let length = this.getTypeLengthSql(cl);
 | 
				
			||||||
 | 
					        // 默认值
 | 
				
			||||||
 | 
					        let defVal = this.getDefaultValueSql(cl);
 | 
				
			||||||
 | 
					        return ` ${cl.name} ${cl.type}${length} ${cl.notNull ? 'NOT NULL' : ''} ${defVal} `;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getCreateTableSql(data: any): string {
 | 
				
			||||||
 | 
					        let createSql = '';
 | 
				
			||||||
 | 
					        let tableCommentSql = '';
 | 
				
			||||||
 | 
					        let columCommentSql = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 创建表结构
 | 
				
			||||||
 | 
					        let pks = [] as string[];
 | 
				
			||||||
 | 
					        let fields: string[] = [];
 | 
				
			||||||
 | 
					        data.fields.res.forEach((item: any) => {
 | 
				
			||||||
 | 
					            item.name && fields.push(this.genColumnBasicSql(item));
 | 
				
			||||||
 | 
					            if (item.pri) {
 | 
				
			||||||
 | 
					                pks.push(item.name);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // 列注释
 | 
				
			||||||
 | 
					            if (item.remark) {
 | 
				
			||||||
 | 
					                columCommentSql += ` comment on column ${data.tableName}.${item.name} is '${item.remark}'; `;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        // 建表
 | 
				
			||||||
 | 
					        createSql = `CREATE TABLE ${data.tableName}
 | 
				
			||||||
 | 
					                     (
 | 
				
			||||||
 | 
					                         ${fields.join(',')}
 | 
				
			||||||
 | 
					                             ${pks ? `, PRIMARY KEY (${pks.join(',')})` : ''}
 | 
				
			||||||
 | 
					                     );`;
 | 
				
			||||||
 | 
					        // 表注释
 | 
				
			||||||
 | 
					        if (data.tableComment) {
 | 
				
			||||||
 | 
					            tableCommentSql = ` comment on table ${data.tableName} is '${data.tableComment}'; `;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return createSql + tableCommentSql + columCommentSql;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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 sql: string[] = [];
 | 
				
			||||||
 | 
					        tableData.indexs.res.forEach((a: any) => {
 | 
				
			||||||
 | 
					            sql.push(` CREATE ${a.unique ? 'UNIQUE' : ''} INDEX ${a.indexName} USING btree ("${a.columnNames.join('","')})"`);
 | 
				
			||||||
 | 
					            if (a.indexComment) {
 | 
				
			||||||
 | 
					                sql.push(`COMMENT ON INDEX ${a.indexName} IS '${a.indexComment}'`);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        return sql.join(';');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getModifyColumnSql(tableName: string, changeData: { del: any[]; add: any[]; upd: any[] }): string {
 | 
				
			||||||
 | 
					        let sql: string[] = [];
 | 
				
			||||||
 | 
					        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}`);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (changeData.upd.length > 0) {
 | 
				
			||||||
 | 
					            changeData.upd.forEach((a) => {
 | 
				
			||||||
 | 
					                let typeLength = this.getTypeLengthSql(a);
 | 
				
			||||||
 | 
					                sql.push(`ALTER TABLE ${tableName} alter column ${a.name} type ${a.type}${typeLength}`);
 | 
				
			||||||
 | 
					                let defaultSql = this.getDefaultValueSql(a);
 | 
				
			||||||
 | 
					                if (defaultSql) {
 | 
				
			||||||
 | 
					                    sql.push(`alter table ${tableName} alter column ${a.name} set ${defaultSql}`);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (changeData.del.length > 0) {
 | 
				
			||||||
 | 
					            changeData.del.forEach((a) => {
 | 
				
			||||||
 | 
					                sql.push(`ALTER TABLE ${tableName} DROP COLUMN ${a.name}`);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return sql.join(';');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getModifyIndexSql(tableName: string, changeData: { del: any[]; add: any[]; upd: any[] }): string {
 | 
				
			||||||
 | 
					        // 不能直接修改索引名或字段、需要先删后加
 | 
				
			||||||
 | 
					        let dropIndexNames: string[] = [];
 | 
				
			||||||
 | 
					        let addIndexs: any[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (changeData.upd.length > 0) {
 | 
				
			||||||
 | 
					            changeData.upd.forEach((a) => {
 | 
				
			||||||
 | 
					                dropIndexNames.push(a.indexName);
 | 
				
			||||||
 | 
					                addIndexs.push(a);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (changeData.del.length > 0) {
 | 
				
			||||||
 | 
					            changeData.del.forEach((a) => {
 | 
				
			||||||
 | 
					                dropIndexNames.push(a.indexName);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (changeData.add.length > 0) {
 | 
				
			||||||
 | 
					            changeData.add.forEach((a) => {
 | 
				
			||||||
 | 
					                addIndexs.push(a);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (dropIndexNames.length > 0 || addIndexs.length > 0) {
 | 
				
			||||||
 | 
					            let sql: string[] = [];
 | 
				
			||||||
 | 
					            if (dropIndexNames.length > 0) {
 | 
				
			||||||
 | 
					                dropIndexNames.forEach((a) => {
 | 
				
			||||||
 | 
					                    sql.push(`DROP INDEX ${a}`);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (addIndexs.length > 0) {
 | 
				
			||||||
 | 
					                addIndexs.forEach((a) => {
 | 
				
			||||||
 | 
					                    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}'`);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return sql.join(';');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return '';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,99 +1,94 @@
 | 
				
			|||||||
export const TYPE_LIST = [
 | 
					import { DbOption, DbType, sqlType } from '@/views/ops/db/component/table/dbs/db-option';
 | 
				
			||||||
    'bigint',
 | 
					import { MysqlOption } from '@/views/ops/db/component/table/dbs/mysql-option';
 | 
				
			||||||
    'binary',
 | 
					import { PostgresqlOption } from '@/views/ops/db/component/table/dbs/postgresql-option';
 | 
				
			||||||
    'blob',
 | 
					
 | 
				
			||||||
    'char',
 | 
					export const MYSQL_TYPE_LIST = ['bigint', 'binary', 'blob', 'char', 'datetime', 'date', 'decimal', 'double', 'enum', 'float', 'int', 'json', 'longblob', 'longtext', 'mediumblob', 'mediumtext', 'set', 'smallint', 'text', 'time', 'timestamp', 'tinyint', 'varbinary', 'varchar'];
 | 
				
			||||||
    'datetime',
 | 
					
 | 
				
			||||||
    'date',
 | 
					export const GAUSS_TYPE_LIST: sqlType[] = [
 | 
				
			||||||
    'decimal',
 | 
					    // 数值 - 整数型
 | 
				
			||||||
    'double',
 | 
					    { udtName: 'int1', dataType: 'tinyint', desc: '微整数,别名为INT1', space: '1字节', range: '0 ~ +255' },
 | 
				
			||||||
    'enum',
 | 
					    { udtName: 'int2', dataType: 'smallint', desc: '小范围整数,别名为INT2。', space: '2字节', range: '-32,768 ~ +32,767' },
 | 
				
			||||||
    'float',
 | 
					    { udtName: 'int4', dataType: 'integer', desc: '常用的整数,别名为INT4。', space: '4字节', range: '-2,147,483,648 ~ +2,147,483,647' },
 | 
				
			||||||
    'int',
 | 
					    { udtName: 'int8', dataType: 'bigint', desc: '大范围的整数,别名为INT8。', space: '8字节', range: '很大' },
 | 
				
			||||||
    'json',
 | 
					
 | 
				
			||||||
    'longblob',
 | 
					    // 数值 - 任意精度型
 | 
				
			||||||
    'longtext',
 | 
					    {
 | 
				
			||||||
    'mediumblob',
 | 
					        udtName: 'numeric',
 | 
				
			||||||
    'mediumtext',
 | 
					        dataType: 'numeric',
 | 
				
			||||||
    'set',
 | 
					        desc: '精度(总位数)取值范围为[1,1000],标度(小数位数)取值范围为[0,精度]。',
 | 
				
			||||||
    'smallint',
 | 
					        space: '每四位(十进制位)占用两个字节,然后在整个数据上加上八个字节的额外开销',
 | 
				
			||||||
    'text',
 | 
					        range: '未指定精度的情况下,小数点前最大131,072位,小数点后最大16,383位',
 | 
				
			||||||
    'time',
 | 
					    },
 | 
				
			||||||
    'timestamp',
 | 
					    // 数值 - 任意精度型
 | 
				
			||||||
    'tinyint',
 | 
					    { udtName: 'decimal', dataType: 'decimal', desc: '等同于number类型', space: '等同于number类型' },
 | 
				
			||||||
    'varbinary',
 | 
					
 | 
				
			||||||
    'varchar',
 | 
					    // 数值 - 序列整型
 | 
				
			||||||
 | 
					    { udtName: 'smallserial', dataType: 'smallserial', desc: '二字节序列整型。', space: '2字节', range: '-32,768 ~ +32,767' },
 | 
				
			||||||
 | 
					    { udtName: 'serial', dataType: 'serial', desc: '四字节序列整型。', space: '4字节', range: '-2,147,483,648 ~ +2,147,483,647' },
 | 
				
			||||||
 | 
					    { udtName: 'bigserial', dataType: 'bigserial', desc: '八字节序列整型', space: '8字节', range: '-9,223,372,036,854,775,808 ~ +9,223,372,036,854,775,807' },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        udtName: 'largeserial',
 | 
				
			||||||
 | 
					        dataType: 'largeserial',
 | 
				
			||||||
 | 
					        desc: '默认插入十六字节序列整型,实际数值类型和numeric相同',
 | 
				
			||||||
 | 
					        space: '变长类型,每四位(十进制位)占用两个字节,然后在整个数据上加上八个字节的额外开销。',
 | 
				
			||||||
 | 
					        range: '小数点前最大131,072位,小数点后最大16,383位。',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 数值 - 浮点类型(不常用 就不列出来了)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 货币类型
 | 
				
			||||||
 | 
					    { udtName: 'money', dataType: 'money', desc: '货币金额', space: '8字节', range: '-92233720368547758.08 ~ +92233720368547758.07' },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 布尔类型
 | 
				
			||||||
 | 
					    { udtName: 'bool', dataType: 'bool', desc: '布尔类型', space: '1字节', range: 'true:真 , false:假 , null:未知(unknown)' },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 字符类型
 | 
				
			||||||
 | 
					    { udtName: 'char', dataType: 'char', desc: '定长字符串,不足补空格。n是指字节长度,如不带精度n,默认精度为1。', space: '最大为10MB' },
 | 
				
			||||||
 | 
					    { udtName: 'character', dataType: 'character', desc: '定长字符串,不足补空格。n是指字节长度,如不带精度n,默认精度为1。', space: '最大为10MB' },
 | 
				
			||||||
 | 
					    { udtName: 'nchar', dataType: 'nchar', desc: '定长字符串,不足补空格。n是指字节长度,如不带精度n,默认精度为1。', space: '最大为10MB' },
 | 
				
			||||||
 | 
					    { udtName: 'varchar', dataType: 'varchar', desc: '变长字符串。PG兼容模式下,n是字符长度。其他兼容模式下,n是指字节长度。', space: '最大为10MB。' },
 | 
				
			||||||
 | 
					    { udtName: 'text', dataType: 'text', desc: '变长字符串。', space: '最大稍微小于1GB-1。' },
 | 
				
			||||||
 | 
					    { udtName: 'clob', dataType: 'clob', desc: '文本大对象。是TEXT类型的别名。', space: '最大稍微小于32TB-1。' },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //特殊字符类型  用的很少,先屏蔽了
 | 
				
			||||||
 | 
					    // { udtName: 'name', dataType: 'name', desc: '用于对象名的内部类型。', space: '64字节。' },
 | 
				
			||||||
 | 
					    // { udtName: '"char"', dataType: '"char"', desc: '单字节内部类型。', space: '1字节。' },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 二进制类型
 | 
				
			||||||
 | 
					    { udtName: 'bytea', dataType: 'bytea', desc: '变长的二进制字符串', space: '4字节加上实际的二进制字符串。最大为1GB减去8203字节(即1073733621字节)。' },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 日期/时间类型
 | 
				
			||||||
 | 
					    { udtName: 'date', dataType: 'date', desc: '日期', space: '4字节' },
 | 
				
			||||||
 | 
					    { udtName: 'time', dataType: 'time', desc: 'TIME [(p)] 只用于一日内时间,p表示小数点后的精度,取值范围为0~6。', space: '8-12字节' },
 | 
				
			||||||
 | 
					    { udtName: 'timestamp', dataType: 'timestamp', desc: 'TIMESTAMP[(p)]日期和时间,p表示小数点后的精度,取值范围为0~6', space: '8字节' },
 | 
				
			||||||
 | 
					    // 带时区的时间戳用的少,先屏蔽了
 | 
				
			||||||
 | 
					    //{ udtName: 'TIMESTAMPTZ', dataType: 'TIMESTAMP WITH TIME ZONE', desc: '带时区的时间戳', space: '8字节' },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        udtName: 'interval',
 | 
				
			||||||
 | 
					        dataType: 'interval',
 | 
				
			||||||
 | 
					        desc: '时间间隔', // 可以跟参数:YEAR,MONTH,DAY,HOUR,MINUTE,SECOND,DAY TO HOUR,DAY TO MINUTE,DAY TO SECOND,HOUR TO MINUTE,HOUR TO SECOND,MINUTE TO SECOND
 | 
				
			||||||
 | 
					        space: '精度取值范围为0~6,且参数为SECOND,DAY TO SECOND,HOUR TO SECOND或MINUTE TO SECOND时,参数p才有效',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    // 几何类型
 | 
				
			||||||
 | 
					    { udtName: 'point', dataType: 'point', desc: '平面中的点, 如:(x,y)', space: '16字节' },
 | 
				
			||||||
 | 
					    { udtName: 'lseg', dataType: 'lseg', desc: '(有限)线段, 如:((x1,y1),(x2,y2))', space: '32字节' },
 | 
				
			||||||
 | 
					    { udtName: 'box', dataType: 'box', desc: '矩形, 如:((x1,y1),(x2,y2))', space: '32字节' },
 | 
				
			||||||
 | 
					    { udtName: 'path', dataType: 'path', desc: '闭合路径(与多边形类似), 如:((x1,y1),...)', space: '16+16n字节' },
 | 
				
			||||||
 | 
					    { udtName: 'path', dataType: 'path', desc: '开放路径(与多边形类似), 如:[(x1,y1),...]', space: '16+16n字节' },
 | 
				
			||||||
 | 
					    { udtName: 'polygon', dataType: 'polygon', desc: '多边形(与闭合路径相似), 如:((x1,y1),...)', space: '40+16n字节' },
 | 
				
			||||||
 | 
					    { udtName: 'circle', dataType: 'polygon', desc: '圆,如:<(x,y),r> (圆心和半径)', space: '24 字节' },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 网络地址类型
 | 
				
			||||||
 | 
					    { udtName: 'cidr', dataType: 'cidr', desc: 'IPv4网络', space: '7字节' },
 | 
				
			||||||
 | 
					    { udtName: 'inet', dataType: 'inet', desc: 'IPv4主机和网络', space: '7字节' },
 | 
				
			||||||
 | 
					    { udtName: 'macaddr', dataType: 'macaddr', desc: 'MAC地址', space: '6字节' },
 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const CHARACTER_SET_NAME_LIST = [
 | 
					export const getDbOption = (dbType: string | undefined): DbOption => {
 | 
				
			||||||
    'armscii8',
 | 
					    if (dbType === DbType.mysql) {
 | 
				
			||||||
    'ascii',
 | 
					        return new MysqlOption();
 | 
				
			||||||
    'big5',
 | 
					    } else if (dbType === DbType.postgresql) {
 | 
				
			||||||
    'binary',
 | 
					        return new PostgresqlOption();
 | 
				
			||||||
    'cp1250',
 | 
					    }
 | 
				
			||||||
    'cp1251',
 | 
					    throw new Error('不支持的数据库');
 | 
				
			||||||
    'cp1256',
 | 
					};
 | 
				
			||||||
    'cp1257',
 | 
					 | 
				
			||||||
    'cp850',
 | 
					 | 
				
			||||||
    'cp852',
 | 
					 | 
				
			||||||
    'cp866',
 | 
					 | 
				
			||||||
    'cp932',
 | 
					 | 
				
			||||||
    'dec8',
 | 
					 | 
				
			||||||
    'eucjpms',
 | 
					 | 
				
			||||||
    'euckr',
 | 
					 | 
				
			||||||
    'gb18030',
 | 
					 | 
				
			||||||
    'gb2312',
 | 
					 | 
				
			||||||
    'gbk',
 | 
					 | 
				
			||||||
    'geostd8',
 | 
					 | 
				
			||||||
    'greek',
 | 
					 | 
				
			||||||
    'hebrew',
 | 
					 | 
				
			||||||
    'hp8',
 | 
					 | 
				
			||||||
    'keybcs2',
 | 
					 | 
				
			||||||
    'koi8r',
 | 
					 | 
				
			||||||
    'koi8u',
 | 
					 | 
				
			||||||
    'latin1',
 | 
					 | 
				
			||||||
    'latin2',
 | 
					 | 
				
			||||||
    'latin5',
 | 
					 | 
				
			||||||
    'latin7',
 | 
					 | 
				
			||||||
    'macce',
 | 
					 | 
				
			||||||
    'macroman',
 | 
					 | 
				
			||||||
    'sjis',
 | 
					 | 
				
			||||||
    'swe7',
 | 
					 | 
				
			||||||
    'tis620',
 | 
					 | 
				
			||||||
    'ucs2',
 | 
					 | 
				
			||||||
    'ujis',
 | 
					 | 
				
			||||||
    'utf16',
 | 
					 | 
				
			||||||
    'utf16le',
 | 
					 | 
				
			||||||
    'utf32',
 | 
					 | 
				
			||||||
    'utf8',
 | 
					 | 
				
			||||||
    'utf8mb4',
 | 
					 | 
				
			||||||
];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const COLLATION_SUFFIX_LIST = [
 | 
					 | 
				
			||||||
    'unicode_ci',
 | 
					 | 
				
			||||||
    'bin',
 | 
					 | 
				
			||||||
    'croatian_ci',
 | 
					 | 
				
			||||||
    'czech_ci',
 | 
					 | 
				
			||||||
    'danish_ci',
 | 
					 | 
				
			||||||
    'esperanto_ci',
 | 
					 | 
				
			||||||
    'estonian_ci',
 | 
					 | 
				
			||||||
    'general_ci',
 | 
					 | 
				
			||||||
    'german2_ci',
 | 
					 | 
				
			||||||
    'hungarian_ci',
 | 
					 | 
				
			||||||
    'icelandic_ci',
 | 
					 | 
				
			||||||
    'latvian_ci',
 | 
					 | 
				
			||||||
    'lithuanian_ci',
 | 
					 | 
				
			||||||
    'persian_ci',
 | 
					 | 
				
			||||||
    'polish_ci',
 | 
					 | 
				
			||||||
    'roman_ci',
 | 
					 | 
				
			||||||
    'romanian_ci',
 | 
					 | 
				
			||||||
    'sinhala_ci',
 | 
					 | 
				
			||||||
    'slovak_ci',
 | 
					 | 
				
			||||||
    'slovenian_ci',
 | 
					 | 
				
			||||||
    'spanish2_ci',
 | 
					 | 
				
			||||||
    'spanish_ci',
 | 
					 | 
				
			||||||
    'swedish_ci',
 | 
					 | 
				
			||||||
    'turkish_ci',
 | 
					 | 
				
			||||||
    'unicode_520_ci',
 | 
					 | 
				
			||||||
    'vietnamese_ci',
 | 
					 | 
				
			||||||
];
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@ import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
 | 
				
			|||||||
import { editor, languages, Position } from 'monaco-editor';
 | 
					import { editor, languages, Position } from 'monaco-editor';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { registerCompletionItemProvider } from '@/components/monaco/completionItemProvider';
 | 
					import { registerCompletionItemProvider } from '@/components/monaco/completionItemProvider';
 | 
				
			||||||
 | 
					import { DbType } from '@/views/ops/db/component/table/dbs/db-option';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const sqlCompletionKeywords = [...sqlLanguage.keywords, ...addSqlLanguage.keywords];
 | 
					const sqlCompletionKeywords = [...sqlLanguage.keywords, ...addSqlLanguage.keywords];
 | 
				
			||||||
const sqlCompletionOperators = [...sqlLanguage.operators, ...addSqlLanguage.operators];
 | 
					const sqlCompletionOperators = [...sqlLanguage.operators, ...addSqlLanguage.operators];
 | 
				
			||||||
@@ -217,10 +218,10 @@ export class DbInst {
 | 
				
			|||||||
    // 获取指定表的默认查询sql
 | 
					    // 获取指定表的默认查询sql
 | 
				
			||||||
    getDefaultSelectSql(table: string, condition: string, orderBy: string, pageNum: number, limit: number = DbInst.DefaultLimit) {
 | 
					    getDefaultSelectSql(table: string, condition: string, orderBy: string, pageNum: number, limit: number = DbInst.DefaultLimit) {
 | 
				
			||||||
        const baseSql = `SELECT * FROM ${this.wrapName(table)} ${condition ? 'WHERE ' + condition : ''} ${orderBy ? orderBy : ''}`;
 | 
					        const baseSql = `SELECT * FROM ${this.wrapName(table)} ${condition ? 'WHERE ' + condition : ''} ${orderBy ? orderBy : ''}`;
 | 
				
			||||||
        if (this.type == 'mysql') {
 | 
					        if (this.type == DbType.mysql) {
 | 
				
			||||||
            return `${baseSql} LIMIT ${(pageNum - 1) * limit}, ${limit};`;
 | 
					            return `${baseSql} LIMIT ${(pageNum - 1) * limit}, ${limit};`;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (this.type == 'postgres') {
 | 
					        if (this.type == DbType.postgresql) {
 | 
				
			||||||
            return `${baseSql} OFFSET ${(pageNum - 1) * limit} LIMIT ${limit};`;
 | 
					            return `${baseSql} OFFSET ${(pageNum - 1) * limit} LIMIT ${limit};`;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return baseSql;
 | 
					        return baseSql;
 | 
				
			||||||
@@ -284,7 +285,7 @@ export class DbInst {
 | 
				
			|||||||
     * @returns
 | 
					     * @returns
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    wrapName = (name: string) => {
 | 
					    wrapName = (name: string) => {
 | 
				
			||||||
        if (this.type == 'mysql') {
 | 
					        if (this.type === DbType.mysql) {
 | 
				
			||||||
            return `\`${name}\``;
 | 
					            return `\`${name}\``;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // if (this.type == 'postgres') {
 | 
					        // if (this.type == 'postgres') {
 | 
				
			||||||
@@ -421,20 +422,20 @@ export class DbInst {
 | 
				
			|||||||
     * @returns
 | 
					     * @returns
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    static getIconName = (dbType: string) => {
 | 
					    static getIconName = (dbType: string) => {
 | 
				
			||||||
        if (dbType == 'mysql') {
 | 
					        if (dbType == DbType.mysql) {
 | 
				
			||||||
            return 'iconfont icon-op-mysql';
 | 
					            return 'iconfont icon-op-mysql';
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (dbType == 'postgres') {
 | 
					        if (dbType == DbType.postgresql) {
 | 
				
			||||||
            return 'iconfont icon-op-postgres';
 | 
					            return 'iconfont icon-op-postgres';
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return 'InfoFilled';
 | 
					        return 'InfoFilled';
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static getIcon = (dbType: string) => {
 | 
					    static getIcon = (dbType: string) => {
 | 
				
			||||||
        if (dbType == 'mysql') {
 | 
					        if (dbType == DbType.mysql) {
 | 
				
			||||||
            return 'iconfont icon-op-mysql';
 | 
					            return 'iconfont icon-op-mysql';
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (dbType == 'postgres') {
 | 
					        if (dbType == DbType.postgresql) {
 | 
				
			||||||
            return 'iconfont icon-op-postgres';
 | 
					            return 'iconfont icon-op-postgres';
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return 'InfoFilled';
 | 
					        return 'InfoFilled';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,9 +23,10 @@ type Column struct {
 | 
				
			|||||||
	ColumnName    string `json:"columnName"`    // 列名
 | 
						ColumnName    string `json:"columnName"`    // 列名
 | 
				
			||||||
	ColumnType    string `json:"columnType"`    // 列类型
 | 
						ColumnType    string `json:"columnType"`    // 列类型
 | 
				
			||||||
	ColumnComment string `json:"columnComment"` // 列备注
 | 
						ColumnComment string `json:"columnComment"` // 列备注
 | 
				
			||||||
	ColumnKey     string `json:"columnKey"`
 | 
						ColumnKey     string `json:"columnKey"`     // 是否为主键,逐渐的话值钱为PRI
 | 
				
			||||||
	ColumnDefault string `json:"columnDefault"`
 | 
						ColumnDefault string `json:"columnDefault"` // 默认值
 | 
				
			||||||
	Nullable      string `json:"nullable"`      // 是否可为null
 | 
						Nullable      string `json:"nullable"`      // 是否可为null
 | 
				
			||||||
 | 
						NumScale      string `json:"numScale"`      // 小数点
 | 
				
			||||||
	Extra         string `json:"extra"`         // 其他信息
 | 
						Extra         string `json:"extra"`         // 其他信息
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,7 +44,8 @@ SELECT
 | 
				
			|||||||
  column_comment columnComment,
 | 
					  column_comment columnComment,
 | 
				
			||||||
  column_key columnKey,
 | 
					  column_key columnKey,
 | 
				
			||||||
  extra extra,
 | 
					  extra extra,
 | 
				
			||||||
  is_nullable nullable
 | 
					  is_nullable nullable,
 | 
				
			||||||
 | 
					  NUMERIC_SCALE numScale
 | 
				
			||||||
from
 | 
					from
 | 
				
			||||||
  information_schema.columns
 | 
					  information_schema.columns
 | 
				
			||||||
WHERE
 | 
					WHERE
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,38 +29,31 @@ where
 | 
				
			|||||||
--PGSQL_INDEX_INFO 表索引信息
 | 
					--PGSQL_INDEX_INFO 表索引信息
 | 
				
			||||||
SELECT
 | 
					SELECT
 | 
				
			||||||
    indexname AS "indexName",
 | 
					    indexname AS "indexName",
 | 
				
			||||||
  indexdef AS "indexComment"
 | 
					    'BTREE' AS "IndexType",
 | 
				
			||||||
FROM
 | 
					    case when indexdef like 'CREATE UNIQUE INDEX%%' then 0 else 1 end as "nonUnique",
 | 
				
			||||||
  pg_indexes
 | 
					    obj_description(b.oid, 'pg_class') AS "indexComment",
 | 
				
			||||||
WHERE
 | 
					    indexdef AS "indexDef",
 | 
				
			||||||
  schemaname = (
 | 
					    c.attname AS "columnName",
 | 
				
			||||||
    select
 | 
					    c.attnum AS "seqInIndex"
 | 
				
			||||||
      current_schema ()
 | 
					FROM pg_indexes a
 | 
				
			||||||
  )
 | 
					     join pg_class b on a.indexname = b.relname
 | 
				
			||||||
  AND tablename = '%s'
 | 
					     join pg_attribute c on b.oid = c.attrelid
 | 
				
			||||||
 | 
					WHERE a.schemaname = (select current_schema())
 | 
				
			||||||
 | 
					  AND a.tablename = '%s';
 | 
				
			||||||
---------------------------------------
 | 
					---------------------------------------
 | 
				
			||||||
--PGSQL_COLUMN_MA 表列信息
 | 
					--PGSQL_COLUMN_MA 表列信息
 | 
				
			||||||
SELECT
 | 
					SELECT
 | 
				
			||||||
	C.relname AS "tableName",
 | 
					    table_name AS "tableName",
 | 
				
			||||||
	A.attname AS "columnName",
 | 
					    column_name AS "columnName",
 | 
				
			||||||
	tc.is_nullable AS "nullable",
 | 
					    is_nullable AS "nullable",
 | 
				
			||||||
	concat_ws ( '', t.typname, SUBSTRING ( format_type ( a.atttypid, a.atttypmod ) FROM '\(.*\)' ) ) AS "columnType",
 | 
					    case when character_maximum_length > 0 then concat(udt_name, '(',character_maximum_length,')') else udt_name end  AS "columnType",
 | 
				
			||||||
	(CASE WHEN ( SELECT COUNT(*) FROM pg_constraint WHERE conrelid = a.attrelid AND conkey[1]= attnum AND contype = 'p' ) > 0 THEN 'PRI' ELSE '' END ) AS "columnKey",
 | 
					    column_default as "columnDefault",
 | 
				
			||||||
	d.description AS "columnComment" 
 | 
					    numeric_scale  AS "numScale",
 | 
				
			||||||
FROM
 | 
					    case when column_default like 'nextval%%' then 'PRI' else '' end "columnKey",
 | 
				
			||||||
	pg_attribute a LEFT JOIN pg_description d ON d.objoid = a.attrelid 
 | 
					    col_description((table_schema || '.' || table_name)::regclass, ordinal_position) AS "columnComment"
 | 
				
			||||||
	AND d.objsubid = A.attnum
 | 
					FROM information_schema.columns
 | 
				
			||||||
	LEFT JOIN pg_class c ON A.attrelid = c.oid
 | 
					WHERE table_schema = (select current_schema()) and table_name = %s
 | 
				
			||||||
	LEFT JOIN pg_namespace pn ON c.relnamespace = pn.oid
 | 
					order by table_name, ordinal_position
 | 
				
			||||||
	LEFT JOIN pg_type t ON a.atttypid = t.oid 
 | 
					 | 
				
			||||||
	JOIN information_schema.columns tc ON tc.column_name = a.attname AND tc.table_name = C.relname AND tc.table_schema = pn.nspname
 | 
					 | 
				
			||||||
WHERE
 | 
					 | 
				
			||||||
	A.attnum >= 0 
 | 
					 | 
				
			||||||
	AND pn.nspname = (select current_schema())
 | 
					 | 
				
			||||||
	AND C.relname in (%s)
 | 
					 | 
				
			||||||
ORDER BY
 | 
					 | 
				
			||||||
	C.relname DESC,
 | 
					 | 
				
			||||||
	A.attnum ASC
 | 
					 | 
				
			||||||
---------------------------------------
 | 
					---------------------------------------
 | 
				
			||||||
--PGSQL_TABLE_DDL_FUNC 表ddl函数
 | 
					--PGSQL_TABLE_DDL_FUNC 表ddl函数
 | 
				
			||||||
 CREATE OR REPLACE FUNCTION showcreatetable(namespace character varying, tablename character varying)
 | 
					 CREATE OR REPLACE FUNCTION showcreatetable(namespace character varying, tablename character varying)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -89,6 +89,7 @@ func (mm *MysqlMetadata) GetColumns(tableNames ...string) ([]Column, error) {
 | 
				
			|||||||
			Nullable:      anyx.ConvString(re["nullable"]),
 | 
								Nullable:      anyx.ConvString(re["nullable"]),
 | 
				
			||||||
			ColumnKey:     anyx.ConvString(re["columnKey"]),
 | 
								ColumnKey:     anyx.ConvString(re["columnKey"]),
 | 
				
			||||||
			ColumnDefault: anyx.ConvString(re["columnDefault"]),
 | 
								ColumnDefault: anyx.ConvString(re["columnDefault"]),
 | 
				
			||||||
 | 
								NumScale:      anyx.ConvString(re["numScale"]),
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return columns, nil
 | 
						return columns, nil
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -149,6 +149,7 @@ func (pm *PgsqlMetadata) GetColumns(tableNames ...string) ([]Column, error) {
 | 
				
			|||||||
			Nullable:      anyx.ConvString(re["nullable"]),
 | 
								Nullable:      anyx.ConvString(re["nullable"]),
 | 
				
			||||||
			ColumnKey:     anyx.ConvString(re["columnKey"]),
 | 
								ColumnKey:     anyx.ConvString(re["columnKey"]),
 | 
				
			||||||
			ColumnDefault: anyx.ConvString(re["columnDefault"]),
 | 
								ColumnDefault: anyx.ConvString(re["columnDefault"]),
 | 
				
			||||||
 | 
								NumScale:      anyx.ConvString(re["numScale"]),
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return columns, nil
 | 
						return columns, nil
 | 
				
			||||||
@@ -183,13 +184,29 @@ func (pm *PgsqlMetadata) GetTableIndex(tableName string) ([]Index, error) {
 | 
				
			|||||||
		indexs = append(indexs, Index{
 | 
							indexs = append(indexs, Index{
 | 
				
			||||||
			IndexName:    re["indexName"].(string),
 | 
								IndexName:    re["indexName"].(string),
 | 
				
			||||||
			ColumnName:   anyx.ConvString(re["columnName"]),
 | 
								ColumnName:   anyx.ConvString(re["columnName"]),
 | 
				
			||||||
			IndexType:    anyx.ConvString(re["indexType"]),
 | 
								IndexType:    anyx.ConvString(re["IndexType"]),
 | 
				
			||||||
			IndexComment: anyx.ConvString(re["indexComment"]),
 | 
								IndexComment: anyx.ConvString(re["indexComment"]),
 | 
				
			||||||
			NonUnique:    anyx.ConvInt(re["nonUnique"]),
 | 
								NonUnique:    anyx.ConvInt(re["nonUnique"]),
 | 
				
			||||||
			SeqInIndex:   anyx.ConvInt(re["seqInIndex"]),
 | 
								SeqInIndex:   anyx.ConvInt(re["seqInIndex"]),
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return indexs, nil
 | 
						// 把查询结果以索引名分组,索引字段以逗号连接
 | 
				
			||||||
 | 
						result := make([]Index, 0)
 | 
				
			||||||
 | 
						key := ""
 | 
				
			||||||
 | 
						for _, v := range indexs {
 | 
				
			||||||
 | 
							// 当前的索引名
 | 
				
			||||||
 | 
							in := v.IndexName
 | 
				
			||||||
 | 
							if key == in {
 | 
				
			||||||
 | 
								// 索引字段已根据名称和顺序排序,故取最后一个即可
 | 
				
			||||||
 | 
								i := len(result) - 1
 | 
				
			||||||
 | 
								// 同索引字段以逗号连接
 | 
				
			||||||
 | 
								result[i].ColumnName = result[i].ColumnName + "," + v.ColumnName
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								key = in
 | 
				
			||||||
 | 
								result = append(result, v)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return result, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 获取建表ddl
 | 
					// 获取建表ddl
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user