Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
718eecc
Add support for boolean token
sebastien-rosset Dec 13, 2017
cc9eb72
Fix geo.intersects typo
sebastien-rosset Feb 27, 2018
54f2547
Support 'in' operator
sebastien-rosset Feb 28, 2018
73a2317
Merge branch 'in_operator' of https://github.com/CiscoM31/godata
sebastien-rosset Feb 28, 2018
1d946b3
Add support for divby operator
sebastien-rosset Feb 28, 2018
a61b385
Add UT for div and divby
sebastien-rosset Feb 28, 2018
07038f5
Support ODATA 'in' operator. Add error validation for ODATA functions…
sebastien-rosset Mar 16, 2018
a1ba7cf
Fix precedence order between 'or' operator and lambda operator. Add u…
sebastien-rosset Mar 19, 2018
fdd223b
Do not crash if an operator does not have enough operands. Add unit t…
sebastien-rosset Mar 21, 2018
602f752
Add substringof function. “substring” function was incorrectly parsed…
sebastien-rosset Mar 21, 2018
98d1bd8
Add more math functions
sebastien-rosset Mar 21, 2018
84f0e7a
substring function can take 2 or 3 arguments
sebastien-rosset Mar 21, 2018
6086a06
Support isof function with one or two arguments. Add @ character for …
sebastien-rosset Mar 21, 2018
a4b4c89
Adding Raw Values of filter, select, orderby and search. These values…
parvathi-nair May 1, 2018
153a76a
Merge pull request #1 from CiscoM31/expandrawval
sebastien-rosset May 10, 2018
92474ba
Fix syntax error in UT
sebastien-rosset May 19, 2018
89be350
CSCvi45267 Add model to parse ?at as a filter
May 21, 2018
79e9a14
typo fix, from filter to at for At query
May 23, 2018
ebf64b7
Merge pull request #3 from CiscoM31/feature/config-changes
sebastien-rosset May 25, 2018
8dbb0d3
Add support for Duration token
sebastien-rosset Apr 1, 2019
869fc6a
Set 'Parent' field when converting from postfix notation to tree
sebastien-rosset Jun 21, 2019
ff9bf7d
Adding Exists Support as a Odata Function
parvathi-nair Oct 3, 2019
c2c4ebb
Merge pull request #5 from CiscoM31/intersight_exist_operator
parvathi-nair Oct 7, 2019
6585b72
Return error if query includes duplicate keywords or if query include…
sebastien-rosset Sep 14, 2020
a9652a2
Return error if query includes duplicate keywords or if query include…
sebastien-rosset Sep 14, 2020
d26d881
Return error if query includes duplicate keywords or if query include…
sebastien-rosset Sep 14, 2020
b55db48
Return error if query includes duplicate keywords or if query include…
sebastien-rosset Sep 14, 2020
15c16ad
Add support for lenient mode
sebastien-rosset Sep 22, 2020
d1e62ce
Merge pull request #6 from CiscoM31/lenient_parser_mode
sebastien-rosset Sep 23, 2020
25ec8b6
Add unit tests
sebastien-rosset Oct 2, 2020
55216cb
Add unit tests
sebastien-rosset Oct 2, 2020
3ff0116
Add unit tests to handle unknown operators
sebastien-rosset Oct 2, 2020
b5d1a8d
Add validation
sebastien-rosset Oct 3, 2020
3c3ed73
Add validation
sebastien-rosset Oct 3, 2020
b6f02db
Add validation
sebastien-rosset Oct 3, 2020
5491cbf
Add validation
sebastien-rosset Oct 3, 2020
eba9607
add go.yml
sebastien-rosset Oct 3, 2020
5f82076
add go.yml
sebastien-rosset Oct 3, 2020
eadcd34
Merge pull request #10 from CiscoM31/workflow-go
sebastien-rosset Oct 3, 2020
0880170
Merge branch 'master-intersight' of github.com:CiscoM31/godata into i…
sebastien-rosset Oct 3, 2020
f58ae1f
add unit tests
sebastien-rosset Oct 3, 2020
fbcb098
Add ODATA unit tests
sebastien-rosset Oct 5, 2020
c2edacd
Merge pull request #7 from CiscoM31/invalid_operators
sebastien-rosset Nov 18, 2020
d94189a
Add unit tests for any
sebastien-rosset Nov 18, 2020
34a885e
Add unit tests for any
sebastien-rosset Nov 18, 2020
85d85bc
Add unit tests for expand + select
sebastien-rosset Nov 19, 2020
b2a9c36
Add unit tests for expand + select
sebastien-rosset Nov 19, 2020
cdd6059
Add unit tests for expand + select
sebastien-rosset Nov 19, 2020
c2b0907
Add unit tests for expand + select
sebastien-rosset Nov 19, 2020
722d146
Merge pull request #12 from CiscoM31/select-expand
sebastien-rosset Nov 19, 2020
545ff4c
Add unit tests for expand + select
sebastien-rosset Nov 19, 2020
b9ecb8b
Merge pull request #13 from CiscoM31/select-expand
sebastien-rosset Nov 19, 2020
ad9ae3d
sync from master
sebastien-rosset Nov 19, 2020
5bae98b
add unit tests for
sebastien-rosset Nov 19, 2020
cb213c8
Merge pull request #14 from CiscoM31/add-odata-functions
sebastien-rosset Nov 19, 2020
1540579
Add ParseNode.String function
sebastien-rosset Nov 19, 2020
7595b56
Add ParseNode.String function
sebastien-rosset Nov 19, 2020
eb13379
Add more unit tests. Leniently allow space between logical operator a…
sebastien-rosset Nov 19, 2020
546ee6e
Merge pull request #15 from CiscoM31/tree-node-string
sebastien-rosset Nov 19, 2020
217eecc
refactor parser
sebastien-rosset Nov 24, 2020
0e6fc0d
Merge branch 'master-intersight' of github.com:CiscoM31/godata into t…
sebastien-rosset Nov 24, 2020
520f688
Support any lambda operator with zero argument
sebastien-rosset Nov 24, 2020
1bd919e
Add support for GUID and fix issues with duration type
sebastien-rosset Nov 24, 2020
f7164a8
Add support for GUID and fix issues with duration type
sebastien-rosset Nov 24, 2020
b713e5f
Add support for GUID and fix issues with duration type
sebastien-rosset Nov 24, 2020
5b634f2
Better tokenization for duration type
sebastien-rosset Nov 25, 2020
6c48657
Merge pull request #16 from CiscoM31/tree-node-string
sebastien-rosset Dec 1, 2020
be57a25
sync from master-intersight
sebastien-rosset Dec 1, 2020
6c33df2
Merge pull request #11 from CiscoM31/any-enhancements
sebastien-rosset Dec 1, 2020
814f285
add unit tests for multiple levels of nested properties
sebastien-rosset Dec 1, 2020
7dc4f38
Merge pull request #17 from CiscoM31/any-enhancements
sebastien-rosset Dec 1, 2020
3a55542
tree representation of any() and all() as a regular function
sebastien-rosset Dec 2, 2020
f609928
tree representation of any() and all() as a regular function
sebastien-rosset Dec 2, 2020
9da0c86
tree representation of any() and all() as a regular function
sebastien-rosset Dec 2, 2020
af08277
tree representation of any() and all() as a regular function
sebastien-rosset Dec 3, 2020
1244f1e
Add unit test
sebastien-rosset Dec 8, 2020
daef125
fix function argument count when argument starts with unary operator,…
sebastien-rosset Dec 8, 2020
bd97dcb
add code comments
sebastien-rosset Dec 9, 2020
2232b70
Merge pull request #18 from CiscoM31/any-enhancements
sebastien-rosset Dec 12, 2020
5a3448e
Create go.yml
sebastien-rosset Jun 18, 2021
8123113
Upgrade to go 1.16
sebastien-rosset Jun 18, 2021
cc7cb19
Merge branch 'master' into master-intersight
sebastien-rosset Jun 18, 2021
e0592d8
add go.mod
sebastien-rosset Jun 18, 2021
e0aa4ba
add action for master-intersight branch
sebastien-rosset Jun 18, 2021
43c0866
comment out code that does not compile
sebastien-rosset Jun 18, 2021
be2beeb
add code comments, fix code when there is an invalid filter syntax
sebastien-rosset Jun 18, 2021
ba5e374
Merge pull request #21 from CiscoM31/add-go-mod
sebastien-rosset Jun 18, 2021
96b471d
Merge pull request #20 from CiscoM31/master-intersight
sebastien-rosset Jun 18, 2021
1e58491
Merge pull request #22 from crestonbunch/master
sebastien-rosset Jun 18, 2021
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
26 changes: 26 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Go

