feat: refs #7562 deleteDeprecatedObjects #6
|
@ -1,2 +1,4 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
db
|
||||
myt.config.yml
|
||||
juan marked this conversation as resolved
Outdated
|
|
@ -6,6 +6,11 @@ mockFunctions:
|
|||
- mockTime
|
||||
- mockUtcTime
|
||||
sumViews: true
|
||||
defaultDefiner: root@localhost
|
||||
deprecMarkRegex: __$
|
||||
deprecCommentRegex: ^@deprecated [0-9]{4}-[0-9]{2}-[0-9]{2}
|
||||
deprecDateRegex: '[0-9]{4}-[0-9]{2}-[0-9]{2}'
|
||||
deprecRetentionPeriod: 60 # Days
|
||||
privileges:
|
||||
userTable: global_priv
|
||||
userWhere: >-
|
||||
|
|
|
@ -43,7 +43,7 @@ class Create extends Command {
|
|||
const params = {
|
||||
schema,
|
||||
name,
|
||||
definer: 'root@localhost'
|
||||
definer: opts.defaultDefiner
|
||||
};
|
||||
|
||||
switch (opts.type) {
|
||||
|
|
126
myt-version.js
126
myt-version.js
|
@ -1,6 +1,7 @@
|
|||
const Myt = require('./myt');
|
||||
const Command = require('./lib/command');
|
||||
const fs = require('fs-extra');
|
||||
const SqlString = require('sqlstring');
|
||||
|
||||
/**
|
||||
* Creates a new version.
|
||||
|
@ -18,7 +19,7 @@ class Version extends Command {
|
|||
static opts = {
|
||||
alias: {
|
||||
name: 'n',
|
||||
guillermo marked this conversation as resolved
juan
commented
Los alias solo tienen que tener una letra y hacer referencia a una palabra inglesa, ej: Los alias solo tienen que tener una letra y hacer referencia a una palabra inglesa, ej: `-p`
|
||||
deprecate: 'kk'
|
||||
deprecate: 'p'
|
||||
},
|
||||
string: [
|
||||
'name'
|
||||
|
@ -128,12 +129,15 @@ class Version extends Command {
|
|||
);
|
||||
await fs.mkdir(newVersionDir);
|
||||
|
||||
await fs.writeFile(
|
||||
`${newVersionDir}/00-firstScript.sql`,
|
||||
opts.deprecate
|
||||
? (this.emit('deprecate'), await deprecate(conn))
|
||||
: '-- Place your SQL code here\n'
|
||||
);
|
||||
if (opts.deprecate) {
|
||||
this.emit('deprecate');
|
||||
await deprecate(conn, opts, newVersionDir);
|
||||
}
|
||||
else
|
||||
guillermo marked this conversation as resolved
juan
commented
`else` y `}` deben estar en la misma linea: `} else`
|
||||
await fs.writeFile(
|
||||
`${newVersionDir}/00-firstScript.sql`,
|
||||
'-- Place your SQL code here\n'
|
||||
);
|
||||
|
||||
this.emit('versionCreated', versionFolder);
|
||||
|
||||
|
@ -147,67 +151,103 @@ class Version extends Command {
|
|||
}
|
||||
}
|
||||
|
||||
async function deprecate(conn) {
|
||||
const [[config]] = await conn.query(`
|
||||
SELECT dateRegex,
|
||||
deprecatedMarkRegex,
|
||||
VN_CURDATE() - INTERVAL daysKeepDeprecatedObjects DAY dated
|
||||
FROM config
|
||||
`);
|
||||
async function deprecate(conn, opts, newVersionDir) {
|
||||
const now = new Date();
|
||||
const minDeprecDate = new Date(now.getTime() - opts.deprecRetentionPeriod * 24 * 60 * 60 * 1000);
|
||||
guillermo marked this conversation as resolved
Outdated
juan
commented
Usar el fichero de configuración de Myt para estos parámetros Usar el fichero de configuración de Myt para estos parámetros
|
||||
const deprecMarkRegex = opts.deprecMarkRegex;
|
||||
const deprecCommentRegex = opts.deprecCommentRegex;
|
||||
const deprecDateRegex = opts.deprecDateRegex;
|
||||
const filePath = `${newVersionDir}/00-deprecate.sql`;
|
||||
|
||||
if (!config || Object.values(config).some(value => value == null || value === ''))
|
||||
throw new Error('missing configuration variables');
|
||||
|
||||
const [sql] = await conn.query(`
|
||||
WITH variables AS (
|
||||
SELECT ? markRegex, ? dateRegex, ? dated
|
||||
)
|
||||
SELECT CONCAT('ALTER TABLE ', c.TABLE_SCHEMA, '.', c.TABLE_NAME, ' DROP PRIMARY KEY;') "sql"
|
||||
// Generate the drops of the primary keys
|
||||
const [primaryKeys] = await conn.query(`
|
||||
SELECT c.TABLE_SCHEMA 'schema', c.TABLE_NAME 'table'
|
||||
FROM information_schema.COLUMNS c
|
||||
LEFT JOIN information_schema.VIEWS v ON v.TABLE_SCHEMA = c.TABLE_SCHEMA
|
||||
AND v.TABLE_NAME = c.TABLE_NAME
|
||||
JOIN information_schema.STATISTICS s ON s.TABLE_SCHEMA = c.TABLE_SCHEMA
|
||||
AND s.TABLE_NAME = c.TABLE_NAME
|
||||
AND s.COLUMN_NAME = c.COLUMN_NAME
|
||||
JOIN variables var
|
||||
WHERE c.COLUMN_NAME REGEXP var.markRegex COLLATE utf8mb4_unicode_ci
|
||||
AND REGEXP_SUBSTR(c.COLUMN_COMMENT, var.dateRegex COLLATE utf8mb4_unicode_ci) < var.dated
|
||||
WHERE c.COLUMN_NAME REGEXP ? COLLATE utf8mb4_unicode_ci
|
||||
AND c.COLUMN_COMMENT REGEXP ? COLLATE utf8mb4_unicode_ci
|
||||
AND REGEXP_SUBSTR(c.COLUMN_COMMENT, ? COLLATE utf8mb4_unicode_ci) < ?
|
||||
AND v.TABLE_NAME IS NULL
|
||||
AND s.INDEX_NAME = 'PRIMARY'
|
||||
UNION
|
||||
SELECT CONCAT('ALTER TABLE ', c.TABLE_SCHEMA, '.', c.TABLE_NAME, ' DROP FOREIGN KEY ', kcu.CONSTRAINT_NAME, ';')
|
||||
`, [deprecMarkRegex, deprecCommentRegex, deprecDateRegex, minDeprecDate]);
|
||||
|
||||
primaryKeys.map(async row => {
|
||||
await fs.appendFile(
|
||||
filePath,
|
||||
'ALTER TABLE ' + SqlString.escapeId(row.schema, true) + '.' +
|
||||
SqlString.escapeId(row.table, true) + ' DROP PRIMARY KEY;\n'
|
||||
);
|
||||
});
|
||||
|
||||
// Generate the drops of the foreign keys
|
||||
const [foreignKeys] = await conn.query(`
|
||||
SELECT c.TABLE_SCHEMA 'schema', c.TABLE_NAME 'table', kcu.CONSTRAINT_NAME 'constraint'
|
||||
FROM information_schema.COLUMNS c
|
||||
LEFT JOIN information_schema.VIEWS v ON v.TABLE_SCHEMA = c.TABLE_SCHEMA
|
||||
AND v.TABLE_NAME = c.TABLE_NAME
|
||||
JOIN information_schema.KEY_COLUMN_USAGE kcu ON kcu.TABLE_SCHEMA = c.TABLE_SCHEMA
|
||||
AND kcu.TABLE_NAME = c.TABLE_NAME
|
||||
AND kcu.COLUMN_NAME = c.COLUMN_NAME
|
||||
JOIN variables var
|
||||
WHERE c.COLUMN_NAME REGEXP var.markRegex COLLATE utf8mb4_unicode_ci
|
||||
AND REGEXP_SUBSTR(c.COLUMN_COMMENT, var.dateRegex COLLATE utf8mb4_unicode_ci) < var.dated
|
||||
WHERE c.COLUMN_NAME REGEXP ? COLLATE utf8mb4_unicode_ci
|
||||
AND c.COLUMN_COMMENT REGEXP ? COLLATE utf8mb4_unicode_ci
|
||||
AND REGEXP_SUBSTR(c.COLUMN_COMMENT, ? COLLATE utf8mb4_unicode_ci) < ?
|
||||
AND v.TABLE_NAME IS NULL
|
||||
AND kcu.REFERENCED_COLUMN_NAME IS NOT NULL
|
||||
UNION
|
||||
SELECT CONCAT('ALTER TABLE ', c.TABLE_SCHEMA, '.', c.TABLE_NAME, ' DROP COLUMN ', c.COLUMN_NAME, ';')
|
||||
`, [deprecMarkRegex, deprecCommentRegex, deprecDateRegex, minDeprecDate]);
|
||||
|
||||
foreignKeys.map(async row => {
|
||||
await fs.appendFile(
|
||||
filePath,
|
||||
'ALTER TABLE ' + SqlString.escapeId(row.schema, true) + '.' +
|
||||
SqlString.escapeId(row.table, true) + ' DROP FOREIGN KEY ' +
|
||||
SqlString.escapeId(row.constraint, true) + ';\n'
|
||||
);
|
||||
guillermo marked this conversation as resolved
Outdated
juan
commented
- Generar el SQL con Javascript en lugar de usar CONCATs SQL
- Escapar identificadores (nombres de esquemas, tablas, columnas...)
- Hacer comprobación **estricta** del patron `@deprecated YYYY-MM-DD`
|
||||
});
|
||||
|
||||
// Generate the drops of the columns
|
||||
const [columns] = await conn.query(`
|
||||
SELECT c.TABLE_SCHEMA 'schema', c.TABLE_NAME 'table', c.COLUMN_NAME 'column'
|
||||
FROM information_schema.COLUMNS c
|
||||
LEFT JOIN information_schema.VIEWS v ON v.TABLE_SCHEMA = c.TABLE_SCHEMA
|
||||
AND v.TABLE_NAME = c.TABLE_NAME
|
||||
LEFT JOIN information_schema.KEY_COLUMN_USAGE kcu ON kcu.TABLE_SCHEMA = c.TABLE_SCHEMA
|
||||
AND kcu.TABLE_NAME = c.TABLE_NAME
|
||||
AND kcu.COLUMN_NAME = c.COLUMN_NAME
|
||||
JOIN variables var
|
||||
WHERE c.COLUMN_NAME REGEXP var.markRegex COLLATE utf8mb4_unicode_ci
|
||||
AND REGEXP_SUBSTR(c.COLUMN_COMMENT, var.dateRegex COLLATE utf8mb4_unicode_ci) < var.dated
|
||||
WHERE c.COLUMN_NAME REGEXP ? COLLATE utf8mb4_unicode_ci
|
||||
AND c.COLUMN_COMMENT REGEXP ? COLLATE utf8mb4_unicode_ci
|
||||
AND REGEXP_SUBSTR(c.COLUMN_COMMENT, ? COLLATE utf8mb4_unicode_ci) <?
|
||||
AND v.TABLE_NAME IS NULL
|
||||
UNION
|
||||
SELECT CONCAT('DROP TABLE ', t.TABLE_SCHEMA, '.', t.TABLE_NAME, ';')
|
||||
FROM information_schema.TABLES t
|
||||
JOIN variables var
|
||||
WHERE t.TABLE_NAME REGEXP var.markRegex COLLATE utf8mb4_unicode_ci
|
||||
AND REGEXP_SUBSTR(t.TABLE_COMMENT, var.dateRegex COLLATE utf8mb4_unicode_ci) < var.dated
|
||||
`, [config.deprecatedMarkRegex, config.dateRegex, config.dated]);
|
||||
`, [deprecMarkRegex, deprecCommentRegex, deprecDateRegex, minDeprecDate]);
|
||||
|
||||
return sql.map(row => row.sql).join('\n');
|
||||
columns.map(async row => {
|
||||
await fs.appendFile(
|
||||
filePath,
|
||||
'ALTER TABLE ' + SqlString.escapeId(row.schema, true) + '.' +
|
||||
SqlString.escapeId(row.table, true) + ' DROP COLUMN ' +
|
||||
SqlString.escapeId(row.column, true) + ';\n'
|
||||
);
|
||||
});
|
||||
|
||||
// Generate the drops of the tables
|
||||
const [tables] = await conn.query(`
|
||||
SELECT TABLE_SCHEMA 'schema', TABLE_NAME 'table'
|
||||
FROM information_schema.TABLES
|
||||
WHERE TABLE_NAME REGEXP ? COLLATE utf8mb4_unicode_ci
|
||||
AND TABLE_COMMENT REGEXP ? COLLATE utf8mb4_unicode_ci
|
||||
AND REGEXP_SUBSTR(TABLE_COMMENT, ? COLLATE utf8mb4_unicode_ci) < ?
|
||||
`, [deprecMarkRegex, deprecCommentRegex, deprecDateRegex, minDeprecDate]);
|
||||
|
||||
tables.map(async row => {
|
||||
await fs.appendFile(
|
||||
filePath,
|
||||
'DROP TABLE ' + SqlString.escapeId(row.schema, true) + '.' +
|
||||
SqlString.escapeId(row.table, true) + ';\n'
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function randomName() {
|
||||
|
|
Loading…
Reference in New Issue
Porque se añaden al gitignore?
Porque si te lo montas para probarlo en el mismo proyecto, te puede subir sin querer los archivos
El proyecto debe probarse desde otro directorio, inicializado con
myt init
.