go-ase is a driver for the databasq/sql package
of Go (golang) to provide access to SAP ASE instances.
It is delivered as Go module.
SAP ASE is the shorthand for SAP Adaptive Server Enterprise, a relational model database server originally known as Sybase SQL Server.
go-ase contains two implementations in cgo in the directory
cgo and in pure go in the directory purego.
cgo enables Go to call C code and to link against shared objects.
The cgo driver requires the shared objects from either the ASE itself
or Client-Library to compile.
The required shared objects from ASE can be found in the installation
path of the ASE under OCS-16_0/lib, where 16_0 is the version of
your ASE installation.
After installing the Client-Library SDK the
shared objects can be found in the folder lib at the chosen
installation path.
The headers are provided at cgo/includes.
The pure go driver has no special requirements other than Go standard
library and the third part modules listed in go.mod.
The packages in this repo can be go get and imported as usual.
For specifics on how to use database/sql please see the
documentation.
Example code:
package main
import (
"database/sql"
_ "github.com/SAP/go-ase/cgo"
)
func main() {
db, err := sql.Open("ase", "ase://user:pass@host:port/")
if err != nil {
log.Printf("Failed to open database: %v", err)
return
}
defer db.Close()
err = db.Ping()
if err != nil {
log.Printf("Failed to ping database: %v", err)
return
}
}/path/to/OCS is the path to your Client-Library SDK installation.
/lib is the folder inside of the SDK installation containing the
shared objects required for the cgo driver.
Compilation:
CGO_LDFLAGS="-L/path/to/OCS/lib" go build -o cmd ./Execution:
LD_LIBRARY_PATH="/path/to/OCS/lib" ./cmdpackage main
import (
"database/sql"
_ "github.com/SAP/go-ase/purego"
)
func main() {
db, err := sql.Open("ase", "ase://user:pass@host:port/")
if err != nil {
log.Printf("Failed to open database: %v", err)
return
}
defer db.Close()
err = db.Ping()
if err != nil {
log.Printf("Failed to ping database: %v", err)
return
}
}Compilation:
go build -o cmd ./Execution:
./cmdMore examples can be found in the folder examples/$type, where $type
is either purego or cgo.
Unit tests for the packages are included in their respective directories
and can be run using go test.
Integration tests are available in tests/ and can be run using go test test/${type}test,
where $type is either purego or cgo.
These require the following environment variables to be set:
ASE_HOSTASE_PORTASE_USERASE_PASS
The cgo tests additionally require the variable ASE_USERSTOREKEY to be set.
The integration tests will create new databases for each connection type to run tests against. After the tests are finished the created databases will be removed.
The configuration is handled through either a data source name (DSN) in one of two forms or through a configuration struct passed to a connector.
All of these support additional properties which can tweak the connection, configuration options in Client-Library or the drivers themselves.
The URI DSN is a common URI like ase://user:pass@host:port/?prop1=val1&prop2=val2.
DSNs in this form are parsed using url.Parse.
The simple DSN is a key/value string: username=user password=pass host=hostname port=4901
Values with spaces must be quoted using single or double quotes.
Each member of libase.libdsn.DsnInfo can be set using any of their
possible json tags. E.g. .Host will receive the values from the keys
host and hostname.
Additional properties are set as key/value pairs as well: ... prop1=val1 prop2=val2. If the parser doesn't recognize a string as
a json tag it assumes that the key/value pair is a property and its
value.
Similar to the URI DSN those property/value pairs are purely additive. Any property that only recognizes a single argument (e.g. a boolean) will only honour the last given value for a property.
As an alternative to the string DSNs cgo.NewConnector and
purego.NewConnector accept a libdsn.DsnInfo directly and return
a driver.Connector, which can be passed to sql.OpenDB:
package main
import (
"database/sql"
"github.com/SAP/go-ase/libase/libdsn"
// "github.com/SAP/go-ase/purego" for the pure go implementation
ase "github.com/SAP/go-ase/cgo"
)
func main() {
d := libdsn.NewDsnInfo()
d.Host = "hostname"
d.Port = "4901"
d.Username = "user"
d.Password = "pass"
connector, err := ase.NewConnector(*d)
if err != nil {
log.Printf("Failed to create connector: %v", err)
return
}
db, err := sql.OpenDB(connector)
if err != nil {
log.Printf("Failed to open database: %v", err)
return
}
defer db.Close()
err = db.Ping()
if err != nil {
log.Printf("Failed to ping ASE: %v", err)
}
}Additional properties can be set by calling d.ConnectProps.Add("prop1", "value1") or d.ConnectProps.Set("prop2", "value2").
Recognized values: yes or any string
When set to yes all client messages will be printed to stderr.
Please note that this is a debug property - for logging you should
register your own message handler with the GlobalClientMessageBroker.
When set to any other string the callback will not bet set.
Recognized values: yes or any string
When set to yes all server messages will be printed to stderr.
Please note that this is a debug property - for logging you should
register your own message handler with the GlobalServerMessageBroker.
When set to any other string the callback will not be set.
Recognized values: string
Sets the application name to the value. This can be used in ASE to determine which application opened a connection.
Defaults to database/sql driver github.com/SAP/go-ase/purego.
Recognized values: string
If the value is recognized by strconv.ParseBool to represent true
the connection will be created as read only.
Recognized values: string
The network must be a network type recognized by net.Dial - at the
time of writing this is either udp or tcp.
This should only be required to be set if the database is only reachable through a UDP proxy.
Defaults to tcp.
Recognized values: integer
Defines how many packages a TDS channel can buffer at most. When working with very large datasets where heavy computation only occurs every hundred packages or so it may be feasible to improve performance by increasing the queue size.
Defaults to 100.
Recognized values: string
The client-hostname to report to the TDS server. Due to protocol limitations this will be cut off after 30 characters.
Defaults to the hostname of the machine, acquired using os.Hostname.
Recognized values: integer
The timeout in seconds when a packet is read. The timeout is reset every time a packet successfully reads data from the connection.
That means the timeout only triggers if no data was read for longer than
packet-read-timeout seconds.
Default to 50.
Recognized values: bool
Activates TLS for the connection. Any other TLS option is ignored unless tls is set to true.
Defaults to true if the target port is 443, false otherwise.
Recognized values: string
Allows to pass SAN for TLS validation.
For compatibility with the cgo implementation you may also use ssl
instead of tls-hostname and pass CN=<SAN> instead of <SAN>.
Defaults to empty string.
Please note that as of go1.15 the CommonName in x509 certificates is no
longer recognized as the hostname if no SANs are present in the
certificate.
If the certificate for your TDS server only utilizes the CN you can
reenable this behaviour by setting GODEBUG to x509ignoreCN=0 in your
environment.
For details see https://golang.google.cn/doc/go1.15#commonname
Recognized values: string
If the value is recognized by strconv.ParseBool to represent true
the TLS certificate of the TDS server will not be validated.
Defaults to empty string / false.
Recognized values: string
Path to a CA file, which may contain multiple CAs, to validate the TDS servers certificate against. If empty the servers trust store is used.
Defaults to empty string.
The pure go implementation is currently in beta and under active development. As such most features of the TDS protocol and ASE are not supported.
Regarding the limitations of prepared statements/dynamic SQL please see the Client-Library documentation.
The Client-Library documentation applies to both the cgo and the pure go implementation as these restrictions are imposed by the implementation of dynamic SQL on the server side.
Currently the following data types are not supported:
- Timestamp
- Univarchar
Due to the limitations of the Client-Library it is not possible to support null types.
Additionally columns of the following data types must be nullable:
- Image
- Binary
The list of known issues is available here.
Feel free to open issues for feature requests, bugs or general feedback here.
Any help to improve this package is highly appreciated.
For details on how to contribute please see the contributing file.
Copyright (c) 2019-2020 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache License 2.0 except as noted otherwise in the LICENSE file