on:
push:
branches: [ master ]
pull_request:
branches: [ master, master-intersight ]

jobs:

build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.16

- name: Build
run: go build -v ./...

- name: Test
run: go test -v ./...

42 changes: 35 additions & 7 deletions errors.go
Original file line number Diff line number Diff line change
@@ -1,38 +1,66 @@
package godata

import "fmt"

type GoDataError struct {
ResponseCode int
Message string
Cause error
}

func (err *GoDataError) Error() string {
return err.Message
}

func (err *GoDataError) Unwrap() error {
return err.Cause
}

func (err *GoDataError) SetCause(e error) *GoDataError {
err.Cause = e
return err
}

func BadRequestError(message string) *GoDataError {
return &GoDataError{400, message}
return &GoDataError{400, message, nil}
}

func NotFoundError(message string) *GoDataError {
return &GoDataError{404, message}
return &GoDataError{404, message, nil}
}

func MethodNotAllowedError(message string) *GoDataError {
return &GoDataError{405, message}
return &GoDataError{405, message, nil}
}

func GoneError(message string) *GoDataError {
return &GoDataError{410, message}
return &GoDataError{410, message, nil}
}

func PreconditionFailedError(message string) *GoDataError {
return &GoDataError{412, message}
return &GoDataError{412, message, nil}
}

