Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ require (
github.com/dolthub/eventsapi_schema v0.0.0-20250725194025-a087efa1ee55
github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2
github.com/dolthub/go-icu-regex v0.0.0-20250820171420-f2b78f56ce9f
github.com/dolthub/go-mysql-server v0.20.1-0.20250910230026-248b1e8cb615
github.com/dolthub/go-mysql-server v0.20.1-0.20250911203031-9319872a4220
github.com/dolthub/sqllogictest/go v0.0.0-20240618184124-ca47f9354216
github.com/dolthub/vitess v0.0.0-20250902225707-0159e964d73d
github.com/fatih/color v1.13.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -258,8 +258,8 @@ github.com/dolthub/fslock v0.0.3 h1:iLMpUIvJKMKm92+N1fmHVdxJP5NdyDK5bK7z7Ba2s2U=
github.com/dolthub/fslock v0.0.3/go.mod h1:QWql+P17oAAMLnL4HGB5tiovtDuAjdDTPbuqx7bYfa0=
github.com/dolthub/go-icu-regex v0.0.0-20250820171420-f2b78f56ce9f h1:oSA8CptGeCEdTdD9LFtv8x4juDfdaLKsx1eocyaj1bE=
github.com/dolthub/go-icu-regex v0.0.0-20250820171420-f2b78f56ce9f/go.mod h1:kpsRG+a196Y69zsAFL0RkQICII9a571lcaxhvQnmrdY=
github.com/dolthub/go-mysql-server v0.20.1-0.20250910230026-248b1e8cb615 h1:j9lSm+NWy+SmpQdopwSDUy5gKOTBhOOZ7BxtTqgd4qk=
github.com/dolthub/go-mysql-server v0.20.1-0.20250910230026-248b1e8cb615/go.mod h1:ymoHIRZoZKO1EH9iUGcq4E6XyIpUaMgZz3ZPeWa828w=
github.com/dolthub/go-mysql-server v0.20.1-0.20250911203031-9319872a4220 h1:0oGeylTL1BHvchWzPMRFeYfLMyT6Qz/+MZcuKLtCJYs=
github.com/dolthub/go-mysql-server v0.20.1-0.20250911203031-9319872a4220/go.mod h1:ymoHIRZoZKO1EH9iUGcq4E6XyIpUaMgZz3ZPeWa828w=
github.com/dolthub/gozstd v0.0.0-20240423170813-23a2903bca63 h1:OAsXLAPL4du6tfbBgK0xXHZkOlos63RdKYS3Sgw/dfI=
github.com/dolthub/gozstd v0.0.0-20240423170813-23a2903bca63/go.mod h1:lV7lUeuDhH5thVGDCKXbatwKy2KW80L4rMT46n+Y2/Q=
github.com/dolthub/ishell v0.0.0-20240701202509-2b217167d718 h1:lT7hE5k+0nkBdj/1UOSFwjWpNxf+LCApbRHgnCA17XE=
Expand Down
2 changes: 1 addition & 1 deletion server/cast/timestamp.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func timestampAssignment() {
FromType: pgtypes.Timestamp,
ToType: pgtypes.Time,
Function: func(ctx *sql.Context, val any, targetType *pgtypes.DoltgresType) (any, error) {
return timeofday.FromTime(val.(time.Time)), nil
return timeofday.FromTime(val.(time.Time)).ToTime(), nil
},
})
}
Expand Down
2 changes: 1 addition & 1 deletion server/cast/timestamptz.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func timestampTZAssignment() {
FromType: pgtypes.TimestampTZ,
ToType: pgtypes.Time,
Function: func(ctx *sql.Context, val any, targetType *pgtypes.DoltgresType) (any, error) {
return timeofday.FromTime(val.(time.Time)), nil
return timeofday.FromTime(val.(time.Time)).ToTime(), nil
},
})
framework.MustAddAssignmentTypeCast(framework.TypeCast{
Expand Down
22 changes: 12 additions & 10 deletions server/config/parameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ type Parameter struct {
Source ParameterSource
ResetVal any
Scope sql.SystemVariableScope
ValidateFunc func(any) (any, bool)
ValidateFunc func(currVal, newVal any) (any, bool)
}

// GetName implements sql.SystemVariable.
Expand All @@ -90,7 +90,9 @@ func (p *Parameter) GetSessionScope() sql.SystemVariableScope {

// SetDefault implements sql.SystemVariable.
func (p *Parameter) SetDefault(a any) {
p.Default = a
if validatedVal, ok := p.ValidateFunc(p.Default, a); ok {
p.Default = validatedVal
}
}

// GetDefault implements sql.SystemVariable.
Expand All @@ -99,32 +101,32 @@ func (p *Parameter) GetDefault() any {
}

// InitValue implements sql.SystemVariable.
func (p *Parameter) InitValue(ctx *sql.Context, val any, global bool) (sql.SystemVarValue, error) {
convertedVal, _, err := p.Type.Convert(ctx, val)
func (p *Parameter) InitValue(ctx *sql.Context, currVal, newVal any, global bool) (sql.SystemVarValue, error) {
convertedNewVal, _, err := p.Type.Convert(ctx, newVal)
if err != nil {
return sql.SystemVarValue{}, err
}
if p.ValidateFunc != nil {
v, ok := p.ValidateFunc(convertedVal)
v, ok := p.ValidateFunc(currVal, convertedNewVal)
if !ok {
return sql.SystemVarValue{}, ErrInvalidValue.New(p.Name, convertedVal)
return sql.SystemVarValue{}, ErrInvalidValue.New(p.Name, convertedNewVal)
}
convertedVal = v
convertedNewVal = v
}
svv := sql.SystemVarValue{
Var: p,
Val: convertedVal,
Val: convertedNewVal,
}
return svv, nil
}

// SetValue implements sql.SystemVariable.
func (p *Parameter) SetValue(ctx *sql.Context, val any, global bool) (sql.SystemVarValue, error) {
func (p *Parameter) SetValue(ctx *sql.Context, currVal, newVal any, global bool) (sql.SystemVarValue, error) {
if p.IsReadOnly() {
return sql.SystemVarValue{}, ErrCannotChangeAtRuntime.New(p.Name)
}
// TODO: Do parsing of units for memory and time parameters
return p.InitValue(ctx, val, global)
return p.InitValue(ctx, currVal, newVal, global)
}

// IsReadOnly implements sql.SystemVariable.
Expand Down
80 changes: 77 additions & 3 deletions server/config/parameters_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package config

import (
"fmt"
"math"
"strings"
"time"
Expand Down Expand Up @@ -699,6 +700,79 @@ var postgresConfigParameters = map[string]sql.SystemVariable{
ResetVal: "ISO, MDY",
// Sourcefile: postgresql.conf
Scope: GetPgsqlScope(PsqlScopeSession),
ValidateFunc: func(curr, new any) (any, bool) {
ds := "ISO"
do := "MDY"
if oldVal, ok := curr.(string); ok {
currentVal := strings.Split(strings.ReplaceAll(oldVal, " ", ""), ",")
if len(currentVal) == 2 {
// the first must be date style and second must be date ordering
ds = currentVal[0]
do = currentVal[1]
}
}
newVal, ok := new.(string)
if !ok {
return "", false
}

var dsSet, doSet bool
values := strings.Split(strings.ReplaceAll(strings.ToLower(newVal), " ", ""), ",")
for _, value := range values {
switch value {
case "iso":
if dsSet {
return "", false
}
ds = "ISO"
dsSet = true
case "sql":
if dsSet {
return "", false
}
ds = "SQL"
dsSet = true
case "postgres":
if dsSet {
return "", false
}
ds = "Postgres"
dsSet = true
case "german":
if dsSet {
return "", false
}
ds = "German"
dsSet = true
if !doSet {
do = "DMY"
}
case "us", "noneuropean", "mdy":
// MDY
if doSet {
return "", false
}
do = "MDY"
doSet = true
case "european", "dmy":
// DMY
if doSet {
return "", false
}
do = "DMY"
doSet = true
case "ymd":
if doSet {
return "", false
}
do = "YMD"
doSet = true
default:
return "", false
}
}
return fmt.Sprintf(`%s, %s`, ds, do), true
},
},
"db_user_namespace": &Parameter{
Name: "db_user_namespace",
Expand Down Expand Up @@ -3464,8 +3538,8 @@ var postgresConfigParameters = map[string]sql.SystemVariable{
// BootVal: "GMT",
ResetVal: "America/Los_Angeles",
Scope: GetPgsqlScope(PsqlScopeSession),
ValidateFunc: func(a any) (any, bool) {
switch v := a.(type) {
ValidateFunc: func(_, new any) (any, bool) {
switch v := new.(type) {
case string:
if strings.ToLower(v) == "local" {
// TODO: fix this
Expand All @@ -3486,7 +3560,7 @@ var postgresConfigParameters = map[string]sql.SystemVariable{
return nil, false
}
}
return a, true
return new, true
},
},
"timezone_abbreviations": &Parameter{
Expand Down
19 changes: 15 additions & 4 deletions server/connection_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ func (h *ConnectionHandler) handleStartup() (bool, error) {
if err = h.sendClientStartupMessages(); err != nil {
return false, err
}
if err = h.chooseInitialDatabase(sm); err != nil {
if err = h.chooseInitialParameters(sm); err != nil {
return false, err
}
return true, h.send(&pgproto3.ReadyForQuery{
Expand Down Expand Up @@ -282,9 +282,20 @@ func (h *ConnectionHandler) sendClientStartupMessages() error {
})
}

// chooseInitialDatabase attempts to choose the initial database for the connection,
// if one is specified in the startup message provided
func (h *ConnectionHandler) chooseInitialDatabase(startupMessage *pgproto3.StartupMessage) error {
// chooseInitialParameters attempts to choose the initial parameter settings for the connection,
// if one is specified in the startup message provided.
func (h *ConnectionHandler) chooseInitialParameters(startupMessage *pgproto3.StartupMessage) error {
for name, value := range startupMessage.Parameters {
// TODO: handle other parameters defined in StartupMessage
switch strings.ToLower(name) {
case "datestyle":
err := h.doltgresHandler.InitSessionParameterDefault(context.Background(), h.mysqlConn, "DateStyle", value)
if err != nil {
return err
}
}
}
// set initial database
db, ok := startupMessage.Parameters["database"]
dbSpecified := ok && len(db) > 0
if !dbSpecified {
Expand Down
5 changes: 5 additions & 0 deletions server/doltgres_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,11 @@ func (h *DoltgresHandler) NewContext(ctx context.Context, c *mysql.Conn, query s
return h.sm.NewContextWithQuery(ctx, c, query)
}

// InitSessionParameterDefault sets a default value to specified parameter for a session.
func (h *DoltgresHandler) InitSessionParameterDefault(ctx context.Context, c *mysql.Conn, name, value string) error {
return h.sm.InitSessionDefaultVariable(ctx, c, name, value)
}

// convertBindParameters handles the conversion from bind parameters to variable values.
func (h *DoltgresHandler) convertBindParameters(ctx *sql.Context, types []uint32, formatCodes []int16, values [][]byte) (map[string]sqlparser.Expr, error) {
bindings := make(map[string]sqlparser.Expr, len(values))
Expand Down
59 changes: 50 additions & 9 deletions server/functions/date.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package functions

import (
"strings"
"time"

"github.com/dolthub/go-mysql-server/sql"
Expand All @@ -41,15 +42,16 @@ var date_in = framework.Function1{
Strict: true,
Callable: func(ctx *sql.Context, _ [2]*pgtypes.DoltgresType, val any) (any, error) {
input := val.(string)
if date, _, err := pgdate.ParseDate(time.Now(), pgdate.ParseModeYMD, input); err == nil {
return date.ToTime()
} else if date, _, err = pgdate.ParseDate(time.Now(), pgdate.ParseModeDMY, input); err == nil {
return date.ToTime()
} else if date, _, err = pgdate.ParseDate(time.Now(), pgdate.ParseModeMDY, input); err == nil {
return date.ToTime()
} else {
return nil, err
formatsInOrder := getDateStyleInputFormat(ctx)
var date pgdate.Date
var err error
for _, format := range formatsInOrder {
date, _, err = pgdate.ParseDate(time.Now(), format, input)
if err == nil {
return date.ToTime()
}
}
return nil, err
},
}

Expand All @@ -60,7 +62,7 @@ var date_out = framework.Function1{
Parameters: [1]*pgtypes.DoltgresType{pgtypes.Date},
Strict: true,
Callable: func(ctx *sql.Context, _ [2]*pgtypes.DoltgresType, val any) (any, error) {
return FormatDateTimeWithBC(val.(time.Time), "2006-01-02", false), nil
return FormatDateTimeWithBC(val.(time.Time), getLayoutStringFormat(ctx, true), false), nil
},
}

Expand Down Expand Up @@ -106,3 +108,42 @@ var date_cmp = framework.Function2{
return int32(ab.Compare(bb)), nil
},
}

// getDateStyleInputFormat returns set the defined format in DateStyle config as the first in the ordered list of date parsing modes.
// TODO: this or something similar should be used in postgres/parser/sem/tree/datum.go when parsing timestamp/timestamptz/date values.
func getDateStyleInputFormat(ctx *sql.Context) []pgdate.ParseMode {
formatsInOrder := []pgdate.ParseMode{pgdate.ParseModeMDY, pgdate.ParseModeDMY, pgdate.ParseModeYMD} // default
if ctx == nil {
return formatsInOrder
}
val, err := ctx.GetSessionVariable(ctx, "datestyle")
if err != nil {
return formatsInOrder
}

ds := strings.ReplaceAll(val.(string), " ", "")
values := strings.Split(ds, ",")
setFormat := pgdate.ParseModeYMD
for _, value := range values {
switch value {
case "MDY":
setFormat = pgdate.ParseModeMDY
case "DMY":
setFormat = pgdate.ParseModeDMY
case "YMD":
setFormat = pgdate.ParseModeYMD
}
}
if setFormat == formatsInOrder[0] {
return formatsInOrder
}

curFirst := formatsInOrder[0]
for i, f := range formatsInOrder {
if setFormat == f {
formatsInOrder[i] = curFirst
}
}
formatsInOrder[0] = setFormat
return formatsInOrder
}
Loading
Loading