Skip to content

Commit c1a8634

Browse files
author
Dean Karn
authored
Merge pull request #1 from go-playground/conversion
Conversion
2 parents c8524fc + 1950a4c commit c1a8634

File tree

13 files changed

+2175
-2
lines changed

13 files changed

+2175
-2
lines changed

.github/workflows/workflow.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
on:
2+
push:
3+
branches:
4+
- master
5+
pull_request:
6+
name: Test
7+
jobs:
8+
test:
9+
strategy:
10+
matrix:
11+
go-version: [1.18.x]
12+
os: [ubuntu-latest, macos-latest, windows-latest]
13+
runs-on: ${{ matrix.os }}
14+
steps:
15+
- name: Install Go
16+
uses: actions/setup-go@v2
17+
with:
18+
go-version: ${{ matrix.go-version }}
19+
20+
- name: Checkout code
21+
uses: actions/checkout@v2
22+
23+
- name: Restore Cache
24+
uses: actions/cache@v2
25+
with:
26+
path: ~/go/pkg/mod
27+
key: ${{ runner.os }}-v1-go-${{ hashFiles('**/go.sum') }}
28+
restore-keys: |
29+
${{ runner.os }}-v1-go-
30+
31+
- name: Test
32+
run: go test -race -covermode=atomic -coverprofile="profile.cov" ./...
33+
34+
- name: Send Coverage
35+
if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.18.x'
36+
uses: shogo82148/actions-goveralls@v1
37+
with:
38+
path-to-profile: profile.cov
39+
40+
golangci:
41+
name: lint
42+
runs-on: ubuntu-latest
43+
steps:
44+
- uses: actions/checkout@v2
45+
- name: golangci-lint
46+
uses: golangci/golangci-lint-action@v2
47+
with:
48+
version: v1.45.0

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Changelog
2+
All notable changes to this project will be documented in this file.
3+
4+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6+
7+
## [Unreleased]
8+
9+
## [0.1.0] - 2022-03-23
10+
### Added
11+
- Initial conversion from https://github.com/rust-playground/ksql.
12+
13+
[Unreleased]: https://github.com/go-playground/ksql/compare/v0.1.0...HEAD
14+
[0.1.0]: https://github.com/rust-playground/ksql/commit/v0.1.0

Makefile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
lint:
2+
golangci-lint run
3+
4+
bench:
5+
$(ENVS) go test -run=NONE -bench=. -benchmem ./...
6+
7+
test:
8+
$(ENVS) go test -race -cover ./...
9+
10+
.PHONY: lint bench test

