diff --git a/packages/api/src/proc/databaseConnectionProcess.js b/packages/api/src/proc/databaseConnectionProcess.js index 89869704..ed3a6cbe 100644 --- a/packages/api/src/proc/databaseConnectionProcess.js +++ b/packages/api/src/proc/databaseConnectionProcess.js @@ -14,6 +14,7 @@ let analysedStructure = null; let lastPing = null; let lastStatus = null; let analysedTime = 0; +let serverVersion; async function checkedAsyncCall(promise) { try { @@ -36,7 +37,7 @@ async function handleFullRefresh() { loadingModel = true; const driver = requireEngineDriver(storedConnection); setStatusName('loadStructure'); - analysedStructure = await checkedAsyncCall(driver.analyseFull(systemConnection)); + analysedStructure = await checkedAsyncCall(driver.analyseFull(systemConnection, serverVersion)); analysedTime = new Date().getTime(); process.send({ msgtype: 'structure', structure: analysedStructure }); process.send({ msgtype: 'structureTime', analysedTime }); @@ -48,7 +49,7 @@ async function handleIncrementalRefresh(forceSend) { loadingModel = true; const driver = requireEngineDriver(storedConnection); setStatusName('checkStructure'); - const newStructure = await checkedAsyncCall(driver.analyseIncremental(systemConnection, analysedStructure)); + const newStructure = await checkedAsyncCall(driver.analyseIncremental(systemConnection, analysedStructure, serverVersion)); analysedTime = new Date().getTime(); if (newStructure != null) { analysedStructure = newStructure; @@ -84,6 +85,7 @@ async function readVersion() { const driver = requireEngineDriver(storedConnection); const version = await driver.getVersion(systemConnection); process.send({ msgtype: 'version', version }); + serverVersion = version; } async function handleConnect({ connection, structure, globalSettings }) { @@ -93,7 +95,7 @@ async function handleConnect({ connection, structure, globalSettings }) { if (!structure) setStatusName('pending'); const driver = requireEngineDriver(storedConnection); systemConnection = await checkedAsyncCall(connectUtility(driver, storedConnection)); - readVersion(); + await checkedAsyncCall(readVersion()); if (structure) { analysedStructure = structure; handleIncrementalRefresh(true); diff --git a/packages/tools/src/DatabaseAnalyser.ts b/packages/tools/src/DatabaseAnalyser.ts index 45d8d7ba..6c92272a 100644 --- a/packages/tools/src/DatabaseAnalyser.ts +++ b/packages/tools/src/DatabaseAnalyser.ts @@ -1,4 +1,4 @@ -import { DatabaseInfo, DatabaseModification, EngineDriver } from 'dbgate-types'; +import { DatabaseInfo, DatabaseModification, EngineDriver, SqlDialect } from 'dbgate-types'; import _sortBy from 'lodash/sortBy'; import _groupBy from 'lodash/groupBy'; import _pick from 'lodash/pick'; @@ -13,8 +13,11 @@ export class DatabaseAnalyser { modifications: DatabaseModification[]; singleObjectFilter: any; singleObjectId: string = null; + dialect: SqlDialect; - constructor(public pool, public driver: EngineDriver) {} + constructor(public pool, public driver: EngineDriver, version) { + this.dialect = (driver?.dialectByVersion && driver?.dialectByVersion(version)) || driver?.dialect; + } async _runAnalysis() { return DatabaseAnalyser.createEmptyStructure(); diff --git a/packages/tools/src/driverBase.ts b/packages/tools/src/driverBase.ts index 7adeb8cf..671f2fc3 100644 --- a/packages/tools/src/driverBase.ts +++ b/packages/tools/src/driverBase.ts @@ -17,8 +17,8 @@ export const driverBase = { dumperClass: SqlDumper, dialect, - async analyseFull(pool) { - const analyser = new this.analyserClass(pool, this); + async analyseFull(pool, version) { + const analyser = new this.analyserClass(pool, this, version); return analyser.fullAnalysis(); }, async analyseSingleObject(pool, name, typeField = 'tables') { @@ -28,8 +28,8 @@ export const driverBase = { analyseSingleTable(pool, name) { return this.analyseSingleObject(pool, name, 'tables'); }, - async analyseIncremental(pool, structure) { - const analyser = new this.analyserClass(pool, this); + async analyseIncremental(pool, structure, version) { + const analyser = new this.analyserClass(pool, this, version); return analyser.incrementalAnalysis(structure); }, createDumper() { diff --git a/packages/types/engines.d.ts b/packages/types/engines.d.ts index 4f751080..0a728b0a 100644 --- a/packages/types/engines.d.ts +++ b/packages/types/engines.d.ts @@ -67,8 +67,8 @@ export interface EngineDriver { name: string; }[] >; - analyseFull(pool: any): Promise; - analyseIncremental(pool: any, structure: DatabaseInfo): Promise; + analyseFull(pool: any, serverVersion): Promise; + analyseIncremental(pool: any, structure: DatabaseInfo, serverVersion): Promise; dialect: SqlDialect; dialectByVersion(version): SqlDialect; createDumper(): SqlDumper; diff --git a/plugins/dbgate-plugin-mongo/src/backend/Analyser.js b/plugins/dbgate-plugin-mongo/src/backend/Analyser.js index d710544a..93265986 100644 --- a/plugins/dbgate-plugin-mongo/src/backend/Analyser.js +++ b/plugins/dbgate-plugin-mongo/src/backend/Analyser.js @@ -1,8 +1,8 @@ const { DatabaseAnalyser } = require('dbgate-tools'); class Analyser extends DatabaseAnalyser { - constructor(pool, driver) { - super(pool, driver); + constructor(pool, driver, version) { + super(pool, driver, version); } async _runAnalysis() { diff --git a/plugins/dbgate-plugin-mssql/src/backend/MsSqlAnalyser.js b/plugins/dbgate-plugin-mssql/src/backend/MsSqlAnalyser.js index e30a94ac..ac756eda 100644 --- a/plugins/dbgate-plugin-mssql/src/backend/MsSqlAnalyser.js +++ b/plugins/dbgate-plugin-mssql/src/backend/MsSqlAnalyser.js @@ -50,8 +50,8 @@ function getColumnInfo({ } class MsSqlAnalyser extends DatabaseAnalyser { - constructor(pool, driver) { - super(pool, driver); + constructor(pool, driver, version) { + super(pool, driver, version); } createQuery(resFileName, typeFields) { diff --git a/plugins/dbgate-plugin-mysql/src/backend/Analyser.js b/plugins/dbgate-plugin-mysql/src/backend/Analyser.js index 4068aea1..18627725 100644 --- a/plugins/dbgate-plugin-mysql/src/backend/Analyser.js +++ b/plugins/dbgate-plugin-mysql/src/backend/Analyser.js @@ -29,8 +29,8 @@ function getColumnInfo({ } class Analyser extends DatabaseAnalyser { - constructor(pool, driver) { - super(pool, driver); + constructor(pool, driver, version) { + super(pool, driver, version); } createQuery(resFileName, typeFields) { diff --git a/plugins/dbgate-plugin-postgres/src/backend/Analyser.js b/plugins/dbgate-plugin-postgres/src/backend/Analyser.js index 351b92b7..3b524325 100644 --- a/plugins/dbgate-plugin-postgres/src/backend/Analyser.js +++ b/plugins/dbgate-plugin-postgres/src/backend/Analyser.js @@ -36,8 +36,8 @@ function getColumnInfo({ } class Analyser extends DatabaseAnalyser { - constructor(pool, driver) { - super(pool, driver); + constructor(pool, driver, version) { + super(pool, driver, version); } createQuery(resFileName, typeFields) { diff --git a/plugins/dbgate-plugin-postgres/src/backend/drivers.js b/plugins/dbgate-plugin-postgres/src/backend/drivers.js index e96c4436..5e3a601d 100644 --- a/plugins/dbgate-plugin-postgres/src/backend/drivers.js +++ b/plugins/dbgate-plugin-postgres/src/backend/drivers.js @@ -133,10 +133,15 @@ const drivers = driverBases.map(driverBase => ({ const m = version.match(/([\d\.]+)/); let versionText = null; + let versionMajor = null; + let versionMinor = null; if (m) { if (isCockroach) versionText = `CockroachDB ${m[1]}`; if (isRedshift) versionText = `Redshift ${m[1]}`; if (isPostgres) versionText = `PostgreSQL ${m[1]}`; + const numbers = m[1].split('.'); + if (numbers[0]) versionMajor = parseInt(numbers[0]); + if (numbers[1]) versionMinor = parseInt(numbers[1]); } return { @@ -145,6 +150,8 @@ const drivers = driverBases.map(driverBase => ({ isPostgres, isCockroach, isRedshift, + versionMajor, + versionMinor, }; }, async readQuery(client, sql, structure) { diff --git a/plugins/dbgate-plugin-postgres/src/frontend/drivers.js b/plugins/dbgate-plugin-postgres/src/frontend/drivers.js index 7599e244..5451bb49 100644 --- a/plugins/dbgate-plugin-postgres/src/frontend/drivers.js +++ b/plugins/dbgate-plugin-postgres/src/frontend/drivers.js @@ -57,6 +57,20 @@ const postgresDriver = { ...dialect, materializedViews: true, }, + + dialectByVersion(version) { + if (version) { + return { + ...dialect, + materializedViews: + version && + version.versionMajor != null && + version.versionMinor != null && + (version.versionMajor > 9 || version.versionMajor == 9 || version.versionMinor >= 3), + }; + } + return dialect; + }, }; /** @type {import('dbgate-types').EngineDriver} */ diff --git a/plugins/dbgate-plugin-sqlite/src/backend/Analyser.js b/plugins/dbgate-plugin-sqlite/src/backend/Analyser.js index 77b0d722..8e9ab36c 100644 --- a/plugins/dbgate-plugin-sqlite/src/backend/Analyser.js +++ b/plugins/dbgate-plugin-sqlite/src/backend/Analyser.js @@ -16,8 +16,8 @@ SELECT `; class Analyser extends DatabaseAnalyser { - constructor(pool, driver) { - super(pool, driver); + constructor(pool, driver, version) { + super(pool, driver, version); } async _getFastSnapshot() {