ase

package module
v0.0.0-...-62e63ab Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 14, 2025 License: Apache-2.0 Imports: 14 Imported by: 1

README ¶

go-ase

PkgGoDev Go Report Card REUSE status

🛑 Repository Sunset Notice (2025-04-14)

Dear Contributers and Users,

This is an announcement that we are planning to officially sunset this repository. This decision was made after careful consideration of the project's current trajectory, community engagement, and resource allocation.

The sunset will happen after a grace period of four weeks following this announcement. Development and support will cease, and the project will be archived.

Thank You: We are grateful for your contributions and support.

For questions or concerns, please reach out.

Description

go-ase is a driver for the database/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.

A cgo implementation can be found here.

Requirements

The go driver has no special requirements other than Go standard library and the third part modules listed in go.mod, e.g. github.com/SAP/go-dblib.

Download and Installation

The packages in this repo can be go get and imported as usual, e.g.:

go get github.com/SAP/go-ase

For specifics on how to use database/sql please see the documentation.

The command-line application goase can be go installed:

$ go install github.com/SAP/go-ase/cmd/goase@latest
go: downloading github.com/SAP/go-ase v0.0.0-20210506093950-9af676a6bab4
$ goase -h
Usage of goase:
      --appname string                   Application Name to transmit to ASE (default "github.com/SAP/go-ase")
      --channel-package-queue-size int   How many TDS packages can be queued in a TDS channel (default 100)
      --client-hostname string           Hostname to send to server (default "dev-ase-sles15sp1-ntnn-1")
      --cursor-cache-rows int            How many rows to cache at once when reading the result set of a cursor (default 1000)
      --database string                  Database
      --debug-log-packages               Log packages as they are transmitted/received
  -f, --f string                         Read SQL commands from file
      --host string                      Hostname to connect to
      --maxColLength int                 Maximum number of characters to print for column (default 50)
      --network string                   Network to use, either 'tcp' or 'udp' (default "tcp")
      --no-query-cursor                  Prevents the use of cursors for database/sql query methods. See README for details.
      --packet-read-timeout int          Time in seconds to wait before aborting a connection when no response is received from the server (default 50)
      --password string                  Password
      --port string                      Port (Example: '443' or 'tls') to connect to
      --tls-ca-file string               Path to CA file to validate server certificate against
      --tls-enable                       Enforce TLS use
      --tls-hostname string              Remote hostname to validate against SANs
      --tls-skip-validation              Skip TLS validation - accepts any TLS certificate
      --username string                  Username
2021/05/06 11:31:44 goase failed: pflag: help requested

Usage

Example code:

package main

import (
    "database/sql"
    _ "github.com/SAP/go-ase"
)

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()

    if err := db.Ping(); err != nil {
        log.Printf("Failed to ping database: %v", err)
        return
    }
}
Compilation
go build -o goase ./cmd/goase/
Execution
./goase
Examples

More examples can be found in the folder examples.

Integration tests

Integration tests are available and can be run using go test --tags=integration and go test ./examples/... --tags=integration.

These require the following environment variables to be set:

  • ASE_HOST
  • ASE_PORT
  • ASE_USER
  • ASE_PASS

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.

Configuration

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 or the drivers themselves.

Data Source Names
URI DSN

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.

Simple DSN

The simple DSN is a key/value string: username=user password=pass host=hostname port=4901

Each member of Info is recognized by its json metadata tag or any of its multiref metadata tags.

Values with spaces must be quoted using single or double quotes.

Connector

As an alternative to the string DSNs ase.NewConnector accept a Info directly and return a driver.Connector, which can be passed to sql.OpenDB:

package main

import (
    "database/sql"

    "github.com/SAP/go-ase"
)

func main() {
    info := ase.NewInfo()
    info.Host = "hostname"
    info.Port = "4901"
    info.Username = "user"
    info.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()

    if err := db.Ping(); err != nil {
        log.Printf("Failed to ping ASE: %v", err)
    }
}
Properties
appname

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.

network

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.

channel-package-queue-size

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.

client-hostname

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.

packet-read-timeout

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.

tls

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.

tls-hostname

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:

GODEBUG=x509ignoreCN=0 <path/to/your/app>
GODEBUG=x509ignoreCN=0 go run ./cmd/goase

For details see https://golang.google.cn/doc/go1.15#commonname

tls-skip-validation

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.

tls-ca

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.

no-query-cursor

Recognized values: bool

Prevents the use of cursors for database/sql query methods.

