1
1
mirror of https://github.com/Fabio286/antares.git synced 2025-06-05 21:59:22 +02:00

feat(SQLite): tables management

This commit is contained in:
2021-11-18 11:36:46 +01:00
parent 3fc227d2de
commit 3efeb45c46
14 changed files with 312 additions and 722 deletions

View File

@ -36,6 +36,7 @@ module.exports = {
schedulerAdd: false, schedulerAdd: false,
databaseEdit: false, databaseEdit: false,
schemaEdit: false, schemaEdit: false,
schemaDrop: false,
tableSettings: false, tableSettings: false,
tableOptions: false, tableOptions: false,
tableArray: false, tableArray: false,
@ -51,6 +52,7 @@ module.exports = {
sortableFields: false, sortableFields: false,
unsigned: false, unsigned: false,
nullable: false, nullable: false,
nullablePrimary: false,
zerofill: false, zerofill: false,
autoIncrement: false, autoIncrement: false,
comment: false, comment: false,

View File

@ -32,6 +32,7 @@ module.exports = {
functionAdd: true, functionAdd: true,
schedulerAdd: true, schedulerAdd: true,
schemaEdit: true, schemaEdit: true,
schemaDrop: true,
tableSettings: true, tableSettings: true,
viewSettings: true, viewSettings: true,
triggerSettings: true, triggerSettings: true,

View File

@ -28,6 +28,7 @@ module.exports = {
triggerFunctionAdd: true, triggerFunctionAdd: true,
routineAdd: true, routineAdd: true,
functionAdd: true, functionAdd: true,
schemaDrop: true,
databaseEdit: false, databaseEdit: false,
tableSettings: true, tableSettings: true,
viewSettings: true, viewSettings: true,

View File

@ -25,7 +25,7 @@ module.exports = {
// Settings // Settings
elementsWrapper: '', elementsWrapper: '',
stringsWrapper: '"', stringsWrapper: '"',
tableAdd: false, tableAdd: true,
viewAdd: false, viewAdd: false,
triggerAdd: false, triggerAdd: false,
triggerFunctionAdd: false, triggerFunctionAdd: false,
@ -34,7 +34,7 @@ module.exports = {
schedulerAdd: false, schedulerAdd: false,
databaseEdit: false, databaseEdit: false,
schemaEdit: false, schemaEdit: false,
tableSettings: false, tableSettings: true,
tableArray: false, tableArray: false,
tableRealCount: true, tableRealCount: true,
viewSettings: false, viewSettings: false,
@ -43,11 +43,12 @@ module.exports = {
routineSettings: false, routineSettings: false,
functionSettings: false, functionSettings: false,
schedulerSettings: false, schedulerSettings: false,
indexes: false, indexes: true,
foreigns: false, foreigns: true,
sortableFields: false, sortableFields: true,
unsigned: false, unsigned: false,
nullable: false, nullable: true,
nullablePrimary: true,
zerofill: false, zerofill: false,
tableOptions: false, tableOptions: false,
autoIncrement: false, autoIncrement: false,

View File

@ -0,0 +1,137 @@
module.exports = [
{
group: 'integer',
types: [
{
name: 'INT',
length: true,
collation: false,
unsigned: true,
zerofill: true
},
{
name: 'INTEGER',
length: true,
collation: false,
unsigned: true,
zerofill: true
},
{
name: 'BIGINT',
length: true,
collation: false,
unsigned: true,
zerofill: true
},
{
name: 'NUMERIC',
length: true,
collation: false,
unsigned: true,
zerofill: true
},
{
name: 'BOOLEAN',
length: false,
collation: false,
unsigned: true,
zerofill: true
}
]
},
{
group: 'float',
types: [
{
name: 'FLOAT',
length: true,
collation: false,
unsigned: false,
zerofill: false
},
{
name: 'REAL',
length: true,
collation: false,
unsigned: false,
zerofill: false
}
]
},
{
group: 'string',
types: [
{
name: 'CHAR',
length: true,
collation: true,
unsigned: false,
zerofill: false
},
{
name: 'VARCHAR',
length: true,
collation: true,
unsigned: false,
zerofill: false
},
{
name: 'TEXT',
length: true,
collation: true,
unsigned: false,
zerofill: false
}
]
},
{
group: 'binary',
types: [
{
name: 'BLOB',
length: true,
collation: false,
unsigned: false,
zerofill: false
}
]
},
{
group: 'time',
types: [
{
name: 'DATE',
length: true,
collation: false,
unsigned: false,
zerofill: false
},
{
name: 'TIME',
length: true,
collation: false,
unsigned: false,
zerofill: false
},
{
name: 'DATETIME',
length: true,
collation: false,
unsigned: false,
zerofill: false
}
]
},
{
group: 'other',
types: [
{
name: 'NONE',
length: false,
collation: false,
unsigned: false,
zerofill: false
}
]
}
];

View File

@ -0,0 +1,5 @@
module.exports = [
'PRIMARY',
'INDEX',
'UNIQUE'
];

View File

@ -571,7 +571,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* CREATE DATABASE * CREATE DATABASE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async createSchema (params) { async createSchema (params) {
@ -581,7 +581,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* ALTER DATABASE * ALTER DATABASE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async alterSchema (params) { async alterSchema (params) {
@ -591,7 +591,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* DROP DATABASE * DROP DATABASE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async dropSchema (params) { async dropSchema (params) {
@ -631,7 +631,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* DROP VIEW * DROP VIEW
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async dropView (params) { async dropView (params) {
@ -642,7 +642,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* ALTER VIEW * ALTER VIEW
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async alterView (params) { async alterView (params) {
@ -663,7 +663,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* CREATE VIEW * CREATE VIEW
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async createView (params) { async createView (params) {
@ -696,7 +696,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* DROP TRIGGER * DROP TRIGGER
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async dropTrigger (params) { async dropTrigger (params) {
@ -707,7 +707,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* ALTER TRIGGER * ALTER TRIGGER
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async alterTrigger (params) { async alterTrigger (params) {
@ -729,7 +729,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* CREATE TRIGGER * CREATE TRIGGER
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async createTrigger (params) { async createTrigger (params) {
@ -803,7 +803,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* DROP PROCEDURE * DROP PROCEDURE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async dropRoutine (params) { async dropRoutine (params) {
@ -814,7 +814,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* ALTER PROCEDURE * ALTER PROCEDURE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async alterRoutine (params) { async alterRoutine (params) {
@ -836,7 +836,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* CREATE PROCEDURE * CREATE PROCEDURE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async createRoutine (params) { async createRoutine (params) {
@ -930,7 +930,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* DROP FUNCTION * DROP FUNCTION
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async dropFunction (params) { async dropFunction (params) {
@ -941,7 +941,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* ALTER FUNCTION * ALTER FUNCTION
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async alterFunction (params) { async alterFunction (params) {
@ -963,7 +963,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* CREATE FUNCTION * CREATE FUNCTION
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async createFunction (params) { async createFunction (params) {
@ -1024,7 +1024,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* DROP EVENT * DROP EVENT
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async dropEvent (params) { async dropEvent (params) {
@ -1035,7 +1035,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* ALTER EVENT * ALTER EVENT
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async alterEvent (params) { async alterEvent (params) {
@ -1061,7 +1061,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* CREATE EVENT * CREATE EVENT
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async createEvent (params) { async createEvent (params) {
@ -1205,7 +1205,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* CREATE TABLE * CREATE TABLE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async createTable (params) { async createTable (params) {
@ -1267,7 +1267,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* ALTER TABLE * ALTER TABLE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async alterTable (params) { async alterTable (params) {
@ -1402,7 +1402,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* DUPLICATE TABLE * DUPLICATE TABLE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async duplicateTable (params) { async duplicateTable (params) {
@ -1413,7 +1413,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* TRUNCATE TABLE * TRUNCATE TABLE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async truncateTable (params) { async truncateTable (params) {
@ -1424,7 +1424,7 @@ export class MySQLClient extends AntaresCore {
/** /**
* DROP TABLE * DROP TABLE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async dropTable (params) { async dropTable (params) {

View File

@ -506,7 +506,7 @@ export class PostgreSQLClient extends AntaresCore {
/** /**
* CREATE SCHEMA * CREATE SCHEMA
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async createSchema (params) { async createSchema (params) {
@ -516,7 +516,7 @@ export class PostgreSQLClient extends AntaresCore {
/** /**
* ALTER DATABASE * ALTER DATABASE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async alterSchema (params) { async alterSchema (params) {
@ -526,7 +526,7 @@ export class PostgreSQLClient extends AntaresCore {
/** /**
* DROP DATABASE * DROP DATABASE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof MySQLClient * @memberof MySQLClient
*/ */
async dropSchema (params) { async dropSchema (params) {
@ -558,7 +558,7 @@ export class PostgreSQLClient extends AntaresCore {
/** /**
* DROP VIEW * DROP VIEW
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof PostgreSQLClient * @memberof PostgreSQLClient
*/ */
async dropView (params) { async dropView (params) {
@ -569,7 +569,7 @@ export class PostgreSQLClient extends AntaresCore {
/** /**
* ALTER VIEW * ALTER VIEW
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof PostgreSQLClient * @memberof PostgreSQLClient
*/ */
async alterView (params) { async alterView (params) {
@ -585,7 +585,7 @@ export class PostgreSQLClient extends AntaresCore {
/** /**
* CREATE VIEW * CREATE VIEW
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof PostgreSQLClient * @memberof PostgreSQLClient
*/ */
async createView (params) { async createView (params) {
@ -640,7 +640,7 @@ export class PostgreSQLClient extends AntaresCore {
/** /**
* DROP TRIGGER * DROP TRIGGER
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof PostgreSQLClient * @memberof PostgreSQLClient
*/ */
async dropTrigger (params) { async dropTrigger (params) {
@ -652,7 +652,7 @@ export class PostgreSQLClient extends AntaresCore {
/** /**
* ALTER TRIGGER * ALTER TRIGGER
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof PostgreSQLClient * @memberof PostgreSQLClient
*/ */
async alterTrigger (params) { async alterTrigger (params) {
@ -674,7 +674,7 @@ export class PostgreSQLClient extends AntaresCore {
/** /**
* CREATE TRIGGER * CREATE TRIGGER
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof PostgreSQLClient * @memberof PostgreSQLClient
*/ */
async createTrigger (params) { async createTrigger (params) {
@ -1086,7 +1086,7 @@ export class PostgreSQLClient extends AntaresCore {
/** /**
* CREATE TABLE * CREATE TABLE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof PostgreSQLClient * @memberof PostgreSQLClient
*/ */
async createTable (params) { async createTable (params) {
@ -1144,7 +1144,7 @@ export class PostgreSQLClient extends AntaresCore {
/** /**
* ALTER TABLE * ALTER TABLE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof PostgreSQLClient * @memberof PostgreSQLClient
*/ */
async alterTable (params) { async alterTable (params) {
@ -1290,7 +1290,7 @@ export class PostgreSQLClient extends AntaresCore {
/** /**
* DUPLICATE TABLE * DUPLICATE TABLE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof PostgreSQLClient * @memberof PostgreSQLClient
*/ */
async duplicateTable (params) { async duplicateTable (params) {
@ -1301,7 +1301,7 @@ export class PostgreSQLClient extends AntaresCore {
/** /**
* TRUNCATE TABLE * TRUNCATE TABLE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof PostgreSQLClient * @memberof PostgreSQLClient
*/ */
async truncateTable (params) { async truncateTable (params) {
@ -1312,7 +1312,7 @@ export class PostgreSQLClient extends AntaresCore {
/** /**
* DROP TABLE * DROP TABLE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof PostgreSQLClient * @memberof PostgreSQLClient
*/ */
async dropTable (params) { async dropTable (params) {

View File

@ -2,6 +2,7 @@
import sqlite from 'better-sqlite3'; import sqlite from 'better-sqlite3';
import { AntaresCore } from '../AntaresCore'; import { AntaresCore } from '../AntaresCore';
import dataTypes from 'common/data-types/mysql'; import dataTypes from 'common/data-types/mysql';
import { NUMBER, FLOAT } from 'common/fieldTypes';
export class SQLiteClient extends AntaresCore { export class SQLiteClient extends AntaresCore {
constructor (args) { constructor (args) {
@ -136,95 +137,35 @@ export class SQLiteClient extends AntaresCore {
* @memberof SQLiteClient * @memberof SQLiteClient
*/ */
async getTableColumns ({ schema, table }) { async getTableColumns ({ schema, table }) {
const { rows } = await this const { rows: fields } = await this.raw(`SELECT * FROM "${schema}".pragma_table_info('${table}')`);
.select('*')
.schema('information_schema')
.from('COLUMNS')
.where({ TABLE_SCHEMA: `= '${schema}'`, TABLE_NAME: `= '${table}'` })
.orderBy({ ORDINAL_POSITION: 'ASC' })
.run();
const { rows: fields } = await this.raw(`SHOW CREATE TABLE \`${schema}\`.\`${table}\``); return fields.map(field => {
const [type, length] = field.type.includes('(')
const remappedFields = fields.map(row => { ? field.type.replace(')', '').split('(').map(el => {
if (!row['Create Table']) return false; if (!isNaN(el)) el = +el;
return el;
let n = 0;
return row['Create Table']
.split('')
.reduce((acc, curr) => {
if (curr === ')') n--;
if (n !== 0) acc += curr;
if (curr === '(') n++;
return acc;
}, '')
.replaceAll('\n', '')
.split(',')
.map(f => {
try {
const fieldArr = f.trim().split(' ');
const nameAndType = fieldArr.slice(0, 2);
if (nameAndType[0].charAt(0) !== '`') return false;
const details = fieldArr.slice(2).join(' ');
let defaultValue = null;
if (details.includes('DEFAULT'))
defaultValue = details.match(/(?<=DEFAULT ).*?$/gs)[0].split(' COMMENT')[0];
// const defaultValueArr = defaultValue.split('');
// if (defaultValueArr[0] === '\'') {
// defaultValueArr.shift();
// defaultValueArr.pop();
// defaultValue = defaultValueArr.join('');
// }
const typeAndLength = nameAndType[1].replace(')', '').split('(');
return {
name: nameAndType[0].replaceAll('`', ''),
type: typeAndLength[0].toUpperCase(),
length: typeAndLength[1] ? typeAndLength[1] : null,
default: defaultValue
};
}
catch (err) {
return false;
}
}) })
.filter(Boolean) : [field.type, null];
.reduce((acc, curr) => {
acc[curr.name] = curr;
return acc;
}, {});
})[0];
return rows.map(field => {
let numLength = field.COLUMN_TYPE.match(/int\(([^)]+)\)/);
numLength = numLength ? +numLength.pop() : null;
const enumValues = /(enum|set)/.test(field.COLUMN_TYPE)
? field.COLUMN_TYPE.match(/\(([^)]+)\)/)[0].slice(1, -1)
: null;
return { return {
name: field.COLUMN_NAME, name: field.name,
key: field.COLUMN_KEY.toLowerCase(), key: null,
type: remappedFields ? remappedFields[field.COLUMN_NAME].type : field.DATA_TYPE, type,
schema: field.TABLE_SCHEMA, schema: schema,
table: field.TABLE_NAME, table: table,
numPrecision: field.NUMERIC_PRECISION, numPrecision: [...NUMBER, ...FLOAT].includes(type) ? length : null,
numLength, datePrecision: null,
enumValues, charLength: ![...NUMBER, ...FLOAT].includes(type) ? length : null,
datePrecision: field.DATETIME_PRECISION, nullable: !field.notnull,
charLength: field.CHARACTER_MAXIMUM_LENGTH, unsigned: null,
nullable: field.IS_NULLABLE.includes('YES'), zerofill: null,
unsigned: field.COLUMN_TYPE.includes('unsigned'), order: field.cid + 1,
zerofill: field.COLUMN_TYPE.includes('zerofill'), default: field.dflt_value,
order: field.ORDINAL_POSITION, charset: null,
default: remappedFields ? remappedFields[field.COLUMN_NAME].default : field.COLUMN_DEFAULT, collation: null,
charset: field.CHARACTER_SET_NAME, autoIncrement: false,
collation: field.COLLATION_NAME, onUpdate: null,
autoIncrement: field.EXTRA.includes('auto_increment'), comment: ''
onUpdate: field.EXTRA.toLowerCase().includes('on update') ? field.EXTRA.replace('on update', '') : '',
comment: field.COLUMN_COMMENT
}; };
}); });
} }
@ -250,33 +191,7 @@ export class SQLiteClient extends AntaresCore {
* @memberof SQLiteClient * @memberof SQLiteClient
*/ */
async getTableOptions ({ schema, table }) { async getTableOptions ({ schema, table }) {
const { rows } = await this.raw(`SHOW TABLE STATUS FROM \`${schema}\` WHERE Name = '${table}'`); return { name: table };
if (rows.length) {
let tableType;
switch (rows[0].Comment) {
case 'VIEW':
tableType = 'view';
break;
default:
tableType = 'table';
break;
}
return {
name: rows[0].Name,
type: tableType,
rows: rows[0].Rows,
created: rows[0].Create_time,
updated: rows[0].Update_time,
engine: rows[0].Engine,
comment: rows[0].Comment,
size: rows[0].Data_length + rows[0].Index_length,
autoIncrement: rows[0].Auto_increment,
collation: rows[0].Collation
};
};
return {};
} }
/** /**
@ -331,78 +246,27 @@ export class SQLiteClient extends AntaresCore {
* @memberof SQLiteClient * @memberof SQLiteClient
*/ */
async getKeyUsage ({ schema, table }) { async getKeyUsage ({ schema, table }) {
const { rows } = await this const { rows } = await this.raw(`SELECT * FROM "${schema}".pragma_foreign_key_list('${table}');`);
.select('*')
.schema('information_schema')
.from('KEY_COLUMN_USAGE')
.where({ TABLE_SCHEMA: `= '${schema}'`, TABLE_NAME: `= '${table}'`, REFERENCED_TABLE_NAME: 'IS NOT NULL' })
.run();
const { rows: extras } = await this
.select('*')
.schema('information_schema')
.from('REFERENTIAL_CONSTRAINTS')
.where({ CONSTRAINT_SCHEMA: `= '${schema}'`, TABLE_NAME: `= '${table}'`, REFERENCED_TABLE_NAME: 'IS NOT NULL' })
.run();
return rows.map(field => { return rows.map(field => {
const extra = extras.find(x => x.CONSTRAINT_NAME === field.CONSTRAINT_NAME);
return { return {
schema: field.TABLE_SCHEMA, schema: schema,
table: field.TABLE_NAME, table: table,
field: field.COLUMN_NAME, field: field.from,
position: field.ORDINAL_POSITION, position: field.id + 1,
constraintPosition: field.POSITION_IN_UNIQUE_CONSTRAINT, constraintPosition: null,
constraintName: field.CONSTRAINT_NAME, constraintName: field.id,
refSchema: field.REFERENCED_TABLE_SCHEMA, refSchema: schema,
refTable: field.REFERENCED_TABLE_NAME, refTable: field.table,
refField: field.REFERENCED_COLUMN_NAME, refField: field.to,
onUpdate: extra.UPDATE_RULE, onUpdate: field.on_update,
onDelete: extra.DELETE_RULE onDelete: field.on_delete
}; };
}); });
} }
async getUsers () {} async getUsers () {}
/**
* CREATE DATABASE
*
* @returns {Array.<Object>} parameters
* @memberof SQLiteClient
*/
async createSchema (params) {
return await this.raw(`CREATE DATABASE \`${params.name}\` COLLATE ${params.collation}`);
}
/**
* ALTER DATABASE
*
* @returns {Array.<Object>} parameters
* @memberof SQLiteClient
*/
async alterSchema (params) {
return await this.raw(`ALTER DATABASE \`${params.name}\` COLLATE ${params.collation}`);
}
/**
* DROP DATABASE
*
* @returns {Array.<Object>} parameters
* @memberof SQLiteClient
*/
async dropSchema (params) {
return await this.raw(`DROP DATABASE \`${params.database}\``);
}
/**
* @returns {Array.<Object>} parameters
* @memberof SQLiteClient
*/
async getDatabaseCollation (params) {
return await this.raw(`SELECT \`DEFAULT_COLLATION_NAME\` FROM \`information_schema\`.\`SCHEMATA\` WHERE \`SCHEMA_NAME\`='${params.database}'`);
}
/** /**
* SHOW CREATE VIEW * SHOW CREATE VIEW
* *
@ -534,357 +398,6 @@ export class SQLiteClient extends AntaresCore {
return await this.raw(sql, { split: false }); return await this.raw(sql, { split: false });
} }
/**
* SHOW CREATE PROCEDURE
*
* @returns {Array.<Object>} view informations
* @memberof SQLiteClient
*/
async getRoutineInformations ({ schema, routine }) {
const sql = `SHOW CREATE PROCEDURE \`${schema}\`.\`${routine}\``;
const results = await this.raw(sql);
return results.rows.map(async row => {
if (!row['Create Procedure']) {
return {
definer: null,
sql: '',
parameters: [],
name: row.Procedure,
comment: '',
security: 'DEFINER',
deterministic: false,
dataAccess: 'CONTAINS SQL'
};
}
const sql = `SELECT *
FROM information_schema.parameters
WHERE SPECIFIC_NAME = '${routine}'
AND SPECIFIC_SCHEMA = '${schema}'
ORDER BY ORDINAL_POSITION
`;
const results = await this.raw(sql);
const parameters = results.rows.map(row => {
return {
name: row.PARAMETER_NAME,
type: row.DATA_TYPE.toUpperCase(),
length: row.NUMERIC_PRECISION || row.DATETIME_PRECISION || row.CHARACTER_MAXIMUM_LENGTH || '',
context: row.PARAMETER_MODE
};
});
let dataAccess = 'CONTAINS SQL';
if (row['Create Procedure'].includes('NO SQL'))
dataAccess = 'NO SQL';
if (row['Create Procedure'].includes('READS SQL DATA'))
dataAccess = 'READS SQL DATA';
if (row['Create Procedure'].includes('MODIFIES SQL DATA'))
dataAccess = 'MODIFIES SQL DATA';
return {
definer: row['Create Procedure'].match(/(?<=DEFINER=).*?(?=\s)/gs)[0],
sql: row['Create Procedure'].match(/(BEGIN|begin)(.*)(END|end)/gs)[0],
parameters: parameters || [],
name: row.Procedure,
comment: row['Create Procedure'].match(/(?<=COMMENT ').*?(?=')/gs) ? row['Create Procedure'].match(/(?<=COMMENT ').*?(?=')/gs)[0] : '',
security: row['Create Procedure'].includes('SQL SECURITY INVOKER') ? 'INVOKER' : 'DEFINER',
deterministic: row['Create Procedure'].includes('DETERMINISTIC'),
dataAccess
};
})[0];
}
/**
* DROP PROCEDURE
*
* @returns {Array.<Object>} parameters
* @memberof SQLiteClient
*/
async dropRoutine (params) {
const sql = `DROP PROCEDURE \`${params.schema}\`.\`${params.routine}\``;
return await this.raw(sql);
}
/**
* ALTER PROCEDURE
*
* @returns {Array.<Object>} parameters
* @memberof SQLiteClient
*/
async alterRoutine (params) {
const { routine } = params;
const tempProcedure = Object.assign({}, routine);
tempProcedure.name = `Antares_${tempProcedure.name}_tmp`;
try {
await this.createRoutine(tempProcedure);
await this.dropRoutine({ schema: routine.schema, routine: tempProcedure.name });
await this.dropRoutine({ schema: routine.schema, routine: routine.oldName });
await this.createRoutine(routine);
}
catch (err) {
return Promise.reject(err);
}
}
/**
* CREATE PROCEDURE
*
* @returns {Array.<Object>} parameters
* @memberof SQLiteClient
*/
async createRoutine (params) {
const parameters = 'parameters' in params
? params.parameters.reduce((acc, curr) => {
acc.push(`${curr.context} \`${curr.name}\` ${curr.type}${curr.length ? `(${curr.length})` : ''}`);
return acc;
}, []).join(',')
: '';
const sql = `CREATE ${params.definer ? `DEFINER=${params.definer} ` : ''}PROCEDURE \`${params.schema}\`.\`${params.name}\`(${parameters})
LANGUAGE SQL
${params.deterministic ? 'DETERMINISTIC' : 'NOT DETERMINISTIC'}
${params.dataAccess}
SQL SECURITY ${params.security}
COMMENT '${params.comment}'
${params.sql}`;
return await this.raw(sql, { split: false });
}
/**
* SHOW CREATE FUNCTION
*
* @returns {Array.<Object>} view informations
* @memberof SQLiteClient
*/
async getFunctionInformations ({ schema, func }) {
const sql = `SHOW CREATE FUNCTION \`${schema}\`.\`${func}\``;
const results = await this.raw(sql);
return results.rows.map(async row => {
if (!row['Create Function']) {
return {
definer: null,
sql: '',
parameters: [],
name: row.Procedure,
comment: '',
security: 'DEFINER',
deterministic: false,
dataAccess: 'CONTAINS SQL',
returns: 'INT',
returnsLength: null
};
}
const sql = `SELECT *
FROM information_schema.parameters
WHERE SPECIFIC_NAME = '${func}'
AND SPECIFIC_SCHEMA = '${schema}'
ORDER BY ORDINAL_POSITION
`;
const results = await this.raw(sql);
const parameters = results.rows.filter(row => row.PARAMETER_MODE).map(row => {
return {
name: row.PARAMETER_NAME,
type: row.DATA_TYPE.toUpperCase(),
length: row.NUMERIC_PRECISION || row.DATETIME_PRECISION || row.CHARACTER_MAXIMUM_LENGTH || '',
context: row.PARAMETER_MODE
};
});
let dataAccess = 'CONTAINS SQL';
if (row['Create Function'].includes('NO SQL'))
dataAccess = 'NO SQL';
if (row['Create Function'].includes('READS SQL DATA'))
dataAccess = 'READS SQL DATA';
if (row['Create Function'].includes('MODIFIES SQL DATA'))
dataAccess = 'MODIFIES SQL DATA';
const output = row['Create Function'].match(/(?<=RETURNS ).*?(?=\s)/gs).length ? row['Create Function'].match(/(?<=RETURNS ).*?(?=\s)/gs)[0].replace(')', '').split('(') : ['', null];
return {
definer: row['Create Function'].match(/(?<=DEFINER=).*?(?=\s)/gs)[0],
sql: row['Create Function'].match(/(BEGIN|begin)(.*)(END|end)/gs)[0],
parameters: parameters || [],
name: row.Function,
comment: row['Create Function'].match(/(?<=COMMENT ').*?(?=')/gs) ? row['Create Function'].match(/(?<=COMMENT ').*?(?=')/gs)[0] : '',
security: row['Create Function'].includes('SQL SECURITY INVOKER') ? 'INVOKER' : 'DEFINER',
deterministic: row['Create Function'].includes('DETERMINISTIC'),
dataAccess,
returns: output[0].toUpperCase(),
returnsLength: +output[1]
};
})[0];
}
/**
* DROP FUNCTION
*
* @returns {Array.<Object>} parameters
* @memberof SQLiteClient
*/
async dropFunction (params) {
const sql = `DROP FUNCTION \`${params.schema}\`.\`${params.func}\``;
return await this.raw(sql);
}
/**
* ALTER FUNCTION
*
* @returns {Array.<Object>} parameters
* @memberof SQLiteClient
*/
async alterFunction (params) {
const { func } = params;
const tempProcedure = Object.assign({}, func);
tempProcedure.name = `Antares_${tempProcedure.name}_tmp`;
try {
await this.createFunction(tempProcedure);
await this.dropFunction({ schema: func.schema, func: tempProcedure.name });
await this.dropFunction({ schema: func.schema, func: func.oldName });
await this.createFunction(func);
}
catch (err) {
return Promise.reject(err);
}
}
/**
* CREATE FUNCTION
*
* @returns {Array.<Object>} parameters
* @memberof SQLiteClient
*/
async createFunction (params) {
const parameters = 'parameters' in params
? params.parameters.reduce((acc, curr) => {
acc.push(`\`${curr.name}\` ${curr.type}${curr.length ? `(${curr.length})` : ''}`);
return acc;
}, []).join(',')
: '';
const body = params.returns ? params.sql : 'BEGIN\n RETURN 0;\nEND';
const sql = `CREATE ${params.definer ? `DEFINER=${params.definer} ` : ''}FUNCTION \`${params.schema}\`.\`${params.name}\`(${parameters}) RETURNS ${params.returns || 'SMALLINT'}${params.returnsLength ? `(${params.returnsLength})` : ''}
LANGUAGE SQL
${params.deterministic ? 'DETERMINISTIC' : 'NOT DETERMINISTIC'}
${params.dataAccess}
SQL SECURITY ${params.security}
COMMENT '${params.comment}'
${body}`;
return await this.raw(sql, { split: false });
}
/**
* SHOW CREATE EVENT
*
* @returns {Array.<Object>} view informations
* @memberof SQLiteClient
*/
async getEventInformations ({ schema, scheduler }) {
const sql = `SHOW CREATE EVENT \`${schema}\`.\`${scheduler}\``;
const results = await this.raw(sql);
return results.rows.map(row => {
const schedule = row['Create Event'];
const execution = schedule.includes('EVERY') ? 'EVERY' : 'ONCE';
const every = execution === 'EVERY' ? row['Create Event'].match(/(?<=EVERY )(\s*([^\s]+)){0,2}/gs)[0].replaceAll('\'', '').split(' ') : [];
const starts = execution === 'EVERY' && schedule.includes('STARTS') ? schedule.match(/(?<=STARTS ').*?(?='\s)/gs)[0] : '';
const ends = execution === 'EVERY' && schedule.includes('ENDS') ? schedule.match(/(?<=ENDS ').*?(?='\s)/gs)[0] : '';
const at = execution === 'ONCE' && schedule.includes('AT') ? schedule.match(/(?<=AT ').*?(?='\s)/gs)[0] : '';
return {
definer: row['Create Event'].match(/(?<=DEFINER=).*?(?=\s)/gs)[0],
sql: row['Create Event'].match(/(?<=DO )(.*)/gs)[0],
name: row.Event,
comment: row['Create Event'].match(/(?<=COMMENT ').*?(?=')/gs) ? row['Create Event'].match(/(?<=COMMENT ').*?(?=')/gs)[0] : '',
state: row['Create Event'].includes('ENABLE') ? 'ENABLE' : row['Create Event'].includes('DISABLE ON SLAVE') ? 'DISABLE ON SLAVE' : 'DISABLE',
preserve: row['Create Event'].includes('ON COMPLETION PRESERVE'),
execution,
every,
starts,
ends,
at
};
})[0];
}
/**
* DROP EVENT
*
* @returns {Array.<Object>} parameters
* @memberof SQLiteClient
*/
async dropEvent (params) {
const sql = `DROP EVENT \`${params.schema}\`.\`${params.scheduler}\``;
return await this.raw(sql);
}
/**
* ALTER EVENT
*
* @returns {Array.<Object>} parameters
* @memberof SQLiteClient
*/
async alterEvent (params) {
const { scheduler } = params;
if (scheduler.execution === 'EVERY' && scheduler.every[0].includes('-'))
scheduler.every[0] = `'${scheduler.every[0]}'`;
const sql = `ALTER ${scheduler.definer ? ` DEFINER=${scheduler.definer}` : ''} EVENT \`${scheduler.schema}\`.\`${scheduler.oldName}\`
ON SCHEDULE
${scheduler.execution === 'EVERY'
? `EVERY ${scheduler.every.join(' ')}${scheduler.starts ? ` STARTS '${scheduler.starts}'` : ''}${scheduler.ends ? ` ENDS '${scheduler.ends}'` : ''}`
: `AT '${scheduler.at}'`}
ON COMPLETION${!scheduler.preserve ? ' NOT' : ''} PRESERVE
${scheduler.name !== scheduler.oldName ? `RENAME TO \`${scheduler.schema}\`.\`${scheduler.name}\`` : ''}
${scheduler.state}
COMMENT '${scheduler.comment}'
DO ${scheduler.sql}`;
return await this.raw(sql, { split: false });
}
/**
* CREATE EVENT
*
* @returns {Array.<Object>} parameters
* @memberof SQLiteClient
*/
async createEvent (params) {
const sql = `CREATE ${params.definer ? ` DEFINER=${params.definer}` : ''} EVENT \`${params.schema}\`.\`${params.name}\`
ON SCHEDULE
${params.execution === 'EVERY'
? `EVERY ${params.every.join(' ')}${params.starts ? ` STARTS '${params.starts}'` : ''}${params.ends ? ` ENDS '${params.ends}'` : ''}`
: `AT '${params.at}'`}
ON COMPLETION${!params.preserve ? ' NOT' : ''} PRESERVE
${params.state}
COMMENT '${params.comment}'
DO ${params.sql}`;
return await this.raw(sql, { split: false });
}
async enableEvent ({ schema, scheduler }) {
const sql = `ALTER EVENT \`${schema}\`.\`${scheduler}\` ENABLE`;
return await this.raw(sql, { split: false });
}
async disableEvent ({ schema, scheduler }) {
const sql = `ALTER EVENT \`${schema}\`.\`${scheduler}\` DISABLE`;
return await this.raw(sql, { split: false });
}
/** /**
* SHOW COLLATION * SHOW COLLATION
* *
@ -946,7 +459,7 @@ export class SQLiteClient extends AntaresCore {
/** /**
* CREATE TABLE * CREATE TABLE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof SQLiteClient * @memberof SQLiteClient
*/ */
async createTable (params) { async createTable (params) {
@ -959,48 +472,43 @@ export class SQLiteClient extends AntaresCore {
} = params; } = params;
const newColumns = []; const newColumns = [];
const newIndexes = []; const newIndexes = [];
const manageIndexes = [];
const newForeigns = []; const newForeigns = [];
let sql = `CREATE TABLE \`${schema}\`.\`${options.name}\``; let sql = `CREATE TABLE "${schema}"."${options.name}"`;
// ADD FIELDS // ADD FIELDS
fields.forEach(field => { fields.forEach(field => {
const typeInfo = this._getTypeInfo(field.type); const typeInfo = this._getTypeInfo(field.type);
const length = typeInfo.length ? field.enumValues || field.numLength || field.charLength || field.datePrecision : false; const length = typeInfo?.length ? field.enumValues || field.numLength || field.charLength || field.datePrecision : false;
newColumns.push(`\`${field.name}\` newColumns.push(`"${field.name}"
${field.type.toUpperCase()}${length ? `(${length})` : ''} ${field.type.toUpperCase()}${length && length !== true ? `(${length})` : ''}
${field.unsigned ? 'UNSIGNED' : ''} ${field.unsigned ? 'UNSIGNED' : ''}
${field.zerofill ? 'ZEROFILL' : ''}
${field.nullable ? 'NULL' : 'NOT NULL'} ${field.nullable ? 'NULL' : 'NOT NULL'}
${field.autoIncrement ? 'AUTO_INCREMENT' : ''} ${field.autoIncrement ? 'AUTO_INCREMENT' : ''}
${field.default ? `DEFAULT ${field.default}` : ''} ${field.default ? `DEFAULT ${field.default}` : ''}
${field.comment ? `COMMENT '${field.comment}'` : ''}
${field.collation ? `COLLATE ${field.collation}` : ''}
${field.onUpdate ? `ON UPDATE ${field.onUpdate}` : ''}`); ${field.onUpdate ? `ON UPDATE ${field.onUpdate}` : ''}`);
}); });
// ADD INDEX // ADD INDEX
indexes.forEach(index => { indexes.forEach(index => {
const fields = index.fields.map(field => `\`${field}\``).join(','); const fields = index.fields.map(field => `"${field}"`).join(',');
let type = index.type; const type = index.type;
if (type === 'PRIMARY') if (type === 'PRIMARY')
newIndexes.push(`PRIMARY KEY (${fields})`); newIndexes.push(`PRIMARY KEY (${fields})`);
else { else
if (type === 'UNIQUE') manageIndexes.push(`CREATE ${type === 'UNIQUE' ? type : ''} INDEX "${index.name}" ON "${options.name}" (${fields})`);
type = 'UNIQUE INDEX';
newIndexes.push(`${type} \`${index.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(`CONSTRAINT "${foreign.constraintName}" FOREIGN KEY ("${foreign.field}") REFERENCES "${foreign.refTable}" ("${foreign.refField}") ON UPDATE ${foreign.onUpdate} ON DELETE ${foreign.onDelete}`);
}); });
sql = `${sql} (${[...newColumns, ...newIndexes, ...newForeigns].join(', ')}) COMMENT='${options.comment}', COLLATE='${options.collation}', ENGINE=${options.engine}`; sql = `${sql} (${[...newColumns, ...newIndexes, ...newForeigns].join(', ')})`;
if (manageIndexes.length) sql = `${sql}; ${manageIndexes.join(';')}`;
return await this.raw(sql); return await this.raw(sql);
} }
@ -1008,168 +516,87 @@ export class SQLiteClient extends AntaresCore {
/** /**
* ALTER TABLE * ALTER TABLE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof SQLiteClient * @memberof SQLiteClient
*/ */
async alterTable (params) { async alterTable (params) {
const { try {
table, await this.raw('BEGIN TRANSACTION');
schema, await this.raw('PRAGMA foreign_keys = 0');
additions,
deletions,
changes,
indexChanges,
foreignChanges,
options
} = params;
let sql = `ALTER TABLE \`${schema}\`.\`${table}\` `; const tmpName = `Antares_${params.table}_tmp`;
const alterColumns = []; await this.raw(`CREATE TABLE "${tmpName}" AS SELECT * FROM "${params.table}"`);
await this.dropTable(params);
// OPTIONS const createTableParams = {
if ('comment' in options) alterColumns.push(`COMMENT='${options.comment}'`); schema: params.schema,
if ('engine' in options) alterColumns.push(`ENGINE=${options.engine}`); fields: params.tableStructure.fields,
if ('autoIncrement' in options) alterColumns.push(`AUTO_INCREMENT=${+options.autoIncrement}`); foreigns: params.tableStructure.foreigns,
if ('collation' in options) alterColumns.push(`COLLATE='${options.collation}'`); indexes: params.tableStructure.indexes.filter(index => !index.name.includes('sqlite_autoindex')),
options: { name: params.tableStructure.name }
};
await this.createTable(createTableParams);
const insertFields = createTableParams.fields
.filter(field => {
return (
params.additions.every(add => add.name !== field.name) &&
params.deletions.every(del => del.name !== field.name)
);
})
.reduce((acc, curr) => {
acc.push(`"${curr.name}"`);
return acc;
}, []);
// ADD FIELDS const selectFields = insertFields.map(field => {
additions.forEach(addition => { const renamedField = params.changes.find(change => `"${change.name}"` === field);
const typeInfo = this._getTypeInfo(addition.type); if (renamedField)
const length = typeInfo.length ? addition.enumValues || addition.numLength || addition.charLength || addition.datePrecision : false; return `"${renamedField.orgName}"`;
return field;
alterColumns.push(`ADD COLUMN \`${addition.name}\`
${addition.type.toUpperCase()}${length ? `(${length})` : ''}
${addition.unsigned ? 'UNSIGNED' : ''}
${addition.zerofill ? 'ZEROFILL' : ''}
${addition.nullable ? 'NULL' : 'NOT NULL'}
${addition.autoIncrement ? 'AUTO_INCREMENT' : ''}
${addition.default ? `DEFAULT ${addition.default}` : ''}
${addition.comment ? `COMMENT '${addition.comment}'` : ''}
${addition.collation ? `COLLATE ${addition.collation}` : ''}
${addition.onUpdate ? `ON UPDATE ${addition.onUpdate}` : ''}
${addition.after ? `AFTER \`${addition.after}\`` : 'FIRST'}`);
}); });
// ADD INDEX await this.raw(`INSERT INTO "${createTableParams.options.name}" (${insertFields.join(',')}) SELECT ${selectFields.join(',')} FROM "${tmpName}"`);
indexChanges.additions.forEach(addition => {
const fields = addition.fields.map(field => `\`${field}\``).join(',');
let type = addition.type;
if (type === 'PRIMARY') await this.dropTable({ schema: params.schema, table: tmpName });
alterColumns.push(`ADD PRIMARY KEY (${fields})`); await this.raw('PRAGMA foreign_keys = 1');
else { await this.raw('COMMIT');
if (type === 'UNIQUE')
type = 'UNIQUE INDEX';
alterColumns.push(`ADD ${type} \`${addition.name}\` (${fields})`);
} }
}); catch (err) {
await this.raw('ROLLBACK');
// ADD FOREIGN KEYS return Promise.reject(err);
foreignChanges.additions.forEach(addition => {
alterColumns.push(`ADD CONSTRAINT \`${addition.constraintName}\` FOREIGN KEY (\`${addition.field}\`) REFERENCES \`${addition.refTable}\` (\`${addition.refField}\`) ON UPDATE ${addition.onUpdate} ON DELETE ${addition.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;
alterColumns.push(`CHANGE COLUMN \`${change.orgName}\` \`${change.name}\`
${change.type.toUpperCase()}${length ? `(${length})` : ''}
${change.unsigned ? 'UNSIGNED' : ''}
${change.zerofill ? 'ZEROFILL' : ''}
${change.nullable ? 'NULL' : 'NOT NULL'}
${change.autoIncrement ? 'AUTO_INCREMENT' : ''}
${change.default ? `DEFAULT ${change.default}` : ''}
${change.comment ? `COMMENT '${change.comment}'` : ''}
${change.collation ? `COLLATE ${change.collation}` : ''}
${change.onUpdate ? `ON UPDATE ${change.onUpdate}` : ''}
${change.after ? `AFTER \`${change.after}\`` : 'FIRST'}`);
});
// CHANGE INDEX
indexChanges.changes.forEach(change => {
if (change.oldType === 'PRIMARY')
alterColumns.push('DROP PRIMARY KEY');
else
alterColumns.push(`DROP INDEX \`${change.oldName}\``);
const fields = change.fields.map(field => `\`${field}\``).join(',');
let type = change.type;
if (type === 'PRIMARY')
alterColumns.push(`ADD PRIMARY KEY (${fields})`);
else {
if (type === 'UNIQUE')
type = 'UNIQUE INDEX';
alterColumns.push(`ADD ${type} \`${change.name}\` (${fields})`);
} }
});
// CHANGE FOREIGN KEYS
foreignChanges.changes.forEach(change => {
alterColumns.push(`DROP FOREIGN KEY \`${change.oldName}\``);
alterColumns.push(`ADD CONSTRAINT \`${change.constraintName}\` FOREIGN KEY (\`${change.field}\`) REFERENCES \`${change.refTable}\` (\`${change.refField}\`) ON UPDATE ${change.onUpdate} ON DELETE ${change.onDelete}`);
});
// DROP FIELDS
deletions.forEach(deletion => {
alterColumns.push(`DROP COLUMN \`${deletion.name}\``);
});
// DROP INDEX
indexChanges.deletions.forEach(deletion => {
if (deletion.type === 'PRIMARY')
alterColumns.push('DROP PRIMARY KEY');
else
alterColumns.push(`DROP INDEX \`${deletion.name}\``);
});
// DROP FOREIGN KEYS
foreignChanges.deletions.forEach(deletion => {
alterColumns.push(`DROP FOREIGN KEY \`${deletion.constraintName}\``);
});
sql += alterColumns.join(', ');
// RENAME
if (options.name) sql += `; RENAME TABLE \`${schema}\`.\`${table}\` TO \`${schema}\`.\`${options.name}\``;
return await this.raw(sql);
} }
/** /**
* DUPLICATE TABLE * DUPLICATE TABLE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof SQLiteClient * @memberof SQLiteClient
*/ */
async duplicateTable (params) { async duplicateTable (params) { // TODO: retrive table informations and create a copy
const sql = `CREATE TABLE \`${params.schema}\`.\`${params.table}_copy\` LIKE \`${params.schema}\`.\`${params.table}\``; const sql = `CREATE TABLE "${params.schema}"."${params.table}_copy" AS SELECT * FROM "${params.schema}"."${params.table}"`;
return await this.raw(sql); return await this.raw(sql);
} }
/** /**
* TRUNCATE TABLE * TRUNCATE TABLE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof SQLiteClient * @memberof SQLiteClient
*/ */
async truncateTable (params) { async truncateTable (params) {
const sql = `TRUNCATE TABLE \`${params.schema}\`.\`${params.table}\``; const sql = `DELETE FROM "${params.schema}"."${params.table}"`;
return await this.raw(sql); return await this.raw(sql);
} }
/** /**
* DROP TABLE * DROP TABLE
* *
* @returns {Array.<Object>} parameters * @returns {Promise<null>}
* @memberof SQLiteClient * @memberof SQLiteClient
*/ */
async dropTable (params) { async dropTable (params) {
const sql = `DROP TABLE \`${params.schema}\`.\`${params.table}\``; const sql = `DROP TABLE "${params.schema}"."${params.table}"`;
return await this.raw(sql); return await this.raw(sql);
} }
@ -1303,6 +730,10 @@ export class SQLiteClient extends AntaresCore {
let remappedFields = fields let remappedFields = fields
? fields.map(field => { ? fields.map(field => {
const parsedType = field.type?.includes('(')
? field.type.split('(')[0]
: field.type;
return { return {
name: field.name, name: field.name,
alias: field.name, alias: field.name,
@ -1311,7 +742,7 @@ export class SQLiteClient extends AntaresCore {
table: field.table, table: field.table,
tableAlias: field.table, tableAlias: field.table,
orgTable: field.table, orgTable: field.table,
type: field.type !== null ? field.type : detectedTypes[field.name] type: field.type !== null ? parsedType : detectedTypes[field.name]
}; };
}).filter(Boolean) }).filter(Boolean)
: []; : [];

View File

@ -13,6 +13,7 @@
<span class="workspace-explorebar-title">{{ connectionName }}</span> <span class="workspace-explorebar-title">{{ connectionName }}</span>
<span v-if="workspace.connectionStatus === 'connected'" class="workspace-explorebar-tools"> <span v-if="workspace.connectionStatus === 'connected'" class="workspace-explorebar-tools">
<i <i
v-if="customizations.schemas"
class="mdi mdi-18px mdi-database-plus c-hand mr-2" class="mdi mdi-18px mdi-database-plus c-hand mr-2"
:title="$t('message.createNewSchema')" :title="$t('message.createNewSchema')"
@click="showNewDBModal" @click="showNewDBModal"

View File

@ -65,7 +65,11 @@
> >
<span class="d-flex"><i class="mdi mdi-18px mdi-database-edit text-light pr-1" /> {{ $t('word.edit') }}</span> <span class="d-flex"><i class="mdi mdi-18px mdi-database-edit text-light pr-1" /> {{ $t('word.edit') }}</span>
</div> </div>
<div class="context-element" @click="showDeleteModal"> <div
v-if="workspace.customizations.schemaDrop"
class="context-element"
@click="showDeleteModal"
>
<span class="d-flex"><i class="mdi mdi-18px mdi-database-remove text-light pr-1" /> {{ $t('word.delete') }}</span> <span class="d-flex"><i class="mdi mdi-18px mdi-database-remove text-light pr-1" /> {{ $t('word.delete') }}</span>
</div> </div>

View File

@ -506,6 +506,12 @@ export default {
uid: this.connection.uid, uid: this.connection.uid,
schema: this.schema, schema: this.schema,
table: this.table, table: this.table,
tableStructure: {
name: this.localOptions.name,
fields: this.localFields,
foreigns: this.localKeyUsage,
indexes: this.localIndexes
},
additions, additions,
changes, changes,
deletions, deletions,

View File

@ -367,7 +367,8 @@ export default {
getWorkspace: 'workspaces/getWorkspace' getWorkspace: 'workspaces/getWorkspace'
}), }),
localLength () { localLength () {
return this.localRow.numLength || this.localRow.charLength || this.localRow.datePrecision || this.localRow.numPrecision || 0; const localLength = this.localRow.numLength || this.localRow.charLength || this.localRow.datePrecision || this.localRow.numPrecision || 0;
return localLength === true ? null : localLength;
}, },
fieldType () { fieldType () {
const fieldType = this.dataTypes.reduce((acc, group) => [...acc, ...group.types], []).filter(type => const fieldType = this.dataTypes.reduce((acc, group) => [...acc, ...group.types], []).filter(type =>
@ -391,7 +392,7 @@ export default {
return this.indexes.some(index => ['PRIMARY', 'UNIQUE'].includes(index.type)); return this.indexes.some(index => ['PRIMARY', 'UNIQUE'].includes(index.type));
}, },
isNullable () { isNullable () {
return !this.indexes.some(index => ['PRIMARY'].includes(index.type)); return this.customizations.nullablePrimary || !this.indexes.some(index => ['PRIMARY'].includes(index.type));
}, },
isInDataTypes () { isInDataTypes () {
let typeNames = []; let typeNames = [];

View File

@ -413,8 +413,8 @@ export default {
customizations = require('common/customizations/postgresql'); customizations = require('common/customizations/postgresql');
break; break;
case 'sqlite': case 'sqlite':
// dataTypes = require('common/data-types/sqlite'); dataTypes = require('common/data-types/sqlite');
// indexTypes = require('common/index-types/sqlite'); indexTypes = require('common/index-types/sqlite');
customizations = require('common/customizations/sqlite'); customizations = require('common/customizations/sqlite');
break; break;
} }