ws4sqlite_client

package module
v0.11.1 Latest Latest
Warning

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

Go to latest
Published: Sep 28, 2022 License: ISC Imports: 7 Imported by: 1

README ¶

🌱 ws4sqlite client for Go(lang)

pkg.go.dev Docs

This is an implementation of a client for ws4sqlite to use with Go. It adds convenience to the communication, by not having to deal with JSON, by performing checks for the requests being well formed and by mapping errors to JDK's exceptions.

Compatibility

Each client's minor release is guaranteed to be compatible with the matching minor release of ws4sqlite. So, for ws4sqlite's version 0.11.0, use any of the client's 0.11.x versions.

In addition, versions 0.11.x of this package are also compatible with versions 0.12.x of ws4sqlite.

The library requires Go 1.17 or higher.

Import

go get github.com/proofrock/ws4sqlite-client-go

Usage

This is a translation in Go code of the "everything included" request documented in the docs. It shows the usage, overall; please refer to the go docs for details.

import ws4 "github.com/proofrock/ws4sqlite-client-go"

//...

// Prepare a client for the transmission. Not thread safe, but cheap to build.
cli, err := ws4.NewClientBuilder().
	WithURL("http://localhost:12321/db2").
	WithInlineAuth("myUser1", "myHotPassword").
	Build()

if err != nil {
	panic(err)
}

// Prepare the request, adding different queries/statements. See the docs for a
// detailed explanation, should be fairly 1:1 to the request at
// https://germ.gitbook.io/ws4sqlite/documentation/requests
req, err := ws4.NewRequestBuilder().
	AddQuery("SELECT * FROM TEMP").
	//
	AddQuery("SELECT * FROM TEMP WHERE ID = :id").
	WithValues(map[string]interface{}{"id": 1}).
	//
	AddStatement("INSERT INTO TEMP (ID, VAL) VALUES (0, 'ZERO')").
	//
	AddStatement("INSERT INTO TEMP (ID, VAL) VALUES (:id, :val)").
	WithNoFail().
	WithValues(map[string]interface{}{"id": 1, "val": "a"}).
	//
	AddStatement("#Q2").
	WithValues(map[string]interface{}{"id": 2, "val": "b"}).
	WithValues(map[string]interface{}{"id": 3, "val": "c"}).
	//
	Build()

if err != nil {
	panic(err)
}

// Call ws4sqlite, obtaining a response and the status code (and a possible error)
// Status code is !=0 if the method got a response from ws4sqlite, regardless of errors.
res, code, err := cli.Send(req)

// Code is 200?
if code != 200 {
	panic("There was an error, and now err can be cast to WsError")
}

if err != nil {
	wserr := err.(ws4.WsError)
	// Error possibly raised by the processing of the request.
	// It contains the same fields from
	// https://germ.gitbook.io/ws4sqlite/documentation/errors#global-errors
	fmt.Printf("HTTP Code: %d\n", wserr.Code)
	fmt.Printf("At subrequest: %d\n", wserr.RequestIdx)
	fmt.Printf("Error: %s\n", wserr.Msg) // or wserr.Error()
	panic("see above")
}

// Unpacking of the response. Every ResponseItem matches a node of the request,
// and each one has exactly one of the following fields populated:
// - Error: reason for the error, if it wasn't successful;
// - RowsUpdated: if the node was a statement and no batching was involved;
//                it's the number of updated rows;
// - RowsUpdatedBatch: if the node was a statement and a batch of values was
//                     provided; it's a slice of the numbers of updated rows
//                     for each batch item;
// - ResultSet: if the node was a query; it's a slice of maps with an item
//              per returned record, and each map has the name of the filed
//              as a key of each entry, and the value as a value.
fmt.Printf("Number of responses: %d\n", len(res.Results))

fmt.Printf("Was 1st response successful? %t\n", res.Results[0].Success)

fmt.Printf("How many records had the 1st response? %d\n", len(res.Results[0].ResultSet))

