@magic-mustard/sqlsync
Version:
SQLSync simplifies database schema evolution by allowing a declarative approach to table management
107 lines (106 loc) • 5.24 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AlterTablesProcessor = void 0;
const namespace_1 = require("../namespace");
const namespace_2 = require("./namespace");
const logger_1 = require("../../utils/logger");
const crypto_1 = require("crypto");
class AlterTablesProcessor extends namespace_1.Parser.AbstractProcessor {
constructor(file, migrations, state, contentBetweenFlags) {
super(file, migrations, state, contentBetweenFlags);
}
process() {
// Extract alter table statements from the file content
const alterTableBlocks = this.getAlterTableBlocks();
// Process each block of statements
this.processAlterTableBlocks(alterTableBlocks);
}
getAlterTableBlocks() {
// Extract ALTER TABLE statements directly from file content
const content = this.file.contents;
const alterTableRegex = /ALTER\s+TABLE\s+[\w."]+\s+[^;]*;/gi;
const matches = content.match(alterTableRegex) || [];
logger_1.logger.debug(`Extracted ALTER TABLE statements: ${matches.length} found`);
return matches;
}
hasAlterTableStatements() {
try {
const blocks = this.getAlterTableBlocks();
return blocks.length > 0;
}
catch (error) {
return false;
}
}
processAlterTableBlocks(blocks) {
// Get the full migration state for alter tables
const migrationState = this.state.getMigrationState(namespace_2.Tables.AlterTableStateIndex);
for (const block of blocks) {
if (!this.validateAlterTableBlock(block)) {
throw new Error(`Invalid ALTER TABLE block in file: ${this.file.path}`);
}
const statements = this.splitIntoAlterStatements(block);
for (const statement of statements) {
const checksum = this.generateChecksum(statement);
// Check if this statement already exists in any migration
let statementExists = false;
for (const [, namespaceData] of Object.entries(migrationState)) {
if (namespaceData[namespace_2.Tables.AlterTableStateIndex] && Object.values(namespaceData[namespace_2.Tables.AlterTableStateIndex]).some((statements) => statements.includes(checksum))) {
statementExists = true;
break;
}
if (statementExists)
break;
}
if (statementExists) {
// Silently ignore as it's already in the state
continue;
}
// Get the current migration state to update using getLatestMigrationName
const currentMigration = this.migrations.getLatestMigrationName();
if (!migrationState[currentMigration]) {
migrationState[currentMigration] = { [namespace_2.Tables.AlterTableStateIndex]: {} };
}
const currentState = migrationState[currentMigration];
// Extract schema and table name from the ALTER TABLE statement
const schemaTableName = this.extractSchemaTableNameFromAlter(statement);
if (!schemaTableName) {
throw new Error(`Failed to extract schema and table name from ALTER TABLE statement in file: ${this.file.path}`);
}
// If new, add to state
if (!currentState[namespace_2.Tables.AlterTableStateIndex][schemaTableName]) {
currentState[namespace_2.Tables.AlterTableStateIndex][schemaTableName] = [];
}
currentState[namespace_2.Tables.AlterTableStateIndex][schemaTableName].push(checksum);
// Update state for the latest migration only
this.state.updateMigrationState(currentState);
// Append to migration
this.migrations.append({
token: statement,
filePath: this.file.path,
checksum: checksum
});
}
}
}
validateAlterTableBlock(block) {
// Simple validation for now; could be improved with a proper SQL parser
const hasAlterTable = block.match(/ALTER\s+TABLE/i);
return block.trim().length > 0 && hasAlterTable !== null;
}
extractSchemaTableNameFromAlter(block) {
// Simple extraction for now; could be improved with a proper SQL parser
const match = block.match(/ALTER\s+TABLE\s+([\w\.]+)/i);
return (match === null || match === void 0 ? void 0 : match[1]) || null;
}
splitIntoAlterStatements(block) {
// Simple split based on semicolon for now; could be improved with a proper SQL parser
return block.split(';')
.filter(statement => statement.trim().length > 0 && statement.match(/ALTER\s+TABLE/i))
.map(statement => statement.trim() + ';');
}
generateChecksum(statement) {
return (0, crypto_1.createHash)('sha256').update(statement).digest('hex');
}
}
exports.AlterTablesProcessor = AlterTablesProcessor;