Giter VIP home page Giter VIP logo

go-crate's Introduction

Contributing

Respect the .editorconfig

If you plan to contribute to this website, be sure to have your text editor follow the .editorconfig file, read more at: http://editorconfig.org/

Development environment

This are the tools you need in your development environment: * hugo * npm * gulp

Run gulp to automatically watch, and build asset files, such as stylesheets and javascript file.

go-crate's People

Contributors

archs avatar chughpiyush avatar herenow avatar jeteon avatar mindscratch avatar rousemobi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-crate's Issues

Blob download should return error if response code is != 200

The Table.Download function, in the blob driver, only returns an error if the golang http Request.Do returns an error. However, if trying to download a file that does not exist, the download function returns the reader but no error, which is a bad experience for the client using the library.

I'd like to propose that if the response status from Crate is != 200, that an error get returned.

UploadEx ignores response code

In Table.UploadEx in the blob package, note that the HTTP response is discarded:

go-crate/blob/blob.go

Lines 150 to 153 in 2eceb6a

_, err = t.c.Do(req)
if err != nil {
return nil, err
}

Compare with how the Upload method handles the HTTP response:

go-crate/blob/blob.go

Lines 127 to 133 in 2eceb6a

resp, err := t.c.Do(req)
if err != nil {
return nil, err
}
if resp.StatusCode != 201 {
return nil, fmt.Errorf("Upload failed: %s", resp.Status)
}

This means that any errors reported by the server get swallowed and UploadEx falsely appears to have completed successfully.

Can't bind to object types

Trying to insert into a <columnName> object using

db.Exec(`insert into test (metadata) values(?)`, value)

throws

Validation failed for metadata: '{metadata = 1}' cannot be cast to type object]

when value is a string.

How do I insert objects using binds?

Crate does not close connections when errors occur interacting with blobs

It seems that Crate misbehaves when errors occur when interacting with blobs. For example, given the following sequence of actions:

Request Expected Reponse Actual Response
GET http://localhost:4200/_blobs/myblob/abc 200 200
GET http://localhost:4200/_blobs/myblob/def 404 404
GET http://localhost:4200/_blobs/myblob/abc 200 404
GET http://localhost:4200/_blobs/myblob/abc 200 200

Its as though the previous failed response is "cached". Turns out, if the header Connection: close is set, everything works as expected. A bug is being filed against the Crate project. In the meantime, this issue is being opened so a PR can be submitted to work around it.

Add support for multiple back-ends?

I've been working on a new project using Crate. We were attracted to Crate primarily for the distributed features it offers with relatively little hassle. However, currently, this driver is set up to communicate with a particular instance and if that instance is down, there doesn't appear to be any way to fall back to the others in the cluster.

Would you be open to having the ability to handle multiple instances added? I'm willing to put in some of the work myself.

This could work either by having a number of URLs specified in the dsn or by querying the sys.nodes table once connected to a node or I suppose preferably both so the user need not specify every node up front but the application is also not stranded should the particular node its set up to communicate with be down.

P.S.: this is of course a prelude to other functionality such as distributing queries among instances.

Bulkservice proposal

I noticed the bulk services is not implemented, I am not sure if you wanted add support for it or not, but I thought I would toss out a possible implementation.

package crate

import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
    "net/url"
    "reflect"
    "sync"
    "github.com/herenow/go-crate"
)

type (
    CrateBulkDriver struct {
        Url    string // Crate http endpoint url
        client *http.Client
        lock   sync.Mutex
    }
    CrateService struct {
        Statement string           `json:"stmt"`
        BulkArgs  [][]interface{}  `json:"bulk_args"`
        Fields    []string         `json:"-"`
        Table     string           `json:"-"`
        Driver    *CrateBulkDriver `json:"-"`
    }
    InsertService struct {
        CrateService
    }
    BulkResponse struct {
        Error    struct {
                    Message string
                    Code    int
                } `json:"error"`
        Cols     []string             `json:"cols"`
        Duration float64              `json:"duration"`
        Results  []BulkResponseResult `json:"results"`
    }
    BulkResponseResult struct {
        Rowcount int `json:"rowcount"`
    }
)

