unixodbc

package module
v0.9.4 Latest Latest
Warning

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

Go to latest
Published: Mar 25, 2024 License: MIT Imports: 12 Imported by: 0

README

Go unixodbc driver

Build Acceptance Tests CodeQL

This topic provides instructions for installing, running, and modifying the go unixodbc driver for connecting to ODBC databases through unixodbc. The driver supports Go's database/sql package.

Prerequisites

The following software packages are required to use the go unixodbc driver.

Go

The latest driver requires the Go language 1.20 or higher.

Operating System

This driver was primarily developed with support of Debian 12, however other linux distributions may work correctly providing that unixodbc 2.3.11 is installed.

unixodbc

unixodbc 2.3.11 or greater must on the system your application is running on. For debian, the following packages must be installed in order for this driver to connect:

  • libssl-dev
  • unixodbc-common
  • unixodbc-dev
  • unixodbc

Supported Databases and Database Drivers

The driver has been developed and tested for the following databases with the corresponding driver, but may work with other proprietary databases:

Database Tested Version Database Driver
postgres 16 odbc-postgresql
Microsoft SQL Server 2022 tdsodbc
mariadb 10.9 odbc-mariadb

Configuration

Basic Connection

Typical connection to the database can be established by importing the go unixodbc driver and opening the connection with sql.Open. The connection string to use will be specific to the database and database driver that you are using:

package main

import (
    _ "github.com/ninthclowd/unixodbc"
    "database/sql"
)

func main(){
    db = sql.Open("unixodbc", "DSN=EXAMPLE")
}

Prepared Statement Caching

The driver supports prepared statement caching on each connection using a LRU algorithm by connecting to the database with sql.OpenDB and supplying an unixodbc.Connector:

package main

import (
    _ "github.com/ninthclowd/unixodbc"
    "database/sql"
)

func main(){
    db = sql.OpenDB(&unixodbc.Connector{
        ConnectionString:   unixodbc.StaticConnStr("DSN=EXAMPLE"),
        StatementCacheSize: 5, // number of prepared statements to cache per connection
    })
}

Dynamic Connection Strings

The driver supports dynamic connection strings for use in databases that require token based authentication. This can be accomplished by implementing unixodbc.ConnectionStringFactory and connecting with sql.OpenDB:

package main

import (
	"github.com/ninthclowd/unixodbc"
	_ "github.com/ninthclowd/unixodbc"
	"database/sql"
)

type GetToken struct {
}

// ConnectionString implements unixodbc.ConnectionStringFactory
func (d *GetToken) ConnectionString() (connStr string, err error) {
	var token string
	// insert code to pull token for each new connection
	// ...

	// create a dynamic connection string and return it
	connStr = "DSN=EXAMPLE;UID=User;PWD=" + token
	return
}

func main() {
	db = sql.OpenDB(&unixodbc.Connector{
		ConnectionString: &GetToken{},
	})
}

Development

The developer notes are hosted with the source code on GitHub.

Acceptance Testing

At this time, most driver functionality is validated through the acceptance tests in the test/acceptance folder using the corresponding workflow and docker-compose.yml. To run these tests, ensure Docker is installed and run make test.

Submitting Pull Requests

You may use your preferred editor to edit the driver code. If you are adding support for a new database, please include new Acceptance Tests for the database if possible. Please make fmt to format your code and make test to validate your code before submitting.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNotImplemented = errors.New("not implemented")
)

Functions

func OpenHandles added in v0.9.3

func OpenHandles() int64

OpenHandles reports the number of handles open to unixodbc. Useful in testing to ensure all handles are closed correctly.

Types

type Connection

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

func (*Connection) Begin

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

Begin will never be called because driver.ConnBeginTx is implemented

func (*Connection) BeginTx

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

BeginTx implements driver.ConnBeginTx

func (*Connection) CheckNamedValue

func (c *Connection) CheckNamedValue(value *driver.NamedValue) error

CheckNamedValue implements driver.NamedValueChecker

func (*Connection) Close

func (c *Connection) Close() error

Close implements driver.Conn

func (*Connection) ExecContext

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

ExecContext implements driver.ExecerContext

func (*Connection) IsValid

func (c *Connection) IsValid() bool

IsValid implements driver.Validator

func (*Connection) Ping

func (c *Connection) Ping(ctx context.Context) error

Ping implements driver.Pinger

func (*Connection) Prepare

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

Prepare will never be called because driver.ConnPrepareContext is implemented

func (*Connection) PrepareContext

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

PrepareContext implements driver.ConnPrepareContext