fmt.Printf("What was the first VAL returned? %s\n", res.Results[0].ResultSet[0]["VAL"])

The encryption extension is supported and documented.

Documentation ¶

Index ¶

Constants ¶

This section is empty.

Variables ¶

This section is empty.

Functions ¶

This section is empty.

Types ¶

type AuthMode ¶

type AuthMode string

Authentication mode for the database remote.

const (
	// HTTP Basic Authentication
	AUTH_MODE_HTTP AuthMode = "HTTP"
	// Credentials are inlined in the request
	AUTH_MODE_INLINE AuthMode = "INLINE"
	// No authentication
	AUTH_MODE_NONE AuthMode = "NONE"
)

type Client ¶

type Client struct {
	ClientBuilder
}

This struct represent a client for ws4sqlite. It can be constructed using the ClientBuilder struct, that configures it with the URL to contact and the authorization (if any). Once instantiated, it can be used to send Requests to the server.

Example:

cli, err := ws4.NewClientBuilder().
               WithURL("http://localhost:12321/db2").
               WithInlineAuth("myUser1", "myHotPassword").
               Build()

cli.Send(...)

func (*Client) Send ¶

func (c *Client) Send(req *Request) (*Response, int, error)

Sends a set of requests to the remote, wrapped in a Request struct. Returns a matching set of responses, wrapped in a Response struct.

Returns a WsError if the remote service returns a processing error. If the communication fails, it returns the "naked" error, so check for cast-ability.

func (*Client) SendWithContext ¶ added in v0.11.1

func (c *Client) SendWithContext(ctx context.Context, req *Request) (*Response, int, error)

SendWithContext sends a set of requests to the remote with context, wrapped in a Request. Returns a matching set of responses, wrapped in a Response struct.

Returns a WsError if the remote service returns a processing error. If the communication fails, it returns the "naked" error, so check for cast-ability.

type ClientBuilder ¶

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

This class is a builder for Client instances. Once configured with the URL to contact and the authorization (if any), it can be used to instantiate a Client.

Example:

cli, err := ws4.NewClientBuilder().
               WithURL("http://localhost:12321/db2").
               WithInlineAuth("myUser1", "myHotPassword").
               Build()

cli.Send(...)

func NewClientBuilder ¶

func NewClientBuilder() *ClientBuilder

First step when building. Generates a new ClientBuilder instance.

func (*ClientBuilder) Build ¶

func (cb *ClientBuilder) Build() (*Client, error)

Returns the Client that was built.

func (*ClientBuilder) WithHTTPAuth ¶

func (cb *ClientBuilder) WithHTTPAuth(user, password string) *ClientBuilder

Builder methods that configures HTTP Basic Authentication; the remote must be configured accordingly.

func (*ClientBuilder) WithInlineAuth ¶

func (cb *ClientBuilder) WithInlineAuth(user, password string) *ClientBuilder

Builder methods that configures INLINE authentication; the remote must be configured accordingly.

func (*ClientBuilder) WithURL ¶

func (cb *ClientBuilder) WithURL(url string) *ClientBuilder

Builder methods that adds a "raw" URL for contacting the ws4sqlite remote.

func (*ClientBuilder) WithURLComponents ¶

func (cb *ClientBuilder) WithURLComponents(protocol Protocol, host string, port int, databaseId string) *ClientBuilder

Builder methods that adds an URL for contacting the ws4sqlite remote, given its components.

func (*ClientBuilder) WithURLComponentsNoPort ¶

func (cb *ClientBuilder) WithURLComponentsNoPort(protocol Protocol, host string, databaseId string) *ClientBuilder

Builder methods that adds an URL for contacting the ws4sqlite remote, given its components but with an implicit port.

type Protocol ¶

type Protocol string

Used in URL composition

const (
	// Adds http://
	PROTOCOL_HTTP Protocol = "http"
	// Adds https://
	PROTOCOL_HTTPS Protocol = "https"
)

type Request ¶

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