README.md

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,95 @@
1-
# ksql
2-
a JSON data expression lexer, parser, cli and library
1+
ksql
2+
=====
3+
![Project status](https://img.shields.io/badge/version-0.1.0-green.svg)
4+
[![GoDoc](https://godoc.org/github.com/go-playground/ksql?status.svg)](https://pkg.go.dev/github.com/go-playground/ksql)
5+
![License](https://img.shields.io/dub/l/vibe-d.svg)
6+
7+
**Is a JSON data expression lexer, parser, cli and library.**
8+
9+
#### Requirements
10+
- Go 1.18+
11+
12+
#### How to install CLI
13+
```shell
14+
~ go install github.com/go-playground/ksql
15+
```
16+
17+
#### Usage
18+
```go
19+
package main
20+
21+
import (
22+
"fmt"
23+
24+
"github.com/go-playground/ksql"
25+
)
26+
27+
func main() {
28+
expression := []byte(`.properties.employees > 20`)
29+
input := []byte(`{"name":"MyCompany", "properties":{"employees": 50}`)
30+
ex, err := ksql.Parse(expression)
31+
if err != nil {
32+
panic(err)
33+
}
34+
35+
result, err := ex.Calculate(input)
36+
if err != nil {
37+
panic(err)
38+
}
39+
fmt.Printf("%v\n", result)
40+
}
41+
42+
```
43+
44+
#### Expressions
45+
Expressions support most mathematical and string expressions see below for details:
46+
47+
#### Syntax & Rules
48+
49+
| Token | Example | Syntax Rules |
50+
|----------------|--------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
51+
| `Equals` | `==` | supports both `==` and `=`. |
52+
| `Add` | `+` | N/A |
53+
| `Subtract` | `-` | N/A |
54+
| `Multiply` | `*` | N/A |
55+
| `Divide` | `/` | N/A |
56+
| `Gt` | `>` | N/A |
57+
| `Gte` | `>=` | N/A |
58+
| `Lt` | `<` | N/A |
59+
| `Lte` | `<=` | N/A |
60+
| `OpenParen` | `(` | N/A |
61+
| `CloseParen` | `)` | N/A |
62+
| `OpenBracket` | `[` | N/A |
63+
| `CloseBracket` | `]` | N/A |
64+
| `Comma` | `,` | N/A |
65+
| `QuotedString` | `"sample text"` | Must start and end with an unescaped `"` character |
66+
| `Number` | `123.45` | Must start and end with a valid `0-9` digit. |
67+
| `Boolen` | `true` | Accepts `true` or `false` as a boolean only. |
68+
| `Identifier` | `.identifier` | Starts with a `.` and ends with whitespace blank space. This crate currently uses [gjson](https://github.com/tidwall/gjson.rs) and so the full gjson syntax for identifiers is supported. |
69+
| `And` | `&&` | N/A |
70+
| `Not` | `!` | Must be before Boolean identifier or expression or be followed by an operation |
71+
| `Or` | <code>&vert;&vert;<code> | N/A |
72+
| `Contains` | `CONTAINS ` | Ends with whitespace blank space. |
73+
| `In` | `IN ` | Ends with whitespace blank space. |
74+
| `StartsWith` | `STARTSWITH ` | Ends with whitespace blank space. |
75+
| `EndsWith` | `ENDSWITH ` | Ends with whitespace blank space. |
76+
| `NULL` | `NULL ` | N/A |
77+
78+
79+
80+
```
81+
82+
#### License
83+
84+
<sup>
85+
Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
86+
2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
87+
</sup>
88+
89+
<br>
90+
91+
<sub>
92+
Unless you explicitly state otherwise, any contribution intentionally submitted
93+
for inclusion in Proteus by you, as defined in the Apache-2.0 license, shall be
94+
dual licensed as above, without any additional terms or conditions.
95+
</sub>

_examples/simple/main.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/go-playground/ksql"
7+
)
8+
9+
func main() {
10+
expression := []byte(`.properties.employees > 20`)
11+
input := []byte(`{"name":"MyCompany", "properties":{"employees": 50}`)
12+
ex, err := ksql.Parse(expression)
13+
if err != nil {
14+
panic(err)
15+
}
16+
17+
result, err := ex.Calculate(input)
18+
if err != nil {
19+
panic(err)
20+
}
21+
fmt.Printf("%v\n", result)
22+
}

benchmarks_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package ksql
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func BenchmarkNumPlusNum(b *testing.B) {
8+
bench(b, "1 + 1", ``)
9+
}
10+
11+
func BenchmarkIdentNum(b *testing.B) {
12+
bench(b, ".field1 + 1", `{"field1":1}`)
13+
}
14+
15+
func BenchmarkIdentIdent(b *testing.B) {
16+
bench(b, ".field1 + .field2", `{"field1":1,"field2":1}`)
17+
}
18+
19+
func BenchmarkFNameLName(b *testing.B) {
20+
bench(b, `.first_name + " " + .last_name`, `{"first_name":"Joey","last_name":"Bloggs"}`)
21+
}
22+
23+
func BenchmarkParenDiv(b *testing.B) {
24+
bench(b, `(1 + 1) / 2`, ``)
25+
}
26+
27+
func BenchmarkParenDivIdents(b *testing.B) {
28+
bench(b, `(.field1 + .field2) / .field3`, `{"field1":1,"field2":1,"field3":2}`)
29+
}
30+
31+
func BenchmarkCompanyEmployees(b *testing.B) {
32+
bench(b, `.properties.employees > 20`, `{"name":"Company","properties":{"employees":50}}`)
33+
}
34+
35+
func BenchmarkParenNot(b *testing.B) {
36+
bench(b, `!(.f1 != .f2)`, `{"f1":true,"f2":false}`)
37+
}
38+
39+
func bench(b *testing.B, expression, input string) {
40+
ex, err := Parse([]byte(expression))
41+
if err != nil {
42+
b.Fatal(err)
43+
}
44+
in := []byte(input)
45+
b.ResetTimer()
46+
b.SetBytes(int64(len(in)))
47+
48+
for i := 0; i < b.N; i++ {
49+
_, err := ex.Calculate(in)
50+
if err != nil {
51+
b.Fatal(err)
52+
}
53+
}
54+
}

errors.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package ksql
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
// Lexer errors
8+
9+
// ErrUnsupportedCharacter represents an unsupported character is expression being lexed.
10+
type ErrUnsupportedCharacter struct {
11+
b byte
12+
}
13+
14+
func (e ErrUnsupportedCharacter) Error() string {
15+
return fmt.Sprintf("Unsupported Character `%s`", string(e.b))
16+
}
17+
18+
// ErrUnterminatedString represents an unterminated string
19+
type ErrUnterminatedString struct {
20+
s string
21+
}
22+
23+
func (e ErrUnterminatedString) Error() string {
24+
return fmt.Sprintf("Unterminated string `%s`", e.s)
25+
}
26+
27+
// ErrInvalidIdentifier represents an invalid identifier string
28+
type ErrInvalidIdentifier struct {
29+
s string
30+
}
31+
32+
func (e ErrInvalidIdentifier) Error() string {
33+
return fmt.Sprintf("Invalid identifier `%s`", e.s)
34+
}
35+
36+
// ErrInvalidBool represents an invalid boolean
37+
type ErrInvalidBool struct {
38+
s string
39+
}
40+
41+
func (e ErrInvalidBool) Error() string {
42+
return fmt.Sprintf("Invalid boolean `%s`", e.s)
43+
}
44+
45+
// ErrInvalidKeyword represents an invalid keyword keyword
46+
type ErrInvalidKeyword struct {
47+
s string
48+
}
49+
50+
func (e ErrInvalidKeyword) Error() string {
51+
return fmt.Sprintf("Invalid keyword `%s`", e.s)
52+
}
53+
54+
// ErrInvalidNumber represents an invalid number
55+
type ErrInvalidNumber struct {
56+
s string
57+
}
58+
59+
func (e ErrInvalidNumber) Error() string {
60+
return fmt.Sprintf("Invalid number `%s`", e.s)
61+
}
62+
63+
// Parser errors
64+
65+
// ErrUnsupportedTypeComparison represents a comparison of incompatible types
66+
type ErrUnsupportedTypeComparison struct {
67+
s string
68+
}
69+
70+
func (e ErrUnsupportedTypeComparison) Error() string {
71+
return fmt.Sprintf("unsupported type comparison: `%s`", e.s)
72+
}

go.mod

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module github.com/go-playground/ksql
2+
3+
go 1.18
4+
5+
require (
6+
github.com/stretchr/testify v1.7.1
7+
github.com/tidwall/gjson v1.14.0
8+
)
9+
10+
require (
11+
github.com/davecgh/go-spew v1.1.0 // indirect
12+
github.com/pmezard/go-difflib v1.0.0 // indirect
13+
github.com/tidwall/match v1.1.1 // indirect
14+
github.com/tidwall/pretty v1.2.0 // indirect
15+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
16+
)

go.sum

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
2+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
4+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
5+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
6+
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
7+
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
8+
github.com/tidwall/gjson v1.14.0 h1:6aeJ0bzojgWLa82gDQHcx3S0Lr/O51I9bJ5nv6JFx5w=
9+
github.com/tidwall/gjson v1.14.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
10+
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
11+
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
12+
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
13+
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
14+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
15+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
16+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
17+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 commit comments

Comments
 (0)