From 06fc89a1015816fd47c201cc7eb78118fc4395a2 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Wed, 19 Apr 2023 18:53:56 +0800 Subject: [PATCH] feat(nocodb): utc timezone handling for mysql --- packages/nocodb/src/lib/meta/NcMetaIOImpl.ts | 33 +++++++++++++---- .../nocodb/src/lib/utils/NcConfigFactory.ts | 35 +++++++++++++++++++ 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/packages/nocodb/src/lib/meta/NcMetaIOImpl.ts b/packages/nocodb/src/lib/meta/NcMetaIOImpl.ts index b04157a088..50e58686de 100644 --- a/packages/nocodb/src/lib/meta/NcMetaIOImpl.ts +++ b/packages/nocodb/src/lib/meta/NcMetaIOImpl.ts @@ -1,5 +1,6 @@ import CryptoJS from 'crypto-js'; import { customAlphabet } from 'nanoid'; +import dayjs from 'dayjs'; import { XKnex } from '../db/sql-data-mapper'; import XcMigrationSource from '../migrations/XcMigrationSource'; import NcConnectionMgr from '../utils/common/NcConnectionMgr'; @@ -94,6 +95,20 @@ export default class NcMetaIOImpl extends NcMetaIO { return (this.trx || this.connection) as any; } + private isMySQL(): boolean { + return ( + this.config?.meta?.db?.client === 'mysql' || + this.config?.meta?.db?.client === 'mysql2' + ); + } + + private now(): any { + if (this.isMySQL()) { + return dayjs().utc().format('YYYY-MM-DD HH:mm:ss'); + } + return dayjs().utc().toISOString(); + } + public updateKnex(connectionConfig): void { this.connection = XKnex(connectionConfig); } @@ -107,6 +122,10 @@ export default class NcMetaIOImpl extends NcMetaIO { migrationSource: new XcMigrationSourcev2(), tableName: 'xc_knex_migrationsv2', }); + if (this.isMySQL()) { + // set timezone + await this.connection.raw(`SET time_zone = '+00:00'`); + } return true; } @@ -238,8 +257,8 @@ export default class NcMetaIOImpl extends NcMetaIO { return this.knexConnection(target).insert({ db_alias: dbAlias, project_id, - created_at: this.knexConnection?.fn?.now(), - updated_at: this.knexConnection?.fn?.now(), + created_at: this.now(), + updated_at: this.now(), ...data, }); } @@ -260,8 +279,8 @@ export default class NcMetaIOImpl extends NcMetaIO { if (project_id !== null) insertObj.project_id = project_id; await this.knexConnection(target).insert({ ...insertObj, - created_at: insertObj?.created_at || this.knexConnection?.fn?.now(), - updated_at: insertObj?.updated_at || this.knexConnection?.fn?.now(), + created_at: insertObj?.created_at || this.now(), + updated_at: insertObj?.updated_at || this.now(), }); return insertObj; } @@ -410,7 +429,7 @@ export default class NcMetaIOImpl extends NcMetaIO { delete data.created_at; - query.update({ ...data, updated_at: this.knexConnection?.fn?.now() }); + query.update({ ...data, updated_at: this.now() }); if (typeof idOrCondition !== 'object') { query.where('id', idOrCondition); } else if (idOrCondition) { @@ -530,8 +549,8 @@ export default class NcMetaIOImpl extends NcMetaIO { // todo: check project name used or not await this.knexConnection('nc_projects').insert({ ...project, - created_at: this.knexConnection?.fn?.now(), - updated_at: this.knexConnection?.fn?.now(), + created_at: this.now(), + updated_at: this.now(), }); // todo diff --git a/packages/nocodb/src/lib/utils/NcConfigFactory.ts b/packages/nocodb/src/lib/utils/NcConfigFactory.ts index 85c1fe1d7c..f521585e92 100644 --- a/packages/nocodb/src/lib/utils/NcConfigFactory.ts +++ b/packages/nocodb/src/lib/utils/NcConfigFactory.ts @@ -232,6 +232,13 @@ export default class NcConfigFactory implements NcConfig { acquireConnectionTimeout: 600000, } as any; + if (url.protocol.startsWith('mysql')) { + dbConfig.connection = { + ...dbConfig.connection, + ...this.mysqlConnectionTypeCastConfig, + }; + } + if (process.env.NODE_TLS_REJECT_UNAUTHORIZED) { dbConfig.connection.ssl = true; } @@ -344,6 +351,14 @@ export default class NcConfigFactory implements NcConfig { } : {}), }; + + if (url.protocol.startsWith('mysql')) { + dbConfig.connection = { + ...dbConfig.connection, + ...this.mysqlConnectionTypeCastConfig, + }; + } + if (process.env.NODE_TLS_REJECT_UNAUTHORIZED) { dbConfig.connection.ssl = true; } @@ -506,6 +521,13 @@ export default class NcConfigFactory implements NcConfig { }, }; } + + if (dbConfig.client.startsWith('mysql')) { + dbConfig.connection = { + ...dbConfig.connection, + ...this.mysqlConnectionTypeCastConfig, + }; + } // todo: const key = ''; @@ -739,6 +761,19 @@ export default class NcConfigFactory implements NcConfig { return res; } + private static mysqlConnectionTypeCastConfig = { + typeCast: function (field, next) { + if ( + field.type === 'DATETIME' && + (field.name === 'created_at' || field.name === 'updated_at') + ) { + return new Date(field.string() + ' UTC'); + } + return next(); + }, + timezone: '+00:00', + }; + // public static initOneClickDeployment() { // if (process.env.NC_ONE_CLICK) { // const url = NcConfigFactory.extractXcUrlFromJdbc(process.env.DATABASE_URL);