Documentation
¶
Overview ¶
Package exasol is a database/sql driver for Exasol, which takes its requests as JSON messages of a WebSocket. It registers the one name "exasol", and takes a DSN of the form exasol://user:password@host:port/schema?key=value (D205).
db, err := sql.Open("exasol", "exasol://sys:exasol@localhost:8563?validateservercertificate=false")
The connection uses TLS, and it checks the certificate of the server unless validateservercertificate is false (D206). The messages are compressed with zlib unless compression is false (D214). A query reads its rows with the command fetch, by the handle of the result set, about one MiB at a time (D210). The server binds the arguments of a statement, which the driver prepares for it (D208). A transaction turns autocommit off while it lasts (D209). When a context ends, the driver sends abortQuery, reads the answer of the aborted statement, and keeps the connection (D211). docs/EXASOL.md holds what the driver knows about the server.
Example ¶
Open a database with a DSN, run a query with arguments, and read each row. The server binds the arguments, so the driver prepares the statement for it.
package main
import (
"context"
"database/sql"
"fmt"
"log"
"github.com/xo/dbimp"
)
func main() { //nolint:testableexamples // The example needs a server, so it has no output to check.
ctx := context.Background()
if err := exampleQuery(ctx); err != nil {
log.Fatal(err)
}
}
func exampleQuery(ctx context.Context) error {
db, err := sql.Open("exasol", "exasol://sys:exasol@localhost:8563?validateservercertificate=false")
if err != nil {
return err
}
defer db.Close()
rows, err := db.QueryContext(ctx, "SELECT ID, NAME, CREATED FROM SHOP.ORDERS WHERE ID > ? AND NAME = ?", 100, "Ann")
if err != nil {
return err
}
defer rows.Close()
for rows.Next() {
var (
id int64
name sql.Null[string]
created dbimp.LocalDateTime
)
if err := rows.Scan(&id, &name, &created); err != nil {
return err
}
fmt.Println(id, name.V, created)
}
return rows.Err()
}
Output:
Example (Options) ¶
The options of a statement go in its arguments, or in its context.
package main
import (
"context"
"database/sql"
"log"
"time"
"github.com/xo/dbimp/exasol"
)
func main() { //nolint:testableexamples // The example needs a server, so it has no output to check.
ctx := context.Background()
db, err := sql.Open("exasol", "exasol://sys:exasol@localhost:8563?validateservercertificate=false")
if err != nil {
log.Print(err)
return
}
defer db.Close()
// Stop the statement after ten seconds, and read three rows at most.
rows, err := db.QueryContext(ctx, "SELECT * FROM SHOP.ORDERS",
exasol.WithTimeout(10*time.Second),
exasol.WithParameter("attributes", map[string]any{"resultSetMaxRows": 3}))
if err != nil {
log.Print(err)
return
}
defer rows.Close()
for rows.Next() {
// Read each row here.
}
if err := rows.Err(); err != nil {
log.Print(err)
}
}
Output:
Example (Transaction) ¶
A transaction turns autocommit off while it lasts. A context that ends stops the statement on the server, and the connection stays usable.
package main
import (
"context"
"database/sql"
"log"
"time"
)
func main() { //nolint:testableexamples // The example needs a server, so it has no output to check.
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
if err := exampleTransaction(ctx); err != nil {
log.Print(err)
}
}
func exampleTransaction(ctx context.Context) error {
db, err := sql.Open("exasol", "exasol://sys:exasol@localhost:8563/SHOP?validateservercertificate=false")
if err != nil {
return err
}
defer db.Close()
tx, err := db.BeginTx(ctx, nil)
if err != nil {
return err
}
defer tx.Rollback()
if _, err := tx.ExecContext(ctx, "UPDATE ORDERS SET NAME = ? WHERE ID = ?", "Bob", 101); err != nil {
return err
}
return tx.Commit()
}
Output:
Index ¶
Examples ¶
Constants ¶
const ( // CodeConnection is the code of a login that the server refused. It is // also the code of a login on a plain ws connection, so the text decides // whether the credential was wrong (measured). CodeConnection = "08004" // CodeTimeout is the code of a statement that ran over the query // timeout. CodeTimeout = "R0001" // CodeAborted is the code of a statement that abortQuery ended. CodeAborted = "R0003" )
The codes of the server that the driver reads (docs/EXASOL.md, Errors).
const Name = "exasol"
Name is the name that the driver registers with database/sql, and the scheme of its DSN.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Config ¶
type Config struct {
// Host is the host of the server.
Host string
// Port is the port of the server, 8563 by default.
Port int
// User and Password are the credentials. The password is the secret of
// the URL (D94).
User string
Password string
// Schema is the schema that the session opens, or "" for none. It is the
// path of the DSN.
Schema string
// NoTLS is true to speak ws and not wss, which the key tls=false asks
// for. The server answers a login on ws with an error, so it is for a
// server behind a proxy that ends TLS.
NoTLS bool
// SkipVerify is true to accept any certificate, which the key
// validateservercertificate=false asks for.
SkipVerify bool
// CertificateFingerprint is the SHA-256 of the certificate of the server,
// in hex. If it is set, it takes the place of the check of the chain of
// the certificate.
CertificateFingerprint string
// NoCompression is true to send and read plain text, which the key
// compression=false asks for (D214).
NoCompression bool
// NoAutocommit is true to log in with autocommit off, which the key
// autocommit=false asks for.
NoAutocommit bool
// FetchSize is the size of a page of a result in KiB, 1024 by default
// (D210).
FetchSize int
// QueryTimeout is the number of seconds that the server lets a statement
// run, or 0 for no limit.
QueryTimeout int
// ClientName is the name that the login sends, "dbimp" by default.
ClientName string
// Protocol is the version of the WebSocket API that the login asks for,
// 3, 4 or 5. The default is 3.
Protocol int
}
Config is the configuration of a connector, which the DSN holds. The caller owns it (D7). The zero value of a field that has a default is the default, so a field that turns a feature off is named for the feature that it turns off.
type Connector ¶
type Connector struct {
// contains filtered or unexported fields
}
Connector opens connections to one server. It holds no connection itself, because each connection owns its WebSocket. A caller can build one from a Config and open it with sql.OpenDB.
func NewConnector ¶
NewConnector returns a Connector for cfg. The connector keeps a copy of cfg, and fills each field that is zero with its default.
type Driver ¶
type Driver struct{}
Driver is the database/sql driver for Exasol.
type Error ¶
type Error struct {
// Code is the code of the exception, such as 42000.
Code string
// Message is the text of the exception.
Message string
}
Error is an error that Exasol reported: a frame with the status error, which holds the text and the code of the exception. The code is the SQLSTATE of the server, five characters, such as 42000 for a syntax error, and the text ends with the id of the session.
func (*Error) Is ¶
Is reports whether err matches target. It matches dbimp.ErrAuthentication for the code 08004 with the text of a failed authentication, which is the answer for a wrong user, a wrong password and a wrong token (recorded: "login with a wrong user: send the credentials"). The same code answers a login on a connection with no TLS, which is no refusal of the credential, and a missing privilege is 42500, so neither matches (D197).
type Option ¶
Option sets an option of one statement (D109). An option comes from the DSN, then from the context through WithOptions, then from an argument of the statement, and a later one wins.
func WithDatabase ¶
WithDatabase sets the schema of the statement, as WithSchema does. The schema is the database of Exasol.
func WithParameter ¶
WithParameter sets any member of the request of the statement by its name, such as "attributes". The value is encoded with json/v2. A member named here replaces one that the driver sets itself, such as "sqlText".
func WithReadonly ¶
WithReadonly asks for a statement that the server refuses to write with. The server has no read-only statement or transaction, so WithReadonly(true) fails with dbimp.ErrNotSupported. A user with no write privilege is read-only.
func WithSchema ¶
WithSchema opens the schema before the statement, if the session has another one open. The schema stays open after the statement, because it is an attribute of the session, as the path of the DSN is.
func WithTimeout ¶
WithTimeout ends the statement after d. When d passes, the driver sends abortQuery, so the server stops the statement, and the connection stays usable (D211). The error is context.DeadlineExceeded. Zero sets no timeout. The key querytimeout of the DSN is the limit that the server keeps itself.