Skip to content
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Changelog (English)
- Upgrade MySQL driver to v1.10.0
- Upgrade Microsoft SQL Server driver to v1.10.0
- Upgrade PostgreSQL driver to v1.12.3
- Oracle datetime values are now passed as strings and converted using `TO_DATE`/`TO_TIMESTAMP` to avoid timezone-related comparison issues in sijms/go-ora. (#55)

v0.27.6
-------
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG_ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Changelog (Japanese)
- Upgrade MySQL driver to v1.10.0
- Upgrade Microsoft SQL Server driver to v1.10.0
- Upgrade PostgreSQL driver to v1.12.3
- sijms/go-ora でのタイムゾーンに関する比較問題を回避するため、Oracle の日時値を文字列として引き渡し、`TO_DATE`/`TO_TIMESTAMP` を使ってコンバートするようにした (#55)

v0.27.6
-------
Expand Down
68 changes: 58 additions & 10 deletions dialect/oracle/main.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
package sqlbless

import (
"database/sql"
"fmt"
"strings"

_ "github.com/sijms/go-ora/v2"

"github.com/hymkor/sqlbless/dialect"
)

func oracleTypeNameToConv(typeName string) func(string) (any, error) {
if strings.HasPrefix(typeName, "TIMESTAMP") || typeName == "DATE" {
return func(s string) (any, error) {
return dialect.ParseAnyDateTime(s)
}
}
return nil
}

var oracleSpec = &dialect.Entry{
Usage: "sqlbless oracle://<USERNAME>:<PASSWORD>@<HOSTNAME>:<PORT>/<SERVICE>",
SQLForColumns: `
Expand All @@ -39,7 +32,62 @@ var oracleSpec = &dialect.Entry{
TypeConverterFor: oracleTypeNameToConv,
TableNameField: "tname",
ColumnNameField: "name",
PlaceHolder: &dialect.PlaceHolderName{Prefix: ":", Format: "v"},
PlaceHolder: new(placeHolder),
}

type withFormat struct {
format string
value any
}

func oracleTypeNameToConv(typeName string) func(string) (any, error) {
var format string
var layout string

if typeName == "DATE" {
format = "TO_DATE(:v%d,'YYYY/MM/DD HH24:MI:SS')"
layout = "2006/01/02 15:04:05"
} else if strings.HasPrefix(typeName, "TIMESTAMP") {
format = "TO_TIMESTAMP(:v%d,'YYYY/MM/DD HH24:MI:SS.FF')"
layout = "2006/01/02 15:04:05.999999"
} else {
return nil
}
return func(s string) (any, error) {
dt, err := dialect.ParseAnyDateTime(s)
if err != nil {
return s, nil
}
return &withFormat{
format: format,
value: dt.Format(layout),
}, nil
}
}

type placeHolder struct {
values []any
}

func (ph *placeHolder) Make(v any) string {
if w, ok := v.(*withFormat); ok {
ph.values = append(ph.values, w.value)
return fmt.Sprintf(w.format, len(ph.values))
}
ph.values = append(ph.values, v)
return fmt.Sprintf(":v%d", len(ph.values))
}

func (ph *placeHolder) NormalizeColumnForWhere(value any, columnName string) string {
return columnName
}

func (ph *placeHolder) Values() (result []any) {
for i, v := range ph.values {
result = append(result, sql.Named(fmt.Sprintf("v%d", i+1), v))
}
ph.values = ph.values[:0]
return
}

func init() {
Expand Down
Loading