driver

package
v0.9.1 Latest Latest
Warning

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

Go to latest
Published: Aug 2, 2017 License: Apache-2.0 Imports: 17 Imported by: 96

Documentation

Overview

Package driver is a native Go SAP HANA driver implementation for the database/sql package.

Example
package main

import (
	"database/sql"
	"log"

	// Register hdb driver.
	_ "github.com/SAP/go-hdb/driver"
)

const (
	driverName = "hdb"
	hdbDsn     = "hdb://user:password@host:port"
)

func main() {
	db, err := sql.Open(driverName, hdbDsn)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	if err := db.Ping(); err != nil {
		log.Fatal(err)
	}
}
Output:

Example (BulkInsert)

ExampleBulkInsert inserts 1000 integer values into database table test. Precondition: the test database table with one field of type integer must exist. The insert SQL command is "bulk insert" instead of "insert". After the insertion of the values a final stmt.Exec() without parameters must be executed.

package main

import (
	"database/sql"
	"log"

	"github.com/SAP/go-hdb/driver"
)

func main() {
	db, err := sql.Open(driver.DriverName, "hdb://user:password@host:port")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	stmt, err := db.Prepare("bulk insert into test values (?)") // Prepare bulk query.
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()

	for i := 0; i < 1000; i++ {
		if _, err := stmt.Exec(i); err != nil {
			log.Fatal(err)
		}
	}
	// Call final stmt.Exec().
	if _, err := stmt.Exec(); err != nil {
		log.Fatal(err)
	}
}
Output:

Example (CallSimpleOut)

ExampleCallSimpleOut creates a stored procedure with one output parameter and executes it. Stored procedures with output parameters must be executed by sql.Query or sql.QueryRow. For variables TestDsn and TestSchema see main_test.go.

const procOut = `create procedure %s.%s (out message nvarchar(1024))
language SQLSCRIPT as
begin
    message := 'Hello World!';
end
`

db, err := sql.Open(DriverName, TestDsn)
if err != nil {
	log.Fatal(err)
}
defer db.Close()

procedure := RandomIdentifier("procOut_")

if _, err := db.Exec(fmt.Sprintf(procOut, TestSchema, procedure)); err != nil { // Create stored procedure.
	log.Fatal(err)
}

var out string

if err := db.QueryRow(fmt.Sprintf("call %s.%s(?)", TestSchema, procedure)).Scan(&out); err != nil {
	log.Fatal(err)
}

fmt.Print(out)
Output:

Hello World!
Example (CallTableOut)

ExampleCallTableOut creates a stored procedure with one table output parameter and executes it. Stored procedures with table output parameters must be executed by sql.Query as sql.QueryRow will close the query after execution and prevent querying output table values. The scan type of a table output parameter is a string containing an opaque value to query table output values by standard sql.Query or sql.QueryRow methods. For variables TestDsn and TestSchema see main_test.go.

const procTable = `create procedure %[1]s.%[2]s (out t %[1]s.%[3]s)
language SQLSCRIPT as
begin
  create local temporary table #test like %[1]s.%[3]s;
  insert into #test values('Hello, 世界');
  insert into #test values('SAP HANA');
  insert into #test values('Go driver');
  t = select * from #test;
  drop table #test;
end
`

db, err := sql.Open(DriverName, TestDsn)
if err != nil {
	log.Fatal(err)
}
defer db.Close()

tableType := RandomIdentifier("TableType_")
procedure := RandomIdentifier("ProcTable_")

if _, err := db.Exec(fmt.Sprintf("create type %s.%s as table (x nvarchar(256))", TestSchema, tableType)); err != nil { // Create table type.
	log.Fatal(err)
}

if _, err := db.Exec(fmt.Sprintf(procTable, TestSchema, procedure, tableType)); err != nil { // Create stored procedure.
	log.Fatal(err)
}

var tableQuery string // Scan variable of table output parameter.

// Query stored procedure.
rows, err := db.Query(fmt.Sprintf("call %s.%s(?)", TestSchema, procedure))
if err != nil {
	log.Fatal(err)
}
defer rows.Close()

if !rows.Next() {
	log.Fatal(rows.Err())
}
if err := rows.Scan(&tableQuery); err != nil {
	log.Fatal(err)
}

// Query stored procedure output table.
tableRows, err := db.Query(tableQuery)
if err != nil {
	log.Fatal(err)
}
defer tableRows.Close()

for tableRows.Next() {
	var x string

	if err := tableRows.Scan(&x); err != nil {
		log.Fatal(err)
	}

	fmt.Println(x)
}
if err := tableRows.Err(); err != nil {
	log.Fatal(err)
}
Output:

Hello, 世界
SAP HANA
Go driver

Index

Examples

Constants

View Source
const (
	DSNLocale  = "locale"  // Client locale as described in the protocol reference.
	DSNTimeout = "timeout" // Driver side connection timeout in seconds.
)