By default go-ase creates cursors when a .Query* method is used.

Depending on the query, expected result set, memory consumption and used hardware this may perform worse than a simple query.

It is strongly suggested to profile this option with your queries before enabling it.

Altneratively you can pass this option on a per-query basis in the context. See the documentation of Conn.QueryContext for details.

Nullable data types

Nullable data types are implemented in go-dblib. However, the implementation differs partially from drivers like isql in regard of "zero-length non-Null" string-types, e.g. "". Instead of inserting such values as " ", the methods stmt.Exec(...) or db.Exec(...) will insert these values as actual NULL values. A legacy-option to insert such "zero-length non-Null" string-type values as " " is planned but not implemented yet. In the meantime, it is possible to reproduce this behaviour by using language tokens as provided by the executable goase.

Limitations

Beta

The go implementation is currently in beta and under active development. As such most features of the TDS protocol and ASE are not supported.

Prepared statements

Regarding the limitations of prepared statements/dynamic SQL please see the Client-Library documentation.

The Client-Library documentation applies to the go implementation as these restrictions are imposed by the implementation of dynamic SQL on the server side.

Unsupported ASE data types

Currently the following data types are not supported:

  • Timestamp
  • Univarchar
  • Nullable Text
  • Nullable Unitext
  • Nullable Unichar
  • Nullable Image

Known Issues

The list of known issues is available here.

How to obtain support

Feel free to open issues for feature requests, bugs or general feedback here.

Contributing

Any help to improve this package is highly appreciated.

For details on how to contribute please see the contributing file.

License

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.

Documentation ¶

Overview ¶

Package ase contains code of the go-ase driver for the database/sql package of Go (golang) to provide access to SAP ASE instances.

Index ¶

Constants ¶

View Source
const DriverName = "ase"

DriverName is the driver name to use with sql.Open for ase databases.

Variables ¶

View Source
var (
	ErrCurNoMoreRows = errors.New("no more rows in cursor")
)

Functions ¶

func AddEEDHooks ¶

func AddEEDHooks(fns ...tds.EEDHook) error

AddEEDHooks registers functions as hooks. The hooks are executed when the driver receives EED packages.

func AddEnvChangeHooks ¶

func AddEnvChangeHooks(fns ...tds.EnvChangeHook) error

AddEnvChangeHooks registers funtions as hooks. The hooks are executed when the driver receives EnvChange packages.

func DefaultTxOptions ¶

func DefaultTxOptions() driver.TxOptions

DefaultTxOptions returns default driver.TxOptions.

func NewConnector ¶

func NewConnector(info *Info) (driver.Connector, error)

NewConnector returns a new connector with the passed configuration.

func NewConnectorWithHooks ¶

func NewConnectorWithHooks(info *Info, envChangeHooks []tds.EnvChangeHook, eedHooks []tds.EEDHook) (driver.Connector, error)

NewConnectorWithHooks returns a new connector with the passed configuration.

Types ¶

type Conn ¶

type Conn struct {
	Conn    *tds.Conn
	Channel *tds.Channel
	Info    *Info
	// contains filtered or unexported fields
}

Conn implements the driver.Conn interface.

func NewConn ¶

func NewConn(ctx context.Context, dsn *Info) (*Conn, error)

NewConn returns a connection with the passed configuration.

func NewConnWithHooks ¶

func NewConnWithHooks(ctx context.Context, info *Info, envChangeHooks []tds.EnvChangeHook, eedHooks []tds.EEDHook) (*Conn, error)

NewConnWithHooks returns a connection with the passed configuration.

func (*Conn) Begin ¶

func (c *Conn) Begin() (driver.Tx, error)

Begin implements the driver.Conn interface.

func (*Conn) BeginTx ¶

func (c *Conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error)

BeginTx implements the driver.ConnBeginTx interface.

func (*Conn) CheckNamedValue ¶

func (conn *Conn) CheckNamedValue(nv *driver.NamedValue) error

CheckNamedValue implements the driver.NamedValueChecker interface.

func (*Conn) Close ¶

func (c *Conn) Close() error

Close implements the driver.Conn interface.

func (*Conn) DirectExec ¶

func (c *Conn) DirectExec(ctx context.Context, query string, args ...interface{}) (driver.Rows, driver.Result, error)

DirectExec is a wrapper for GenericExec and meant to be used when directly accessing this library, rather than using database/sql.

The primary advantage are the variadic args, which can be normal values and are automatically transformed to driver.NamedValues for GenericExec.

