Giter Club home page Giter Club logo

cqlr's Introduction

cqlr

Build Status

cqlr extends the gocql runtime API and adds the ability to auto-bind a CQL iterator to a struct:

type Tweet struct {
	Timeline string     `cql:"timeline"`
	Id       gocql.UUID `cql:"id"`
	Text     string     `cql:"text"`
}

var s *gocql.Session

q := s.Query(`SELECT text, id, timeline FROM tweet WHERE timeline = ?`, "me")
b := cqlr.BindQuery(q)

var t Tweet
for b.Scan(&t) {
	// Application specific code goes here
}

You can also bind structs to INSERT statements:

tw := Tweet{
	Timeline: "me",
	Id:       gocql.TimeUUID(),
	Text:     "some random message",
}

var s *gocql.Session

b := Bind(`INSERT INTO tweet (timeline, id, text) VALUES (?, ?, ?)`, tw)
if err := b.Exec(s); err != nil {
	// .....
}

Supported CQL Operations

  • SELECT with BindQuery(), Bind() and Scan()
  • INSERT, UPDATE and DELETE with Bind()
  • Maps and Lists (without deltafication)

Not Yet Supported CQL Operations

  • CAS
  • Counters
  • Sets

Feature Roadmap

(In no particular order of priority)

  • Support for all CQL operations
  • Batching
  • Re-binding new struct instances to existing binding instances
  • Protoype guess-based CQL CRUD
  • Investigate implementing the skip metadata flag in EXECUTE with the gocql driver
  • Consider exposing a low level binary interface in gocql that handles query argument marshaling

Supported Binding Mechanisms

Right now, cqlr supports the following mechanisms to bind iterators:

  • Application supplied binding function
  • Map of column name to struct field name
  • By struct tags
  • By field names

Cassandra Support

Right now cqlr is known to work against Cassandra 2.0.9.

Motivation

gocql users are looking for ways to automatically bind query results to application defined structs, but this functionality is not available in the core library. In addition, it is possible that the core library does not want to support this feature, because it significantly increases the functional scope of that codebase. So the goal of cqlr is to see if this functionality can be layered on top of the core gocql API in a re-useable way.

Design

cqlr should sit on top of the core gocql runtime and concern itself only with struct binding. There are two modes of operation:

  • Binding a struct's fields to the query parameters of a particular statement using Bind()
  • Wrapping a gocql *Query instance to perform runtime introspection of the target struct in conjunction with meta data provided by the query result

The binding is specifically stateful so that down the line, the first loop execution can perform expensive introspection and subsequent loop invocations can benefit from this cached runtime metadata. So in a sense, it is a bit like cqlc, except that the metadata processing is done on the first loop, rather than at compile time.

Status

Right now this is an experiment to try to come up with a design that people think is useful and can be implemented sanely.

cqlr's People

Contributors

0x6e6562 avatar phillipcouto 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

Watchers

 avatar  avatar  avatar

cqlr's Issues

Docs or examples for beginners?

Firstly, thanks for cqlr, seems to be the missing piece for easily binding structs to cql queries.

I'm starting out with Go, and still coming to terms with much of it. Tried reading the source to figure out what the various functions do, but the lack of documentation and slightly opaque variable names made for pretty tough reading.

Are you open to adding some code comments or a few more examples beyond the existing readme? I would offer to submit a pull request, but I'm struggling to understand the code...

can not marshal *gocql.UUID into uuid

I have a struct that looks like this:

type MyStruct struct {
    Id        gocql.UUID         `json:"id"                     cql:"id"`
    Name      string             `json:"name"                   cql:"name"`
}

And my code looks like this:

func (m *MyStruct) myFunc() error {
    id, err := gocql.RandomUUID()
    if err != nil {
        return err
    }
    qs := `INSERT INTO myTable (id, name) VALUES(?,?)`
    m.Id = id
    err = cqlr.Bind(qs, m).Exec(session)

    return err
}

But when I run my code, I get this error:

can not marshal *gocql.UUID into uuid

What is going on?

Casing of column names in query generates "insufficient column mapping"

This is a repost of #1 because I am still experiencing a similar issue. Shouldn't it be case insensitive? Or could we give it a better error message? This was really confusing and started looking all over the C* table and looking over my code for other mistakes.

This is broken

type testModel struct {
    uuid   gocql.UUID
    value1 string
    value2 int
}

But this one works.

type testModel struct {
    Uuid   gocql.UUID
    Value1 string
    Value2 int
}

cqlr masks gocql errors when Scanning

I noticed when working on a project that I wasn't getting any results from Cassandra, even though there were results in the database. My code looks like something like this:

    qs := "SELECT a, b, c FROM my_table"
    query := cqlr.BindQuery(s.Session.Query(qs))

    var object MyObject
    objects := make([]MyObject, 0)
    for query.Scan(&object) {
        objects = append(objects, object)
    }

    if err := query.Close(); err != nil {
        return objects, err
    }

    return objects, nil

Given that MyObject is special in how it is marshalled / unmarshalled, I suspected that there was some error in how I conduct that, but the above code throws no errors.

As it turns out, cqlr masks the error. On cqlr.go#L74, an error is only returned if cqlr had a problem. If there is a problem unmarshalling (as might happen in cqlr.go#L107, the error won't be caught until iter is closed... which doesn't happen.

I think that all that is needed is that in Binding.Close, it returns b.err or b.iter.Close().

Cannot unmarshal into anonymous structs

It seems that cqlr cannot unmarshal Cassandra results into structs with anonymous fields:

type Type1 struct {
  ID *string `cql:"id"`
  Name *string `cql:"name"`
}

type Type2 struct {
  *Type1
  Description *string `cql:"description"`
}

and then using those:

q := fmt.Sprintf(`SELECT id,name,description FROM %s WHERE id=?`, store.table)
query := store.connection.Session.Query(q, uuid)
b := cqlr.BindQuery(query)
res := &Type2{}
for b.Scan(res) {
  // res.Type1.* are all nil
}

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.