func (*Connection) QueryContext

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

QueryContext implements driver.QueryerContext

func (*Connection) ResetSession

func (c *Connection) ResetSession(ctx context.Context) error

ResetSession implements driver.SessionResetter

type ConnectionStringFactory

type ConnectionStringFactory interface {
	ConnectionString() (string, error)
}

ConnectionStringFactory can be implemented to provide dynamic connection strings for each new connection to the database, allowing for connections to systems that require token based authentication

type Connector

type Connector struct {
	// ConnectionString is a factory that generates connection strings for each new connection that is opened.
	//Use StaticConnStr if you have a static connection string that does not need to change with each new connection.
	//Ex: If you are connecting using a system DSN called "myDatabase", this could be:
	//	StaticConnStr("DSN=myDatabase")
	ConnectionString ConnectionStringFactory
	// StatementCacheSize is the number of prepared statements to cache for each connection.  The driver will cache
	// statements up to this limit and purge them using the least recently used algorithm.  0 will disable prepared
	// statement caching.
	StatementCacheSize int
	// contains filtered or unexported fields
}

Connector can be used with sql.OpenDB to allow more control of the unixodbc driver

func (*Connector) Close

func (c *Connector) Close() error

Close implements io.Closer

func (*Connector) Connect

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

Connect implements driver.Connector

func (*Connector) Driver

func (c *Connector) Driver() driver.Driver

Driver implements driver.Connector

type DiagRec

type DiagRec struct {
	State     string
	ErrorCode int
	Message   string
}

type Driver

type Driver struct{}

func (*Driver) Open

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

Open should never be called because driver.DriverContext is implemented

func (*Driver) OpenConnector

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

OpenConnector implements driver.DriverContext

type Error

type Error struct {
	DiagRecords []*DiagRec
}

func (*Error) Error

func (e *Error) Error() string

type MultipleErrors

type MultipleErrors map[string]error

func (MultipleErrors) Error

func (m MultipleErrors) Error() error

type PreparedStatement

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

func (*PreparedStatement) Close

func (s *PreparedStatement) Close() error

Close implements driver.Stmt

func (*PreparedStatement) Exec

func (s *PreparedStatement) Exec(args []driver.Value) (driver.Result, error)

Exec will never be called because driver.StmtExecContext is implemented

func (*PreparedStatement) ExecContext

func (s *PreparedStatement) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error)

ExecContext implements driver.StmtExecContext

func (*PreparedStatement) NumInput

func (s *PreparedStatement) NumInput() int

NumInput implements driver.Stmt

func (*PreparedStatement) Query

func (s *PreparedStatement) Query(args []driver.Value) (driver.Rows, error)

Query will never be called because driver.StmtQueryContext is implemented

func (*PreparedStatement) QueryContext

func (s *PreparedStatement) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error)

QueryContext implements driver.StmtQueryContext

type Rows

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

func (*Rows) Close

func (r *Rows) Close() error

Close implements driver.Rows

func (*Rows) ColumnTypeLength

func (r *Rows) ColumnTypeLength(index int) (length int64, ok bool)

ColumnTypeLength implements driver.RowsColumnTypeLength

func (*Rows) ColumnTypeNullable

func (r *Rows) ColumnTypeNullable(index int) (nullable, ok bool)

ColumnTypeNullable implements driver.RowsColumnTypeNullable

func (*Rows) ColumnTypePrecisionScale

func (r *Rows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool)

ColumnTypePrecisionScale implements driver.RowsColumnTypePrecisionScale

func (*Rows) ColumnTypeScanType

func (r *Rows) ColumnTypeScanType(index int) reflect.Type

ColumnTypeScanType implements driver.RowsColumnTypeScanType

func (*Rows) Columns

func (r *Rows) Columns() []string

Columns implements driver.Rows

func (*Rows) Next

func (r *Rows) Next(dest []driver.Value) error

Next implements driver.Rows

type StaticConnStr

type StaticConnStr string

StaticConnStr converts a static connection string into ConnectionStringFactory usable by Connector

func (StaticConnStr) ConnectionString

func (s StaticConnStr) ConnectionString() (string, error)

type TX

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

func (*TX) Commit

func (t *TX) Commit() error

func (*TX) Rollback

func (t *TX) Rollback() error

type Time

type Time struct {
	Hours   byte
	Minutes byte
	Seconds byte
}

Directories

Path Synopsis
internal
api
Package api provides Go bindings for unixodbc.
Package api provides Go bindings for unixodbc.

Jump to

Keyboard shortcuts

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