Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Feature/rsql #13

Merged
merged 6 commits into from
Dec 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: sqlike
name: build
on:
push:
branches:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Sequel ORM

[![Build Status](https://github.com/si3nloong/sqlike/workflows/sqlike/badge.svg?branch=master)](https://github.com/si3nloong/sqlike/actions)
[![Build Status](https://github.com/si3nloong/sqlike/workflows/build/badge.svg?branch=master)](https://github.com/si3nloong/sqlike/actions)

```bash
go get github.com/si3nloong/sqlike
Expand Down
2 changes: 1 addition & 1 deletion examples/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ func TestExamples(t *testing.T) {
Database("sqlike")

{
RSQLExamples(t, db)
MigrateExamples(t, db)
IndexExamples(t, db)
InsertExamples(t, db)
Expand All @@ -57,6 +56,7 @@ func TestExamples(t *testing.T) {
ExtraExamples(t, db, mg)
JSONExamples(t, db)
CasbinExamples(t, db)
RSQLExamples(t, db)
}

// Errors
Expand Down
File renamed without changes.
46 changes: 36 additions & 10 deletions examples/rsql.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package examples

import (
"log"
"testing"

"github.com/si3nloong/sqlike/sql/expr"
Expand All @@ -13,13 +12,17 @@ import (
)

type rsqlStruct struct {
ID int64 `sqlike:",primary_key"`
Status Enum `sqlike:",enum=SUCCESS|FAILED|UNKNOWN"`
ID int64 `sqlike:",primary_key"`
Name string
LongText string
Status Enum `sqlike:",enum=SUCCESS|FAILED|UNKNOWN"`
}

type queryStruct struct {
Name string `rsql:"name,filter,sort"`
ID int64 `rsql:"id,select,filter,sort"`
Status string `rsql:",filter,sort"`
Text string `rsql:"text,filter,column=LongText"`
Status Enum `rsql:",filter,sort"`
}

// RSQLExamples :
Expand All @@ -28,6 +31,7 @@ func RSQLExamples(t *testing.T, db *sqlike.Database) {
parser *rsql.Parser
params *rsql.Params
err error
errs error
)

table := db.Table("rsql_struct")
Expand Down Expand Up @@ -56,23 +60,45 @@ func RSQLExamples(t *testing.T, db *sqlike.Database) {
parser = rsql.MustNewParser(src)
require.NotNil(t, parser)

query := `$select=&$filter=(id==value)&$sort=&$limit=100`

// Valid rsql filter
{

query := `$filter=(name==test;status==SUCCESS)&$limit=100`
params, err = parser.ParseQuery(query)
require.NoError(t, err)
require.NotNil(t, params)
require.Equal(t, expr.And(
expr.Equal("Name", "test"),
expr.Equal("Status", Success),
), params.Filters)

_, err = table.Find(actions.Find().
Where(
params.Filters,
expr.Equal("Status", Success),
), options.Find().SetDebug(true))
require.NoError(t, err)
}

log.Println(parser)
log.Println(params.Filters)
// Invalid rsql select
{
query := `$select=t1,t2`
params, errs = parser.ParseQuery(query)
require.Nil(t, params)
require.Error(t, errs)
}

// Invalid rsql sort
{
query := `$sort=t1,t2`
params, errs = parser.ParseQuery(query)
require.Nil(t, params)
require.Error(t, errs)
}

// Invalid rsql limit
{
query := `$limit=abcd`
params, errs = parser.ParseQuery(query)
require.Nil(t, params)
require.Error(t, errs)
}
}
9 changes: 9 additions & 0 deletions sqlike/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,16 @@ func (db *Database) BuildIndexes(filepath ...string) error {
file := pwd + "/index.yaml"
if len(filepath) > 0 {
file = filepath[0]
goto READFILE
}
if _, err := os.Stat(file); os.IsNotExist(err) {
file = pwd + "/index.yml"
if _, err := os.Stat(file); os.IsNotExist(err) {
return err
}
}

READFILE:
b, err := ioutil.ReadFile(file)
if err != nil {
return err
Expand Down
96 changes: 0 additions & 96 deletions sqlike/rsql/default_filter.go

This file was deleted.

8 changes: 2 additions & 6 deletions sqlike/rsql/default_lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ func newDefaultTokenLexer() *defaultTokenLexer {
}

func (l *defaultTokenLexer) addActions(lexer *lexmachine.Lexer) {
lexer.Add([]byte(`\s`), handleSpace)
lexer.Add([]byte(`\s`), l.token("whitespace"))
lexer.Add([]byte(`\(|\)`), l.token("grouping"))
lexer.Add([]byte(`\"(\\.|[^\"])*\"`), l.token("string"))
lexer.Add([]byte(`(\,|or)`), l.token("or"))
lexer.Add([]byte(`(\;|and)`), l.token("and"))
lexer.Add([]byte(`(\-)?([0-9]*\.[0-9]+|[0-9]+)`), l.token("numeric"))
lexer.Add([]byte(`[a-zA-Z0-9\_\.\%]+`), l.token("text"))
lexer.Add([]byte(`(\=\=|\!\=|\>|\>\=|\<|\<\=|\=ne\=|\=nin\=)`), l.token("operator"))
lexer.Add([]byte(`(\=\=|\!\=|\>|\>\=|\<|\<\=|\=ne\=|\=in\=|\=nin\=)`), l.token("operator"))
l.lexer = lexer
}

Expand All @@ -42,7 +42,3 @@ func (l *defaultTokenLexer) token(name string) lexmachine.Action {
return s.Token(l.ids[name], string(m.Bytes), m), nil
}
}

func handleSpace(scan *lexmachine.Scanner, match *machines.Match) (interface{}, error) {
return nil, nil
}
8 changes: 4 additions & 4 deletions sqlike/rsql/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,24 @@ type FieldError struct {

// Error :
func (fe FieldError) Error() string {
return "rsql: invalid field " + strconv.Quote(fe.Name) + " in " + fe.Module
return "invalid field " + strconv.Quote(fe.Name) + " in " + fe.Module
}

// Errors :
type Errors []*FieldError

// Error :
func (errs Errors) Error() string {
blr := util.AcquireString()
defer util.ReleaseString(blr)
var (
fe *FieldError
blr = util.AcquireString()
length = len(errs)
)
defer util.ReleaseString(blr)
for i := 0; i < length; i++ {
fe = errs[i]
if i > 0 {
blr.WriteByte('\n')
blr.WriteString("; ")
}
blr.WriteString(fe.Error())
}
Expand Down
60 changes: 53 additions & 7 deletions sqlike/rsql/filter.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,65 @@
package rsql

import "log"
import (
"github.com/si3nloong/sqlike/sql/expr"
"github.com/si3nloong/sqlike/sqlike/primitive"
)

func (p *Parser) parseFilter(values map[string]string, params *Params) (errs Errors) {
val, ok := values[p.FilterTag]
log.Println("QueryString :", string(val))
if !ok || len(val) < 1 {
return nil
return
}

lxr, _ := p.lexer.Scanner([]byte(val))
scan := &Scanner{parser: p, Scanner: lxr}
if err := scan.ParseToken(); err != nil {
log.Println("Error :", err)
grp := new(primitive.Group)
stack := make([]bool, 0)

for {
tkn, eof := scan.NextToken()
if eof {
break
}

char := string(tkn.Lexeme)
switch tkn.Type {
case Whitespace:
// skip
case Group:
{
if char == "(" {
stack = append(stack, true)
grp.Values = append(grp.Values, expr.Raw("("))
continue
}

if len(stack) < 0 {
errs = append(errs, &FieldError{Module: p.FilterTag})
continue
}

stack = stack[:len(stack)-1]
grp.Values = append(grp.Values, expr.Raw(")"))
}

case Text:
// check expression
if err := scan.ParseExpression(grp, tkn); err != nil {

}

case String:
if err := scan.ParseExpression(grp, tkn); err != nil {

}
case And:
grp.Values = append(grp.Values, primitive.And)
case Or:
grp.Values = append(grp.Values, primitive.Or)
}
}
params.Filters = scan.values
return nil

params.Filters = *grp
return
}
10 changes: 5 additions & 5 deletions sqlike/rsql/limit.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ func (p *Parser) parseLimit(values map[string]string, params *Params) (errs Erro
val, ok := values[p.LimitTag]
delete(values, p.LimitTag)
if !ok || len(val) < 1 {
return nil
return
}

u64, err := strconv.ParseUint(val, 10, 64)
if err != nil {
errs = append(errs, &FieldError{Value: "invalid value, " + val, Module: p.LimitTag})
return errs
return
}
if u64 > uint64(maxUint) {
errs = append(errs, &FieldError{Value: fmt.Sprintf("overflow unsigned integer, %d", u64), Module: p.LimitTag})
return errs
return
}
params.Limit = uint(u64)
if params.Limit > p.MaxLimit {
params.Limit = p.MaxLimit // prevent toxic query (limit)
errs = append(errs, &FieldError{Value: "maximum value of limit", Module: p.LimitTag})
return errs
return
}
return nil
return
}
6 changes: 0 additions & 6 deletions sqlike/rsql/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,3 @@ func parseRawQuery(m map[string]string, query string) (err error) {
}
return err
}

// // expression = [ "(" ]
// // ( constraint / expression )
// // [ operator ( constraint / expression ) ]
// // [ ")" ]
// // operator = ";" / ","
Loading