mysql icon indicating copy to clipboard operation
mysql copied to clipboard

Set session timezone to UTC when loc is UTC and timezone undefined

Open felipecaputo opened this issue 4 years ago • 6 comments

Description

Accord to the proposal at #1114, implemented a change that will set the database session timezone to UTC when loc == nil or locis UTC and the database time_zone is not set.

Checklist

  • [x] Code compiles correctly
  • [x] Created tests which fail without the change (if possible)
  • [x] All tests passing
  • [x] Extended the README / documentation, if necessary
  • [x] Added myself / the copyright holder to the AUTHORS file

felipecaputo avatar Jun 01 '20 18:06 felipecaputo

In Mac tests are passing, but for Linux no. I'll boot my Linux PC later to try there and fix the problem

felipecaputo avatar Jun 01 '20 19:06 felipecaputo

I think this is a breaking change, as MySQL uses the session time zone to parse the time string. Example:

package main

import (
	"database/sql"
	"fmt"
	"time"

	"github.com/go-sql-driver/mysql"
)

func main() {
	dsn := mysql.NewConfig()
	dsn.Params = map[string]string{"time_zone": "'+08:00'"}
	dsn.ParseTime = true
	dsn.Loc = time.UTC
	dsn.User = "root"
	dsn.DBName = "test"

	db, err := sql.Open("mysql", dsn.FormatDSN())
	if err != nil {
		panic(err)
	}
	defer db.Close()

	_, err = db.Exec("DROP TABLE IF EXISTS foo")
	if err != nil {
		panic(err)
	}
	_, err = db.Exec("CREATE TABLE foo (c TIMESTAMP(6))")
	if err != nil {
		panic(err)
	}
	_, err = db.Exec("INSERT INTO foo VALUES ('2020-10-01 05:12:34')")
	if err != nil {
		panic(err)
	}

	var r float64
	err = db.QueryRow("SELECT UNIX_TIMESTAMP(c) FROM foo").Scan(&r)
	if err != nil {
		panic(err)
	}
	fmt.Println(int64(r))
}

If you change "time_zone": "'+08:00'" to something else like "time_zone": "'+00:00'", the output varies.

breezewish avatar Oct 10 '21 10:10 breezewish

Hi @breeswish, I will get back into this (sorry to have forgotten) but when the session timezone is set, there are no changes (shouldn't be)

The idea is to not be a breaking change since it will set the session time zone to the same as loc, only when loc is empty or UTC, but never overwrite user defined information [link here]

felipecaputo avatar Oct 15 '21 20:10 felipecaputo

The idea is to not be a breaking change since it will set the session time zone to the same as loc, only when loc is empty or UTC, but never overwrite user defined information [link here]

What happen if the application is relying on the default timezone of MySQL?

methane avatar Oct 16 '21 01:10 methane

The idea is to not be a breaking change since it will set the session time zone to the same as loc, only when loc is empty or UTC, but never overwrite user defined information [link here]

I have the same concern as @methane . Consider this scenario:

a. The default timezone of MySQL is a local time zone. Let's take local time zone is +08:00 as an example, the MySQL session default timezone is +08:00 now. b. The application uses go-mysql-driver contains the behavior: Insert a timestamp by using the human readable form: MySQL will parse this human readable form using the default time zone (+08:00) and store its UTC time value.

Note: the user does not explicitly specify a timezone using the driver, but is relying on the default time zone.

c. Now, if the driver starts to change the time zone by default, e.g. changing to UTC, the next stored time value will be broken. The broken time value can be easily found by selecting using UNIX_TIMESTAMP() (which is not relying on the session time zone).

breezewish avatar Oct 16 '21 09:10 breezewish

@methane @breeswish

This was what was happening with us, the database was -04:00 and we were not setting the session time zone, in database we had TIMESTAMP fields, with an example of 2021-10-19T20:00:00-0400, but when we get the date from the database, was loc was niland assumed UTC by default, we ended up with 2021-10-19T20:00:00Z as the session timezone and loc had different values [link to example]

The fact is that, if we had applications that doesn't set the session timezone and are treating data outside the driver, it can lead to a breaking change.

felipecaputo avatar Oct 18 '21 12:10 felipecaputo

I think user should set time_zone explicitly if it is needed.

methane avatar May 28 '23 05:05 methane