mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-29 07:36:01 +00:00
Merge branch 'master' of https://github.com/dbgate/dbgate
This commit is contained in:
@@ -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],
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
@@ -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[],
|
||||
|
||||
@@ -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 [];
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user