mirror of https://github.com/Fabio286/antares.git
feat(Firebird SQL): table add/edit/delete support
This commit is contained in:
parent
27566c1dfa
commit
1b5cc315dd
|
@ -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,
|
||||||
|
|
|
@ -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
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
export default [
|
|
||||||
'PRIMARY',
|
|
||||||
'UNIQUE'
|
|
||||||
];
|
|
|
@ -1,6 +0,0 @@
|
||||||
export default [
|
|
||||||
'PRIMARY',
|
|
||||||
'INDEX',
|
|
||||||
'UNIQUE',
|
|
||||||
'FULLTEXT'
|
|
||||||
];
|
|
|
@ -1,5 +0,0 @@
|
||||||
export default [
|
|
||||||
'PRIMARY',
|
|
||||||
'INDEX',
|
|
||||||
'UNIQUE'
|
|
||||||
];
|
|
|
@ -1,5 +0,0 @@
|
||||||
export default [
|
|
||||||
'PRIMARY',
|
|
||||||
'INDEX',
|
|
||||||
'UNIQUE'
|
|
||||||
];
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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: ''
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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: ''
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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\'';
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue