Documentation
¶
Overview ¶
Package spanner is a database/sql driver for Google Cloud Spanner, which runs GoogleSQL over its REST API, https://spanner.googleapis.com/v1, with HTTPS and JSON, and never over gRPC. It registers the one name "spanner", and takes a DSN of the form spanner://host:port/project/instance/database?credential_file=/path/key.json (D191).
db, err := sql.Open("spanner", "spanner:///my-project/my-instance/my-db?credential_file=/path/key.json")
The key credential_file names the key file of a service account. The driver signs a JWT with its private key, with RS256 and the scopes spanner.admin and spanner.data, exchanges it at the token endpoint of the key file for an access token, and renews the token before it ends. The driver sends the token to the host of the DSN only. A caller that gets its tokens from elsewhere sets Config.Token, and a DSN for the emulator, such as spanner://localhost:9020/p/i/d, needs no credential.
The driver makes one multiplexed session for each connector, and makes a new one when the server answers NOT_FOUND. It reads every result with executeStreamingSql, one token at a time, and joins a value that the server splits across messages. A DML statement outside a transaction runs in a transaction that the driver begins and commits. BeginTx calls beginTransaction. A transaction that the server aborts returns ErrAborted, and the caller runs the whole transaction again. A DDL statement goes to updateDatabaseDdl, and the driver waits until its operation is done. docs/SPANNER.md holds what the driver knows about the server.
Index ¶
Constants ¶
const ( // ErrAborted is the error of a transaction that the server aborted, with // the status ABORTED and HTTP 409. The server holds no lock for it any // more. The caller must run the whole transaction again, and // Error.RetryDelay holds the wait that the server asks for (D191 item 6). ErrAborted dbimp.Error = "the transaction was aborted" // ErrSessionNotFound is the error of a statement whose session the server // does not know any more. The statement did not run. The connector drops // the session and makes a new one for the next statement (D191 item 3). ErrSessionNotFound dbimp.Error = "the session was not found" // ErrCanceled is the error of a long running operation that someone // canceled, with the gRPC code 1. The driver cancels an operation when the // context of a DDL statement ends (D191 item 4). ErrCanceled dbimp.Error = "the operation was canceled" )
The sentinel errors of the driver. Each one wraps into a failure with errors.Is (D6).
const Name = "spanner"
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. It is spanner.googleapis.com when the
// DSN names none.
Host string
// Port is the port of the server: 443 with TLS, and 9020 without it, as
// the emulator serves it.
Port int
// TLS is true for HTTPS. The key tls sets it, and a host that is
// localhost or a loopback address defaults to false, so that the DSN of
// the emulator needs no key. Without TLS the driver sends a token only
// when the DSN names a credential file.
TLS bool
// Project, Instance and Database are the three parts of the path of the DSN
// (D191). They name the database
// projects/{Project}/instances/{Instance}/databases/{Database}.
Project string
Instance string
Database string
// CredentialFile is the path to the key file of a service account, in the
// JSON form that Google Cloud writes (D191 item 5). The driver signs a
// token with the private key in it. The text of the key never sits in a
// DSN (D94). A DSN with TLS must name a file, unless Token is set.
CredentialFile string
// Token returns an access token, for a caller that gets its tokens from
// elsewhere. It replaces CredentialFile, and the driver calls it for each
// request, so it must cache its token. It is not part of a DSN (D191 item
// 5).
Token func(ctx context.Context) (string, error)
}
Config is the configuration of a connector, which the DSN holds. The caller owns it (D7).
func ParseDSN ¶
ParseDSN parses a DSN of the form spanner://host:port/project/instance/database?credential_file=/path/key.json (D27, D35 and D191). The path holds the project, the instance and the database, and all three are required. The host and the port are optional. The keys are credential_file, the path to the key file of a service account, and tls, a boolean. The driver refuses any other key. The user of the URL is ignored, because it only names a principal for dbmeta (D195 item 6). The password of the URL is not used, because the key file is too large for it, so the DSN refuses a password.
type Connector ¶
type Connector struct {
// contains filtered or unexported fields
}
Connector opens connections to one instance. It owns its transport, and every connection shares it, with the token and the sessions. 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. It reads no key file and sends no request, so a key file that is not valid fails the first Connect.
func (*Connector) Close ¶
Close closes the idle connections of the transport. A multiplexed session cannot be deleted (recorded: "deleteSession of the multiplexed session"), so the server ends it.
type Driver ¶
type Driver struct{}
Driver is the database/sql driver for Spanner.
type Error ¶
type Error struct {
// HTTPStatus is the status code of the response, and 0 for an error that
// came inside a body with HTTP 200, as an error after some rows does.
HTTPStatus int
// Code is the member code.
Code int
// Status is the name of the gRPC code, such as ABORTED. An error of an
// operation has no name, so the driver names it from the number.
Status string
// Message is the message of the server. The member message holds a
// backslash and an n where a line break belongs (recorded: "a syntax
// error"), so the driver takes the text of the detail LocalizedMessage,
// and turns the two characters into a line break when there is none.
Message string
// RetryDelay is the wait that the detail RetryInfo asks for, or 0.
RetryDelay time.Duration
// contains filtered or unexported fields
}
Error is an error that Spanner reported. The body of an error is {"error": {"code", "message", "status", "details"}}. The code is the HTTP status in an answer, and the gRPC number in the error of a long running operation or of executeBatchDml (recorded).
type Option ¶
Option sets an option of one statement or of one transaction (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. The DSN of this driver has no key that can change for one statement, so the options start empty.
func WithDatabase ¶
WithDatabase sets the database of one statement, as the last part of the path of the DSN does. The name is the id of a database of the project and the instance of the DSN, such as "other". The driver keeps one session for each database. A statement of a transaction runs in the database of the transaction, so WithDatabase with another database fails the statement with dbimp.ErrNotSupported (D109).
func WithParameter ¶
WithParameter sets a member of the body of the request by its name, for a setting that the driver has no option for. It replaces a member that the driver sets itself. For a statement it sets a member of executeStreamingSql, such as queryMode, queryOptions, requestOptions, directedReadOptions or transaction. For a transaction it sets a member of beginTransaction, such as options, and the members maxCommitDelay, returnCommitStats and requestOptions of the commit. A value of nil fails the statement with dbimp.ErrInvalidValue.
func WithReadonly ¶
WithReadonly asks that the statement write nothing. The driver runs the statement in a read-only transaction that has no commit, so the server refuses a DML statement with HTTP 400 (recorded: "a DML statement in a read only transaction"). A DDL statement fails with dbimp.ErrNotSupported. In BeginTx, WithReadonly(true) makes the transaction read-only, as sql.TxOptions does.
func WithTimeout ¶
WithTimeout asks for a time that the server gives the statement. Spanner has no such setting for a request of the REST API, because the deadline belongs to the client (docs/SPANNER.md, "Cancellation and timeouts"), so a positive value fails the statement with dbimp.ErrNotSupported. The context of the statement is the way to bound it. Zero asks for nothing.