Skip to content

Commit

Permalink
feat sub query
Browse files Browse the repository at this point in the history
  • Loading branch information
baxiry committed Jul 20, 2024
1 parent c2cea5f commit bdc339d
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 66 deletions.
148 changes: 86 additions & 62 deletions engine/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import (
"github.com/tidwall/gjson"
)

func getIds(query gjson.Result) (string, error) {
func getIds(query gjson.Result) (ids []int64) {

coll := query.Get("collection").Str
if coll == "" {
return "", fmt.Errorf("no collection")
return nil
}

mtch := query.Get("match")
Expand All @@ -28,63 +28,55 @@ func getIds(query gjson.Result) (string, error) {

stmt := `select rowid, record from ` + coll

sub := query.Get("subQuery")
sub := query.Get("sQuery")

if sub.Raw != "" {
fmt.Println("sub.Row is : ", sub.Raw)
ids, _ := getIds(sub)
stmt += ` where rowid in (` + ids + `);`
fmt.Println(stmt)
ids = getIds(sub)
}

rows, err := db.db.Query(stmt)
if err != nil {
return "", fmt.Errorf("db.Query %s", err)
return nil
}
defer rows.Close()

record := ""
rowids := ""
rowid := ""
rowid := 0

for rows.Next() {
if limit == 0 {
break
}

record = ""
rowid = ""
err := rows.Scan(&rowid, &record)
if err != nil {
return "", fmt.Errorf("row.Scan %s", err)
}
rowid = 0
_ = rows.Scan(&rowid, &record)

ok, err := match(mtch, record)
if err != nil {
return "", fmt.Errorf("match %s", err)
fmt.Printf("match %s\n", err)
return nil
}

if ok {
if skip != 0 {
skip--
continue
}
rowids += rowid + ","
ids = append(ids, int64(rowid))
limit--
}
}
fmt.Println("\n", ids)

if rowids == "" {
return "", fmt.Errorf("zero value")
}

return rowids[:len(rowids)-1], nil
return ids
}

// gjson.Type :
// json:5, array:5, int:2, string:3
// gjson.Type => json:5, array:5, int:2, string:3

// match verifies that data matches the conditions
func match(filter gjson.Result, data string) (result bool, err error) {
func match(filter gjson.Result, data string, ids ...int64) (result bool, err error) {
// TODO should return syntax error if op unknown

result = true
Expand All @@ -93,122 +85,155 @@ func match(filter gjson.Result, data string) (result bool, err error) {

dataVal := gjson.Get(data, queryKey.Str)

if queryVal.Type == 5 { // 5:json-array, 2:int, 3:string
queryVal.ForEach(func(subQueryKey, subQueryVal gjson.Result) bool {
if queryVal.Type == 5 { // 5:json
// {name:{$eq:"adam"}, age:{$gt: 18}}

queryVal.ForEach(func(sQueryKey, sQueryVal gjson.Result) bool {

if subQueryVal.Type == 3 { // 3:string,
//fmt.Println("here with: ", subQueryKey.String())
if sQueryVal.Type == 3 { // 3:string,
// from : {$eq:"adam"} , sQueryKey is $eq, sQueryVal is "adam"

switch subQueryKey.Str {
switch sQueryKey.Str {

// comparition
// compare sQueryKey
case "$gt":
if !(dataVal.Str > subQueryVal.Str) {
if !(dataVal.Str > sQueryVal.Str) {
result = false
}
return result

case "$lt":
if !(dataVal.Str < subQueryVal.Str) {
if !(dataVal.Str < sQueryVal.Str) {
result = false
}
return result

case "$gte":
if !(dataVal.Str >= subQueryVal.Str) {
if !(dataVal.Str >= sQueryVal.Str) {
result = false
}
return result

case "$lte":
if !(dataVal.Str <= subQueryVal.Str) {
if !(dataVal.Str <= sQueryVal.Str) {
result = false
}
return result

case "$eq":
if dataVal.Str != subQueryVal.Str {
if dataVal.Str != sQueryVal.Str {
result = false
}
return result
case "$ne":
if dataVal.Str == subQueryVal.Str {
if dataVal.Str == sQueryVal.Str {
result = false
}
return result

//
case "$or": // not in

result = false
return result

case "$st": // start with ..
if !strings.HasPrefix(dataVal.Str, subQueryVal.Str) {
if !strings.HasPrefix(dataVal.Str, sQueryVal.Str) {
result = false
}
return result

case "$en": // end with ..
if !strings.HasSuffix(dataVal.Str, subQueryVal.Str) {
if !strings.HasSuffix(dataVal.Str, sQueryVal.Str) {
result = false
}
return result

case "$c": // contains ..
if !strings.Contains(dataVal.Str, subQueryVal.Str) {
if !strings.Contains(dataVal.Str, sQueryVal.Str) {
result = false
}
return result

// Handle sub Database Query
case "$sub":
ln := len(ids)
if ln == 0 {
result = false
return result
}

switch sQueryVal.Str {
// what ??

case "$in": // in array
for _, v := range ids {
//fmt.Println("sQueryVal", sQueryVal)
if dataVal.Num == float64(v) {
return result
}
}
result = false
return result

case "$nin": // not in
for _, v := range ids {
if dataVal.Num == float64(v) {
result = false
return result
}
}
return result

} // end switch of sub query

// return sub query case
return result

default:
err = fmt.Errorf("unknown %s operation", subQueryKey.Value())
//fmt.Println("..wher here", subQueryKey.Value(), subQueryKey.Type)
err = fmt.Errorf("unknown %s operation", sQueryKey.Str)
//fmt.Println("..wher here", sQueryKey.Value(), sQueryKey.Type)
result = false
return result
}
}

switch subQueryKey.Str {
// if sQueryVal is number
switch sQueryKey.Str {

case "$gt":
if !(dataVal.Num > subQueryVal.Num) {
if !(dataVal.Num > sQueryVal.Num) {
result = false
}
return result

case "$lt":
if !(dataVal.Num < subQueryVal.Num) {
if !(dataVal.Num < sQueryVal.Num) {
result = false
}
return result

case "$gte":
if !(dataVal.Num >= subQueryVal.Num) {
if !(dataVal.Num >= sQueryVal.Num) {
result = false
}
return result

case "$lte":
if !(dataVal.Num <= subQueryVal.Num) {
if !(dataVal.Num <= sQueryVal.Num) {
result = false
}
return result

case "$eq":
if dataVal.Num != subQueryVal.Num {
if dataVal.Num != sQueryVal.Num {
result = false
}
return result

case "$ne":
if dataVal.Num == subQueryVal.Num {
if dataVal.Num == sQueryVal.Num {
result = false
}
return result

case "$in": // in array
for _, v := range subQueryVal.Array() {
//fmt.Println("subQueryVal", subQueryVal)
for _, v := range sQueryVal.Array() {
//fmt.Println("sQueryVal", sQueryVal)
if dataVal.Num == v.Num {
return result
}
Expand All @@ -217,7 +242,7 @@ func match(filter gjson.Result, data string) (result bool, err error) {
return result

case "$nin": // not in
for _, v := range subQueryVal.Array() {
for _, v := range sQueryVal.Array() {
if dataVal.Num == v.Num {
result = false
return result
Expand All @@ -228,8 +253,6 @@ func match(filter gjson.Result, data string) (result bool, err error) {
default:

// {$and:[{name:{$eq:"adam"}},{name:{$eq:"jawad"}}]}
// {$or: [{name:{$eq:"adam"}}, {name:{$eq:"jawad"}}]}

if queryKey.Str == "$and" {

for _, v := range queryVal.Array() {
Expand All @@ -242,6 +265,7 @@ func match(filter gjson.Result, data string) (result bool, err error) {
return result
}

// {$or: [{name:{$eq:"adam"}}, {name:{$eq:"jawad"}}]}
if queryKey.Str == "$or" {

for _, v := range queryVal.Array() {
Expand All @@ -255,7 +279,7 @@ func match(filter gjson.Result, data string) (result bool, err error) {
return result
}

err = fmt.Errorf("unknown %s operation", subQueryKey.Str)
err = fmt.Errorf("unknown %s operation", sQueryKey.Str)
result = false
return result
}
Expand All @@ -265,14 +289,14 @@ func match(filter gjson.Result, data string) (result bool, err error) {
return result
}

// when value of query is number {age: 10}
// if queryVal is number : {age: 10}
if queryVal.Type == 2 {
if queryVal.Num != dataVal.Num {
result = false
}
}

// when value of query is string : {name: "adam"}
// if queryVal is string : {name: "adam"}
if queryVal.Str != dataVal.Str {
result = false
}
Expand Down
9 changes: 5 additions & 4 deletions engine/queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,10 @@ func (db *DB) findMany(query gjson.Result) (res string) {
stmt := `select record from ` + coll

sub := query.Get("subQuery")
var ids []int64
if sub.Raw != "" {
ids, _ := getIds(sub)
stmt += ` where rowid in (` + ids + `);`
ids = getIds(sub)
//stmt += ` where rowid in (` + ids + `);`
//fmt.Println(stmt)
}

Expand Down Expand Up @@ -245,7 +246,7 @@ func (db *DB) findMany(query gjson.Result) (res string) {
return err.Error() // TODO standaring errors
}

ok, err := match(mtch, record)
ok, err := match(mtch, record, ids...)
if err != nil {
return err.Error()
}
Expand Down Expand Up @@ -357,7 +358,7 @@ func (db *DB) deleteOne(query gjson.Result) string {
// should close here
rows.Close()

_, err = db.db.Exec(`delete from ` + coll + ` where rowid = ` + rowid) // fast
_, err = db.db.Exec(`delete from ` + coll + ` where rowid = ` + rowid) // + is fast
if err != nil {
fmt.Println(err.Error())
return err.Error()
Expand Down

0 comments on commit bdc339d

Please sign in to comment.