feat(Firebird SQL): table add/edit/delete support

This commit is contained in:
Fabio Di Stasio 2022-11-15 16:46:12 +01:00
parent 27566c1dfa
commit 1b5cc315dd
20 changed files with 241 additions and 200 deletions

View File

@ -1,10 +1,14 @@
import { Customizations } from '../interfaces/customizations'; import { Customizations } from '../interfaces/customizations';
// Everything OFF
export const defaults: Customizations = { export const defaults: Customizations = {
// Defaults // Defaults
defaultPort: null, defaultPort: null,
defaultUser: null, defaultUser: null,
defaultDatabase: null, defaultDatabase: null,
dataTypes: [],
indexTypes: [],
foreignActions: [],
// Core // Core
database: false, database: false,
collations: false, collations: false,
@ -45,7 +49,6 @@ export const defaults: Customizations = {
exportByChunks: false, exportByChunks: false,
schemaImport: false, schemaImport: false,
tableSettings: false, tableSettings: false,
tableOptions: false,
tableArray: false, tableArray: false,
tableRealCount: false, tableRealCount: false,
viewSettings: false, viewSettings: false,

View File

@ -1,10 +1,26 @@
import { Customizations } from '../interfaces/customizations'; import { Customizations } from '../interfaces/customizations';
import { defaults } from './defaults';
import firebirdTypes from '../data-types/firebird';
export const customizations: Customizations = { export const customizations: Customizations = {
...defaults,
// Defaults // Defaults
defaultPort: 3050, defaultPort: 3050,
defaultUser: 'SYSDBA', defaultUser: 'SYSDBA',
defaultDatabase: null, defaultDatabase: null,
dataTypes: firebirdTypes,
indexTypes: [
'PRIMARY',
// 'CHECK',
'UNIQUE'
],
foreignActions: [
'RESTRICT',
'NO ACTION',
'CASCADE',
'SET NULL',
'SET DEFAULT'
],
// Core // Core
database: true, database: true,
collations: false, collations: false,
@ -23,72 +39,14 @@ export const customizations: Customizations = {
tables: true, tables: true,
views: false, views: false,
triggers: true, triggers: true,
triggerFunctions: false,
routines: false, routines: false,
functions: false, functions: false,
schedulers: false,
// Settings // Settings
elementsWrapper: '', elementsWrapper: '"',
stringsWrapper: '\'', stringsWrapper: '\'',
tableAdd: false, tableAdd: true,
tableTruncateDisableFKCheck: false,
viewAdd: false,
triggerAdd: false,
triggerFunctionAdd: false,
routineAdd: false,
functionAdd: false,
schedulerAdd: false,
databaseEdit: false,
schemaEdit: false,
schemaDrop: false,
schemaExport: false,
exportByChunks: false,
schemaImport: false,
tableSettings: true, tableSettings: true,
tableOptions: false, indexes: true,
tableArray: false, foreigns: true,
tableRealCount: false, nullable: true
viewSettings: false,
triggerSettings: false,
triggerFunctionSettings: false,
routineSettings: false,
functionSettings: false,
schedulerSettings: false,
indexes: false,
foreigns: false,
sortableFields: false,
unsigned: false,
nullable: true,
nullablePrimary: false,
zerofill: false,
autoIncrement: false,
comment: false,
collation: false,
definer: false,
onUpdate: false,
viewAlgorithm: false,
viewSqlSecurity: false,
viewUpdateOption: false,
procedureDeterministic: false,
procedureDataAccess: false,
procedureSql: null,
procedureContext: false,
procedureLanguage: false,
functionDeterministic: false,
functionDataAccess: false,
functionSql: null,
functionContext: false,
functionLanguage: false,
triggerSql: null,
triggerStatementInCreation: false,
triggerMultipleEvents: false,
triggerTableInName: false,
triggerUpdateColumns: false,
triggerOnlyRename: false,
triggerEnableDisable: false,
triggerFunctionSql: null,
triggerFunctionlanguages: null,
parametersLength: false,
languages: null,
readOnlyMode: false
}; };

View File

@ -1,5 +1,6 @@
import { Customizations } from '../interfaces/customizations'; import { Customizations } from '../interfaces/customizations';
import { defaults } from './defaults'; import { defaults } from './defaults';
import mysqlTypes from '../data-types/mysql';
export const customizations: Customizations = { export const customizations: Customizations = {
...defaults, ...defaults,
@ -7,6 +8,19 @@ export const customizations: Customizations = {
defaultPort: 3306, defaultPort: 3306,
defaultUser: 'root', defaultUser: 'root',
defaultDatabase: null, defaultDatabase: null,
dataTypes: mysqlTypes,
indexTypes: [
'PRIMARY',
'INDEX',
'UNIQUE',
'FULLTEXT'
],
foreignActions: [
'RESTRICT',
'CASCADE',
'SET NULL',
'NO ACTION'
],
// Core // Core
connectionSchema: true, connectionSchema: true,
collations: true, collations: true,

View File

@ -1,5 +1,6 @@
import { Customizations } from '../interfaces/customizations'; import { Customizations } from '../interfaces/customizations';
import { defaults } from './defaults'; import { defaults } from './defaults';
import postgresqlTypes from '../data-types/postgresql';
export const customizations: Customizations = { export const customizations: Customizations = {
...defaults, ...defaults,
@ -7,6 +8,18 @@ export const customizations: Customizations = {
defaultPort: 5432, defaultPort: 5432,
defaultUser: 'postgres', defaultUser: 'postgres',
defaultDatabase: 'postgres', defaultDatabase: 'postgres',
dataTypes: postgresqlTypes,
indexTypes: [
'PRIMARY',
'INDEX',
'UNIQUE'
],
foreignActions: [
'RESTRICT',
'CASCADE',
'SET NULL',
'NO ACTION'
],
// Core // Core
database: true, database: true,
sslConnection: true, sslConnection: true,

View File

@ -1,8 +1,21 @@
import { Customizations } from '../interfaces/customizations'; import { Customizations } from '../interfaces/customizations';
import { defaults } from './defaults'; import { defaults } from './defaults';
import sqliteTypes from '../data-types/sqlite';
export const customizations: Customizations = { export const customizations: Customizations = {
...defaults, ...defaults,
dataTypes: sqliteTypes,
indexTypes: [
'PRIMARY',
'INDEX',
'UNIQUE'
],
foreignActions: [
'RESTRICT',
'CASCADE',
'SET NULL',
'NO ACTION'
],
// Core // Core
fileConnection: true, fileConnection: true,
// Structure // Structure

View File

@ -1,4 +0,0 @@
export default [
'PRIMARY',
'UNIQUE'
];

View File

@ -1,6 +0,0 @@
export default [
'PRIMARY',
'INDEX',
'UNIQUE',
'FULLTEXT'
];

View File

@ -1,5 +0,0 @@
export default [
'PRIMARY',
'INDEX',
'UNIQUE'
];

View File

@ -1,5 +0,0 @@
export default [
'PRIMARY',
'INDEX',
'UNIQUE'
];

View File

@ -1,8 +1,13 @@
import { TypesGroup } from './antares';
export interface Customizations { export interface Customizations {
// Defaults // Defaults
defaultPort?: number; defaultPort?: number;
defaultUser?: string; defaultUser?: string;
defaultDatabase?: string; defaultDatabase?: string;
dataTypes?: TypesGroup[];
indexTypes?: string[];
foreignActions?: string[];
// Core // Core
database?: boolean; database?: boolean;
collations?: boolean; collations?: boolean;
@ -30,7 +35,6 @@ export interface Customizations {
stringsWrapper: string; stringsWrapper: string;
tableAdd?: boolean; tableAdd?: boolean;
tableSettings?: boolean; tableSettings?: boolean;
tableOptions?: boolean;
tableArray?: boolean; tableArray?: boolean;
tableRealCount?: boolean; tableRealCount?: boolean;
tableTruncateDisableFKCheck?: boolean; tableTruncateDisableFKCheck?: boolean;

View File

@ -227,10 +227,11 @@ export default (connections: {[key: string]: antares.Client}) => {
}).join(','); }).join(',');
try { try {
const result = await connections[params.uid] const result: unknown = await connections[params.uid]
.schema(params.schema) .schema(params.schema)
.delete(params.table) .delete(params.table)
.where({ [params.primary]: `IN (${idString})` }) .where({ [params.primary]: `IN (${idString})` })
.limit(params.rows.length)
.run(); .run();
return { status: 'success', response: result }; return { status: 'success', response: result };
@ -289,6 +290,7 @@ export default (connections: {[key: string]: antares.Client}) => {
break; break;
case 'pg': case 'pg':
case 'sqlite': case 'sqlite':
case 'firebird':
escapedParam = `'${params.row[key].value.replaceAll('\'', '\'\'')}'`; escapedParam = `'${params.row[key].value.replaceAll('\'', '\'\'')}'`;
break; break;
} }

View File

@ -2,7 +2,7 @@ import * as path from 'path';
import * as antares from 'common/interfaces/antares'; import * as antares from 'common/interfaces/antares';
import * as firebird from 'node-firebird'; import * as firebird from 'node-firebird';
import { AntaresCore } from '../AntaresCore'; import { AntaresCore } from '../AntaresCore';
import dataTypes from 'common/data-types/sqlite'; import dataTypes from 'common/data-types/firebird';
import { FLOAT, NUMBER } from 'common/fieldTypes'; import { FLOAT, NUMBER } from 'common/fieldTypes';
export class FirebirdSQLClient extends AntaresCore { export class FirebirdSQLClient extends AntaresCore {
@ -67,6 +67,27 @@ export class FirebirdSQLClient extends AntaresCore {
.filter(_type => _type.name === type.toUpperCase())[0]; .filter(_type => _type.name === type.toUpperCase())[0];
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
protected _reducer (acc: string[], curr: any) {
const type = typeof curr;
switch (type) {
case 'number':
case 'string':
return [...acc, curr];
case 'object':
if (Array.isArray(curr))
return [...acc, ...curr];
else {
const clausoles = [];
for (const key in curr)
clausoles.push(`"${key}" ${curr[key]}`);
return clausoles;
}
}
}
async connect () { async connect () {
if (!this._poolSize) if (!this._poolSize)
this._connection = await this.getConnection(); this._connection = await this.getConnection();
@ -337,7 +358,7 @@ export class FirebirdSQLClient extends AntaresCore {
name: index.INDEX_NAME.trim(), name: index.INDEX_NAME.trim(),
column: index.FIELD_NAME.trim(), column: index.FIELD_NAME.trim(),
indexType: null as never, indexType: null as never,
type: index.INDEX_TYPE.trim(), type: index.INDEX_TYPE.trim() === 'PRIMARY KEY' ? 'PRIMARY' : index.INDEX_TYPE.trim(),
cardinality: null as never, cardinality: null as never,
comment: '', comment: '',
indexComment: '' indexComment: ''
@ -411,7 +432,6 @@ export class FirebirdSQLClient extends AntaresCore {
async createTable (params: antares.CreateTableParams) { async createTable (params: antares.CreateTableParams) {
const { const {
schema,
fields, fields,
foreigns, foreigns,
indexes, indexes,
@ -419,10 +439,9 @@ export class FirebirdSQLClient extends AntaresCore {
} = params; } = params;
const newColumns: string[] = []; const newColumns: string[] = [];
const newIndexes: string[] = []; const newIndexes: string[] = [];
const manageIndexes: string[] = [];
const newForeigns: string[] = []; const newForeigns: string[] = [];
let sql = `CREATE TABLE "${schema}"."${options.name}"`; let sql = `CREATE TABLE "${options.name}"`;
// ADD FIELDS // ADD FIELDS
fields.forEach(field => { fields.forEach(field => {
@ -431,11 +450,8 @@ export class FirebirdSQLClient extends AntaresCore {
newColumns.push(`"${field.name}" newColumns.push(`"${field.name}"
${field.type.toUpperCase()}${length ? `(${length})` : ''} ${field.type.toUpperCase()}${length ? `(${length})` : ''}
${field.unsigned ? 'UNSIGNED' : ''}
${field.nullable ? 'NULL' : 'NOT NULL'}
${field.autoIncrement ? 'AUTO_INCREMENT' : ''}
${field.default !== null ? `DEFAULT ${field.default || '\'\''}` : ''} ${field.default !== null ? `DEFAULT ${field.default || '\'\''}` : ''}
${field.onUpdate ? `ON UPDATE ${field.onUpdate}` : ''}`); ${field.nullable ? '' : 'NOT NULL'}`);
}); });
// ADD INDEX // ADD INDEX
@ -443,19 +459,23 @@ export class FirebirdSQLClient extends AntaresCore {
const fields = index.fields.map(field => `"${field}"`).join(','); const fields = index.fields.map(field => `"${field}"`).join(',');
const type = index.type; const type = index.type;
if (type === 'PRIMARY') newIndexes.push(`CONSTRAINT "${index.name}" ${type === 'PRIMARY' ? 'PRIMARY KEY' : type} (${fields})`);
newIndexes.push(`PRIMARY KEY (${fields})`);
else
manageIndexes.push(`CREATE ${type === 'UNIQUE' ? type : ''} INDEX "${index.name}" ON "${options.name}" (${fields})`);
}); });
// ADD FOREIGN KEYS // ADD FOREIGN KEYS
foreigns.forEach(foreign => { foreigns.forEach(foreign => {
newForeigns.push(`CONSTRAINT "${foreign.constraintName}" FOREIGN KEY ("${foreign.field}") REFERENCES "${foreign.refTable}" ("${foreign.refField}") ON UPDATE ${foreign.onUpdate} ON DELETE ${foreign.onDelete}`); newForeigns.push(`
ADD CONSTRAINT "${foreign.constraintName}"
FOREIGN KEY ("${foreign.field}") REFERENCES "${foreign.refTable}" ("${foreign.refField}")
${foreign.onUpdate !== 'RESTRICT' ? `ON UPDATE ${foreign.onUpdate}` : ''}
${foreign.onDelete !== 'RESTRICT' ? `ON DELETE ${foreign.onDelete}` : ''}
`);
}); });
sql = `${sql} (${[...newColumns, ...newIndexes, ...newForeigns].join(', ')})`; sql = `${sql} (${[...newColumns, ...newIndexes].join(', ')})`;
if (manageIndexes.length) sql = `${sql}; ${manageIndexes.join(';')}`;
if (newForeigns.length)
sql = `${sql}; ALTER TABLE "${options.name}" ${newForeigns.join(';')}`;
return await this.raw(sql); return await this.raw(sql);
} }
@ -463,58 +483,111 @@ export class FirebirdSQLClient extends AntaresCore {
async alterTable (params: antares.AlterTableParams) { async alterTable (params: antares.AlterTableParams) {
const { const {
table, table,
schema,
additions, additions,
deletions, deletions,
changes, changes,
tableStructure indexChanges,
foreignChanges
} = params; } = params;
try { let sql = `ALTER TABLE "${table}" `;
await this.raw('BEGIN TRANSACTION'); const alterColumns: string[] = [];
await this.raw('PRAGMA foreign_keys = 0'); const newForeigns: string[] = [];
const tmpName = `Antares_${table}_tmp`; // OPTIONS
await this.raw(`CREATE TABLE "${tmpName}" AS SELECT * FROM "${table}"`); // if ('comment' in options) alterColumns.push(`COMMENT='${options.comment}'`);
await this.dropTable(params); // if ('engine' in options) alterColumns.push(`ENGINE=${options.engine}`);
// if ('autoIncrement' in options) alterColumns.push(`AUTO_INCREMENT=${+options.autoIncrement}`);
// if ('collation' in options) alterColumns.push(`COLLATE='${options.collation}'`);
const createTableParams = { // ADD FIELDS
schema: schema, additions.forEach(addition => {
fields: tableStructure.fields, const typeInfo = this.getTypeInfo(addition.type);
foreigns: tableStructure.foreigns, const length = typeInfo.length ? addition.enumValues || addition.numLength || addition.charLength || addition.datePrecision : false;
indexes: tableStructure.indexes.filter(index => !index.name.includes('sqlite_autoindex')),
options: { name: tableStructure.name }
};
await this.createTable(createTableParams);
const insertFields = createTableParams.fields
.filter(field => {
return (
additions.every(add => add.name !== field.name) &&
deletions.every(del => del.name !== field.name)
);
})
.reduce((acc, curr) => {
acc.push(`"${curr.name}"`);
return acc;
}, []);
const selectFields = insertFields.map(field => { alterColumns.push(`ADD "${addition.name}"
const renamedField = changes.find(change => `"${change.name}"` === field); ${addition.type.toUpperCase()}${length ? `(${length})` : ''}
if (renamedField) ${addition.default !== null ? `DEFAULT ${addition.default || '\'\''}` : ''}
return `"${renamedField.orgName}"`; ${addition.nullable ? '' : 'NOT NULL'}`);
return field;
}); });
await this.raw(`INSERT INTO "${createTableParams.options.name}" (${insertFields.join(',')}) SELECT ${selectFields.join(',')} FROM "${tmpName}"`); // ADD INDEX
indexChanges.additions.forEach(addition => {
const fields = addition.fields.map(field => `"${field}"`).join(',');
const type = addition.type;
await this.dropTable({ schema: schema, table: tmpName }); alterColumns.push(`ADD CONSTRAINT "${addition.name}" ${type === 'PRIMARY' ? 'PRIMARY KEY' : type} (${fields})`);
await this.raw('PRAGMA foreign_keys = 1'); });
await this.raw('COMMIT');
} // ADD FOREIGN KEYS
catch (err) { foreignChanges.additions.forEach(foreign => {
await this.raw('ROLLBACK'); newForeigns.push(`
return Promise.reject(err); ADD CONSTRAINT "${foreign.constraintName}"
} FOREIGN KEY ("${foreign.field}") REFERENCES "${foreign.refTable}" ("${foreign.refField}")
${foreign.onUpdate !== 'RESTRICT' ? `ON UPDATE ${foreign.onUpdate}` : ''}
${foreign.onDelete !== 'RESTRICT' ? `ON DELETE ${foreign.onDelete}` : ''}
`);
});
// CHANGE FIELDS
changes.forEach(change => {
const typeInfo = this.getTypeInfo(change.type);
const length = typeInfo.length ? change.enumValues || change.numLength || change.charLength || change.datePrecision : false;
if (change.orgName !== change.name)
alterColumns.push(`ALTER COLUMN "${change.orgName}" TO "${change.name}"`);
alterColumns.push(`ALTER COLUMN "${change.name}" TYPE ${change.type.toUpperCase()}${length ? `(${length}${change.numScale ? `,${change.numScale}` : ''})` : ''}`);
if (change.default !== null)
alterColumns.push(`ALTER COLUMN "${change.name}" SET DEFAULT ${change.default || '\'\''}`);
alterColumns.push(`ALTER COLUMN "${change.name}" ${!change.nullable ? 'SET ' : 'DROP '} NOT NULL`);
// TODO: position
});
// CHANGE INDEX
indexChanges.changes.forEach(change => {
alterColumns.push(`DROP CONSTRAINT "${change.oldName}"`);
const fields = change.fields.map(field => `"${field}"`).join(',');
const type = change.type;
alterColumns.push(`ADD CONSTRAINT "${change.name}" ${type === 'PRIMARY' ? 'PRIMARY KEY' : type} (${fields})`);
});
// CHANGE FOREIGN KEYS
foreignChanges.changes.forEach(change => {
alterColumns.push(`DROP CONSTRAINT "${change.oldName}"`);
alterColumns.push(`
ADD CONSTRAINT "${change.constraintName}"
FOREIGN KEY ("${change.field}") REFERENCES "${change.refTable}" ("${change.refField}")
${change.onUpdate !== 'RESTRICT' ? `ON UPDATE ${change.onUpdate}` : ''}
${change.onDelete !== 'RESTRICT' ? `ON DELETE ${change.onDelete}` : ''}
`);
});
// DROP FIELDS
deletions.forEach(deletion => {
alterColumns.push(`DROP "${deletion.name}"`);
});
// DROP INDEX
indexChanges.deletions.forEach(deletion => {
alterColumns.push(`DROP CONSTRAINT "${deletion.name}"`);
});
// DROP FOREIGN KEYS
foreignChanges.deletions.forEach(deletion => {
alterColumns.push(`DROP CONSTRAINT "${deletion.constraintName}"`);
});
if (alterColumns.length)
sql += alterColumns.join(', ');
if (newForeigns.length)
sql = `${sql}; ALTER TABLE "${table}" ${newForeigns.join(';')}`;
return await this.raw(sql);
} }
async duplicateTable (params: { schema: string; table: string }) { // TODO: retrive table informations and create a copy async duplicateTable (params: { schema: string; table: string }) { // TODO: retrive table informations and create a copy
@ -660,10 +733,10 @@ export class FirebirdSQLClient extends AntaresCore {
getSQL () { getSQL () {
// LIMIT // LIMIT
const limitRaw = this._query.limit ? ` first ${this._query.limit}` : ''; const limitRaw = this._query.limit ? ` FIRST ${this._query.limit}` : '';
// OFFSET // OFFSET
const offsetRaw = this._query.offset ? ` skip ${this._query.offset}` : ''; const offsetRaw = this._query.offset ? ` SKIP ${this._query.offset}` : '';
// SELECT // SELECT
const selectArray = this._query.select.reduce(this._reducer, []); const selectArray = this._query.select.reduce(this._reducer, []);
@ -680,7 +753,7 @@ export class FirebirdSQLClient extends AntaresCore {
else if (Object.keys(this._query.insert).length) else if (Object.keys(this._query.insert).length)
fromRaw = 'INTO'; fromRaw = 'INTO';
fromRaw += this._query.from ? ` ${this._query.from} ` : ''; fromRaw += this._query.from ? ` "${this._query.from}" ` : '';
// WHERE // WHERE
const whereArray = this._query.where const whereArray = this._query.where
@ -696,7 +769,7 @@ export class FirebirdSQLClient extends AntaresCore {
let insertRaw = ''; let insertRaw = '';
if (this._query.insert.length) { if (this._query.insert.length) {
const fieldsList = Object.keys(this._query.insert[0]); const fieldsList = Object.keys(this._query.insert[0]).map(col => '"' + col + '"');
const rowsList = this._query.insert.map(el => `(${Object.values(el).join(', ')})`); const rowsList = this._query.insert.map(el => `(${Object.values(el).join(', ')})`);
insertRaw = `(${fieldsList.join(', ')}) VALUES ${rowsList.join(', ')} `; insertRaw = `(${fieldsList.join(', ')}) VALUES ${rowsList.join(', ')} `;
@ -710,7 +783,7 @@ export class FirebirdSQLClient extends AntaresCore {
const orderByArray = this._query.orderBy.reduce(this._reducer, []); const orderByArray = this._query.orderBy.reduce(this._reducer, []);
const orderByRaw = orderByArray.length ? `ORDER BY ${orderByArray.join(', ')} ` : ''; const orderByRaw = orderByArray.length ? `ORDER BY ${orderByArray.join(', ')} ` : '';
return `${selectRaw}${updateRaw ? 'UPDATE' : ''}${insertRaw ? 'INSERT ' : ''}${this._query.delete ? 'DELETE ' : ''}${fromRaw}${updateRaw}${whereRaw}${groupByRaw}${orderByRaw}${insertRaw}`; return `${selectRaw}${updateRaw ? `UPDATE${' '+limitRaw||''}` : ''}${insertRaw ? 'INSERT ' : ''}${this._query.delete ? 'DELETE ' : ''}${fromRaw}${updateRaw}${whereRaw}${groupByRaw}${orderByRaw}${' '+(this._query.delete ? ` ROWS ${this._query.limit}` : '')||''}${insertRaw}`;
} }
async raw<T = antares.QueryResult> (sql: string, args?: antares.QueryParams) { async raw<T = antares.QueryResult> (sql: string, args?: antares.QueryParams) {
@ -878,10 +951,10 @@ export class FirebirdSQLClient extends AntaresCore {
}); });
} }
catch (err) { catch (err) {
if (args.autocommit) { if (args.autocommit)
this._connection.detach();
this._runningConnections.delete(args.tabUid); this._runningConnections.delete(args.tabUid);
}
this.destroy();
reject(err); reject(err);
} }
@ -890,10 +963,10 @@ export class FirebirdSQLClient extends AntaresCore {
keysArr = keysArr ? [...keysArr, ...response] : response; keysArr = keysArr ? [...keysArr, ...response] : response;
} }
catch (err) { catch (err) {
if (args.autocommit) { if (args.autocommit)
this._connection.detach();
this._runningConnections.delete(args.tabUid); this._runningConnections.delete(args.tabUid);
}
this.destroy();
reject(err); reject(err);
} }
} }
@ -902,7 +975,7 @@ export class FirebirdSQLClient extends AntaresCore {
} }
catch (err) { catch (err) {
reject(err); reject(err);
this._connection.detach(); this.destroy();
} }
timeStop = new Date(); timeStop = new Date();

View File

@ -540,11 +540,7 @@ export class PostgreSQLClient extends AntaresCore {
return { return {
name: row.constraint_name, name: row.constraint_name,
column: row.column_name, column: row.column_name,
indexType: null as null, type: row.constraint_type
type: row.constraint_type,
cardinality: null as null,
comment: '',
indexComment: ''
}; };
}); });
} }

View File

@ -217,11 +217,7 @@ export class SQLiteClient extends AntaresCore {
remappedIndexes.push({ remappedIndexes.push({
name: 'PRIMARY', name: 'PRIMARY',
column: key.name, column: key.name,
indexType: null as never, type: 'PRIMARY'
type: 'PRIMARY',
cardinality: null as never,
comment: '',
indexComment: ''
}); });
} }

View File

@ -531,9 +531,10 @@ const clearChanges = () => {
}; };
const addField = () => { const addField = () => {
const uid = uidGen();
localFields.value.push({ localFields.value.push({
_antares_id: uidGen(), _antares_id: uid,
name: `${t('word.field', 1)}_${++newFieldsCounter.value}`, name: `${t('word.field', 1)}_${uid.substring(0, 4)}`,
key: '', key: '',
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
type: (workspace.value.dataTypes[0] as any).types[0].name, type: (workspace.value.dataTypes[0] as any).types[0].name,

View File

@ -113,7 +113,7 @@
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="form-label col-3 pt-0"> <label class="form-label col-3">
{{ t('message.referenceTable') }} {{ t('message.referenceTable') }}
</label> </label>
<div class="column"> <div class="column">
@ -219,13 +219,8 @@ const foreignProxy = ref([]);
const selectedForeignID = ref(''); const selectedForeignID = ref('');
const modalInnerHeight = ref(400); const modalInnerHeight = ref(400);
const refFields = ref({} as {[key: string]: TableField[]}); const refFields = ref({} as {[key: string]: TableField[]});
const foreignActions = [
'RESTRICT',
'CASCADE',
'SET NULL',
'NO ACTION'
];
const foreignActions = computed(() => props.workspace.customizations.foreignActions);
const selectedForeignObj = computed(() => foreignProxy.value.find(foreign => foreign._antares_id === selectedForeignID.value)); const selectedForeignObj = computed(() => foreignProxy.value.find(foreign => foreign._antares_id === selectedForeignID.value));
const isChanged = computed(() => JSON.stringify(props.localKeyUsage) !== JSON.stringify(foreignProxy.value)); const isChanged = computed(() => JSON.stringify(props.localKeyUsage) !== JSON.stringify(foreignProxy.value));
@ -254,16 +249,17 @@ const getModalInnerHeight = () => {
}; };
const addForeign = () => { const addForeign = () => {
const uid = uidGen();
foreignProxy.value = [...foreignProxy.value, { foreignProxy.value = [...foreignProxy.value, {
_antares_id: uidGen(), _antares_id: uid,
constraintName: `FK_${uidGen()}`, constraintName: `FK_${uid.substring(0, 4)}`,
refSchema: props.schema, refSchema: props.schema,
table: props.table, table: props.table,
refTable: '', refTable: '',
field: '', field: '',
refField: '', refField: '',
onUpdate: foreignActions[0], onUpdate: foreignActions.value[0],
onDelete: foreignActions[0] onDelete: foreignActions.value[0]
}]; }];
if (foreignProxy.value.length === 1) if (foreignProxy.value.length === 1)
@ -271,6 +267,7 @@ const addForeign = () => {
setTimeout(() => { setTimeout(() => {
indexesPanel.value.scrollTop = indexesPanel.value.scrollHeight + 60; indexesPanel.value.scrollTop = indexesPanel.value.scrollHeight + 60;
selectedForeignID.value = uid;
}, 20); }, 20);
}; };

View File

@ -92,7 +92,7 @@
<BaseSelect <BaseSelect
v-model="selectedIndexObj.type" v-model="selectedIndexObj.type"
:options="indexTypes" :options="indexTypes"
:option-disabled="(opt: any) => opt === 'PRIMARY'" :option-disabled="(opt: any) => opt === 'PRIMARY' && hasPrimary"
class="form-select" class="form-select"
/> />
</div> </div>
@ -160,6 +160,7 @@ const modalInnerHeight = ref(400);
const selectedIndexObj = computed(() => indexesProxy.value.find(index => index._antares_id === selectedIndexID.value)); const selectedIndexObj = computed(() => indexesProxy.value.find(index => index._antares_id === selectedIndexID.value));
const isChanged = computed(() => JSON.stringify(props.localIndexes) !== JSON.stringify(indexesProxy.value)); const isChanged = computed(() => JSON.stringify(props.localIndexes) !== JSON.stringify(indexesProxy.value));
const hasPrimary = computed(() => indexesProxy.value.some(index => ['PRIMARY', 'PRIMARY KEY'].includes(index.type)));
const confirmIndexesChange = () => { const confirmIndexesChange = () => {
indexesProxy.value = indexesProxy.value.filter(index => index.fields.length); indexesProxy.value = indexesProxy.value.filter(index => index.fields.length);
@ -179,15 +180,12 @@ const getModalInnerHeight = () => {
}; };
const addIndex = () => { const addIndex = () => {
const uid = uidGen();
indexesProxy.value = [...indexesProxy.value, { indexesProxy.value = [...indexesProxy.value, {
_antares_id: uidGen(), _antares_id: uid,
name: 'NEW_INDEX', name: `INDEX_${uid.substring(0, 4)}`,
fields: [], fields: [],
type: 'INDEX', type: props.workspace.customizations.primaryAsIndex ? props.indexTypes[0] : props.indexTypes[1]
comment: '',
indexType: 'BTREE',
indexComment: '',
cardinality: 0
}]; }];
if (indexesProxy.value.length === 1) if (indexesProxy.value.length === 1)
@ -195,6 +193,7 @@ const addIndex = () => {
setTimeout(() => { setTimeout(() => {
indexesPanel.value.scrollTop = indexesPanel.value.scrollHeight + 60; indexesPanel.value.scrollTop = indexesPanel.value.scrollHeight + 60;
selectedIndexID.value = uid;
}, 20); }, 20);
}; };

View File

@ -501,8 +501,8 @@ const editOFF = () => {
localRow.value.enumValues = ''; localRow.value.enumValues = '';
if (fieldType.value.length) { if (fieldType.value.length) {
if (['integer', 'float', 'binary', 'spatial'].includes(fieldType.value.group)) localRow.value.numLength = 11; if (['integer', 'float', 'binary', 'spatial'].includes(fieldType.value.group)) localRow.value.numLength = 10;
if (['string'].includes(fieldType.value.group)) localRow.value.charLength = 15; if (['string'].includes(fieldType.value.group)) localRow.value.charLength = 20;
if (['time'].includes(fieldType.value.group)) localRow.value.datePrecision = 0; if (['time'].includes(fieldType.value.group)) localRow.value.datePrecision = 0;
if (['other'].includes(fieldType.value.group)) localRow.value.enumValues = '\'valA\',\'valB\''; if (['other'].includes(fieldType.value.group)) localRow.value.enumValues = '\'valA\',\'valB\'';
} }

View File

@ -271,7 +271,7 @@ const keyName = (key: string) => {
case 'mul': case 'mul':
return 'INDEX'; return 'INDEX';
case 'fk': case 'fk':
return 'FOREIGN KEY'; return 'REFERENCES';
default: default:
return 'UNKNOWN ' + key; return 'UNKNOWN ' + key;
} }

View File

@ -176,8 +176,6 @@ export const useWorkspacesStore = defineStore('workspaces', {
: workspace); : workspace);
} }
else { else {
let dataTypes: TypesGroup[] = [];
let indexTypes: string[] = [];
let clientCustomizations: Customizations; let clientCustomizations: Customizations;
const { updateLastConnection } = connectionsStore; const { updateLastConnection } = connectionsStore;
@ -186,26 +184,20 @@ export const useWorkspacesStore = defineStore('workspaces', {
switch (connection.client) { switch (connection.client) {
case 'mysql': case 'mysql':
case 'maria': case 'maria':
dataTypes = require('common/data-types/mysql').default;
indexTypes = require('common/index-types/mysql').default;
clientCustomizations = customizations.mysql; clientCustomizations = customizations.mysql;
break; break;
case 'pg': case 'pg':
dataTypes = require('common/data-types/postgresql').default;
indexTypes = require('common/index-types/postgresql').default;
clientCustomizations = customizations.pg; clientCustomizations = customizations.pg;
break; break;
case 'sqlite': case 'sqlite':
dataTypes = require('common/data-types/sqlite').default;
indexTypes = require('common/index-types/sqlite').default;
clientCustomizations = customizations.sqlite; clientCustomizations = customizations.sqlite;
break; break;
case 'firebird': case 'firebird':
dataTypes = require('common/data-types/firebird').default;
indexTypes = require('common/index-types/firebird').default;
clientCustomizations = customizations.firebird; clientCustomizations = customizations.firebird;
break; break;
} }
const dataTypes = clientCustomizations.dataTypes;
const indexTypes = clientCustomizations.indexTypes;
const { status, response: version } = await Schema.getVersion(connection.uid); const { status, response: version } = await Schema.getVersion(connection.uid);