DSN query parameters. For parameter client locale see http://help.sap.com/hana/SAP_HANA_SQL_Command_Network_Protocol_Reference_en.pdf.

View Source
const (
	DSNDefaultTimeout = 300 // Default value connection timeout (300 seconds = 5 minutes).
)

DSN query default values.

View Source
const DriverName = "hdb"

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

View Source
const DriverVersion = "0.9.1"

DriverVersion is the version number of the hdb driver.

Variables

View Source
var ErrDecimalOutOfRange = errors.New("decimal out of range error")

ErrDecimalOutOfRange means that a big.Rat exceeds the size of hdb decimal fields.

View Source
var ErrFloatOutOfRange = errors.New("float out of range error")

ErrorIntegerOutOfRange means that a float exceeds the size of the hdb float field.

View Source
var ErrIntegerOutOfRange = errors.New("integer out of range error")

ErrorIntegerOutOfRange means that an integer exceeds the size of the hdb integer field.

Functions

This section is empty.

Types

type DSN

type DSN string

DSN is here for the purposes of documentation only. A DSN string is an URL string with the following format

hdb://<username>:<password>@<host address>:<port number>

and optional query parameters (see DSN query parameters and DSN query default values).

Example:

hdb://myuser:mypassword@localhost:30015?timeout=60
Example

ExampleDsn shows how to construct a DSN (data source name) as url.

package main

import (
	"database/sql"
	"log"
	"net/url"

	"github.com/SAP/go-hdb/driver"
)

// Dsn creates data source name with the help of the net/url package.
func dsn() string {
	dsn := &url.URL{
		Scheme: driver.DriverName,
		User:   url.UserPassword("user", "password"),
		Host:   "host:port",
	}
	return dsn.String()
}

// ExampleDsn shows how to construct a DSN (data source name) as url.
func main() {
	db, err := sql.Open(driver.DriverName, dsn())
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	if err := db.Ping(); err != nil {
		log.Fatal(err)
	}
}
Output:

type Decimal

type Decimal big.Rat

A Decimal is the driver representation of a database decimal field value as big.Rat.

Example

ExampleDecimal creates a table with a single decimal attribute, insert a record into it and select the entry afterwards. This demonstrates the usage of the type Decimal to write and scan decimal database attributes. For variables TestDsn and TestSchema see main_test.go.

db, err := sql.Open(DriverName, TestDsn)
if err != nil {
	log.Fatal(err)
}
defer db.Close()

tableName := RandomIdentifier("table_")

if _, err := db.Exec(fmt.Sprintf("create table %s.%s (x decimal)", TestSchema, tableName)); err != nil { // Create table with decimal attribute.
	log.Fatal(err)
}

// Decimal values are represented in Go as big.Rat.
in := (*Decimal)(big.NewRat(1, 1)) // Create *big.Rat and cast to Decimal.

if _, err := db.Exec(fmt.Sprintf("insert into %s.%s values(?)", TestSchema, tableName), in); err != nil { // Insert record.
	log.Fatal(err)
}

var out Decimal // Declare scan variable.

if err := db.QueryRow(fmt.Sprintf("select * from %s.%s", TestSchema, tableName)).Scan(&out); err != nil {
	log.Fatal(err)
}

fmt.Printf("Decimal value: %s", (*big.Rat)(&out).String()) // Cast scan variable to *big.Rat to use *big.Rat methods.
Output:

Decimal value: 1/1

func (*Decimal) Scan

func (d *Decimal) Scan(src interface{}) error

Scan implements the database/sql/Scanner interface.

func (Decimal) Value

func (d Decimal) Value() (driver.Value, error)

Value implements the database/sql/Valuer interface.

type Error

type Error interface {
	Code() int           // Code return the database error code.
	Position() int       // Position returns the start position of erroneous sql statements sent to the database server.
	Level() p.ErrorLevel // Level return one of the database server predefined error levels.
	Text() string        // Text return the error description sent from database server.
	IsWarning() bool     // IsWarning returns true if the HDB error level equals 0.
	IsError() bool       // IsError returns true if the HDB error level equals 1.
	IsFatal() bool       // IsFatal returns true if the HDB error level equals 2.
}

Error represents errors send by the database server.

Example
package main

import (
	"database/sql"
	"log"

	"github.com/SAP/go-hdb/driver"
)

func main() {
	db, err := sql.Open("hdb", "hdb://user:password@host:port")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	stmt, err := db.Query("select * from dummy")
	if err != nil {
		// Type assertion of database server error message.
		if dbError, ok := err.(driver.Error); ok {
			log.Printf("code %d text %s", dbError.Code(), dbError.Text())
		}
	}
	stmt.Close()
}
Output:

type Identifier

type Identifier string

Identifier in hdb SQL statements like schema or table name.

func RandomIdentifier

func RandomIdentifier(prefix string) Identifier

Random Identifier returns a random Identifier prefixed by the prefix parameter. This function is used to generate database objects with random names for test and example code.

