This commit is contained in:
SPRINX0\prochazka
2024-11-18 13:47:47 +01:00
5 changed files with 104 additions and 27 deletions

View File

@@ -82,30 +82,34 @@ async function testDatabaseDeploy(engine, conn, driver, dbModelsYaml, options) {
dbdiffOptionsExtra.schemaMode = 'ignore';
for (const loadedDbModel of dbModelsYaml) {
const { sql, isEmpty } = await generateDeploySql({
systemConnection: conn.isPreparedOnly ? undefined : conn,
connection: conn.isPreparedOnly ? conn : undefined,
driver,
loadedDbModel,
dbdiffOptionsExtra,
});
console.debug('Generated deploy script:', sql);
if (!allowDropStatements) {
expect(sql.toUpperCase().includes('DROP ')).toBeFalsy();
}
if (_.isString(loadedDbModel)) {
await driver.script(conn, loadedDbModel);
} else {
const { sql, isEmpty } = await generateDeploySql({
systemConnection: conn.isPreparedOnly ? undefined : conn,
connection: conn.isPreparedOnly ? conn : undefined,
driver,
loadedDbModel,
dbdiffOptionsExtra,
});
console.debug('Generated deploy script:', sql);
if (!allowDropStatements) {
expect(sql.toUpperCase().includes('DROP ')).toBeFalsy();
}
console.log('dbModelsYaml.length', dbModelsYaml.length, index);
if (testEmptyLastScript && index == dbModelsYaml.length - 1) {
expect(isEmpty).toBeTruthy();
}
console.log('dbModelsYaml.length', dbModelsYaml.length, index);
if (testEmptyLastScript && index == dbModelsYaml.length - 1) {
expect(isEmpty).toBeTruthy();
}
await deployDb({
systemConnection: conn.isPreparedOnly ? undefined : conn,
connection: conn.isPreparedOnly ? conn : undefined,
driver,
loadedDbModel,
dbdiffOptionsExtra,
});
await deployDb({
systemConnection: conn.isPreparedOnly ? undefined : conn,
connection: conn.isPreparedOnly ? conn : undefined,
driver,
loadedDbModel,
dbdiffOptionsExtra,
});
}
index++;
}
@@ -416,6 +420,48 @@ describe('Deploy database', () => {
})
);
test.each(engines.map(engine => [engine.label, engine]))(
'Change column to NOT NULL column with default - %s',
testWrapper(async (conn, driver, engine) => {
await testDatabaseDeploy(engine, conn, driver, [
[
{
name: 't1.table.yaml',
json: {
name: 't1',
columns: [
{ name: 'id', type: 'int', notNull: true },
{ name: 'val', type: 'int' },
],
primaryKey: ['id'],
},
},
],
'insert into t1 (id, val) values (1, 1); insert into t1 (id) values (2)',
[
{
name: 't1.table.yaml',
json: {
name: 't1',
columns: [
{ name: 'id', type: 'int', notNull: true },
{ name: 'val', type: 'int', notNull: true, default: '20' },
],
primaryKey: ['id'],
},
},
],
]);
const res1 = await driver.query(conn, `select val from t1 where id = 1`);
expect(res1.rows[0].val).toEqual(1);
const res2 = await driver.query(conn, `select val from t1 where id = 2`);
expect(res2.rows[0].val).toEqual(20);
})
);
const T1 = {
name: 't1.table.yaml',
json: {
@@ -428,6 +474,18 @@ describe('Deploy database', () => {
},
};
const T2 = {
name: 't2.table.yaml',
json: {
name: 't2',
columns: [
{ name: 'id', type: 'int' },
{ name: 'val', type: 'int' },
],
primaryKey: ['id'],
},
};
const T1_DELETED = {
name: '_deleted_t1.table.yaml',
json: {
@@ -686,4 +744,15 @@ describe('Deploy database', () => {
expect(res5.rows[0].run_count == 2).toBeTruthy();
})
);
test.each(engines.map(engine => [engine.label, engine]))(
'Mark table removed, one remains - %s',
testWrapper(async (conn, driver, engine) => {
await testDatabaseDeploy(engine, conn, driver, [[T1, T2], [T2], [T2]], {
markDeleted: true,
disallowExtraObjects: true,
finalCheckAgainstModel: [T1_DELETED, T2],
});
})
);
});

View File

@@ -731,6 +731,12 @@ export class SqlDumper implements AlterProcessor {
this.put(formatString, optionValue);
}
fillNewNotNullDefaults(col: ColumnInfo) {
if (col.notNull && col.defaultValue != null) {
this.putCmd('^update %f ^set %i = %s ^where %i ^is ^null', col, col.columnName, col.defaultValue, col.columnName);
}
}
fillPreloadedRows(
table: NamedObjectInfo,
oldRows: any[],

View File

@@ -459,7 +459,7 @@ export class AlterPlan {
// console.log('*****************RECREATED NEEDED', op, operationType, isAllowed);
// console.log(this.dialect);
if (!this.opts.allowTableRecreate) {
if (this.opts.noDropTable && !this.opts.allowTableRecreate) {
// skip this operation, as it cannot be achieved
return [];
}

View File

@@ -132,6 +132,7 @@ class MsSqlDumper extends SqlDumper {
} else {
this.dropDefault(oldcol);
if (oldcol.columnName != newcol.columnName) this.renameColumn(oldcol, newcol.columnName);
this.fillNewNotNullDefaults(newcol);
this.put('^alter ^table %f ^alter ^column %i ', oldcol, oldcol.columnName, newcol.columnName);
this.columnDefinition(newcol, { includeDefault: false });
this.endCommand();

View File

@@ -76,10 +76,6 @@ class Dumper extends SqlDumper {
if (!testEqualTypes(oldcol, newcol)) {
this.putCmd('^alter ^table %f ^alter ^column %i ^type %s', oldcol, newcol.columnName, newcol.dataType);
}
if (oldcol.notNull != newcol.notNull) {
if (newcol.notNull) this.putCmd('^alter ^table %f ^alter ^column %i ^set ^not ^null', newcol, newcol.columnName);
else this.putCmd('^alter ^table %f ^alter ^column %i ^drop ^not ^null', newcol, newcol.columnName);
}
if (oldcol.defaultValue != newcol.defaultValue) {
if (newcol.defaultValue == null) {
this.putCmd('^alter ^table %f ^alter ^column %i ^drop ^default', newcol, newcol.columnName);
@@ -92,6 +88,11 @@ class Dumper extends SqlDumper {
);
}
}
if (oldcol.notNull != newcol.notNull) {
this.fillNewNotNullDefaults(newcol);
if (newcol.notNull) this.putCmd('^alter ^table %f ^alter ^column %i ^set ^not ^null', newcol, newcol.columnName);
else this.putCmd('^alter ^table %f ^alter ^column %i ^drop ^not ^null', newcol, newcol.columnName);
}
}
putValue(value) {