Container class for a request to ws4sqlite. Built with RequestBuilder.

type RequestBuilder ¶

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

A builder class to build a Request to send to the ws4sqlite server with the <Client>.Send(Request) method.

If an error is encountered during built, it's returned at Build() time, to be able to chain.

func NewRequestBuilder ¶

func NewRequestBuilder() *RequestBuilder

First step when building. Generates a new RequestBuilder instance.

func (*RequestBuilder) AddQuery ¶

func (rb *RequestBuilder) AddQuery(query string) *RequestBuilder

Adds a new request to the list, for a query. It must be configured later on with the proper methods.

func (*RequestBuilder) AddStatement ¶

func (rb *RequestBuilder) AddStatement(statement string) *RequestBuilder

Adds a new request to the list, for a statement. It must be configured later on with the proper methods.

func (*RequestBuilder) Build ¶

func (rb *RequestBuilder) Build() (*Request, error)

Returns the Request that was built, returning also any error that was encountered during build.

func (*RequestBuilder) WithDecoder ¶

func (rb *RequestBuilder) WithDecoder(password string, fields ...string) *RequestBuilder

Add a decoder to the request. Allowed only for queries.

func (*RequestBuilder) WithEncoder ¶

func (rb *RequestBuilder) WithEncoder(password string, fields ...string) *RequestBuilder

Add an encoder to the request. Allowed only for statements.

func (*RequestBuilder) WithEncoderAndCompression ¶

func (rb *RequestBuilder) WithEncoderAndCompression(password string, compressionLevel int, fields ...string) *RequestBuilder

Add an encoder to the request, with compression. Allowed only for statements.

func (*RequestBuilder) WithNoFail ¶

func (rb *RequestBuilder) WithNoFail() *RequestBuilder

Specify that the request must not cause a general failure.

func (*RequestBuilder) WithValues ¶

func (rb *RequestBuilder) WithValues(values map[string]interface{}) *RequestBuilder

Adds a list of values (ok, amap) for the request. If there's already one, it creates a batch.

type Response ¶

type Response struct {
	// Slice with the results, each one is a ResponseItem
	Results []ResponseItem
}

Response coming from the endpoint, that is a list of single responses matching the list of request that were submitted. The single responses are of type ResponseItem.

type ResponseItem ¶

type ResponseItem struct {
	// Was the request successful?
	Success bool
	// If the node was a statement and no batching was involved, it's the number of updated
	// rows
	RowsUpdated *int64
	// If the node was a statement and a batch of values was provided, it's a slice of the
	// numbers of updated rows for each batch item
	RowsUpdatedBatch []int64
	// If the node was a query, it's a slice of maps with an item per returned record, and
	// each map has the name of the filed as a key of each entry, and the value as a value
	ResultSet []map[string]interface{}
	// Reason for the error, if the request wasn't successful
	Error string
}

Single response coming from ws4sqlite. Every ResponseItem matches a node of the request, and each one has exactly one of the following fields populated/not null:

- Error: reason for the error, if it wasn't successful;

- RowsUpdated: if the node was a statement and no batching was involved; it's the number of updated rows;

- RowsUpdatedBatch: if the node was a statement and a batch of values was provided; it's a slice of the numbers of updated row for each batch item;

- ResultSet: if the node was a query; it's a slice of maps with an item per returned record, and each map has the name of the filed as a key of each entry, and the value as a value.

type WsError ¶

type WsError struct {
	// The index of the statement/query that failed
	RequestIdx int `json:"reqIdx"`
	// Error message
	Msg string `json:"error"`
	// HTTP code
	Code int `json:"-"`
}

This is an exception that wraps the error structure of ws4sqlite. See the docs at https://germ.gitbook.io/ws4sqlite/documentation/errors#global-errors

It has fields for the error message, the index of the node that failed, and for the HTTP code.</p>

func (WsError) Error ¶

func (m WsError) Error() string

Jump to

Keyboard shortcuts

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