feat: refs #7562 No sql concat and more

This commit is contained in:
Guillermo Bonet 2024-09-06 09:46:24 +02:00
parent a38cda0ba3
commit 5ac41532d9
4 changed files with 91 additions and 44 deletions

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
.DS_Store .DS_Store
node_modules node_modules
db
myt.config.yml

View File

@ -6,6 +6,11 @@ mockFunctions:
- mockTime - mockTime
- mockUtcTime - mockUtcTime
sumViews: true 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: privileges:
userTable: global_priv userTable: global_priv
userWhere: >- userWhere: >-

View File

@ -43,7 +43,7 @@ class Create extends Command {
const params = { const params = {
schema, schema,
name, name,
definer: 'root@localhost' definer: opts.defaultDefiner
}; };
switch (opts.type) { switch (opts.type) {

View File

@ -1,6 +1,7 @@
const Myt = require('./myt'); const Myt = require('./myt');
const Command = require('./lib/command'); const Command = require('./lib/command');
const fs = require('fs-extra'); const fs = require('fs-extra');
const SqlString = require('sqlstring');
/** /**
* Creates a new version. * Creates a new version.
@ -18,7 +19,7 @@ class Version extends Command {
static opts = { static opts = {
alias: { alias: {
name: 'n', name: 'n',
deprecate: 'kk' deprecate: 'p'
}, },
string: [ string: [
'name' 'name'
@ -128,11 +129,14 @@ class Version extends Command {
); );
await fs.mkdir(newVersionDir); await fs.mkdir(newVersionDir);
if (opts.deprecate) {
this.emit('deprecate');
await deprecate(conn, opts, newVersionDir);
}
else
await fs.writeFile( await fs.writeFile(
`${newVersionDir}/00-firstScript.sql`, `${newVersionDir}/00-firstScript.sql`,
opts.deprecate '-- Place your SQL code here\n'
? (this.emit('deprecate'), await deprecate(conn))
: '-- Place your SQL code here\n'
); );
this.emit('versionCreated', versionFolder); this.emit('versionCreated', versionFolder);
@ -147,67 +151,103 @@ class Version extends Command {
} }
} }
async function deprecate(conn) { async function deprecate(conn, opts, newVersionDir) {
const [[config]] = await conn.query(` const now = new Date();
SELECT dateRegex, const minDeprecDate = new Date(now.getTime() - opts.deprecRetentionPeriod * 24 * 60 * 60 * 1000);
deprecatedMarkRegex, const deprecMarkRegex = opts.deprecMarkRegex;
VN_CURDATE() - INTERVAL daysKeepDeprecatedObjects DAY dated const deprecCommentRegex = opts.deprecCommentRegex;
FROM config const deprecDateRegex = opts.deprecDateRegex;
`); const filePath = `${newVersionDir}/00-deprecate.sql`;
if (!config || Object.values(config).some(value => value == null || value === '')) // Generate the drops of the primary keys
throw new Error('missing configuration variables'); const [primaryKeys] = await conn.query(`
SELECT c.TABLE_SCHEMA 'schema', c.TABLE_NAME 'table'
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"
FROM information_schema.COLUMNS c FROM information_schema.COLUMNS c
LEFT JOIN information_schema.VIEWS v ON v.TABLE_SCHEMA = c.TABLE_SCHEMA LEFT JOIN information_schema.VIEWS v ON v.TABLE_SCHEMA = c.TABLE_SCHEMA
AND v.TABLE_NAME = c.TABLE_NAME AND v.TABLE_NAME = c.TABLE_NAME
JOIN information_schema.STATISTICS s ON s.TABLE_SCHEMA = c.TABLE_SCHEMA JOIN information_schema.STATISTICS s ON s.TABLE_SCHEMA = c.TABLE_SCHEMA
AND s.TABLE_NAME = c.TABLE_NAME AND s.TABLE_NAME = c.TABLE_NAME
AND s.COLUMN_NAME = c.COLUMN_NAME AND s.COLUMN_NAME = c.COLUMN_NAME
JOIN variables var WHERE c.COLUMN_NAME REGEXP ? COLLATE utf8mb4_unicode_ci
WHERE c.COLUMN_NAME REGEXP var.markRegex COLLATE utf8mb4_unicode_ci AND c.COLUMN_COMMENT REGEXP ? COLLATE utf8mb4_unicode_ci
AND REGEXP_SUBSTR(c.COLUMN_COMMENT, var.dateRegex COLLATE utf8mb4_unicode_ci) < var.dated AND REGEXP_SUBSTR(c.COLUMN_COMMENT, ? COLLATE utf8mb4_unicode_ci) < ?
AND v.TABLE_NAME IS NULL AND v.TABLE_NAME IS NULL
AND s.INDEX_NAME = 'PRIMARY' AND s.INDEX_NAME = 'PRIMARY'
UNION `, [deprecMarkRegex, deprecCommentRegex, deprecDateRegex, minDeprecDate]);
SELECT CONCAT('ALTER TABLE ', c.TABLE_SCHEMA, '.', c.TABLE_NAME, ' DROP FOREIGN KEY ', kcu.CONSTRAINT_NAME, ';')
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 FROM information_schema.COLUMNS c
LEFT JOIN information_schema.VIEWS v ON v.TABLE_SCHEMA = c.TABLE_SCHEMA LEFT JOIN information_schema.VIEWS v ON v.TABLE_SCHEMA = c.TABLE_SCHEMA
AND v.TABLE_NAME = c.TABLE_NAME AND v.TABLE_NAME = c.TABLE_NAME
JOIN information_schema.KEY_COLUMN_USAGE kcu ON kcu.TABLE_SCHEMA = c.TABLE_SCHEMA JOIN information_schema.KEY_COLUMN_USAGE kcu ON kcu.TABLE_SCHEMA = c.TABLE_SCHEMA
AND kcu.TABLE_NAME = c.TABLE_NAME AND kcu.TABLE_NAME = c.TABLE_NAME
AND kcu.COLUMN_NAME = c.COLUMN_NAME AND kcu.COLUMN_NAME = c.COLUMN_NAME
JOIN variables var WHERE c.COLUMN_NAME REGEXP ? COLLATE utf8mb4_unicode_ci
WHERE c.COLUMN_NAME REGEXP var.markRegex COLLATE utf8mb4_unicode_ci AND c.COLUMN_COMMENT REGEXP ? COLLATE utf8mb4_unicode_ci
AND REGEXP_SUBSTR(c.COLUMN_COMMENT, var.dateRegex COLLATE utf8mb4_unicode_ci) < var.dated AND REGEXP_SUBSTR(c.COLUMN_COMMENT, ? COLLATE utf8mb4_unicode_ci) < ?
AND v.TABLE_NAME IS NULL AND v.TABLE_NAME IS NULL
AND kcu.REFERENCED_COLUMN_NAME IS NOT NULL AND kcu.REFERENCED_COLUMN_NAME IS NOT NULL
UNION `, [deprecMarkRegex, deprecCommentRegex, deprecDateRegex, minDeprecDate]);
SELECT CONCAT('ALTER TABLE ', c.TABLE_SCHEMA, '.', c.TABLE_NAME, ' DROP COLUMN ', c.COLUMN_NAME, ';')
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'
);
});
// 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 FROM information_schema.COLUMNS c
LEFT JOIN information_schema.VIEWS v ON v.TABLE_SCHEMA = c.TABLE_SCHEMA LEFT JOIN information_schema.VIEWS v ON v.TABLE_SCHEMA = c.TABLE_SCHEMA
AND v.TABLE_NAME = c.TABLE_NAME AND v.TABLE_NAME = c.TABLE_NAME
LEFT JOIN information_schema.KEY_COLUMN_USAGE kcu ON kcu.TABLE_SCHEMA = c.TABLE_SCHEMA LEFT JOIN information_schema.KEY_COLUMN_USAGE kcu ON kcu.TABLE_SCHEMA = c.TABLE_SCHEMA
AND kcu.TABLE_NAME = c.TABLE_NAME AND kcu.TABLE_NAME = c.TABLE_NAME
AND kcu.COLUMN_NAME = c.COLUMN_NAME AND kcu.COLUMN_NAME = c.COLUMN_NAME
JOIN variables var WHERE c.COLUMN_NAME REGEXP ? COLLATE utf8mb4_unicode_ci
WHERE c.COLUMN_NAME REGEXP var.markRegex COLLATE utf8mb4_unicode_ci AND c.COLUMN_COMMENT REGEXP ? COLLATE utf8mb4_unicode_ci
AND REGEXP_SUBSTR(c.COLUMN_COMMENT, var.dateRegex COLLATE utf8mb4_unicode_ci) < var.dated AND REGEXP_SUBSTR(c.COLUMN_COMMENT, ? COLLATE utf8mb4_unicode_ci) <?
AND v.TABLE_NAME IS NULL AND v.TABLE_NAME IS NULL
UNION `, [deprecMarkRegex, deprecCommentRegex, deprecDateRegex, minDeprecDate]);
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]);
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() { function randomName() {