func (*Conn) ExecContext ¶

func (c *Conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error)

ExecContext implements the driver.ExecerContext.

func (*Conn) GenericExec ¶

func (c *Conn) GenericExec(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, driver.Result, error)

GenericExec is the central method through which SQL statements are sent to ASE.

func (*Conn) NewCursor ¶

func (c *Conn) NewCursor(ctx context.Context, query string, args ...interface{}) (*Cursor, error)

NewCursor creates a new cursor.

NewCursor is a wrapper around NewCursorWithValues that converts arguments into driver.NamedValues.

func (*Conn) NewCursorWithValues ¶

func (c *Conn) NewCursorWithValues(ctx context.Context, query string, args []driver.NamedValue) (*Cursor, error)

NewCursorWithValues creates a new cursor.

func (*Conn) NewRows ¶

func (conn *Conn) NewRows() *Rows

func (*Conn) NewStmt ¶

func (c *Conn) NewStmt(ctx context.Context, name, query string, create_proc bool) (*Stmt, error)

NewStmt creates a new statement.

func (*Conn) NewTransaction ¶

func (c *Conn) NewTransaction(ctx context.Context, opts driver.TxOptions, name string) (*Transaction, error)

NewTransaction creates a new transaction.

func (Conn) Ping ¶

func (c Conn) Ping(ctx context.Context) error

Ping implements the driver.Pinger interface.

func (*Conn) Prepare ¶

func (c *Conn) Prepare(query string) (driver.Stmt, error)

Prepare implements the driver.Conn interface.

func (*Conn) PrepareContext ¶

func (c *Conn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error)

PrepareContext implements the driver.ConnPrepareContext interface.

func (*Conn) QueryContext ¶

func (c *Conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error)

QueryContext implements the driver.QueryerContext.

QueryContext utilizes cursors unless c.Info.NoQueryCursor is set or the context has the value "NoQueryContext" set to true.

If the context has NoQueryCursor set it overrides c.Info.NoQueryCursor.

type Connector ¶

type Connector struct {
	Info           *Info
	EnvChangeHooks []tds.EnvChangeHook
	EEDHooks       []tds.EEDHook
}

Connector implements the driver.Connector interface.

func (*Connector) Connect ¶

func (c *Connector) Connect(ctx context.Context) (driver.Conn, error)

Connect implements the driver.Connector interface.

func (Connector) Driver ¶

func (c Connector) Driver() driver.Driver

Driver implements the driver.Connector interface.

type Cursor ¶

type Cursor struct {
	// contains filtered or unexported fields
}

Cursor is used to interact with a cursor on the ASE server.

func (*Cursor) Close ¶

func (cursor *Cursor) Close(ctx context.Context) error

Close closes the cursor.

func (Cursor) CursorID ¶

func (cursor Cursor) CursorID() int

CursorID returns the ID assigned to the cursor by ASE.

func (*Cursor) Fetch ¶

func (cursor *Cursor) Fetch(ctx context.Context) (*CursorRows, error)

Fetch returns CursorRows to iterate over the rows selected by a cursor.

func (*Cursor) NewCursorRows ¶

func (cursor *Cursor) NewCursorRows() (*CursorRows, error)

NewCursorRows returns CursorRows for a Cursor.

It does not immediately fetch a result set from the remote. See .Fetch.

type CursorRows ¶

type CursorRows struct {
	// contains filtered or unexported fields
}

CursorRows is used to iterate over the result set of a cursor.

func (*CursorRows) Close ¶

func (rows *CursorRows) Close() error

Close closes CursorRows and its associated Cursor.

func (CursorRows) ColumnTypeDatabaseTypeName ¶

func (rows CursorRows) ColumnTypeDatabaseTypeName(index int) string

ColumnTypeDatabaseTypeName implements the driver.RowsColumnTypeDatabaseTypeName interface.

func (CursorRows) ColumnTypeDisplayLength ¶

func (rows CursorRows) ColumnTypeDisplayLength(index int) (int64, bool)

ColumnTypeDisplayLength returns a best guess of the maximum length required to display the values of the column.

func (CursorRows) ColumnTypeLength ¶

func (rows CursorRows) ColumnTypeLength(index int) (int64, bool)

ColumnTypeLength implements the driver.RowsColumnTypeLength interface.

func (CursorRows) ColumnTypeNullable ¶

func (rows CursorRows) ColumnTypeNullable(index int) (bool, bool)

ColumnTypeNullable implements the driver.RowsColumnTypeNullable interface.

