Skip to content

Commit

Permalink
some performance fix (replacing appending bytes to bytes.Buffer.Write())
Browse files Browse the repository at this point in the history
  • Loading branch information
sijms committed Feb 6, 2021
1 parent 67f66eb commit d862030
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 148 deletions.
11 changes: 6 additions & 5 deletions connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ func (conn *Connection) Prepare(query string) (driver.Stmt, error) {
return NewStmt(query, conn), nil
}

func (conn *Connection) Ping(ctx context.Context) error {
func (conn *Connection) Ping(_ context.Context) error {
conn.connOption.Tracer.Print("Ping")
conn.session.ResetBuffer()
return (&simpleObject{
Expand Down Expand Up @@ -293,10 +293,10 @@ func (conn *Connection) Open() error {
conn.connOption.ServiceName = conn.SessionProperties["AUTH_SC_SERVICE_NAME"]
conn.connOption.DomainName = conn.SessionProperties["AUTH_SC_DB_DOMAIN"]
conn.connOption.DBName = conn.SessionProperties["AUTH_SC_DBUNIQUE_NAME"]
//_, err = conn.GetNLS()
//if err != nil {
// return err
//}
_, err = conn.GetNLS()
if err != nil {
return err
}

return nil
}
Expand Down Expand Up @@ -355,6 +355,7 @@ func NewConnection(databaseUrl string) (*Connection, error) {
if len(conStr.Trace) > 0 {
tf, err := os.Create(conStr.Trace)
if err != nil {
//noinspection GoErrorStringFormat
return nil, fmt.Errorf("Can't open trace file: %w", err)
}
connOption.Tracer = trace.NewTraceWriter(tf)
Expand Down
250 changes: 130 additions & 120 deletions connection_string.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,18 +107,19 @@ func NewConnectionString() *ConnectionString {
ConnectionPoolTimeout: 15,
}
}
func NewConnectionStringFromString(connectionString string) (*ConnectionString, error) {
// initialize
ret := NewConnectionString()
// parse
err := ret.Parse(connectionString)
if err != nil {
return nil, err
}
// validate
ret.validate()
return ret, nil
}

//func NewConnectionStringFromString(connectionString string) (*ConnectionString, error) {
// // initialize
// ret := NewConnectionString()
// // parse
// err := ret.Parse(connectionString)
// if err != nil {
// return nil, err
// }
// // validate
// ret.validate()
// return ret, nil
//}

func (connStr *ConnectionString) validate() {
if !connStr.Pooling {
Expand Down Expand Up @@ -213,7 +214,11 @@ func newConnectionStringFromUrl(databaseUrl string) (*ConnectionString, error) {
if err != nil {
return nil, errors.New("CONNECTION POOL TIMEOUT value must be an integer")
}
//case "CONNECTION LIFETIME":
case "CONNECTION LIFETIME":
ret.ConnectionLifeTime, err = strconv.Atoi(val[0])
if err != nil {
return nil, errors.New("CONNECTION LIFETIME value must be an integer")
}
case "PERSIST SECURITY INFO":
ret.PasswordSecurityInfo = val[0] == "TRUE"
case "POOLING":
Expand Down Expand Up @@ -264,111 +269,116 @@ func newConnectionStringFromUrl(databaseUrl string) (*ConnectionString, error) {
ret.validate()
return ret, nil
}
func (conStr *ConnectionString) Parse(s string) error {

var upperInvariant = strings.ToUpper(s)
var attribs = strings.Split(upperInvariant, ";")
for _, attrib := range attribs {
fields := strings.Split(attrib, "=")
if len(fields) != 2 {
return errors.New("error in connection string")
}
key := fields[0]
val := fields[1]
var err error
switch key {
case "DATA SOURCE":
conStr.DataSource = val
case "DBA PRIVILEGE":
conStr.DBAPrivilege = DBAPrivilegeFromString(val)
case "ENLIST":
conStr.EnList = EnListFromString(val)
case "CONNECT TIMEOUT":
fallthrough
case "CONNECTION TIMEOUT":
conStr.ConnectionTimeOut, err = strconv.Atoi(val)
if err != nil {
return errors.New("CONNECTION TIMEOUT value must be an integer")
}
case "INC POOL SIZE":
conStr.IncrPoolSize, err = strconv.Atoi(val)
if err != nil {
return errors.New("INC POOL SIZE value must be an integer")
}
case "DECR POOL SIZE":
conStr.DecrPoolSize, err = strconv.Atoi(val)
if err != nil {
return errors.New("DECR POOL SIZE value must be an integer")
}
case "MAX POOL SIZE":
conStr.MaxPoolSize, err = strconv.Atoi(val)
if err != nil {
return errors.New("MAX POOL SIZE value must be an integer")
}
case "MIN POOL SIZE":
conStr.MinPoolSize, err = strconv.Atoi(val)
if err != nil {
return errors.New("MIN POOL SIZE value must be an integer")
}
case "POOL REGULATOR":
conStr.PoolReglator, err = strconv.Atoi(val)
if err != nil {
return errors.New("POOL REGULATOR value must be an integer")
}
case "STATEMENT CACHE SIZE":
conStr.StmtCacheSize, err = strconv.Atoi(val)
if err != nil {
return errors.New("STATEMENT CACHE SIZE value must be an integer")
}
case "CONNECTION POOL TIMEOUT":
conStr.ConnectionPoolTimeout, err = strconv.Atoi(val)
if err != nil {
return errors.New("CONNECTION POOL TIMEOUT value must be an integer")
}
case "CONNECTION LIFETIME":
case "PERSIST SECURITY INFO":
conStr.PasswordSecurityInfo = val == "TRUE"
case "POOLING":
conStr.Pooling = val == "TRUE"
case "VALIDATE CONNECTION":
conStr.ValidateConnection = val == "TRUE"
case "STATEMENT CACHE PURGE":
conStr.StmtCachePurge = val == "TRUE"
case "HA EVENTS":
conStr.HaEvent = val == "TRUE"
case "LOAD BALANCING":
conStr.LoadBalance = val == "TRUE"
case "METADATA POOLING":
conStr.MetadataBooling = val == "TRUE"
case "SELF TUNING":
conStr.SelfTuning = val == "TRUE"
case "CONTEXT CONNECTION":
conStr.ContextConnection = val == "TRUE"
case "PROMOTABLE TRANSACTION":
if val == "ROMOTABLE" {
conStr.PromotableTransaction = Promotable
} else {
conStr.PromotableTransaction = Local
}
case "APPLICATION EDITION":
conStr.ApplicationEdition = val
case "USER ID":
val = strings.Trim(val, "'")
conStr.UserID = strings.Trim(val, "\"")
if conStr.UserID == "\\" {
// get os user and password
}
case "PROXY USER ID":
val = strings.Trim(val, "'")
conStr.ProxyUserID = strings.Trim(val, "\"")
case "PASSWORD":
val = strings.Trim(val, "'")
conStr.Password = strings.Trim(val, "\"")
case "PROXY PASSWORD":
val = strings.Trim(val, "'")
conStr.ProxyPassword = strings.Trim(val, "\"")
}

}
return nil
}
//func (conStr *ConnectionString) Parse(s string) error {
//
// var upperInvariant = strings.ToUpper(s)
// var attribs = strings.Split(upperInvariant, ";")
// for _, attrib := range attribs {
// fields := strings.Split(attrib, "=")
// if len(fields) != 2 {
// return errors.New("error in connection string")
// }
// key := fields[0]
// val := fields[1]
// var err error
// switch key {
// case "DATA SOURCE":
// conStr.DataSource = val
// case "DBA PRIVILEGE":
// conStr.DBAPrivilege = DBAPrivilegeFromString(val)
// case "ENLIST":
// conStr.EnList = EnListFromString(val)
// case "CONNECT TIMEOUT":
// fallthrough
// case "CONNECTION TIMEOUT":
// conStr.ConnectionTimeOut, err = strconv.Atoi(val)
// if err != nil {
// return errors.New("CONNECTION TIMEOUT value must be an integer")
// }
// case "INC POOL SIZE":
// conStr.IncrPoolSize, err = strconv.Atoi(val)
// if err != nil {
// return errors.New("INC POOL SIZE value must be an integer")
// }
// case "DECR POOL SIZE":
// conStr.DecrPoolSize, err = strconv.Atoi(val)
// if err != nil {
// return errors.New("DECR POOL SIZE value must be an integer")
// }
// case "MAX POOL SIZE":
// conStr.MaxPoolSize, err = strconv.Atoi(val)
// if err != nil {
// return errors.New("MAX POOL SIZE value must be an integer")
// }
// case "MIN POOL SIZE":
// conStr.MinPoolSize, err = strconv.Atoi(val)
// if err != nil {
// return errors.New("MIN POOL SIZE value must be an integer")
// }
// case "POOL REGULATOR":
// conStr.PoolReglator, err = strconv.Atoi(val)
// if err != nil {
// return errors.New("POOL REGULATOR value must be an integer")
// }
// case "STATEMENT CACHE SIZE":
// conStr.StmtCacheSize, err = strconv.Atoi(val)
// if err != nil {
// return errors.New("STATEMENT CACHE SIZE value must be an integer")
// }
// case "CONNECTION POOL TIMEOUT":
// conStr.ConnectionPoolTimeout, err = strconv.Atoi(val)
// if err != nil {
// return errors.New("CONNECTION POOL TIMEOUT value must be an integer")
// }
// case "CONNECTION LIFETIME":
// conStr.ConnectionLifeTime, err = strconv.Atoi(val)
// if err != nil {
// return errors.New("CONNECTION LIFETIME value must be an integer")
// }
// case "PERSIST SECURITY INFO":
// conStr.PasswordSecurityInfo = val == "TRUE"
// case "POOLING":
// conStr.Pooling = val == "TRUE"
// case "VALIDATE CONNECTION":
// conStr.ValidateConnection = val == "TRUE"
// case "STATEMENT CACHE PURGE":
// conStr.StmtCachePurge = val == "TRUE"
// case "HA EVENTS":
// conStr.HaEvent = val == "TRUE"
// case "LOAD BALANCING":
// conStr.LoadBalance = val == "TRUE"
// case "METADATA POOLING":
// conStr.MetadataBooling = val == "TRUE"
// case "SELF TUNING":
// conStr.SelfTuning = val == "TRUE"
// case "CONTEXT CONNECTION":
// conStr.ContextConnection = val == "TRUE"
// case "PROMOTABLE TRANSACTION":
// if val == "ROMOTABLE" {
// conStr.PromotableTransaction = Promotable
// } else {
// conStr.PromotableTransaction = Local
// }
// case "APPLICATION EDITION":
// conStr.ApplicationEdition = val
// case "USER ID":
// val = strings.Trim(val, "'")
// conStr.UserID = strings.Trim(val, "\"")
// if conStr.UserID == "\\" {
// // get os user and password
// }
// case "PROXY USER ID":
// val = strings.Trim(val, "'")
// conStr.ProxyUserID = strings.Trim(val, "\"")
// case "PASSWORD":
// val = strings.Trim(val, "'")
// conStr.Password = strings.Trim(val, "\"")
// case "PROXY PASSWORD":
// val = strings.Trim(val, "'")
// conStr.ProxyPassword = strings.Trim(val, "\"")
// }
//
// }
// return nil
//}
46 changes: 29 additions & 17 deletions data_type_nego.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package go_ora

import (
"bytes"
"encoding/binary"
"errors"
"fmt"
Expand Down Expand Up @@ -438,42 +439,53 @@ func buildTypeNego(nego *TCPNego, session *network.Session) (*DataTypeNego, erro
}

func (nego *DataTypeNego) bytes() []byte {
var result = make([]byte, 7, 1000)
var result bytes.Buffer
//var result = make([]byte, 7, 1000)
if nego.Server.ServerCompileTimeCaps == nil || len(nego.Server.ServerCompileTimeCaps) <= 27 || nego.Server.ServerCompileTimeCaps[27] == 0 {
nego.CompileTimeCaps[27] = 0
}
result[0] = nego.MessageCode
//binary.BigEndian.PutUint16(result[2:], 0)
//binary.BigEndian.PutUint16(result[4:], 0)
result[5] = nego.Server.ServerFlags
result[6] = uint8(len(nego.CompileTimeCaps))
result = append(result, nego.CompileTimeCaps...)
result = append(result, uint8(len(nego.RuntimeCap)))
result = append(result, nego.RuntimeCap...)
//result.WriteByte(nego.MessageCode)
result.Write([]byte{nego.MessageCode, 0, 0, 0, 0, nego.Server.ServerFlags, uint8(len(nego.CompileTimeCaps))})
result.Write(nego.CompileTimeCaps)
result.WriteByte(uint8(len(nego.RuntimeCap)))
result.Write(nego.RuntimeCap)
//result[0] = nego.MessageCode
//result[5] = nego.Server.ServerFlags
//result[6] = uint8(len(nego.CompileTimeCaps))
//result = append(result, nego.CompileTimeCaps...)
//result = append(result, uint8(len(nego.RuntimeCap)))
//result = append(result, nego.RuntimeCap...)
if nego.RuntimeCap[1]&1 == 1 {
result = append(result, TZBytes()...)
result.Write(TZBytes())
//result = append(result, TZBytes()...)
if nego.CompileTimeCaps[37]&2 == 2 {
result = append(result, []byte{0, 0, 0, 0}...)
result.Write([]byte{0, 0, 0, 0})
//result = append(result, []byte{0, 0, 0, 0}...)
}
}
temp := []byte{0, 0}
binary.LittleEndian.PutUint16(temp, uint16(nego.Server.ServernCharset))
result = append(result, temp...)
result.Write(temp)
//result = append(result, temp...)
// marshal type reps
size := nego.RuntimeTypeAndRep[0]
if nego.CompileTimeCaps[27] == 0 {
for _, x := range nego.RuntimeTypeAndRep[1:size] {
result = append(result, uint8(x))
result.WriteByte(uint8(x))
//result = append(result, uint8(x))
}
result = append(result, 0)
result.WriteByte(0)
//result = append(result, 0)
} else {
for _, x := range nego.RuntimeTypeAndRep[1:size] {
binary.BigEndian.PutUint16(temp, uint16(x))
result = append(result, temp...)
//result = append(result, temp...)
result.Write(temp)
}
result = append(result, []byte{0, 0}...)
result.Write([]byte{0, 0})
//result = append(result, []byte{0, 0}...)
}
return result
return result.Bytes()
}

func TZBytes() []byte {
Expand Down
Loading

0 comments on commit d862030

Please sign in to comment.