Fix DATE type parsing in SQLite
This commit is contained in:
@@ -31,7 +31,7 @@ const (
|
||||
|
||||
var (
|
||||
// make a custom driver with REGEX support
|
||||
driver = &sqlite3.SQLiteDriver{
|
||||
customDriver = &sqlite3.SQLiteDriver{
|
||||
ConnectHook: func(conn *sqlite3.SQLiteConn) (err error) {
|
||||
// register regexp function and use Go's regexp fn
|
||||
if err = conn.RegisterFunc("regexp", regexp.MatchString, true); err != nil {
|
||||
@@ -45,9 +45,9 @@ var (
|
||||
|
||||
func init() {
|
||||
// register alter driver
|
||||
sql.Register(altSchema, driver)
|
||||
sql.Register(altSchema, customDriver)
|
||||
// register drbug driver
|
||||
sql.Register(debugSchema, sqlmw.Driver(driver, instrumentation.Debug()))
|
||||
sql.Register(debugSchema, sqlmw.Driver(customDriver, instrumentation.Debug()))
|
||||
|
||||
store.Register(Connect, SCHEMA, altSchema, debugSchema)
|
||||
}
|
||||
|
||||
@@ -52,14 +52,41 @@ func (d sqliteDialect) TableCodec(m *dal.Model) drivers.TableCodec {
|
||||
return drivers.NewTableCodec(m, d)
|
||||
}
|
||||
|
||||
func (d sqliteDialect) TypeWrap(t dal.Type) drivers.Type {
|
||||
func (d sqliteDialect) TypeWrap(dt dal.Type) drivers.Type {
|
||||
// Any exception to general type-wrap implementation in the drivers package
|
||||
// should be placed here
|
||||
return drivers.TypeWrap(t)
|
||||
|
||||
// Any exception to general type-wrap implementation in the drivers package
|
||||
// should be placed here
|
||||
switch c := dt.(type) {
|
||||
case *dal.TypeDate:
|
||||
return &TypeDate{c}
|
||||
}
|
||||
|
||||
return drivers.TypeWrap(dt)
|
||||
}
|
||||
|
||||
func (sqliteDialect) AttributeCast(attr *dal.Attribute, val exp.LiteralExpression) (exp.LiteralExpression, error) {
|
||||
return drivers.AttributeCast(attr, val)
|
||||
var (
|
||||
c exp.CastExpression
|
||||
)
|
||||
|
||||
switch attr.Type.(type) {
|
||||
case *dal.TypeDate:
|
||||
ce := exp.NewCaseExpression().
|
||||
When(val.RegexpLike(drivers.CheckDateISO8061), val).
|
||||
Else(drivers.LiteralNULL)
|
||||
|
||||
// if we cast to DATE result value is treated like number (int64) and
|
||||
// we only get the year part. So we need to cast to TEXT first
|
||||
// and the the full-date is parsed into time.Time
|
||||
c = exp.NewCastExpression(ce, "TEXT")
|
||||
default:
|
||||
return drivers.AttributeCast(attr, val)
|
||||
}
|
||||
|
||||
return exp.NewLiteralExpression("?", c), nil
|
||||
|
||||
}
|
||||
|
||||
func (sqliteDialect) AttributeToColumn(attr *dal.Attribute) (col *ddl.Column, err error) {
|
||||
@@ -84,12 +111,12 @@ func (sqliteDialect) AttributeToColumn(attr *dal.Attribute) (col *ddl.Column, er
|
||||
col.Default = ddl.DefaultValueCurrentTimestamp(t.DefaultCurrentTimestamp)
|
||||
|
||||
case *dal.TypeDate:
|
||||
col.Type.Name = "DATE"
|
||||
col.Type.Name = "TEXT"
|
||||
col.Default = ddl.DefaultValueCurrentTimestamp(t.DefaultCurrentTimestamp)
|
||||
|
||||
case *dal.TypeNumber:
|
||||
col.Type.Name = "NUMERIC"
|
||||
// @todo precision, scale?
|
||||
// @todo precision, scale? x
|
||||
col.Default = ddl.DefaultNumber(t.HasDefault, t.Precision, t.DefaultValue)
|
||||
|
||||
case *dal.TypeText:
|
||||
|
||||
40
store/adapters/rdbms/drivers/sqlite/types.go
Normal file
40
store/adapters/rdbms/drivers/sqlite/types.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package sqlite
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
"github.com/spf13/cast"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/dal"
|
||||
"github.com/cortezaproject/corteza-server/store/adapters/rdbms/drivers"
|
||||
)
|
||||
|
||||
type (
|
||||
TypeDate struct{ *dal.TypeDate }
|
||||
)
|
||||
|
||||
func (*TypeDate) MakeScanBuffer() any { return new(sql.NullString) }
|
||||
|
||||
func (t *TypeDate) Decode(raw any) (any, bool, error) {
|
||||
dec, is := raw.(*sql.NullString)
|
||||
if !is {
|
||||
return nil, false, fmt.Errorf("unexpected raw type %T for Time", raw)
|
||||
}
|
||||
|
||||
if !dec.Valid {
|
||||
return time.Time{}, false, nil
|
||||
}
|
||||
|
||||
parsed, err := cast.StringToDate(dec.String)
|
||||
if err != nil {
|
||||
return time.Time{}, false, err
|
||||
}
|
||||
|
||||
return parsed.Format(drivers.DateLayout), true, nil
|
||||
}
|
||||
|
||||
func (t *TypeDate) Encode(val any) (driver.Value, error) {
|
||||
return val, nil
|
||||
}
|
||||
Reference in New Issue
Block a user