func (CursorRows) ColumnTypePrecisionScale ¶

func (rows CursorRows) ColumnTypePrecisionScale(index int) (int64, int64, bool)

ColumnTypePrecisionScale implements the driver.RowsColumnTypePrecisionScale interface.

func (CursorRows) ColumnTypeScanType ¶

func (rows CursorRows) ColumnTypeScanType(index int) reflect.Type

ColumnTypeScanType implements the driver.RowsColumnTypeScanType interface.

func (CursorRows) Columns ¶

func (rows CursorRows) Columns() []string

Columns implements the driver.Rows interface.

func (*CursorRows) Next ¶

func (rows *CursorRows) Next(dst []driver.Value) error

Next implements driver.Rows.

type Driver ¶

type Driver struct {
	// contains filtered or unexported fields
}

Driver implements the driver.Driver interface.

func (Driver) Open ¶

func (d Driver) Open(name string) (driver.Conn, error)

Open implements the driver.Driver interface.

func (Driver) OpenConnector ¶

func (d Driver) OpenConnector(name string) (driver.Connector, error)

OpenConnector implements the driver.DriverContext interface.

type Info ¶

type Info struct {
	tds.Info

	AppName string `json:"appname" doc:"Application Name to transmit to ASE"`

	NoQueryCursor bool `json:"no-query-cursor" doc:"Prevents the use of cursors for database/sql query methods. See README for details."`

	CursorCacheRows int `json:"cursor-cache-rows" doc:"How many rows to cache at once when reading the result set of a cursor"`
}

func NewInfo ¶

func NewInfo() (*Info, error)

NewInfo returns a bare Info for github.com/SAP/go-dblib/dsn with defaults.

func NewInfoWithEnv ¶

func NewInfoWithEnv() (*Info, error)

NewInfoWithEnv is a convenience function returning an Info with values filled from the environment with the prefix 'ASE'.

func NewInfoWithFlags ¶

func NewInfoWithFlags() (*Info, *flag.FlagSet, error)

NewInfoFlags is a convenience function returning an Info filled with defaults and a flagset with flags bound to the members of the returned info.

type NoQueryCursor ¶

type NoQueryCursor bool

type Result ¶

type Result struct {
	// contains filtered or unexported fields
}

Result implements the driver.Result interface.

func (Result) LastInsertId ¶

func (result Result) LastInsertId() (int64, error)

LastInsertId implements the driver.Result interface.

func (Result) RowsAffected ¶

func (result Result) RowsAffected() (int64, error)

RowsAffected implements the driver.Result interface.

type Rows ¶

type Rows struct {
	Conn *Conn

	RowFmt *tds.RowFmtPackage
	// contains filtered or unexported fields
}

Rows implements the driver.Rows interface.

func (*Rows) Close ¶

func (rows *Rows) Close() error

Close implements the driver.Rows interface.

func (Rows) ColumnTypeDatabaseTypeName ¶

func (rows Rows) ColumnTypeDatabaseTypeName(index int) string

ColumnTypeDatabaseTypeName implements the driver.RowsColumnTypeDatabaseTypeName interface.

func (Rows) ColumnTypeDisplayLength ¶

func (rows Rows) ColumnTypeDisplayLength(index int) (int64, bool)

ColumnTypeDisplayLength returns a best guess of the maximum length required to display the values of the column.

func (Rows) ColumnTypeLength ¶

func (rows Rows) ColumnTypeLength(index int) (int64, bool)

ColumnTypeLength implements the driver.RowsColumnTypeLength interface.

func (Rows) ColumnTypeNullable ¶

func (rows Rows) ColumnTypeNullable(index int) (bool, bool)

ColumnTypeNullable implements the driver.RowsColumnTypeNullable interface.

func (Rows) ColumnTypePrecisionScale ¶

func (rows Rows) ColumnTypePrecisionScale(index int) (int64, int64, bool)

ColumnTypePrecisionScale implements the driver.RowsColumnTypePrecisionScale interface.

func (Rows) ColumnTypeScanType ¶

func (rows Rows) ColumnTypeScanType(index int) reflect.Type

ColumnTypeScanType implements the driver.RowsColumnTypeScanType interface.

func (Rows) Columns ¶

func (rows Rows) Columns() []string

Columns implements the driver.Rows interface.

func (*Rows) HasNextResultSet ¶

func (rows *Rows) HasNextResultSet() bool

HasNextResultSet implements the driver.RowsNextResultSet interface.

