nodb

package module
v0.0.0-...-c0700b7 Latest Latest
Warning

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

Go to latest
Published: Jul 5, 2017 License: BSD-2-Clause-Views Imports: 13 Imported by: 0

README

SQL array comprehensions in Go. GoDoc Build Status Coverage Status Donate

  • Great for complex in-memory caches, or in-memory joins across various datastores
  • Development faster than in-memory DBs: no table creation, inserts, IPC, CGO or de/serialization
  • Sort Easily: "ORDER BY last_name, importance DESC"
  • Every struct is a table row. A (slice OR chan) of them is a table. -- chan tables will cache to a slice as needed. (Today to avoid caching, it needs to be the first table & no subsequent Right join)
  • Pass in & use any func. time.Time is your time format.
  • Use any types you want, just provide & use the functions you needed.

Example:

// Lets thank our 10 biggest customers this month:
var results []struct{
  Name string
  Email string
  MonthlyTotal float64
}
err := nodb.Inline(&results, 
    "SELECT name, email, SUM(o.total) AS monthlyTotal",
    "FROM", customer,"AS cust JOIN", order,"AS o ON cust.id=o.custID",
    "WHERE o.whenCompleted > ", time.Now().Add(-30*24*time.Hour),
    "GROUP BY cust.id",
    "ORDER BY monthlyTotal DESC",
    "LIMIT 10")
// If no error: the results' structs will contain shallow-copies of their elements.

DB Driver method:

  import "github.com/snadrus/nodb"
  ...
  // Once:
  nodb.Add("myTable", []ABC{{1, "hello", 1.0}, {2, "db", 2.0}, {3, "world", 3.0}})  
  connection := sqlx.MustConnect("nodb", "cache")         

  // As-Needed:           
  var results []ABC
  err := connection.Select(&results, "SELECT * FROM myTable WHERE C > 1.5")
  fmt.Println(results) // []ABC{{2, "db", 2.0}, {3, "world", 3.0}}

Benefitting:

  • no-Join policy scenarios (like Cassandra): ACID your way.
  • SQL in caches
  • Building your own DB.

FAQ:

  • Dual License
    • BSD or commercial license.
  • Why are nodb.Do results not saved?
    • Results reach the destination by name. Use an "AS" to select the destination field.
  • How compatible?
    • Common parts of ANSI SQL. It's right or will error. Case-insensitive query of public members. See TODOs for omissions
  • How extensible?
    • Add functions per query Obj & use them anywhere in the query.
  • How can I help?
    • Open a bug in github.org/snadrus/nodb and send a merge request.
  • Types?
    • Are GoLang types. Pass-in functions: func Hour(t time.Time) int { return t.Hour() }
    • Time renders as UnixNano() for comparison/arithmatic/etc including time.Duration
  • Where did this come from?
    • It's the personal efforts of Andrew Jackson who also had the idea.
  • How fast really?
    • It is in-memory & pipelined for multicore. Correctness first, query planning second.
    • 30-year-optimized DBs mostly win with on-disk layout & permanent indexes. Neither makes sense here.
    • Lots of work is possible in query planner stage to make use of special circumstances.
  • Memory Risk:
    • Object copying isn't light. GROUPBY/DISTINCT/ORDER_BY is even heavier.

Design: (the first?) 100% Go SQL engine Go libs for SQL parsing and interface{} evaluating. Native GoLang libs for all else: reflect, sort, template (functions) Process:

  • Rich "Rows" are formed of all joined, renamed, calculated data for a source row
  • Processing occurs on these.
  • SELECT rows (just requested data) are formed.
  • The SELECT rows are mapped back to the destination by name Closures are the greatest! The setups return functions that have context.

Recently Added:

  • Subqueries
  • chan (struct) Tables. If it's the first table, it also won't cache
  • SELECT count(distinct __)
  • DISTINCT (whole SELECT row)