func InternalServerError(message string) *GoDataError {
return &GoDataError{500, message}
return &GoDataError{500, message, nil}
}

func NotImplementedError(message string) *GoDataError {
return &GoDataError{501, message}
return &GoDataError{501, message, nil}
}

type UnsupportedQueryParameterError struct {
Parameter string
}

func (err *UnsupportedQueryParameterError) Error() string {
return fmt.Sprintf("Query parameter '%s' is not supported", err.Parameter)
}

type DuplicateQueryParameterError struct {
Parameter string
}

func (err *DuplicateQueryParameterError) Error() string {
return fmt.Sprintf("Query parameter '%s' cannot be specified more than once", err.Parameter)
}
108 changes: 56 additions & 52 deletions example/main.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package example

/*
import (
. "godata"
)
*/

func HelloWorld() {

Expand All @@ -17,58 +19,60 @@ func AuthorizationMiddleware() {
}

func main() {
provider := &MySQLGoDataProvider{
Hostname: "localhost",
Port: "3306",
Database: "Coffee",
Username: "dev",
Password: "dev",
}

roaster := provider.ExposeEntity("roaster", "Roaster")
roaster.ExposeKey("id", "RoasterID", GoDataInt32)
roaster.ExposePrimitive("name", "Name", GoDataString)
roaster.ExposePrimitive("location", "Location", GoDataString)
roaster.ExposePrimitive("website", "Website", GoDataString)
roasterSet := provider.ExposeEntitySet(roaster, "Roasters")

variety := provider.ExposeEntity("variety", "Variety")
variety.ExposeKey("id", "VarietyID", GoDataInt32)
variety.ExposePrimitive("name", "Name", GoDataString)
varietySet := provider.ExposeEntitySet(variety, "Varieties")

roastLevel := provider.ExposeEntity("roast_level", "RoastLevel")
roastLevel.ExposeKey("id", "RoastLevelID", GoDataInt32)
roastLevel.ExposePrimitive("order", "Order", GoDataInt32)
roastLevel.ExposePrimitive("name", "Name", GoDataString)
roastLevel.ExposePrimitive("qualifier", "Qualifier", GoDataString)
roastLevelSet := provider.ExposeEntitySet(roastLevel, "RoastLevels")

process := provider.ExposeEntity("process", "Process")
process.ExposeKey("id", "ProcessID", GoDataInt32)
process.ExposePrimitive("name", "Name", GoDataString)
processSet := provider.ExposeEntitySet(process, "Processes")

bean := provider.ExposeEntity("bean", "Bean")
bean.ExposeKey("id", "BeanID", GoDataInt32)
bean.ExposePrimitive("country", "Country", GoDataString)
bean.ExposePrimitive("region", "Region", GoDataString)
bean.ExposePrimitive("min_elevation", "MinElevation", GoDataInt32)
bean.ExposePrimitive("max_elevation", "MaxElevation", GoDataInt32)
beanSet := provider.ExposeEntitySet(bean, "Beans")

// map many beans to one roaster
provider.ExposeManyToOne(bean, roaster, "roaster_id", "Roaster", "Beans")
provider.ExposeManyToOne(bean, roastLevel, "roaster_level_id", "RoastLevel", "Beans")
provider.ExposeManyToOne(bean, process, "process_id", "Process", "Beans")
provider.ExposeManyToMany(bean, variety, "bean_variety_map", "Varieties", "Beans")
provider.BindProperty(beanSet, roasterSet, "Roaster", "Roaster", "Beans", "Beans")
provider.BindProperty(beanSet, roastLevelSet, "RoastLevel", "RoastLevel", "Beans", "Beans")
provider.BindProperty(beanSet, processSet, "Process", "Process", "Beans", "Beans")
provider.BindProperty(beanSet, varietySet, "Varieties", "Varieties", "Beans", "Beans")

service := BuildService(provider)
service.ListenAndServe(":8080", "http://localhost")
/*
provider := &MySQLGoDataProvider{
Hostname: "localhost",
Port: "3306",
Database: "Coffee",
Username: "dev",
Password: "dev",
}

roaster := provider.ExposeEntity("roaster", "Roaster")
roaster.ExposeKey("id", "RoasterID", GoDataInt32)
roaster.ExposePrimitive("name", "Name", GoDataString)
roaster.ExposePrimitive("location", "Location", GoDataString)
roaster.ExposePrimitive("website", "Website", GoDataString)
roasterSet := provider.ExposeEntitySet(roaster, "Roasters")

variety := provider.ExposeEntity("variety", "Variety")
variety.ExposeKey("id", "VarietyID", GoDataInt32)
variety.ExposePrimitive("name", "Name", GoDataString)
varietySet := provider.ExposeEntitySet(variety, "Varieties")

roastLevel := provider.ExposeEntity("roast_level", "RoastLevel")
roastLevel.ExposeKey("id", "RoastLevelID", GoDataInt32)
roastLevel.ExposePrimitive("order", "Order", GoDataInt32)
roastLevel.ExposePrimitive("name", "Name", GoDataString)
roastLevel.ExposePrimitive("qualifier", "Qualifier", GoDataString)
roastLevelSet := provider.ExposeEntitySet(roastLevel, "RoastLevels")

process := provider.ExposeEntity("process", "Process")
process.ExposeKey("id", "ProcessID", GoDataInt32)
process.ExposePrimitive("name", "Name", GoDataString)
processSet := provider.ExposeEntitySet(process, "Processes")

bean := provider.ExposeEntity("bean", "Bean")
bean.ExposeKey("id", "BeanID", GoDataInt32)
bean.ExposePrimitive("country", "Country", GoDataString)
bean.ExposePrimitive("region", "Region", GoDataString)
bean.ExposePrimitive("min_elevation", "MinElevation", GoDataInt32)
bean.ExposePrimitive("max_elevation", "MaxElevation", GoDataInt32)
beanSet := provider.ExposeEntitySet(bean, "Beans")

// map many beans to one roaster
provider.ExposeManyToOne(bean, roaster, "roaster_id", "Roaster", "Beans")
provider.ExposeManyToOne(bean, roastLevel, "roaster_level_id", "RoastLevel", "Beans")
provider.ExposeManyToOne(bean, process, "process_id", "Process", "Beans")
provider.ExposeManyToMany(bean, variety, "bean_variety_map", "Varieties", "Beans")
provider.BindProperty(beanSet, roasterSet, "Roaster", "Roaster", "Beans", "Beans")
provider.BindProperty(beanSet, roastLevelSet, "RoastLevel", "RoastLevel", "Beans", "Beans")
provider.BindProperty(beanSet, processSet, "Process", "Process", "Beans", "Beans")
provider.BindProperty(beanSet, varietySet, "Varieties", "Varieties", "Beans", "Beans")

service := BuildService(provider)
service.ListenAndServe(":8080", "http://localhost")
*/

//service.AttachMiddleware(CacheMiddleware)
//service.AttachMiddleware(AuthorizationMiddleware)
Expand Down
12 changes: 11 additions & 1 deletion expand_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ var GlobalExpandTokenizer = ExpandTokenizer()
type ExpandItem struct {
Path []*Token
Filter *GoDataFilterQuery
At *GoDataFilterQuery
Search *GoDataSearchQuery
OrderBy *GoDataOrderByQuery
Skip *GoDataSkipQuery
Expand Down Expand Up @@ -161,7 +162,7 @@ func ParseExpandOption(queue *tokenQueue, item *ExpandItem) error {
return BadRequestError("Invalid expand clause.")
}
queue.Dequeue() // drop the '=' from the front of the queue
body := queue.String()
body := queue.GetValue()

if head == "$filter" {
filter, err := ParseFilterString(body)
Expand All @@ -172,6 +173,15 @@ func ParseExpandOption(queue *tokenQueue, item *ExpandItem) error {
}
}

if head == "at" {
at, err := ParseFilterString(body)
if err == nil {
item.At = at
} else {
return err
}
}

if head == "$search" {
search, err := ParseSearchString(body)
if err == nil {
Expand Down
4 changes: 2 additions & 2 deletions expand_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,13 @@ func TestExpandNestedCommas(t *testing.T) {

if output.ExpandItems[0].Select.SelectItems[0].Segments[0].Value != "FirstName" {
actual := output.ExpandItems[0].Select.SelectItems[0].Segments[0]
t.Error("First select segment is '" + actual.Value + "' not 'FirstName'")
t.Error("First select segment is '" + actual.Value + "', expected 'FirstName'")
return
}

if output.ExpandItems[0].Select.SelectItems[1].Segments[0].Value != "LastName" {
actual := output.ExpandItems[0].Select.SelectItems[1].Segments[0]
t.Error("First select segment is '" + actual.Value + "' not 'LastName'")
t.Error("First select segment is '" + actual.Value + "', expected 'LastName'")
return
}

Expand Down
Loading