Skip to content

Commit

Permalink
add support for 846 charset
Browse files Browse the repository at this point in the history
  • Loading branch information
sijms committed Sep 19, 2023
1 parent 6d358c3 commit 6d2aef5
Show file tree
Hide file tree
Showing 4 changed files with 3,254 additions and 32 deletions.
78 changes: 56 additions & 22 deletions v2/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,18 @@ const (
//PROXY LogonMode = 0x400
)

var oracleDriver = &OracleDriver{cusTyp: map[string]customType{}}

// from GODROR
const wrapResultset = "--WRAP_RESULTSET--"

// Querier is the QueryContext of sql.Conn.
type Querier interface {
QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
}
type GetDriverInterface interface {
Driver() driver.Driver
}

/////

Expand Down Expand Up @@ -107,11 +112,13 @@ type OracleConnector struct {
dialer network.DialerContext
}
type OracleDriver struct {
dataCollected bool
cusTyp map[string]customType
mu sync.Mutex
serverCharset int
serverNCharset int
dataCollected bool
cusTyp map[string]customType
mu sync.Mutex
sStrConv converters.IStringConverter
nStrConv converters.IStringConverter
//serverCharset int
//serverNCharset int
//Conn *Connection
//Server string
//Port int
Expand All @@ -124,12 +131,22 @@ type OracleDriver struct {
}

func init() {
sql.Register("oracle", &OracleDriver{cusTyp: map[string]customType{}})
sql.Register("oracle", oracleDriver)
}

func (drv *OracleDriver) OpenConnector(name string) (driver.Connector, error) {
func GetDefaultDriver() *OracleDriver {
return oracleDriver
}

return &OracleConnector{drv: drv, connectString: name}, nil
func NewDriver() *OracleDriver {
return &OracleDriver{cusTyp: map[string]customType{}}
}
func NewConnector(connString string) driver.Connector {
return &OracleConnector{connectString: connString, drv: NewDriver()}
}
func (drv *OracleDriver) OpenConnector(connString string) (driver.Connector, error) {
// create hash from connection string
return &OracleConnector{drv: drv, connectString: connString}, nil
}

func (connector *OracleConnector) Connect(ctx context.Context) (driver.Conn, error) {
Expand All @@ -139,7 +156,12 @@ func (connector *OracleConnector) Connect(ctx context.Context) (driver.Conn, err
return nil, err
}
conn.cusTyp = connector.drv.cusTyp

if connector.drv.sStrConv != nil {
conn.sStrConv = connector.drv.sStrConv.Clone()
}
if connector.drv.nStrConv != nil {
conn.nStrConv = connector.drv.nStrConv.Clone()
}
conn.connOption.Dialer = connector.dialer
err = conn.OpenWithContext(ctx)
if err != nil {
Expand All @@ -154,8 +176,12 @@ func (driver *OracleDriver) collectData(conn *Connection) {
driver.mu.Lock()
defer driver.mu.Unlock()
driver.UserId = conn.connOption.UserID
driver.serverCharset = conn.tcpNego.ServerCharset
driver.serverNCharset = conn.tcpNego.ServernCharset
if driver.sStrConv == nil {
driver.sStrConv = conn.sStrConv.Clone()
}
if driver.nStrConv == nil {
driver.nStrConv = conn.nStrConv.Clone()
}
driver.dataCollected = true
}
}
Expand Down Expand Up @@ -185,9 +211,12 @@ func (drv *OracleDriver) Open(name string) (driver.Conn, error) {

// SetStringConverter this function is used to set a custom string converter interface
// that will be used to encode and decode strings and bytearrays
func (conn *Connection) SetStringConverter(converter converters.IStringConverter) {
conn.sStrConv = converter
conn.session.StrConv = converter
// passing nil will use driver string converter for supported langs
func SetStringConverter(db GetDriverInterface, charset, nCharset converters.IStringConverter) {
if driver, ok := db.Driver().(*OracleDriver); ok {
driver.sStrConv = charset
driver.nStrConv = nCharset
}
}

// GetNLS return NLS properties of the connection.
Expand Down Expand Up @@ -1275,6 +1304,7 @@ func RegisterType(conn *sql.DB, typeName, arrayTypeName string, typeObj interfac
if err != nil {
return err
}

if driver, ok := conn.Driver().(*OracleDriver); ok {
return RegisterTypeWithOwner(conn, driver.UserId, typeName, arrayTypeName, typeObj)
}
Expand Down Expand Up @@ -1360,14 +1390,14 @@ func RegisterTypeWithOwner(conn *sql.DB, owner, typeName, arrayTypeName string,
param.CharsetForm = 1
param.ContFlag = 16
param.MaxCharLen = int(length.Int64)
param.CharsetID = driver.serverCharset
param.CharsetID = driver.sStrConv.GetLangID()
param.MaxLen = int(length.Int64) * converters.MaxBytePerChar(param.CharsetID)
case "NVARCHAR2":
param.DataType = NCHAR
param.CharsetForm = 2
param.ContFlag = 16
param.MaxCharLen = int(length.Int64)
param.CharsetID = driver.serverNCharset
param.CharsetID = driver.nStrConv.GetLangID()
param.MaxLen = int(length.Int64) * converters.MaxBytePerChar(param.CharsetID)
case "TIMESTAMP":
fallthrough
Expand All @@ -1384,14 +1414,14 @@ func RegisterTypeWithOwner(conn *sql.DB, owner, typeName, arrayTypeName string,
param.DataType = OCIClobLocator
param.CharsetForm = 1
param.ContFlag = 16
param.CharsetID = driver.serverCharset
param.CharsetID = driver.sStrConv.GetLangID()
param.MaxCharLen = int(length.Int64)
param.MaxLen = int(length.Int64) * converters.MaxBytePerChar(param.CharsetID)
case "NCLOB":
param.DataType = OCIClobLocator
param.CharsetForm = 2
param.ContFlag = 16
param.CharsetID = driver.serverNCharset
param.CharsetID = driver.nStrConv.GetLangID()
param.MaxCharLen = int(length.Int64)
param.MaxLen = int(length.Int64) * converters.MaxBytePerChar(param.CharsetID)
default:
Expand Down Expand Up @@ -1473,14 +1503,18 @@ func (conn *Connection) protocolNegotiation() error {
tracer.Print("Server Charset: ", conn.tcpNego.ServerCharset)
tracer.Print("Server National Charset: ", conn.tcpNego.ServernCharset)
// create string converter object
conn.sStrConv = converters.NewStringConverter(conn.tcpNego.ServerCharset)
if conn.sStrConv == nil {
return fmt.Errorf("the server use charset with id: %d which is not supported by the driver", conn.tcpNego.ServerCharset)
conn.sStrConv = converters.NewStringConverter(conn.tcpNego.ServerCharset)
if conn.sStrConv == nil {
return fmt.Errorf("the server use charset with id: %d which is not supported by the driver", conn.tcpNego.ServerCharset)
}
}
conn.session.StrConv = conn.sStrConv
conn.nStrConv = converters.NewStringConverter(conn.tcpNego.ServernCharset)
if conn.nStrConv == nil {
return fmt.Errorf("the server use ncharset with id: %d which is not supported by the driver", conn.tcpNego.ServernCharset)
conn.nStrConv = converters.NewStringConverter(conn.tcpNego.ServernCharset)
if conn.nStrConv == nil {
return fmt.Errorf("the server use ncharset with id: %d which is not supported by the driver", conn.tcpNego.ServernCharset)
}
}
conn.tcpNego.ServerFlags |= 2
return nil
Expand Down
13 changes: 13 additions & 0 deletions v2/converters/string_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type IStringConverter interface {
Encode(string) []byte
Decode([]byte) string
GetLangID() int
Clone() IStringConverter
//SetLangID(langID int) int
}

Expand Down Expand Up @@ -55,6 +56,18 @@ func MaxBytePerChar(charsetID int) int {
return 1
}
}

func (conv *StringConverter) Clone() IStringConverter {
return &StringConverter{
LangID: conv.LangID,
CharWidth: conv.CharWidth,
eReplace: conv.eReplace,
dReplace: conv.dReplace,
dBuffer: conv.dBuffer,
dBuffer2: conv.dBuffer2,
eBuffer: conv.eBuffer,
}
}
func (conv *StringConverter) GetLangID() int {
return conv.LangID
}
Expand Down
Loading

0 comments on commit 6d2aef5

Please sign in to comment.