Skip to content

Commit

Permalink
sessionctx: add 'time_zone' session variable (#2375)
Browse files Browse the repository at this point in the history
  • Loading branch information
tiancaiamao authored Jan 3, 2017
1 parent e38c67e commit 27c0c76
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 2 deletions.
6 changes: 6 additions & 0 deletions sessionctx/variable/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package variable
import (
"strings"
"sync"
"time"

"github.com/juju/errors"
"github.com/pingcap/tidb/mysql"
Expand Down Expand Up @@ -144,6 +145,10 @@ type SessionVars struct {
// CurrInsertValues is used to record current ValuesExpr's values.
// See http://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values
CurrInsertValues interface{}

// Per-connection time zones. Each client that connects has its own time zone setting, given by the session time_zone variable.
// See https://dev.mysql.com/doc/refman/5.7/en/time-zone-support.html
TimeZone *time.Location
}

// NewSessionVars creates a session vars object.
Expand Down Expand Up @@ -224,6 +229,7 @@ const (
SQLModeVar = "sql_mode"
AutocommitVar = "autocommit"
CharacterSetResults = "character_set_results"
TimeZone = "time_zone"
)

// GetTiDBSystemVar gets variable value for name.
Expand Down
24 changes: 24 additions & 0 deletions sessionctx/varsutil/varsutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ func SetSessionSystemVar(vars *variable.SessionVars, name string, value types.Da
return errors.Trace(err)
}
switch name {
case variable.TimeZone:
vars.TimeZone = parseTimeZone(sVal)
case variable.SQLModeVar:
sVal = strings.ToUpper(sVal)
if strings.Contains(sVal, "STRICT_TRANS_TABLES") || strings.Contains(sVal, "STRICT_ALL_TABLES") {
Expand Down Expand Up @@ -112,6 +114,28 @@ func SetSessionSystemVar(vars *variable.SessionVars, name string, value types.Da
return nil
}

func parseTimeZone(s string) *time.Location {
if s == "SYSTEM" {
// TODO: Support global time_zone variable, it should be set to global time_zone value.
return time.Local
}

loc, err := time.LoadLocation(s)
if err == nil {
return loc
}

// The value can be given as a string indicating an offset from UTC, such as '+10:00' or '-6:00'.
if strings.HasPrefix(s, "+") || strings.HasPrefix(s, "-") {
d, err := types.ParseDuration(s[1:], 0)
if err == nil {
return time.FixedZone("UTC", int(d.Duration/time.Second))
}
}

return nil
}

func setSnapshotTS(s *variable.SessionVars, sVal string) error {
if sVal == "" {
s.SnapshotTS = 0
Expand Down
20 changes: 18 additions & 2 deletions sessionctx/varsutil/varsutil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package varsutil

import (
"testing"
"time"

. "github.com/pingcap/check"
"github.com/pingcap/tidb/sessionctx/variable"
Expand Down Expand Up @@ -57,7 +58,7 @@ func (s *testVarsutilSuite) TestVarsutil(c *C) {

c.Assert(SetSessionSystemVar(v, "character_set_results", types.Datum{}), IsNil)

// Test case for get TiDBSkipConstraintCheck session variable
// Test case for get TiDBSkipConstraintCheck session variable.
val, err = GetSessionSystemVar(v, variable.TiDBSkipConstraintCheck)
c.Assert(err, IsNil)
c.Assert(val, Equals, "0")
Expand All @@ -77,7 +78,7 @@ func (s *testVarsutilSuite) TestVarsutil(c *C) {
c.Assert(err, IsNil)
c.Assert(val, Equals, "1")

// Test case for get TiDBSkipDDLWait session variable
// Test case for get TiDBSkipDDLWait session variable.
val, err = GetSessionSystemVar(v, variable.TiDBSkipDDLWait)
c.Assert(val, Equals, "0")
c.Assert(v.SkipDDLWait, IsFalse)
Expand All @@ -87,4 +88,19 @@ func (s *testVarsutilSuite) TestVarsutil(c *C) {
c.Assert(v.SkipDDLWait, IsTrue)
val, err = GetSessionSystemVar(v, variable.TiDBSkipDDLWait)
c.Assert(val, Equals, "1")

// Test case for time_zone session variable.
SetSessionSystemVar(v, variable.TimeZone, types.NewStringDatum("Europe/Helsinki"))
c.Assert(v.TimeZone.String(), Equals, "Europe/Helsinki")
SetSessionSystemVar(v, variable.TimeZone, types.NewStringDatum("US/Eastern"))
c.Assert(v.TimeZone.String(), Equals, "US/Eastern")
SetSessionSystemVar(v, variable.TimeZone, types.NewStringDatum("SYSTEM"))
c.Assert(v.TimeZone.String(), Equals, "Local")
SetSessionSystemVar(v, variable.TimeZone, types.NewStringDatum("+10:00"))
c.Assert(v.TimeZone.String(), Equals, "UTC")
t1 := time.Date(2000, 1, 1, 0, 0, 0, 0, v.TimeZone)
t2 := time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)
c.Assert(t2.Sub(t1), Equals, 10*time.Hour)
SetSessionSystemVar(v, variable.TimeZone, types.NewStringDatum("-6:00"))
c.Assert(v.TimeZone.String(), Equals, "UTC")
}

0 comments on commit 27c0c76

Please sign in to comment.