func (*Rows) Next ¶

func (rows *Rows) Next(dst []driver.Value) error

Next implements the driver.Rows interface.

func (*Rows) NextResultSet ¶

func (rows *Rows) NextResultSet() error

NextResultSet implements the driver.RowsNextResultSet interface.

type Stmt ¶

type Stmt struct {
	// contains filtered or unexported fields
}

Stmt implements the driver.Stmt interface.

func (Stmt) CheckNamedValue ¶

func (stmt Stmt) CheckNamedValue(nv *driver.NamedValue) error

CheckNamedValue implements the driver.NamedValueChecker interface.

func (*Stmt) Close ¶

func (stmt *Stmt) Close() error

Close implements the driver.Stmt interface.

func (Stmt) DirectExec ¶

func (stmt Stmt) DirectExec(ctx context.Context, args ...interface{}) (driver.Rows, driver.Result, error)

DirectExec is a wrapper for GenericExec and meant to be used when directly accessing this library, rather than using database/sql.

The primary advantage are the variadic args, which can be normal values and are automatically transformed to driver.NamedValues for GenericExec.

func (Stmt) Exec ¶

func (stmt Stmt) Exec(args []driver.Value) (driver.Result, error)

Exec implements the driver.Stmt interface.

func (Stmt) ExecContext ¶

func (stmt Stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error)

ExecContext implements the driver.StmtExecContext interface.

func (Stmt) GenericExec ¶

func (stmt Stmt) GenericExec(ctx context.Context, args []driver.NamedValue) (driver.Rows, driver.Result, error)

GenericExec is the central method through which SQL statements are sent to ASE.

func (Stmt) NumInput ¶

func (stmt Stmt) NumInput() int

NumInput implements the driver.Stmt interface.

func (Stmt) Query ¶

func (stmt Stmt) Query(args []driver.Value) (driver.Rows, error)

Query implements the driver.Stmt interface.

func (Stmt) QueryContext ¶

func (stmt Stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error)

QueryContext implements the driver.StmtQueryContext interface.

func (*Stmt) Reset ¶

func (stmt *Stmt) Reset()

Reset resets a statement.

type Transaction ¶

type Transaction struct {
	// contains filtered or unexported fields
}

Transaction implements the driver.Tx interface.

func (Transaction) Commit ¶

func (tx Transaction) Commit() error

Commit implements the driver.Tx interface.

func (Transaction) Name ¶

func (tx Transaction) Name() string

Name returns the name of the transaction.

func (Transaction) NewTransaction ¶

func (tx Transaction) NewTransaction(ctx context.Context, opts driver.TxOptions) (*Transaction, error)

NewTransaction creates a new transaction.

func (Transaction) Rollback ¶

func (tx Transaction) Rollback() error

Rollback implements the driver.Tx interface.

Directories ¶

Path Synopsis
cmd
columnTypes
This example shows how to retrieve column type information.
This example shows how to retrieve column type information.
cursor
This example shows how to use cursor with the go-ase driver.
This example shows how to use cursor with the go-ase driver.
directExec
This example shows how to utilize the DirectExecer interface to receive both the driver.Rows and driver.Result of a SQL query.
This example shows how to utilize the DirectExecer interface to receive both the driver.Rows and driver.Result of a SQL query.
eedexample
This example shows how to retrieve the wrapped tds.EEDError to access messages sent by the TDS server in the context of an SQL statement.
This example shows how to retrieve the wrapped tds.EEDError to access messages sent by the TDS server in the context of an SQL statement.
noQueryCursor
go-ase uses cursor by default for all SQL queries.
go-ase uses cursor by default for all SQL queries.
preparedStatement
This example shows a simple interaction with a TDS server using the database/sql interface, prepared statements and the pure go driver.
This example shows a simple interaction with a TDS server using the database/sql interface, prepared statements and the pure go driver.
recorder
This example shows how tds.EEDHooks can be utilized to record and inspect a number of tds.EEDPackages received during a transaction.
This example shows how tds.EEDHooks can be utilized to record and inspect a number of tds.EEDPackages received during a transaction.
simple
This example shows a simple interaction with a TDS server using the database/sql interface and the pure go driver.
This example shows a simple interaction with a TDS server using the database/sql interface and the pure go driver.
template
TODO describe what the example does or shows here
TODO describe what the example does or shows here
transaction
This example shows the use of transactions using the database/sql interface and the pure go driver.
This example shows the use of transactions using the database/sql interface and the pure go driver.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL