Skip to content

Commit

Permalink
Record Route, Schema Validation Error and Record not found for Filter…
Browse files Browse the repository at this point in the history
… Error #162

Merge pull request #162 from TanmoySG/records-route

- closes #161 
- closes #159 
- closes #158
  • Loading branch information
TanmoySG authored Sep 24, 2024
2 parents 8ea9ba7 + 5f4e65b commit c170156
Show file tree
Hide file tree
Showing 10 changed files with 127 additions and 53 deletions.
12 changes: 6 additions & 6 deletions internal/filter/filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,19 @@ func Test_Filter(t *testing.T) {
"1": {
Identifier: "1",
Data: map[string]interface{}{
"filed": "val",
"field": "val",
"num": "1",
},
},
"2": {
Identifier: "1",
Identifier: "2",
Data: map[string]interface{}{
"field": "value",
"num": "2",
},
},
"3": {
Identifier: "1",
Identifier: "3",
Data: map[string]interface{}{
"field": "value",
"num": "3",
Expand All @@ -46,21 +46,21 @@ func Test_Filter(t *testing.T) {

expectedData := map[model.Identifier]*model.Record{
"2": {
Identifier: "1",
Identifier: "2",
Data: map[string]interface{}{
"field": "value",
"num": "2",
},
},
"3": {
Identifier: "1",
Identifier: "3",
Data: map[string]interface{}{
"field": "value",
"num": "3",
},
},
}

data := f.Filter("pkey", testData)
data := f.Filter("num", testData)
assert.Equal(t, &expectedData, &data)
}
20 changes: 11 additions & 9 deletions internal/filter/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,18 @@ func UseFilter(filter interface{}) (*Filter, *er.WdbError) {
return &dataFilter, nil
}

func filter(primaryKey model.Identifier, data map[model.Identifier]*model.Record, filter Filter, iterator func(model.Identifier, model.Record)) {
func filter(primaryKey model.Identifier, data map[model.Identifier]*model.Record, filter Filter, iterator func(*model.Identifier, *model.Record)) {
if filter.Key == "id" || filter.Key == primaryKey.String() {
// search with primaryKey/id
d, exists := data[model.Identifier(filter.Value.(string))]
if exists {
iterator(d.Identifier, *data[d.Identifier])
iterator(&d.Identifier, data[d.Identifier])
}
} else if filter.Key == "recordId" {
// search with recordId
for identifier, record := range data {
if record.RecordId.String() == filter.Value {
iterator(identifier, *record)
iterator(&identifier, record)
break
}
}
Expand All @@ -65,25 +65,27 @@ func filter(primaryKey model.Identifier, data map[model.Identifier]*model.Record
dataMap := record.DataMap()
if exists, _ := fieldExists(filter.Key, dataMap); exists {
if equal(dataMap[filter.Key], filter.Value) {
iterator(identifier, *record)
iterator(&identifier, record)
}
}
}
}
}

func (f Filter) Filter(primaryKey model.Identifier, data map[model.Identifier]*model.Record) map[model.Identifier]*model.Record {
func (f Filter) Filter(primaryKey model.Identifier, data map[model.Identifier]*model.Record) (map[model.Identifier]*model.Record) {
filteredData := make(map[model.Identifier]*model.Record)

filter(primaryKey, data, f, func(id model.Identifier, record model.Record) {
filteredData[id] = &record
filter(primaryKey, data, f, func(id *model.Identifier, record *model.Record) {
if id != nil && record != nil {
filteredData[*id] = record
}
})

return filteredData
}

func (f Filter) Iterate(primaryKey model.Identifier, data map[model.Identifier]*model.Record, iterator func(model.Identifier, model.Record)) {
filter(primaryKey, data, f, func(id model.Identifier, record model.Record) {
func (f Filter) Iterate(primaryKey model.Identifier, data map[model.Identifier]*model.Record, iterator func(*model.Identifier, *model.Record)) {
filter(primaryKey, data, f, func(id *model.Identifier, record *model.Record) {
iterator(id, record)
})
}
Expand Down
69 changes: 45 additions & 24 deletions internal/records/records.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,64 +76,85 @@ func (r Records) Read(filters interface{}) (map[model.Identifier]*model.Record,
}

filteredData := f.Filter(*r.PrimaryKey, r.Data)
if len(filteredData) == 0 {
return nil, &er.RecordDoesNotExistsError
}

return filteredData, nil
}

return r.Data, nil
}

func (r Records) Update(updatedData interface{}, filters interface{}) *er.WdbError {
var recordsCount int = 0
var f *filter.Filter
var err *er.WdbError

if filters == nil {
return &er.FilterMissingError

}

f, err := filter.UseFilter(filters)
f, err = filter.UseFilter(filters)
if err != nil {
return err
}

var iterError *er.WdbError

f.Iterate(*r.PrimaryKey, r.Data, func(identifier model.Identifier, dataRow model.Record) {

data, err := maps.Merge(maps.Marshal(updatedData), dataRow.DataMap())
if err != nil {
iterError = &er.DataEncodeDecodeError
} else {
schema, err := schema.UseSchema(r.Schema)

if err != nil {
iterError = err
f.Iterate(*r.PrimaryKey, r.Data, func(identifier *model.Identifier, dataRow *model.Record) {
if identifier != nil && dataRow != nil {
data, mergeErr := maps.Merge(maps.Marshal(updatedData), dataRow.DataMap())
if mergeErr != nil {
err = &er.DataEncodeDecodeError
} else {
isValid, err := schema.Validate(data)
if err == nil && isValid {
r.Data[identifier].Data = &data
r.Data[identifier].Metadata = metadata.Use(r.Data[identifier].Metadata).BasicChangeMetadata()
schema, schemaErr := schema.UseSchema(r.Schema)
if schemaErr != nil {
err = schemaErr
} else {
isValid, schemaErr := schema.Validate(data)
if schemaErr == nil && isValid {
r.Data[*identifier].Data = &data
r.Data[*identifier].Metadata = metadata.Use(r.Data[*identifier].Metadata).BasicChangeMetadata()
}
err = schemaErr
}
iterError = err
}
recordsCount++
}
})

if iterError != nil {
return iterError
if recordsCount == 0 && err == nil {
return &er.RecordDoesNotExistsError
}
return nil

return err
}

func (r Records) Delete(filters interface{}) *er.WdbError {
var recordsCount int = 0
var f *filter.Filter
var err *er.WdbError

if filters != nil {
f, err := filter.UseFilter(filters)
f, err = filter.UseFilter(filters)
if err != nil {
return err
}

f.Iterate(*r.PrimaryKey, r.Data, func(identifier model.Identifier, dataRow model.Record) {
delete(r.Data, identifier)
f.Iterate(*r.PrimaryKey, r.Data, func(identifier *model.Identifier, dataRow *model.Record) {
if identifier != nil {
delete(r.Data, *identifier)
recordsCount++
}
})

if recordsCount == 0 {
return &er.RecordDoesNotExistsError
}

return nil
}

return &er.FilterMissingError
}

Expand Down
40 changes: 31 additions & 9 deletions internal/server/handlers/records.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

const (
emptyFilter = ""
idKey = "id"
)

type queryRequest struct {
Expand Down Expand Up @@ -63,6 +64,8 @@ func (wh wdbHandlers) ReadRecords(c *fiber.Ctx) error {
databaseName := c.Params("database")
collectionName := c.Params("collection")

id := c.Params("id")

entities := model.Entities{
Databases: &databaseName,
Collections: &collectionName,
Expand All @@ -73,13 +76,18 @@ func (wh wdbHandlers) ReadRecords(c *fiber.Ctx) error {
apiError = error
} else {
filterKey, filterValue := c.Query("key"), c.Query("value")
if filterKey == emptyFilter || filterValue == emptyFilter {
filter = nil
} else {
if id != emptyFilter {
filter = map[string]interface{}{
"key": idKey,
"value": id,
}
} else if filterKey != emptyFilter || filterValue != emptyFilter {
filter = map[string]interface{}{
"key": filterKey,
"value": filterValue,
}
} else {
filter = nil
}

fetchedData, apiError = wh.wdbClient.GetRecords(model.Identifier(databaseName), model.Identifier(collectionName), filter)
Expand Down Expand Up @@ -151,6 +159,8 @@ func (wh wdbHandlers) DeleteRecords(c *fiber.Ctx) error {
databaseName := c.Params("database")
collectionName := c.Params("collection")

id := c.Params("id")

entities := model.Entities{
Databases: &databaseName,
Collections: &collectionName,
Expand All @@ -161,13 +171,18 @@ func (wh wdbHandlers) DeleteRecords(c *fiber.Ctx) error {
apiError = error
} else {
filterKey, filterValue := c.Query("key"), c.Query("value")
if filterKey == emptyFilter || filterValue == emptyFilter {
filter = nil
} else {
if id != emptyFilter {
filter = map[string]interface{}{
"key": idKey,
"value": id,
}
} else if filterKey != emptyFilter || filterValue != emptyFilter {
filter = map[string]interface{}{
"key": filterKey,
"value": filterValue,
}
} else {
filter = nil
}

apiError = wh.wdbClient.DeleteRecords(model.Identifier(databaseName), model.Identifier(collectionName), filter)
Expand All @@ -193,6 +208,8 @@ func (wh wdbHandlers) UpdateRecords(c *fiber.Ctx) error {
databaseName := c.Params("database")
collectionName := c.Params("collection")

id := c.Params("id")

entities := model.Entities{
Databases: &databaseName,
Collections: &collectionName,
Expand All @@ -208,13 +225,18 @@ func (wh wdbHandlers) UpdateRecords(c *fiber.Ctx) error {
}

filterKey, filterValue := c.Query("key"), c.Query("value")
if filterKey == emptyFilter || filterValue == emptyFilter {
filter = nil
} else {
if id != emptyFilter {
filter = map[string]interface{}{
"key": idKey,
"value": id,
}
} else if filterKey != emptyFilter || filterValue != emptyFilter {
filter = map[string]interface{}{
"key": filterKey,
"value": filterValue,
}
} else {
filter = nil
}

apiError = wh.wdbClient.UpdateRecords(model.Identifier(databaseName), model.Identifier(collectionName), incomingUpdatedData, filter)
Expand Down
7 changes: 6 additions & 1 deletion internal/server/routes/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,18 @@ const (
FetchCollection = "/databases/:database/collections/:collection"
DeleteCollection = "/databases/:database/collections/:collection"

// Data Routes
// Records Routes
AddRecords = "/databases/:database/collections/:collection/records"
ReadRecords = "/databases/:database/collections/:collection/records"
QueryRecords = "/databases/:database/collections/:collection/records/query" // route for executing jsonpath queries
DeleteRecords = "/databases/:database/collections/:collection/records"
UpdateRecords = "/databases/:database/collections/:collection/records"

// Record Routes
ReadRecord = "/databases/:database/collections/:collection/records/:id"
DeleteRecord = "/databases/:database/collections/:collection/records/:id"
UpdateRecord = "/databases/:database/collections/:collection/records/:id"

// Role Routes
CreateRole = "/roles"
ListRoles = "/roles"
Expand Down
7 changes: 6 additions & 1 deletion internal/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,18 @@ func (ws wdbServer) Start() {
api.Get(routes.FetchCollection, ws.handler.FetchCollection)
api.Delete(routes.DeleteCollection, ws.handler.DeleteCollection)

// Data Routes
// Records Routes
api.Post(routes.AddRecords, ws.handler.AddRecords)
api.Get(routes.ReadRecords, ws.handler.ReadRecords)
api.Post(routes.QueryRecords, ws.handler.QueryRecords)
api.Delete(routes.DeleteRecords, ws.handler.DeleteRecords)
api.Patch(routes.UpdateRecords, ws.handler.UpdateRecords)

// Record Routes
api.Get(routes.ReadRecord, ws.handler.ReadRecords)
api.Delete(routes.DeleteRecord, ws.handler.DeleteRecords)
api.Patch(routes.UpdateRecord, ws.handler.UpdateRecords)

// Role Routes
api.Post(routes.CreateRole, ws.handler.CreateRole)
api.Get(routes.ListRoles, ws.handler.ListRoles)
Expand Down
4 changes: 2 additions & 2 deletions internal/upgrades/steps/step_migrate_data_to_records.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ func MigrateDataToRecords(c config.Config) error {

for dbKey, db := range dbs {
if _, ok := db["collections"]; !ok {
return fmt.Errorf("no collections")
return fmt.Errorf("no collections found for database: %s", dbKey)
}

for cKey, collection := range db["collections"] {
if _, ok := collection.(map[string]interface{})["data"]; !ok {
fmt.Println("no data found")
fmt.Println("no data field found for collection: ", cKey)
continue
}

Expand Down
1 change: 1 addition & 0 deletions internal/upgrades/steps/steps.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func Run(c config.Config) error {
}

if constraints.Check(currentVersion) {
fmt.Println("Running Upgrades...")
return MigrateDataToRecords(c)
} else {
fmt.Println("No upgrades to run...")
Expand Down
Loading

0 comments on commit c170156

Please sign in to comment.