TODO:

  • Functions in WHERE clause -- Needs parser upgrades to be used in WHERE clauses

  • Perf: -- WHERE clause per-table first IF this table is involved in it. -- MAPS for ON relation (presume unique, work if not unique)

  • Parentheses joins. Build a joinElement without a left, but keep its append order

  • NULL (nil) support is wonky at best. Avoid if possible.

  • TODOs in the code.

  • Functions on objects: Hour(t) --> t.Hour() -- Needs parser upgrades to be used in WHERE clauses

  • DB Proxy (Cassandra or a variety at once) -- SubQueries + mmap for JOIN/GROUP intermediaries

  • OPTIMIZATION: Per-table elimination of rows without all data available: -- THEN: make errored expr.E returns include partial eval. <-- bad idea. No way to combine. Overhead

  • OPTIMIZATION: RowMap["1Prototype"] pointing to previous map. Reduces join effort. BETTER: have a .GetValue("name") function that works on all the various types.

  • OPTIMIZATION: index idea: zeroed index will represent position offset to real table values, so all zeroes is "this order". Then we are free to sort using govaluate to build an index on-the-fly without painful/risky reordering. Indexes are great for groupby fields: walking them in sorted order means no memalloc

  • OPTIMIZATION: expr needs return a rollup of what tables a subexpression uses.

    • Inv of constant. Use to determine if needs re-eval
    • Aides planner in slicing-up processing
    • OPTIMIZATION: pre-determine the table rows that match the WHERE query.
  • Planner v2: run short-circuit expr, then recurse. Medium: just left-align those with indexes. leftist for 1 channel

  • Joiner: hard-version:

    • if you're an inner loop, consider marking those you skip
    • if unsorted & "equals" join, map or sort
  • MEM exhaustion risk: group/distinct/orderby mmaped hashes. (MEDIUM)

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Add

func Add(key string, item interface{})

Add a table ([]struct) or function to the database

func Delete

func Delete(key string)

Delete a user-added item from the database

func Do

func Do(query string, result interface{}, src Obj) error

Do an SQL 'query' against 'src' entries and (copy) results into 'result' See doc.go for more details. src points to tables ([]AnyStruct) and functions

func EnableLogging

func EnableLogging()

func Filter

func Filter(query string, result interface{}, input interface{}) error

Filter the input using an SQL WHERE content. 1-level-dep copy results. Available: AND, OR, go math symbols, (), Struct Field names, single quotes, single equal ( ID > 5 ) AND !(Name='Bob')

func Inline

func Inline(result interface{}, inlineQuery ...interface{}) error

Inline SQL and argument expression, such as: Inline(&res,

	"SELECT customer.name, customer.phone, COUNT(order.id) AS count FROM ",
	customers,
 " AS customers JOIN ",
 orders,
 " AS orders ON orders.customer_id = customers.id",
 "WHERE ",func(d time.Time)bool{return time.Since(d)< 30*time.Day},"(order.date)" )

Types

type Conn

type Conn struct {
	context.Context
	Cancel context.CancelFunc
}

func (Conn) Begin

func (c Conn) Begin() (driver.Tx, error)

func (Conn) Close

func (c Conn) Close() error

func (Conn) Prepare

func (c Conn) Prepare(s string) (driver.Stmt, error)

type NoDBDriver

type NoDBDriver struct{}

func (NoDBDriver) Open

func (n NoDBDriver) Open(s string) (driver.Conn, error)

type Obj

type Obj map[string]interface{}

Obj is the 3rd parameter to Do. Use it to name tables & custom functions

type Stmt

type Stmt struct {
	context.Context
	Cancel context.CancelFunc
	S      string
}

func (Stmt) Close

func (s Stmt) Close() error

func (Stmt) Exec

func (s Stmt) Exec(args []driver.Value) (driver.Result, error)

func (Stmt) NumInput

func (s Stmt) NumInput() int

func (Stmt) Query

func (s Stmt) Query(args []driver.Value) (driver.Rows, error)

type Tx

type Tx struct{}

func (Tx) Commit

func (t Tx) Commit() error

func (Tx) Rollback

func (t Tx) Rollback() error

Directories

Path Synopsis
These are the internal libraries for NoDB.
These are the internal libraries for NoDB.
sel

Jump to

Keyboard shortcuts

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