Skip to content

Commit

Permalink
fix(mysql): respect database timezone setting in $.number (#85)
Browse files Browse the repository at this point in the history
  • Loading branch information
Hieuzest authored Apr 16, 2024
1 parent 2f1f990 commit 6a65bfc
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 10 deletions.
13 changes: 13 additions & 0 deletions packages/mysql/src/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export interface Compat {
maria?: boolean
maria105?: boolean
mysql57?: boolean
timezone?: string
}

export class MySQLBuilder extends Builder {
Expand All @@ -23,16 +24,28 @@ export class MySQLBuilder extends Builder {
'\\': '\\\\',
}

readonly _localTimezone = `+${(new Date()).getTimezoneOffset() / -60}:00`.replace('+-', '-')
readonly _dbTimezone: string

prequeries: string[] = []

constructor(protected driver: Driver, tables?: Dict<Model>, private compat: Compat = {}) {
super(driver, tables)
this._dbTimezone = compat.timezone ?? 'SYSTEM'

this.evalOperators.$sum = (expr) => this.createAggr(expr, value => `ifnull(sum(${value}), 0)`, undefined, value => `ifnull(minato_cfunc_sum(${value}), 0)`)
this.evalOperators.$avg = (expr) => this.createAggr(expr, value => `avg(${value})`, undefined, value => `minato_cfunc_avg(${value})`)
this.evalOperators.$min = (expr) => this.createAggr(expr, value => `min(${value})`, undefined, value => `minato_cfunc_min(${value})`)
this.evalOperators.$max = (expr) => this.createAggr(expr, value => `max(${value})`, undefined, value => `minato_cfunc_max(${value})`)

this.evalOperators.$number = (arg) => {
const value = this.parseEval(arg)
const type = Type.fromTerm(arg)
const res = type.type === 'time' ? `unix_timestamp(convert_tz(addtime('1970-01-01 00:00:00', ${value}), '${this._localTimezone}', '${this._dbTimezone}'))`
: ['timestamp', 'date'].includes(type.type!) ? `unix_timestamp(convert_tz(${value}, '${this._localTimezone}', '${this._dbTimezone}'))` : `(0+${value})`
return this.asEncoded(`ifnull(${res}, 0)`, false)
}

this.transformers['boolean'] = {
encode: value => `if(${value}=b'1', 1, 0)`,
decode: value => `if(${value}=1, b'1', b'0')`,
Expand Down
4 changes: 3 additions & 1 deletion packages/mysql/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,16 @@ export class MySQLDriver extends Driver<MySQLDriver.Config> {
...this.config,
})

const version = Object.values((await this.query(`SELECT version()`))[0])[0] as string
const [version, timezone] = Object.values((await this.query(`SELECT version(), @@GLOBAL.time_zone`))[0]) as string[]
// https://jira.mariadb.org/browse/MDEV-30623
this._compat.maria = version.includes('MariaDB')
// https://jira.mariadb.org/browse/MDEV-26506
this._compat.maria105 = !!version.match(/10.5.\d+-MariaDB/)
// For json_table
this._compat.mysql57 = !!version.match(/5.7.\d+/)

this._compat.timezone = timezone

if (this._compat.mysql57 || this._compat.maria) {
await this._setupCompatFunctions()
}
Expand Down
9 changes: 0 additions & 9 deletions packages/sql-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,6 @@ export class Builder {
protected modifiedTable?: string
protected transformers: Dict<Transformer> = Object.create(null)

protected readonly _timezone = `+${(new Date()).getTimezoneOffset() / -60}:00`.replace('+-', '-')

constructor(protected driver: Driver, tables?: Dict<Model>) {
this.state.tables = tables

Expand Down Expand Up @@ -167,13 +165,6 @@ export class Builder {

// typecast
$literal: ([value, type]) => this.escape(value, type as any),
$number: (arg) => {
const value = this.parseEval(arg)
const type = Type.fromTerm(arg)
const res = type.type === 'time' ? `unix_timestamp(convert_tz(addtime('1970-01-01 00:00:00', ${value}), '${this._timezone}', '+0:00'))`
: ['timestamp', 'date'].includes(type.type!) ? `unix_timestamp(convert_tz(${value}, '${this._timezone}', '+0:00'))` : `(0+${value})`
return this.asEncoded(`ifnull(${res}, 0)`, false)
},

// aggregation
$sum: (expr) => this.createAggr(expr, value => `ifnull(sum(${value}), 0)`),
Expand Down

0 comments on commit 6a65bfc

Please sign in to comment.