func (Identifier) String

func (i Identifier) String() string

String implements Stringer interface.

type Lob

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

A Lob is the driver representation of a database large object field. A Lob object uses an io.Reader object as source for writing content to a database lob field. A Lob object uses an io.Writer object as destination for reading content from a database lob field. A Lob can be created by contructor method NewLob with io.Reader and io.Writer as parameters or created by new, setting io.Reader and io.Writer by SetReader and SetWriter methods.

Example (Read)

ExampleLobRead reads data from a largs data object database field into a bytes.Buffer. Precondition: the test database table with one field of type BLOB, CLOB or NCLOB must exist. For illustrative purposes we assume, that the database table has exactly one record, so that we can use db.QueryRow.

package main

import (
	"bytes"
	"database/sql"
	"log"

	"github.com/SAP/go-hdb/driver"
)

func main() {
	b := new(bytes.Buffer)

	db, err := sql.Open("hdb", "hdb://user:password@host:port")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	lob := new(driver.Lob)
	lob.SetWriter(b) // SetWriter sets the io.Writer object, to which the database content of the lob field is written.

	if err := db.QueryRow("select * from test").Scan(lob); err != nil {
		log.Fatal(err)
	}
}
Output:

Example (Write)

ExampleLobWrite inserts data read from a file into a database large object field. Precondition: the test database table with one field of type BLOB, CLOB or NCLOB and the test.txt file in the working directory must exist. Lob fields cannot be written in hdb auto commit mode - therefore the insert has to be executed within a transaction.

package main

import (
	"database/sql"
	"log"
	"os"

	"github.com/SAP/go-hdb/driver"
)

func main() {
	file, err := os.Open("test.txt") // Open file.
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	db, err := sql.Open("hdb", "hdb://user:password@host:port")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	tx, err := db.Begin() // Start Transaction to avoid database error: SQL Error 596 - LOB streaming is not permitted in auto-commit mode.
	if err != nil {
		log.Fatal(err)
	}

	stmt, err := tx.Prepare("insert into test values(?)")
	if err != nil {
		log.Fatal(err)
	}

	lob := new(driver.Lob)
	lob.SetReader(file) // SetReader sets the io.Reader object, which content is written to the database lob field.

	if _, err := stmt.Exec(lob); err != nil {
		log.Fatal(err)
	}

	stmt.Close()

	if err := tx.Commit(); err != nil {
		log.Fatal(err)
	}
}
Output:

func NewLob

func NewLob(rd io.Reader, wr io.Writer) *Lob

NewLob creates a new Lob instance with the io.Reader and io.Writer given as parameters.

func (*Lob) Scan

func (l *Lob) Scan(src interface{}) error

Scan implements the database/sql/Scanner interface.

func (*Lob) SetReader

func (l *Lob) SetReader(rd io.Reader)

SetReader sets the io.Reader source for a lob field to be written to database.

func (*Lob) SetWriter

func (l *Lob) SetWriter(wr io.Writer)

SetWriter sets the io.Writer destination for a lob field to be read from database.

func (*Lob) Value

func (l *Lob) Value() (driver.Value, error)

Value implements the database/sql/Valuer interface.

type NullBytes added in v0.9.1

type NullBytes struct {
	Bytes []byte
	Valid bool // Valid is true if Bytes is not NULL
}

NullBytes represents an []byte that may be null. NullBytes implements the Scanner interface so it can be used as a scan destination, similar to NullString.

func (*NullBytes) Scan added in v0.9.1

func (n *NullBytes) Scan(value interface{}) error

Scan implements the Scanner interface.

func (NullBytes) Value added in v0.9.1

func (n NullBytes) Value() (driver.Value, error)

Value implements the driver Valuer interface.

type NullDecimal

type NullDecimal struct {
	Decimal *Decimal
	Valid   bool // Valid is true if Decimal is not NULL
}

NullDecimal represents an Decimal that may be null. NullDecimal implements the Scanner interface so it can be used as a scan destination, similar to NullString.

func (*NullDecimal) Scan

func (n *NullDecimal) Scan(value interface{}) error

Scan implements the Scanner interface.

func (NullDecimal) Value

func (n NullDecimal) Value() (driver.Value, error)

Value implements the driver Valuer interface.

type NullTime

type NullTime struct {
	Time  time.Time
	Valid bool // Valid is true if Time is not NULL
}

NullTime represents an time.Time that may be null. NullTime implements the Scanner interface so it can be used as a scan destination, similar to NullString.

func (*NullTime) Scan

func (n *NullTime) Scan(value interface{}) error

Scan implements the Scanner interface.

func (NullTime) Value

func (n NullTime) Value() (driver.Value, error)

Value implements the driver Valuer interface.

Directories

Path Synopsis
Package sqltrace implements driver sql trace functions.
Package sqltrace implements driver sql trace functions.

Jump to

Keyboard shortcuts

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