// Init a new "Connection" to a Crate Data Storage instance.
// Note that the connection is not tested until the first query.
func NewBulkConnection(crate_url string) (c *CrateBulkDriver, e error) {
    c = &CrateBulkDriver{
        lock: sync.Mutex{},
    }
    u, err := url.Parse(crate_url)

    if err != nil {
        return nil, err
    }

    sanUrl := fmt.Sprintf("%s://%s", u.Scheme, u.Host)

    c.Url = sanUrl
    c.client = &http.Client{}

    return c, nil
}

// Creates a new insert service for crate, using the table and fields
func (driver *CrateBulkDriver) NewInsertService(table string, fields ...string) (i *InsertService) {
    buffer := &bytes.Buffer{}
    values := &bytes.Buffer{}
    fmt.Fprintf(buffer, "INSERT INTO %s (", table)
    fmt.Fprintf(values, "VALUES (")
    first := true
    for _, field := range fields {
        if !first {
            buffer.WriteString(", ")
            values.WriteString(", ")
        } else {
            first = false
        }
        buffer.WriteString(field)
        values.WriteString("?")
    }
    buffer.WriteString(") ")
    values.WriteString(") ")
    buffer.Write(values.Bytes())
    i = &InsertService{
        CrateService{
            Statement: string(buffer.Bytes()),
            Table:     table,
            Fields:    fields,
            Driver:    driver,
        },
    }
    return i
}

// Add a specfic interface to the bulk args, could blow up if field name does not exist
func (service *InsertService) Add(data interface{}) {
    // Simplest addition
    orderedValues := make([]interface{}, len(service.Fields))
    for i, v := range service.Fields {
        orderedValues[i] = reflect.ValueOf(data).Elem().FieldByName(v).Interface()
    }
    service.BulkArgs = append(service.BulkArgs, orderedValues)

}

// Use the map to add a bulk arguement
func (service *InsertService) AddMap(data map[string]interface{}) {
    // Simplest addition
    orderedValues := make([]interface{}, len(service.Fields))
    for i, v := range service.Fields {
        orderedValues[i] = data[v]
    }
    service.BulkArgs = append(service.BulkArgs, orderedValues)
}

// Perform the bulk operation on this service
func (service *CrateService) Do() (*BulkResponse, error) {
    service.Driver.lock.Lock()
    defer service.Driver.lock.Unlock()
    res := &BulkResponse{}
    if len(service.BulkArgs) == 0 {
        return res, nil
    }
    endpoint := service.Driver.Url + "/_sql?pretty"

    buf, err := json.Marshal(service)

    if err != nil {
        return nil, err
    }

    data := bytes.NewReader(buf)

    resp, err := service.Driver.client.Post(endpoint, "application/json", data)
    if err != nil {
        return nil, err
    }

    defer resp.Body.Close()
    d := json.NewDecoder(resp.Body)

    // We need to set this, or long integers will be interpreted as floats
    d.UseNumber()

    err = d.Decode(res)

    //fmt.Printf("\n\n response: %#v \n",res)

    if err != nil {
        return nil, err
    }

    //  // Check for db errors
    if res.Error.Code != 0 {
        err = &crate.CrateErr{
            Code:    res.Error.Code,
            Message: res.Error.Message,
        }
        return nil, err
    }

    return res, nil
}

I havent done the update or delete services but as you can see they would be pretty easy to add. The only extra thing I could see is adding a function to BulkResponse to check to see if any of the results returned a -1...

thoughts ??

Unable to drop blob tables containing hyphens

If the name of a blob table contains a hyphen, then the name must be surrounded by double quotes, otherwise, crate reports an error [SQLParseException: line 1:21: mismatched input '-' expecting {<EOF>, '.', ';'}]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.