mirror of
https://github.com/pikami/cosmium.git
synced 2026-01-25 20:32:59 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4659d90a9 | ||
|
|
503e6bb8ad | ||
|
|
e5ddc143f0 | ||
|
|
66ea859f34 | ||
|
|
3584f9b5ce |
@@ -9,11 +9,6 @@ builds:
|
|||||||
- arm64
|
- arm64
|
||||||
env:
|
env:
|
||||||
- CGO_ENABLED=0
|
- CGO_ENABLED=0
|
||||||
ignore:
|
|
||||||
- goos: linux
|
|
||||||
goarch: arm64
|
|
||||||
- goos: windows
|
|
||||||
goarch: arm64
|
|
||||||
|
|
||||||
release:
|
release:
|
||||||
prerelease: auto
|
prerelease: auto
|
||||||
@@ -32,11 +27,14 @@ brews:
|
|||||||
email: git@pikami.org
|
email: git@pikami.org
|
||||||
|
|
||||||
dockers:
|
dockers:
|
||||||
- image_templates:
|
- id: docker-linux-amd64
|
||||||
- "ghcr.io/pikami/{{ .ProjectName }}:{{ .Version }}"
|
goos: linux
|
||||||
- "ghcr.io/pikami/{{ .ProjectName }}:latest"
|
goarch: amd64
|
||||||
|
image_templates:
|
||||||
|
- "ghcr.io/pikami/{{ .ProjectName }}:{{ .Version }}-amd64"
|
||||||
|
- "ghcr.io/pikami/{{ .ProjectName }}:latest-amd64"
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
use: docker
|
use: buildx
|
||||||
build_flag_templates:
|
build_flag_templates:
|
||||||
- "--platform=linux/amd64"
|
- "--platform=linux/amd64"
|
||||||
- "--pull"
|
- "--pull"
|
||||||
@@ -47,6 +45,38 @@ dockers:
|
|||||||
- "--label=org.opencontainers.image.created={{.Date}}"
|
- "--label=org.opencontainers.image.created={{.Date}}"
|
||||||
- "--label=org.opencontainers.image.revision={{.FullCommit}}"
|
- "--label=org.opencontainers.image.revision={{.FullCommit}}"
|
||||||
- "--label=org.opencontainers.image.version={{.Version}}"
|
- "--label=org.opencontainers.image.version={{.Version}}"
|
||||||
|
- id: docker-linux-arm64
|
||||||
|
goos: linux
|
||||||
|
goarch: arm64
|
||||||
|
image_templates:
|
||||||
|
- "ghcr.io/pikami/{{ .ProjectName }}:{{ .Version }}-arm64"
|
||||||
|
- "ghcr.io/pikami/{{ .ProjectName }}:latest-arm64"
|
||||||
|
- "ghcr.io/pikami/{{ .ProjectName }}:{{ .Version }}-arm64v8"
|
||||||
|
- "ghcr.io/pikami/{{ .ProjectName }}:latest-arm64v8"
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
use: buildx
|
||||||
|
build_flag_templates:
|
||||||
|
- "--platform=linux/arm64"
|
||||||
|
- "--pull"
|
||||||
|
- "--label=org.opencontainers.image.title={{.ProjectName}}"
|
||||||
|
- "--label=org.opencontainers.image.description=Lightweight Cosmos DB emulator"
|
||||||
|
- "--label=org.opencontainers.image.url=https://github.com/pikami/cosmium"
|
||||||
|
- "--label=org.opencontainers.image.source=https://github.com/pikami/cosmium"
|
||||||
|
- "--label=org.opencontainers.image.created={{.Date}}"
|
||||||
|
- "--label=org.opencontainers.image.revision={{.FullCommit}}"
|
||||||
|
- "--label=org.opencontainers.image.version={{.Version}}"
|
||||||
|
|
||||||
|
docker_manifests:
|
||||||
|
- name_template: 'ghcr.io/pikami/{{ .ProjectName }}:latest'
|
||||||
|
image_templates:
|
||||||
|
- "ghcr.io/pikami/{{ .ProjectName }}:latest-amd64"
|
||||||
|
- "ghcr.io/pikami/{{ .ProjectName }}:latest-arm64"
|
||||||
|
- "ghcr.io/pikami/{{ .ProjectName }}:latest-arm64v8"
|
||||||
|
- name_template: 'ghcr.io/pikami/{{ .ProjectName }}:{{ .Version }}'
|
||||||
|
image_templates:
|
||||||
|
- "ghcr.io/pikami/{{ .ProjectName }}:{{ .Version }}-amd64"
|
||||||
|
- "ghcr.io/pikami/{{ .ProjectName }}:{{ .Version }}-arm64"
|
||||||
|
- "ghcr.io/pikami/{{ .ProjectName }}:{{ .Version }}-arm64v8"
|
||||||
|
|
||||||
checksum:
|
checksum:
|
||||||
name_template: 'checksums.txt'
|
name_template: 'checksums.txt'
|
||||||
|
|||||||
@@ -8,5 +8,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func CosmiumExport(c *gin.Context) {
|
func CosmiumExport(c *gin.Context) {
|
||||||
c.IndentedJSON(http.StatusOK, repositories.GetState())
|
repositoryState, err := repositories.GetState()
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Data(http.StatusOK, "application/json", []byte(repositoryState))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||||
"github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos"
|
"github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos"
|
||||||
@@ -162,6 +164,56 @@ func Test_Documents(t *testing.T) {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("Should handle parallel writes", func(t *testing.T) {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
rutineCount := 100
|
||||||
|
results := make(chan error, rutineCount)
|
||||||
|
|
||||||
|
createCall := func(i int) {
|
||||||
|
defer wg.Done()
|
||||||
|
item := map[string]interface{}{
|
||||||
|
"id": fmt.Sprintf("id-%d", i),
|
||||||
|
"pk": fmt.Sprintf("pk-%d", i),
|
||||||
|
"val": i,
|
||||||
|
}
|
||||||
|
bytes, err := json.Marshal(item)
|
||||||
|
if err != nil {
|
||||||
|
results <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
_, err = collectionClient.CreateItem(
|
||||||
|
ctx,
|
||||||
|
azcosmos.PartitionKey{},
|
||||||
|
bytes,
|
||||||
|
&azcosmos.ItemOptions{
|
||||||
|
EnableContentResponseOnWrite: false,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
results <- err
|
||||||
|
|
||||||
|
collectionClient.ReadItem(ctx, azcosmos.PartitionKey{}, fmt.Sprintf("id-%d", i), nil)
|
||||||
|
collectionClient.DeleteItem(ctx, azcosmos.PartitionKey{}, fmt.Sprintf("id-%d", i), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < rutineCount; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go createCall(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
close(results)
|
||||||
|
|
||||||
|
for err := range results {
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error creating item: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Documents_Patch(t *testing.T) {
|
func Test_Documents_Patch(t *testing.T) {
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ Cosmium strives to support the core features of Cosmos DB, including:
|
|||||||
|
|
||||||
| Feature | Implemented |
|
| Feature | Implemented |
|
||||||
| ----------------------------- | ----------- |
|
| ----------------------------- | ----------- |
|
||||||
| Subqueries | No |
|
| Subqueries | Yes |
|
||||||
| Joins | No |
|
| Joins | Yes |
|
||||||
| Computed properties | No |
|
| Computed properties | No |
|
||||||
| Coalesce operators | No |
|
| Coalesce operators | No |
|
||||||
| Bitwise operators | No |
|
| Bitwise operators | No |
|
||||||
@@ -62,16 +62,18 @@ Cosmium strives to support the core features of Cosmos DB, including:
|
|||||||
|
|
||||||
### Array Functions
|
### Array Functions
|
||||||
|
|
||||||
| Function | Implemented |
|
| Function | Implemented |
|
||||||
| -------------- | ----------- |
|
| ------------------ | ----------- |
|
||||||
| ARRAY_CONCAT | Yes |
|
| ARRAY_CONCAT | Yes |
|
||||||
| ARRAY_CONTAINS | No |
|
| ARRAY_CONTAINS | No |
|
||||||
| ARRAY_LENGTH | Yes |
|
| ARRAY_CONTAINS_ANY | No |
|
||||||
| ARRAY_SLICE | Yes |
|
| ARRAY_CONTAINS_ALL | No |
|
||||||
| CHOOSE | No |
|
| ARRAY_LENGTH | Yes |
|
||||||
| ObjectToArray | No |
|
| ARRAY_SLICE | Yes |
|
||||||
| SetIntersect | Yes |
|
| CHOOSE | No |
|
||||||
| SetUnion | Yes |
|
| ObjectToArray | No |
|
||||||
|
| SetIntersect | Yes |
|
||||||
|
| SetUnion | Yes |
|
||||||
|
|
||||||
### Conditional Functions
|
### Conditional Functions
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func GetAllCollections(databaseId string) ([]repositorymodels.Collection, repositorymodels.RepositoryStatus) {
|
func GetAllCollections(databaseId string) ([]repositorymodels.Collection, repositorymodels.RepositoryStatus) {
|
||||||
|
storeState.RLock()
|
||||||
|
defer storeState.RUnlock()
|
||||||
|
|
||||||
if _, ok := storeState.Databases[databaseId]; !ok {
|
if _, ok := storeState.Databases[databaseId]; !ok {
|
||||||
return make([]repositorymodels.Collection, 0), repositorymodels.StatusNotFound
|
return make([]repositorymodels.Collection, 0), repositorymodels.StatusNotFound
|
||||||
}
|
}
|
||||||
@@ -20,6 +23,9 @@ func GetAllCollections(databaseId string) ([]repositorymodels.Collection, reposi
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetCollection(databaseId string, collectionId string) (repositorymodels.Collection, repositorymodels.RepositoryStatus) {
|
func GetCollection(databaseId string, collectionId string) (repositorymodels.Collection, repositorymodels.RepositoryStatus) {
|
||||||
|
storeState.RLock()
|
||||||
|
defer storeState.RUnlock()
|
||||||
|
|
||||||
if _, ok := storeState.Databases[databaseId]; !ok {
|
if _, ok := storeState.Databases[databaseId]; !ok {
|
||||||
return repositorymodels.Collection{}, repositorymodels.StatusNotFound
|
return repositorymodels.Collection{}, repositorymodels.StatusNotFound
|
||||||
}
|
}
|
||||||
@@ -32,6 +38,9 @@ func GetCollection(databaseId string, collectionId string) (repositorymodels.Col
|
|||||||
}
|
}
|
||||||
|
|
||||||
func DeleteCollection(databaseId string, collectionId string) repositorymodels.RepositoryStatus {
|
func DeleteCollection(databaseId string, collectionId string) repositorymodels.RepositoryStatus {
|
||||||
|
storeState.Lock()
|
||||||
|
defer storeState.Unlock()
|
||||||
|
|
||||||
if _, ok := storeState.Databases[databaseId]; !ok {
|
if _, ok := storeState.Databases[databaseId]; !ok {
|
||||||
return repositorymodels.StatusNotFound
|
return repositorymodels.StatusNotFound
|
||||||
}
|
}
|
||||||
@@ -46,6 +55,9 @@ func DeleteCollection(databaseId string, collectionId string) repositorymodels.R
|
|||||||
}
|
}
|
||||||
|
|
||||||
func CreateCollection(databaseId string, newCollection repositorymodels.Collection) (repositorymodels.Collection, repositorymodels.RepositoryStatus) {
|
func CreateCollection(databaseId string, newCollection repositorymodels.Collection) (repositorymodels.Collection, repositorymodels.RepositoryStatus) {
|
||||||
|
storeState.Lock()
|
||||||
|
defer storeState.Unlock()
|
||||||
|
|
||||||
var ok bool
|
var ok bool
|
||||||
var database repositorymodels.Database
|
var database repositorymodels.Database
|
||||||
if database, ok = storeState.Databases[databaseId]; !ok {
|
if database, ok = storeState.Databases[databaseId]; !ok {
|
||||||
|
|||||||
@@ -11,10 +11,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func GetAllDatabases() ([]repositorymodels.Database, repositorymodels.RepositoryStatus) {
|
func GetAllDatabases() ([]repositorymodels.Database, repositorymodels.RepositoryStatus) {
|
||||||
|
storeState.RLock()
|
||||||
|
defer storeState.RUnlock()
|
||||||
|
|
||||||
return maps.Values(storeState.Databases), repositorymodels.StatusOk
|
return maps.Values(storeState.Databases), repositorymodels.StatusOk
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDatabase(id string) (repositorymodels.Database, repositorymodels.RepositoryStatus) {
|
func GetDatabase(id string) (repositorymodels.Database, repositorymodels.RepositoryStatus) {
|
||||||
|
storeState.RLock()
|
||||||
|
defer storeState.RUnlock()
|
||||||
|
|
||||||
if database, ok := storeState.Databases[id]; ok {
|
if database, ok := storeState.Databases[id]; ok {
|
||||||
return database, repositorymodels.StatusOk
|
return database, repositorymodels.StatusOk
|
||||||
}
|
}
|
||||||
@@ -23,6 +29,9 @@ func GetDatabase(id string) (repositorymodels.Database, repositorymodels.Reposit
|
|||||||
}
|
}
|
||||||
|
|
||||||
func DeleteDatabase(id string) repositorymodels.RepositoryStatus {
|
func DeleteDatabase(id string) repositorymodels.RepositoryStatus {
|
||||||
|
storeState.Lock()
|
||||||
|
defer storeState.Unlock()
|
||||||
|
|
||||||
if _, ok := storeState.Databases[id]; !ok {
|
if _, ok := storeState.Databases[id]; !ok {
|
||||||
return repositorymodels.StatusNotFound
|
return repositorymodels.StatusNotFound
|
||||||
}
|
}
|
||||||
@@ -33,6 +42,9 @@ func DeleteDatabase(id string) repositorymodels.RepositoryStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func CreateDatabase(newDatabase repositorymodels.Database) (repositorymodels.Database, repositorymodels.RepositoryStatus) {
|
func CreateDatabase(newDatabase repositorymodels.Database) (repositorymodels.Database, repositorymodels.RepositoryStatus) {
|
||||||
|
storeState.Lock()
|
||||||
|
defer storeState.Unlock()
|
||||||
|
|
||||||
if _, ok := storeState.Databases[newDatabase.ID]; ok {
|
if _, ok := storeState.Databases[newDatabase.ID]; ok {
|
||||||
return repositorymodels.Database{}, repositorymodels.Conflict
|
return repositorymodels.Database{}, repositorymodels.Conflict
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func GetAllDocuments(databaseId string, collectionId string) ([]repositorymodels.Document, repositorymodels.RepositoryStatus) {
|
func GetAllDocuments(databaseId string, collectionId string) ([]repositorymodels.Document, repositorymodels.RepositoryStatus) {
|
||||||
|
storeState.RLock()
|
||||||
|
defer storeState.RUnlock()
|
||||||
|
|
||||||
if _, ok := storeState.Databases[databaseId]; !ok {
|
if _, ok := storeState.Databases[databaseId]; !ok {
|
||||||
return make([]repositorymodels.Document, 0), repositorymodels.StatusNotFound
|
return make([]repositorymodels.Document, 0), repositorymodels.StatusNotFound
|
||||||
}
|
}
|
||||||
@@ -27,6 +30,9 @@ func GetAllDocuments(databaseId string, collectionId string) ([]repositorymodels
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetDocument(databaseId string, collectionId string, documentId string) (repositorymodels.Document, repositorymodels.RepositoryStatus) {
|
func GetDocument(databaseId string, collectionId string, documentId string) (repositorymodels.Document, repositorymodels.RepositoryStatus) {
|
||||||
|
storeState.RLock()
|
||||||
|
defer storeState.RUnlock()
|
||||||
|
|
||||||
if _, ok := storeState.Databases[databaseId]; !ok {
|
if _, ok := storeState.Databases[databaseId]; !ok {
|
||||||
return repositorymodels.Document{}, repositorymodels.StatusNotFound
|
return repositorymodels.Document{}, repositorymodels.StatusNotFound
|
||||||
}
|
}
|
||||||
@@ -43,6 +49,9 @@ func GetDocument(databaseId string, collectionId string, documentId string) (rep
|
|||||||
}
|
}
|
||||||
|
|
||||||
func DeleteDocument(databaseId string, collectionId string, documentId string) repositorymodels.RepositoryStatus {
|
func DeleteDocument(databaseId string, collectionId string, documentId string) repositorymodels.RepositoryStatus {
|
||||||
|
storeState.Lock()
|
||||||
|
defer storeState.Unlock()
|
||||||
|
|
||||||
if _, ok := storeState.Databases[databaseId]; !ok {
|
if _, ok := storeState.Databases[databaseId]; !ok {
|
||||||
return repositorymodels.StatusNotFound
|
return repositorymodels.StatusNotFound
|
||||||
}
|
}
|
||||||
@@ -61,6 +70,9 @@ func DeleteDocument(databaseId string, collectionId string, documentId string) r
|
|||||||
}
|
}
|
||||||
|
|
||||||
func CreateDocument(databaseId string, collectionId string, document map[string]interface{}) (repositorymodels.Document, repositorymodels.RepositoryStatus) {
|
func CreateDocument(databaseId string, collectionId string, document map[string]interface{}) (repositorymodels.Document, repositorymodels.RepositoryStatus) {
|
||||||
|
storeState.Lock()
|
||||||
|
defer storeState.Unlock()
|
||||||
|
|
||||||
var ok bool
|
var ok bool
|
||||||
var documentId string
|
var documentId string
|
||||||
var database repositorymodels.Database
|
var database repositorymodels.Database
|
||||||
@@ -111,7 +123,7 @@ func ExecuteQueryDocuments(databaseId string, collectionId string, query string,
|
|||||||
|
|
||||||
if typedQuery, ok := parsedQuery.(parsers.SelectStmt); ok {
|
if typedQuery, ok := parsedQuery.(parsers.SelectStmt); ok {
|
||||||
typedQuery.Parameters = queryParameters
|
typedQuery.Parameters = queryParameters
|
||||||
return memoryexecutor.Execute(typedQuery, covDocs), repositorymodels.StatusOk
|
return memoryexecutor.ExecuteQuery(typedQuery, covDocs), repositorymodels.StatusOk
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, repositorymodels.BadRequest
|
return nil, repositorymodels.BadRequest
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ import (
|
|||||||
|
|
||||||
// I have no idea what this is tbh
|
// I have no idea what this is tbh
|
||||||
func GetPartitionKeyRanges(databaseId string, collectionId string) ([]repositorymodels.PartitionKeyRange, repositorymodels.RepositoryStatus) {
|
func GetPartitionKeyRanges(databaseId string, collectionId string) ([]repositorymodels.PartitionKeyRange, repositorymodels.RepositoryStatus) {
|
||||||
|
storeState.RLock()
|
||||||
|
defer storeState.RUnlock()
|
||||||
|
|
||||||
databaseRid := databaseId
|
databaseRid := databaseId
|
||||||
collectionRid := collectionId
|
collectionRid := collectionId
|
||||||
var timestamp int64 = 0
|
var timestamp int64 = 0
|
||||||
|
|||||||
@@ -66,6 +66,9 @@ func LoadStateFS(filePath string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func SaveStateFS(filePath string) {
|
func SaveStateFS(filePath string) {
|
||||||
|
storeState.RLock()
|
||||||
|
defer storeState.RUnlock()
|
||||||
|
|
||||||
data, err := json.MarshalIndent(storeState, "", "\t")
|
data, err := json.MarshalIndent(storeState, "", "\t")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("Failed to save state: %v\n", err)
|
logger.Errorf("Failed to save state: %v\n", err)
|
||||||
@@ -80,8 +83,17 @@ func SaveStateFS(filePath string) {
|
|||||||
logger.Infof("Documents: %d\n", getLength(storeState.Documents))
|
logger.Infof("Documents: %d\n", getLength(storeState.Documents))
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetState() repositorymodels.State {
|
func GetState() (string, error) {
|
||||||
return storeState
|
storeState.RLock()
|
||||||
|
defer storeState.RUnlock()
|
||||||
|
|
||||||
|
data, err := json.MarshalIndent(storeState, "", "\t")
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("Failed to serialize state: %v\n", err)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(data), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getLength(v interface{}) int {
|
func getLength(v interface{}) int {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package repositorymodels
|
package repositorymodels
|
||||||
|
|
||||||
|
import "sync"
|
||||||
|
|
||||||
type Database struct {
|
type Database struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
TimeStamp int64 `json:"_ts"`
|
TimeStamp int64 `json:"_ts"`
|
||||||
@@ -101,6 +103,8 @@ type PartitionKeyRange struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type State struct {
|
type State struct {
|
||||||
|
sync.RWMutex
|
||||||
|
|
||||||
// Map databaseId -> Database
|
// Map databaseId -> Database
|
||||||
Databases map[string]Database `json:"databases"`
|
Databases map[string]Database `json:"databases"`
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ type SelectStmt struct {
|
|||||||
Table Table
|
Table Table
|
||||||
JoinItems []JoinItem
|
JoinItems []JoinItem
|
||||||
Filters interface{}
|
Filters interface{}
|
||||||
|
Exists bool
|
||||||
Distinct bool
|
Distinct bool
|
||||||
Count int
|
Count int
|
||||||
Offset int
|
Offset int
|
||||||
@@ -14,7 +15,8 @@ type SelectStmt struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Table struct {
|
type Table struct {
|
||||||
Value string
|
Value string
|
||||||
|
SelectItem SelectItem
|
||||||
}
|
}
|
||||||
|
|
||||||
type JoinItem struct {
|
type JoinItem struct {
|
||||||
@@ -30,6 +32,7 @@ const (
|
|||||||
SelectItemTypeArray
|
SelectItemTypeArray
|
||||||
SelectItemTypeConstant
|
SelectItemTypeConstant
|
||||||
SelectItemTypeFunctionCall
|
SelectItemTypeFunctionCall
|
||||||
|
SelectItemTypeSubQuery
|
||||||
)
|
)
|
||||||
|
|
||||||
type SelectItem struct {
|
type SelectItem struct {
|
||||||
|
|||||||
@@ -122,4 +122,25 @@ func Test_Parse(t *testing.T) {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("Should parse IN selector", func(t *testing.T) {
|
||||||
|
testQueryParse(
|
||||||
|
t,
|
||||||
|
`SELECT c.id FROM c IN c.tags`,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{
|
||||||
|
Path: []string{"c", "id"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{
|
||||||
|
Value: "c",
|
||||||
|
SelectItem: parsers.SelectItem{
|
||||||
|
Path: []string{"c", "tags"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -4,16 +4,19 @@ package nosql
|
|||||||
import "github.com/pikami/cosmium/parsers"
|
import "github.com/pikami/cosmium/parsers"
|
||||||
|
|
||||||
func makeSelectStmt(
|
func makeSelectStmt(
|
||||||
columns, table, joinItems,
|
columns, fromClause, joinItems,
|
||||||
whereClause interface{}, distinctClause interface{},
|
whereClause interface{}, distinctClause interface{},
|
||||||
count interface{}, groupByClause interface{}, orderList interface{},
|
count interface{}, groupByClause interface{}, orderList interface{},
|
||||||
offsetClause interface{},
|
offsetClause interface{},
|
||||||
) (parsers.SelectStmt, error) {
|
) (parsers.SelectStmt, error) {
|
||||||
selectStmt := parsers.SelectStmt{
|
selectStmt := parsers.SelectStmt{
|
||||||
SelectItems: columns.([]parsers.SelectItem),
|
SelectItems: columns.([]parsers.SelectItem),
|
||||||
Table: table.(parsers.Table),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if fromTable, ok := fromClause.(parsers.Table); ok {
|
||||||
|
selectStmt.Table = fromTable
|
||||||
|
}
|
||||||
|
|
||||||
if joinItemsArray, ok := joinItems.([]interface{}); ok && len(joinItemsArray) > 0 {
|
if joinItemsArray, ok := joinItems.([]interface{}); ok && len(joinItemsArray) > 0 {
|
||||||
selectStmt.JoinItems = make([]parsers.JoinItem, len(joinItemsArray))
|
selectStmt.JoinItems = make([]parsers.JoinItem, len(joinItemsArray))
|
||||||
for i, joinItem := range joinItemsArray {
|
for i, joinItem := range joinItemsArray {
|
||||||
@@ -56,10 +59,18 @@ func makeSelectStmt(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func makeJoin(table interface{}, column interface{}) (parsers.JoinItem, error) {
|
func makeJoin(table interface{}, column interface{}) (parsers.JoinItem, error) {
|
||||||
return parsers.JoinItem{
|
joinItem := parsers.JoinItem{}
|
||||||
Table: table.(parsers.Table),
|
|
||||||
SelectItem: column.(parsers.SelectItem),
|
if selectItem, isSelectItem := column.(parsers.SelectItem); isSelectItem {
|
||||||
}, nil
|
joinItem.SelectItem = selectItem
|
||||||
|
joinItem.Table.Value = selectItem.Alias
|
||||||
|
}
|
||||||
|
|
||||||
|
if tableTyped, isTable := table.(parsers.Table); isTable {
|
||||||
|
joinItem.Table = tableTyped
|
||||||
|
}
|
||||||
|
|
||||||
|
return joinItem, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeSelectItem(name interface{}, path interface{}, selectItemType parsers.SelectItemType) (parsers.SelectItem, error) {
|
func makeSelectItem(name interface{}, path interface{}, selectItemType parsers.SelectItemType) (parsers.SelectItem, error) {
|
||||||
@@ -177,13 +188,13 @@ SelectStmt <- Select ws
|
|||||||
distinctClause:DistinctClause? ws
|
distinctClause:DistinctClause? ws
|
||||||
topClause:TopClause? ws
|
topClause:TopClause? ws
|
||||||
columns:Selection ws
|
columns:Selection ws
|
||||||
From ws table:TableName ws
|
fromClause:FromClause? ws
|
||||||
joinClauses:JoinClause* ws
|
joinClauses:(ws join:JoinClause { return join, nil })* ws
|
||||||
whereClause:(ws Where ws condition:Condition { return condition, nil })?
|
whereClause:(ws Where ws condition:Condition { return condition, nil })?
|
||||||
groupByClause:(ws GroupBy ws columns:ColumnList { return columns, nil })?
|
groupByClause:(ws GroupBy ws columns:ColumnList { return columns, nil })?
|
||||||
orderByClause:OrderByClause?
|
orderByClause:(ws order:OrderByClause { return order, nil })?
|
||||||
offsetClause:OffsetClause? {
|
offsetClause:(ws offset:OffsetClause { return offset, nil })? {
|
||||||
return makeSelectStmt(columns, table, joinClauses, whereClause,
|
return makeSelectStmt(columns, fromClause, joinClauses, whereClause,
|
||||||
distinctClause, topClause, groupByClause, orderByClause, offsetClause)
|
distinctClause, topClause, groupByClause, orderByClause, offsetClause)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,8 +204,49 @@ TopClause <- Top ws count:Integer {
|
|||||||
return count, nil
|
return count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FromClause <- From ws table:TableName selectItem:(ws "IN"i ws column:SelectItem { return column, nil })? {
|
||||||
|
tableTyped := table.(parsers.Table)
|
||||||
|
|
||||||
|
if selectItem != nil {
|
||||||
|
tableTyped.SelectItem = selectItem.(parsers.SelectItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tableTyped, nil
|
||||||
|
} / From ws subQuery:SubQuerySelectItem {
|
||||||
|
subQueryTyped := subQuery.(parsers.SelectItem)
|
||||||
|
table := parsers.Table{
|
||||||
|
Value: subQueryTyped.Alias,
|
||||||
|
SelectItem: subQueryTyped,
|
||||||
|
}
|
||||||
|
return table, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
SubQuery <- exists:(exists:Exists ws { return exists, nil })? "(" ws selectStmt:SelectStmt ws ")" {
|
||||||
|
if selectStatement, isGoodValue := selectStmt.(parsers.SelectStmt); isGoodValue {
|
||||||
|
selectStatement.Exists = exists != nil
|
||||||
|
return selectStatement, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return selectStmt, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
SubQuerySelectItem <- subQuery:SubQuery asClause:(ws alias:AsClause { return alias, nil })? {
|
||||||
|
selectItem := parsers.SelectItem{
|
||||||
|
Type: parsers.SelectItemTypeSubQuery,
|
||||||
|
Value: subQuery,
|
||||||
|
}
|
||||||
|
|
||||||
|
if tableName, isString := asClause.(string); isString {
|
||||||
|
selectItem.Alias = tableName
|
||||||
|
}
|
||||||
|
|
||||||
|
return selectItem, nil
|
||||||
|
}
|
||||||
|
|
||||||
JoinClause <- Join ws table:TableName ws "IN"i ws column:SelectItem {
|
JoinClause <- Join ws table:TableName ws "IN"i ws column:SelectItem {
|
||||||
return makeJoin(table, column)
|
return makeJoin(table, column)
|
||||||
|
} / Join ws subQuery:SubQuerySelectItem {
|
||||||
|
return makeJoin(nil, subQuery)
|
||||||
}
|
}
|
||||||
|
|
||||||
OffsetClause <- "OFFSET"i ws offset:IntegerLiteral ws "LIMIT"i ws limit:IntegerLiteral {
|
OffsetClause <- "OFFSET"i ws offset:IntegerLiteral ws "LIMIT"i ws limit:IntegerLiteral {
|
||||||
@@ -241,7 +293,7 @@ SelectProperty <- name:Identifier path:(DotFieldAccess / ArrayFieldAccess)* {
|
|||||||
return makeSelectItem(name, path, parsers.SelectItemTypeField)
|
return makeSelectItem(name, path, parsers.SelectItemTypeField)
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectItem <- selectItem:(Literal / FunctionCall / SelectArray / SelectObject / SelectProperty) asClause:AsClause? {
|
SelectItem <- selectItem:(SubQuerySelectItem / Literal / FunctionCall / SelectArray / SelectObject / SelectProperty) asClause:AsClause? {
|
||||||
var itemResult parsers.SelectItem
|
var itemResult parsers.SelectItem
|
||||||
switch typedValue := selectItem.(type) {
|
switch typedValue := selectItem.(type) {
|
||||||
case parsers.SelectItem:
|
case parsers.SelectItem:
|
||||||
@@ -322,11 +374,13 @@ From <- "FROM"i
|
|||||||
|
|
||||||
Join <- "JOIN"i
|
Join <- "JOIN"i
|
||||||
|
|
||||||
|
Exists <- "EXISTS"i
|
||||||
|
|
||||||
Where <- "WHERE"i
|
Where <- "WHERE"i
|
||||||
|
|
||||||
And <- "AND"i
|
And <- "AND"i
|
||||||
|
|
||||||
Or <- "OR"i
|
Or <- "OR"i wss
|
||||||
|
|
||||||
GroupBy <- "GROUP"i ws "BY"i
|
GroupBy <- "GROUP"i ws "BY"i
|
||||||
|
|
||||||
@@ -677,4 +731,6 @@ non_escape_character <- !(escape_character) char:.
|
|||||||
|
|
||||||
ws <- [ \t\n\r]*
|
ws <- [ \t\n\r]*
|
||||||
|
|
||||||
|
wss <- [ \t\n\r]+
|
||||||
|
|
||||||
EOF <- !.
|
EOF <- !.
|
||||||
|
|||||||
125
parsers/nosql/subquery_test.go
Normal file
125
parsers/nosql/subquery_test.go
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
package nosql_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/pikami/cosmium/parsers"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Parse_SubQuery(t *testing.T) {
|
||||||
|
|
||||||
|
t.Run("Should parse FROM subquery", func(t *testing.T) {
|
||||||
|
testQueryParse(
|
||||||
|
t,
|
||||||
|
`SELECT c.id FROM (SELECT VALUE cc["info"] FROM cc) AS c`,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{Path: []string{"c", "id"}},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{
|
||||||
|
Value: "c",
|
||||||
|
SelectItem: parsers.SelectItem{
|
||||||
|
Alias: "c",
|
||||||
|
Type: parsers.SelectItemTypeSubQuery,
|
||||||
|
Value: parsers.SelectStmt{
|
||||||
|
Table: parsers.Table{Value: "cc"},
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{Path: []string{"cc", "info"}, IsTopLevel: true},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should parse JOIN subquery", func(t *testing.T) {
|
||||||
|
testQueryParse(
|
||||||
|
t,
|
||||||
|
`SELECT c.id, cc.name FROM c JOIN (SELECT tag.name FROM tag IN c.tags) AS cc`,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{Path: []string{"c", "id"}},
|
||||||
|
{Path: []string{"cc", "name"}},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{
|
||||||
|
Value: "c",
|
||||||
|
},
|
||||||
|
JoinItems: []parsers.JoinItem{
|
||||||
|
{
|
||||||
|
Table: parsers.Table{
|
||||||
|
Value: "cc",
|
||||||
|
},
|
||||||
|
SelectItem: parsers.SelectItem{
|
||||||
|
Alias: "cc",
|
||||||
|
Type: parsers.SelectItemTypeSubQuery,
|
||||||
|
Value: parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{Path: []string{"tag", "name"}},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{
|
||||||
|
Value: "tag",
|
||||||
|
SelectItem: parsers.SelectItem{
|
||||||
|
Path: []string{"c", "tags"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should parse JOIN EXISTS subquery", func(t *testing.T) {
|
||||||
|
testQueryParse(
|
||||||
|
t,
|
||||||
|
`SELECT c.id
|
||||||
|
FROM c
|
||||||
|
JOIN (
|
||||||
|
SELECT VALUE EXISTS(SELECT tag.name FROM tag IN c.tags)
|
||||||
|
) AS hasTags
|
||||||
|
WHERE hasTags`,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{Path: []string{"c", "id"}},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{
|
||||||
|
Value: "c",
|
||||||
|
},
|
||||||
|
JoinItems: []parsers.JoinItem{
|
||||||
|
{
|
||||||
|
Table: parsers.Table{Value: "hasTags"},
|
||||||
|
SelectItem: parsers.SelectItem{
|
||||||
|
Alias: "hasTags",
|
||||||
|
Type: parsers.SelectItemTypeSubQuery,
|
||||||
|
Value: parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{
|
||||||
|
IsTopLevel: true,
|
||||||
|
Type: parsers.SelectItemTypeSubQuery,
|
||||||
|
Value: parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{Path: []string{"tag", "name"}},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{
|
||||||
|
Value: "tag",
|
||||||
|
SelectItem: parsers.SelectItem{
|
||||||
|
Path: []string{"c", "tags"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Exists: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Filters: parsers.SelectItem{
|
||||||
|
Path: []string{"hasTags"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -6,21 +6,19 @@ import (
|
|||||||
"github.com/pikami/cosmium/parsers"
|
"github.com/pikami/cosmium/parsers"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c memoryExecutorContext) aggregate_Avg(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) aggregate_Avg(arguments []interface{}) interface{} {
|
||||||
selectExpression := arguments[0].(parsers.SelectItem)
|
selectExpression := arguments[0].(parsers.SelectItem)
|
||||||
sum := 0.0
|
sum := 0.0
|
||||||
count := 0
|
count := 0
|
||||||
|
|
||||||
if array, isArray := row.([]RowWithJoins); isArray {
|
for _, item := range r.grouppedRows {
|
||||||
for _, item := range array {
|
value := item.resolveSelectItem(selectExpression)
|
||||||
value := c.getFieldValue(selectExpression, item)
|
if numericValue, ok := value.(float64); ok {
|
||||||
if numericValue, ok := value.(float64); ok {
|
sum += numericValue
|
||||||
sum += numericValue
|
count++
|
||||||
count++
|
} else if numericValue, ok := value.(int); ok {
|
||||||
} else if numericValue, ok := value.(int); ok {
|
sum += float64(numericValue)
|
||||||
sum += float64(numericValue)
|
count++
|
||||||
count++
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,41 +29,37 @@ func (c memoryExecutorContext) aggregate_Avg(arguments []interface{}, row RowTyp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) aggregate_Count(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) aggregate_Count(arguments []interface{}) interface{} {
|
||||||
selectExpression := arguments[0].(parsers.SelectItem)
|
selectExpression := arguments[0].(parsers.SelectItem)
|
||||||
count := 0
|
count := 0
|
||||||
|
|
||||||
if array, isArray := row.([]RowWithJoins); isArray {
|
for _, item := range r.grouppedRows {
|
||||||
for _, item := range array {
|
value := item.resolveSelectItem(selectExpression)
|
||||||
value := c.getFieldValue(selectExpression, item)
|
if value != nil {
|
||||||
if value != nil {
|
count++
|
||||||
count++
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) aggregate_Max(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) aggregate_Max(arguments []interface{}) interface{} {
|
||||||
selectExpression := arguments[0].(parsers.SelectItem)
|
selectExpression := arguments[0].(parsers.SelectItem)
|
||||||
max := 0.0
|
max := 0.0
|
||||||
count := 0
|
count := 0
|
||||||
|
|
||||||
if array, isArray := row.([]RowWithJoins); isArray {
|
for _, item := range r.grouppedRows {
|
||||||
for _, item := range array {
|
value := item.resolveSelectItem(selectExpression)
|
||||||
value := c.getFieldValue(selectExpression, item)
|
if numericValue, ok := value.(float64); ok {
|
||||||
if numericValue, ok := value.(float64); ok {
|
if numericValue > max {
|
||||||
if numericValue > max {
|
max = numericValue
|
||||||
max = numericValue
|
|
||||||
}
|
|
||||||
count++
|
|
||||||
} else if numericValue, ok := value.(int); ok {
|
|
||||||
if float64(numericValue) > max {
|
|
||||||
max = float64(numericValue)
|
|
||||||
}
|
|
||||||
count++
|
|
||||||
}
|
}
|
||||||
|
count++
|
||||||
|
} else if numericValue, ok := value.(int); ok {
|
||||||
|
if float64(numericValue) > max {
|
||||||
|
max = float64(numericValue)
|
||||||
|
}
|
||||||
|
count++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,25 +70,23 @@ func (c memoryExecutorContext) aggregate_Max(arguments []interface{}, row RowTyp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) aggregate_Min(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) aggregate_Min(arguments []interface{}) interface{} {
|
||||||
selectExpression := arguments[0].(parsers.SelectItem)
|
selectExpression := arguments[0].(parsers.SelectItem)
|
||||||
min := math.MaxFloat64
|
min := math.MaxFloat64
|
||||||
count := 0
|
count := 0
|
||||||
|
|
||||||
if array, isArray := row.([]RowWithJoins); isArray {
|
for _, item := range r.grouppedRows {
|
||||||
for _, item := range array {
|
value := item.resolveSelectItem(selectExpression)
|
||||||
value := c.getFieldValue(selectExpression, item)
|
if numericValue, ok := value.(float64); ok {
|
||||||
if numericValue, ok := value.(float64); ok {
|
if numericValue < min {
|
||||||
if numericValue < min {
|
min = numericValue
|
||||||
min = numericValue
|
|
||||||
}
|
|
||||||
count++
|
|
||||||
} else if numericValue, ok := value.(int); ok {
|
|
||||||
if float64(numericValue) < min {
|
|
||||||
min = float64(numericValue)
|
|
||||||
}
|
|
||||||
count++
|
|
||||||
}
|
}
|
||||||
|
count++
|
||||||
|
} else if numericValue, ok := value.(int); ok {
|
||||||
|
if float64(numericValue) < min {
|
||||||
|
min = float64(numericValue)
|
||||||
|
}
|
||||||
|
count++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,21 +97,19 @@ func (c memoryExecutorContext) aggregate_Min(arguments []interface{}, row RowTyp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) aggregate_Sum(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) aggregate_Sum(arguments []interface{}) interface{} {
|
||||||
selectExpression := arguments[0].(parsers.SelectItem)
|
selectExpression := arguments[0].(parsers.SelectItem)
|
||||||
sum := 0.0
|
sum := 0.0
|
||||||
count := 0
|
count := 0
|
||||||
|
|
||||||
if array, isArray := row.([]RowWithJoins); isArray {
|
for _, item := range r.grouppedRows {
|
||||||
for _, item := range array {
|
value := item.resolveSelectItem(selectExpression)
|
||||||
value := c.getFieldValue(selectExpression, item)
|
if numericValue, ok := value.(float64); ok {
|
||||||
if numericValue, ok := value.(float64); ok {
|
sum += numericValue
|
||||||
sum += numericValue
|
count++
|
||||||
count++
|
} else if numericValue, ok := value.(int); ok {
|
||||||
} else if numericValue, ok := value.(int); ok {
|
sum += float64(numericValue)
|
||||||
sum += float64(numericValue)
|
count++
|
||||||
count++
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,17 +7,17 @@ import (
|
|||||||
"github.com/pikami/cosmium/parsers"
|
"github.com/pikami/cosmium/parsers"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c memoryExecutorContext) array_Concat(arguments []interface{}, row RowType) []interface{} {
|
func (r rowContext) array_Concat(arguments []interface{}) []interface{} {
|
||||||
var result []interface{}
|
var result []interface{}
|
||||||
for _, arg := range arguments {
|
for _, arg := range arguments {
|
||||||
array := c.parseArray(arg, row)
|
array := r.parseArray(arg)
|
||||||
result = append(result, array...)
|
result = append(result, array...)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) array_Length(arguments []interface{}, row RowType) int {
|
func (r rowContext) array_Length(arguments []interface{}) int {
|
||||||
array := c.parseArray(arguments[0], row)
|
array := r.parseArray(arguments[0])
|
||||||
if array == nil {
|
if array == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@@ -25,15 +25,15 @@ func (c memoryExecutorContext) array_Length(arguments []interface{}, row RowType
|
|||||||
return len(array)
|
return len(array)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) array_Slice(arguments []interface{}, row RowType) []interface{} {
|
func (r rowContext) array_Slice(arguments []interface{}) []interface{} {
|
||||||
var ok bool
|
var ok bool
|
||||||
var start int
|
var start int
|
||||||
var length int
|
var length int
|
||||||
array := c.parseArray(arguments[0], row)
|
array := r.parseArray(arguments[0])
|
||||||
startEx := c.getFieldValue(arguments[1].(parsers.SelectItem), row)
|
startEx := r.resolveSelectItem(arguments[1].(parsers.SelectItem))
|
||||||
|
|
||||||
if arguments[2] != nil {
|
if arguments[2] != nil {
|
||||||
lengthEx := c.getFieldValue(arguments[2].(parsers.SelectItem), row)
|
lengthEx := r.resolveSelectItem(arguments[2].(parsers.SelectItem))
|
||||||
|
|
||||||
if length, ok = lengthEx.(int); !ok {
|
if length, ok = lengthEx.(int); !ok {
|
||||||
logger.Error("array_Slice - got length parameters of wrong type")
|
logger.Error("array_Slice - got length parameters of wrong type")
|
||||||
@@ -65,9 +65,9 @@ func (c memoryExecutorContext) array_Slice(arguments []interface{}, row RowType)
|
|||||||
return array[start:end]
|
return array[start:end]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) set_Intersect(arguments []interface{}, row RowType) []interface{} {
|
func (r rowContext) set_Intersect(arguments []interface{}) []interface{} {
|
||||||
set1 := c.parseArray(arguments[0], row)
|
set1 := r.parseArray(arguments[0])
|
||||||
set2 := c.parseArray(arguments[1], row)
|
set2 := r.parseArray(arguments[1])
|
||||||
|
|
||||||
intersection := make(map[interface{}]struct{})
|
intersection := make(map[interface{}]struct{})
|
||||||
if set1 == nil || set2 == nil {
|
if set1 == nil || set2 == nil {
|
||||||
@@ -88,9 +88,9 @@ func (c memoryExecutorContext) set_Intersect(arguments []interface{}, row RowTyp
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) set_Union(arguments []interface{}, row RowType) []interface{} {
|
func (r rowContext) set_Union(arguments []interface{}) []interface{} {
|
||||||
set1 := c.parseArray(arguments[0], row)
|
set1 := r.parseArray(arguments[0])
|
||||||
set2 := c.parseArray(arguments[1], row)
|
set2 := r.parseArray(arguments[1])
|
||||||
|
|
||||||
var result []interface{}
|
var result []interface{}
|
||||||
union := make(map[interface{}]struct{})
|
union := make(map[interface{}]struct{})
|
||||||
@@ -111,9 +111,9 @@ func (c memoryExecutorContext) set_Union(arguments []interface{}, row RowType) [
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) parseArray(argument interface{}, row RowType) []interface{} {
|
func (r rowContext) parseArray(argument interface{}) []interface{} {
|
||||||
exItem := argument.(parsers.SelectItem)
|
exItem := argument.(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
arrValue := reflect.ValueOf(ex)
|
arrValue := reflect.ValueOf(ex)
|
||||||
if arrValue.Kind() != reflect.Slice {
|
if arrValue.Kind() != reflect.Slice {
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ import (
|
|||||||
"github.com/pikami/cosmium/parsers"
|
"github.com/pikami/cosmium/parsers"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Abs(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Abs(arguments []interface{}) interface{} {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
switch val := ex.(type) {
|
switch val := ex.(type) {
|
||||||
case float64:
|
case float64:
|
||||||
@@ -26,9 +26,9 @@ func (c memoryExecutorContext) math_Abs(arguments []interface{}, row RowType) in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Acos(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Acos(arguments []interface{}) interface{} {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
val, valIsNumber := numToFloat64(ex)
|
val, valIsNumber := numToFloat64(ex)
|
||||||
if !valIsNumber {
|
if !valIsNumber {
|
||||||
@@ -44,9 +44,9 @@ func (c memoryExecutorContext) math_Acos(arguments []interface{}, row RowType) i
|
|||||||
return math.Acos(val) * 180 / math.Pi
|
return math.Acos(val) * 180 / math.Pi
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Asin(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Asin(arguments []interface{}) interface{} {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
val, valIsNumber := numToFloat64(ex)
|
val, valIsNumber := numToFloat64(ex)
|
||||||
if !valIsNumber {
|
if !valIsNumber {
|
||||||
@@ -62,9 +62,9 @@ func (c memoryExecutorContext) math_Asin(arguments []interface{}, row RowType) i
|
|||||||
return math.Asin(val) * 180 / math.Pi
|
return math.Asin(val) * 180 / math.Pi
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Atan(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Atan(arguments []interface{}) interface{} {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
val, valIsNumber := numToFloat64(ex)
|
val, valIsNumber := numToFloat64(ex)
|
||||||
if !valIsNumber {
|
if !valIsNumber {
|
||||||
@@ -75,9 +75,9 @@ func (c memoryExecutorContext) math_Atan(arguments []interface{}, row RowType) i
|
|||||||
return math.Atan(val) * 180 / math.Pi
|
return math.Atan(val) * 180 / math.Pi
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Ceiling(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Ceiling(arguments []interface{}) interface{} {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
switch val := ex.(type) {
|
switch val := ex.(type) {
|
||||||
case float64:
|
case float64:
|
||||||
@@ -90,9 +90,9 @@ func (c memoryExecutorContext) math_Ceiling(arguments []interface{}, row RowType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Cos(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Cos(arguments []interface{}) interface{} {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
val, valIsNumber := numToFloat64(ex)
|
val, valIsNumber := numToFloat64(ex)
|
||||||
if !valIsNumber {
|
if !valIsNumber {
|
||||||
@@ -103,9 +103,9 @@ func (c memoryExecutorContext) math_Cos(arguments []interface{}, row RowType) in
|
|||||||
return math.Cos(val)
|
return math.Cos(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Cot(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Cot(arguments []interface{}) interface{} {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
val, valIsNumber := numToFloat64(ex)
|
val, valIsNumber := numToFloat64(ex)
|
||||||
if !valIsNumber {
|
if !valIsNumber {
|
||||||
@@ -121,9 +121,9 @@ func (c memoryExecutorContext) math_Cot(arguments []interface{}, row RowType) in
|
|||||||
return 1 / math.Tan(val)
|
return 1 / math.Tan(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Degrees(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Degrees(arguments []interface{}) interface{} {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
val, valIsNumber := numToFloat64(ex)
|
val, valIsNumber := numToFloat64(ex)
|
||||||
if !valIsNumber {
|
if !valIsNumber {
|
||||||
@@ -134,9 +134,9 @@ func (c memoryExecutorContext) math_Degrees(arguments []interface{}, row RowType
|
|||||||
return val * (180 / math.Pi)
|
return val * (180 / math.Pi)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Exp(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Exp(arguments []interface{}) interface{} {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
val, valIsNumber := numToFloat64(ex)
|
val, valIsNumber := numToFloat64(ex)
|
||||||
if !valIsNumber {
|
if !valIsNumber {
|
||||||
@@ -147,9 +147,9 @@ func (c memoryExecutorContext) math_Exp(arguments []interface{}, row RowType) in
|
|||||||
return math.Exp(val)
|
return math.Exp(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Floor(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Floor(arguments []interface{}) interface{} {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
switch val := ex.(type) {
|
switch val := ex.(type) {
|
||||||
case float64:
|
case float64:
|
||||||
@@ -162,9 +162,9 @@ func (c memoryExecutorContext) math_Floor(arguments []interface{}, row RowType)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_IntBitNot(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_IntBitNot(arguments []interface{}) interface{} {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
switch val := ex.(type) {
|
switch val := ex.(type) {
|
||||||
case int:
|
case int:
|
||||||
@@ -175,9 +175,9 @@ func (c memoryExecutorContext) math_IntBitNot(arguments []interface{}, row RowTy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Log10(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Log10(arguments []interface{}) interface{} {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
val, valIsNumber := numToFloat64(ex)
|
val, valIsNumber := numToFloat64(ex)
|
||||||
if !valIsNumber {
|
if !valIsNumber {
|
||||||
@@ -193,9 +193,9 @@ func (c memoryExecutorContext) math_Log10(arguments []interface{}, row RowType)
|
|||||||
return math.Log10(val)
|
return math.Log10(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Radians(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Radians(arguments []interface{}) interface{} {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
val, valIsNumber := numToFloat64(ex)
|
val, valIsNumber := numToFloat64(ex)
|
||||||
if !valIsNumber {
|
if !valIsNumber {
|
||||||
@@ -206,9 +206,9 @@ func (c memoryExecutorContext) math_Radians(arguments []interface{}, row RowType
|
|||||||
return val * (math.Pi / 180.0)
|
return val * (math.Pi / 180.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Round(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Round(arguments []interface{}) interface{} {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
switch val := ex.(type) {
|
switch val := ex.(type) {
|
||||||
case float64:
|
case float64:
|
||||||
@@ -221,9 +221,9 @@ func (c memoryExecutorContext) math_Round(arguments []interface{}, row RowType)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Sign(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Sign(arguments []interface{}) interface{} {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
switch val := ex.(type) {
|
switch val := ex.(type) {
|
||||||
case float64:
|
case float64:
|
||||||
@@ -248,9 +248,9 @@ func (c memoryExecutorContext) math_Sign(arguments []interface{}, row RowType) i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Sin(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Sin(arguments []interface{}) interface{} {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
val, valIsNumber := numToFloat64(ex)
|
val, valIsNumber := numToFloat64(ex)
|
||||||
if !valIsNumber {
|
if !valIsNumber {
|
||||||
@@ -261,9 +261,9 @@ func (c memoryExecutorContext) math_Sin(arguments []interface{}, row RowType) in
|
|||||||
return math.Sin(val)
|
return math.Sin(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Sqrt(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Sqrt(arguments []interface{}) interface{} {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
val, valIsNumber := numToFloat64(ex)
|
val, valIsNumber := numToFloat64(ex)
|
||||||
if !valIsNumber {
|
if !valIsNumber {
|
||||||
@@ -274,9 +274,9 @@ func (c memoryExecutorContext) math_Sqrt(arguments []interface{}, row RowType) i
|
|||||||
return math.Sqrt(val)
|
return math.Sqrt(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Square(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Square(arguments []interface{}) interface{} {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
val, valIsNumber := numToFloat64(ex)
|
val, valIsNumber := numToFloat64(ex)
|
||||||
if !valIsNumber {
|
if !valIsNumber {
|
||||||
@@ -287,9 +287,9 @@ func (c memoryExecutorContext) math_Square(arguments []interface{}, row RowType)
|
|||||||
return math.Pow(val, 2)
|
return math.Pow(val, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Tan(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Tan(arguments []interface{}) interface{} {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
val, valIsNumber := numToFloat64(ex)
|
val, valIsNumber := numToFloat64(ex)
|
||||||
if !valIsNumber {
|
if !valIsNumber {
|
||||||
@@ -300,9 +300,9 @@ func (c memoryExecutorContext) math_Tan(arguments []interface{}, row RowType) in
|
|||||||
return math.Tan(val)
|
return math.Tan(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Trunc(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Trunc(arguments []interface{}) interface{} {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
switch val := ex.(type) {
|
switch val := ex.(type) {
|
||||||
case float64:
|
case float64:
|
||||||
@@ -315,11 +315,11 @@ func (c memoryExecutorContext) math_Trunc(arguments []interface{}, row RowType)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Atn2(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Atn2(arguments []interface{}) interface{} {
|
||||||
exItem1 := arguments[0].(parsers.SelectItem)
|
exItem1 := arguments[0].(parsers.SelectItem)
|
||||||
exItem2 := arguments[1].(parsers.SelectItem)
|
exItem2 := arguments[1].(parsers.SelectItem)
|
||||||
ex1 := c.getFieldValue(exItem1, row)
|
ex1 := r.resolveSelectItem(exItem1)
|
||||||
ex2 := c.getFieldValue(exItem2, row)
|
ex2 := r.resolveSelectItem(exItem2)
|
||||||
|
|
||||||
y, yIsNumber := numToFloat64(ex1)
|
y, yIsNumber := numToFloat64(ex1)
|
||||||
x, xIsNumber := numToFloat64(ex2)
|
x, xIsNumber := numToFloat64(ex2)
|
||||||
@@ -332,11 +332,11 @@ func (c memoryExecutorContext) math_Atn2(arguments []interface{}, row RowType) i
|
|||||||
return math.Atan2(y, x)
|
return math.Atan2(y, x)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_IntAdd(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_IntAdd(arguments []interface{}) interface{} {
|
||||||
exItem1 := arguments[0].(parsers.SelectItem)
|
exItem1 := arguments[0].(parsers.SelectItem)
|
||||||
exItem2 := arguments[1].(parsers.SelectItem)
|
exItem2 := arguments[1].(parsers.SelectItem)
|
||||||
ex1 := c.getFieldValue(exItem1, row)
|
ex1 := r.resolveSelectItem(exItem1)
|
||||||
ex2 := c.getFieldValue(exItem2, row)
|
ex2 := r.resolveSelectItem(exItem2)
|
||||||
|
|
||||||
ex1Number, ex1IsNumber := numToInt(ex1)
|
ex1Number, ex1IsNumber := numToInt(ex1)
|
||||||
ex2Number, ex2IsNumber := numToInt(ex2)
|
ex2Number, ex2IsNumber := numToInt(ex2)
|
||||||
@@ -349,11 +349,11 @@ func (c memoryExecutorContext) math_IntAdd(arguments []interface{}, row RowType)
|
|||||||
return ex1Number + ex2Number
|
return ex1Number + ex2Number
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_IntBitAnd(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_IntBitAnd(arguments []interface{}) interface{} {
|
||||||
exItem1 := arguments[0].(parsers.SelectItem)
|
exItem1 := arguments[0].(parsers.SelectItem)
|
||||||
exItem2 := arguments[1].(parsers.SelectItem)
|
exItem2 := arguments[1].(parsers.SelectItem)
|
||||||
ex1 := c.getFieldValue(exItem1, row)
|
ex1 := r.resolveSelectItem(exItem1)
|
||||||
ex2 := c.getFieldValue(exItem2, row)
|
ex2 := r.resolveSelectItem(exItem2)
|
||||||
|
|
||||||
ex1Int, ex1IsInt := numToInt(ex1)
|
ex1Int, ex1IsInt := numToInt(ex1)
|
||||||
ex2Int, ex2IsInt := numToInt(ex2)
|
ex2Int, ex2IsInt := numToInt(ex2)
|
||||||
@@ -366,11 +366,11 @@ func (c memoryExecutorContext) math_IntBitAnd(arguments []interface{}, row RowTy
|
|||||||
return ex1Int & ex2Int
|
return ex1Int & ex2Int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_IntBitLeftShift(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_IntBitLeftShift(arguments []interface{}) interface{} {
|
||||||
exItem1 := arguments[0].(parsers.SelectItem)
|
exItem1 := arguments[0].(parsers.SelectItem)
|
||||||
exItem2 := arguments[1].(parsers.SelectItem)
|
exItem2 := arguments[1].(parsers.SelectItem)
|
||||||
ex1 := c.getFieldValue(exItem1, row)
|
ex1 := r.resolveSelectItem(exItem1)
|
||||||
ex2 := c.getFieldValue(exItem2, row)
|
ex2 := r.resolveSelectItem(exItem2)
|
||||||
|
|
||||||
num1, num1IsInt := numToInt(ex1)
|
num1, num1IsInt := numToInt(ex1)
|
||||||
num2, num2IsInt := numToInt(ex2)
|
num2, num2IsInt := numToInt(ex2)
|
||||||
@@ -383,11 +383,11 @@ func (c memoryExecutorContext) math_IntBitLeftShift(arguments []interface{}, row
|
|||||||
return num1 << uint(num2)
|
return num1 << uint(num2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_IntBitOr(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_IntBitOr(arguments []interface{}) interface{} {
|
||||||
exItem1 := arguments[0].(parsers.SelectItem)
|
exItem1 := arguments[0].(parsers.SelectItem)
|
||||||
exItem2 := arguments[1].(parsers.SelectItem)
|
exItem2 := arguments[1].(parsers.SelectItem)
|
||||||
ex1 := c.getFieldValue(exItem1, row)
|
ex1 := r.resolveSelectItem(exItem1)
|
||||||
ex2 := c.getFieldValue(exItem2, row)
|
ex2 := r.resolveSelectItem(exItem2)
|
||||||
|
|
||||||
num1, num1IsInt := ex1.(int)
|
num1, num1IsInt := ex1.(int)
|
||||||
num2, num2IsInt := ex2.(int)
|
num2, num2IsInt := ex2.(int)
|
||||||
@@ -400,11 +400,11 @@ func (c memoryExecutorContext) math_IntBitOr(arguments []interface{}, row RowTyp
|
|||||||
return num1 | num2
|
return num1 | num2
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_IntBitRightShift(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_IntBitRightShift(arguments []interface{}) interface{} {
|
||||||
exItem1 := arguments[0].(parsers.SelectItem)
|
exItem1 := arguments[0].(parsers.SelectItem)
|
||||||
exItem2 := arguments[1].(parsers.SelectItem)
|
exItem2 := arguments[1].(parsers.SelectItem)
|
||||||
ex1 := c.getFieldValue(exItem1, row)
|
ex1 := r.resolveSelectItem(exItem1)
|
||||||
ex2 := c.getFieldValue(exItem2, row)
|
ex2 := r.resolveSelectItem(exItem2)
|
||||||
|
|
||||||
num1, num1IsInt := numToInt(ex1)
|
num1, num1IsInt := numToInt(ex1)
|
||||||
num2, num2IsInt := numToInt(ex2)
|
num2, num2IsInt := numToInt(ex2)
|
||||||
@@ -417,11 +417,11 @@ func (c memoryExecutorContext) math_IntBitRightShift(arguments []interface{}, ro
|
|||||||
return num1 >> uint(num2)
|
return num1 >> uint(num2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_IntBitXor(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_IntBitXor(arguments []interface{}) interface{} {
|
||||||
exItem1 := arguments[0].(parsers.SelectItem)
|
exItem1 := arguments[0].(parsers.SelectItem)
|
||||||
exItem2 := arguments[1].(parsers.SelectItem)
|
exItem2 := arguments[1].(parsers.SelectItem)
|
||||||
ex1 := c.getFieldValue(exItem1, row)
|
ex1 := r.resolveSelectItem(exItem1)
|
||||||
ex2 := c.getFieldValue(exItem2, row)
|
ex2 := r.resolveSelectItem(exItem2)
|
||||||
|
|
||||||
num1, num1IsInt := ex1.(int)
|
num1, num1IsInt := ex1.(int)
|
||||||
num2, num2IsInt := ex2.(int)
|
num2, num2IsInt := ex2.(int)
|
||||||
@@ -434,11 +434,11 @@ func (c memoryExecutorContext) math_IntBitXor(arguments []interface{}, row RowTy
|
|||||||
return num1 ^ num2
|
return num1 ^ num2
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_IntDiv(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_IntDiv(arguments []interface{}) interface{} {
|
||||||
exItem1 := arguments[0].(parsers.SelectItem)
|
exItem1 := arguments[0].(parsers.SelectItem)
|
||||||
exItem2 := arguments[1].(parsers.SelectItem)
|
exItem2 := arguments[1].(parsers.SelectItem)
|
||||||
ex1 := c.getFieldValue(exItem1, row)
|
ex1 := r.resolveSelectItem(exItem1)
|
||||||
ex2 := c.getFieldValue(exItem2, row)
|
ex2 := r.resolveSelectItem(exItem2)
|
||||||
|
|
||||||
num1, num1IsInt := ex1.(int)
|
num1, num1IsInt := ex1.(int)
|
||||||
num2, num2IsInt := ex2.(int)
|
num2, num2IsInt := ex2.(int)
|
||||||
@@ -451,11 +451,11 @@ func (c memoryExecutorContext) math_IntDiv(arguments []interface{}, row RowType)
|
|||||||
return num1 / num2
|
return num1 / num2
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_IntMul(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_IntMul(arguments []interface{}) interface{} {
|
||||||
exItem1 := arguments[0].(parsers.SelectItem)
|
exItem1 := arguments[0].(parsers.SelectItem)
|
||||||
exItem2 := arguments[1].(parsers.SelectItem)
|
exItem2 := arguments[1].(parsers.SelectItem)
|
||||||
ex1 := c.getFieldValue(exItem1, row)
|
ex1 := r.resolveSelectItem(exItem1)
|
||||||
ex2 := c.getFieldValue(exItem2, row)
|
ex2 := r.resolveSelectItem(exItem2)
|
||||||
|
|
||||||
num1, num1IsInt := ex1.(int)
|
num1, num1IsInt := ex1.(int)
|
||||||
num2, num2IsInt := ex2.(int)
|
num2, num2IsInt := ex2.(int)
|
||||||
@@ -468,11 +468,11 @@ func (c memoryExecutorContext) math_IntMul(arguments []interface{}, row RowType)
|
|||||||
return num1 * num2
|
return num1 * num2
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_IntSub(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_IntSub(arguments []interface{}) interface{} {
|
||||||
exItem1 := arguments[0].(parsers.SelectItem)
|
exItem1 := arguments[0].(parsers.SelectItem)
|
||||||
exItem2 := arguments[1].(parsers.SelectItem)
|
exItem2 := arguments[1].(parsers.SelectItem)
|
||||||
ex1 := c.getFieldValue(exItem1, row)
|
ex1 := r.resolveSelectItem(exItem1)
|
||||||
ex2 := c.getFieldValue(exItem2, row)
|
ex2 := r.resolveSelectItem(exItem2)
|
||||||
|
|
||||||
num1, num1IsInt := ex1.(int)
|
num1, num1IsInt := ex1.(int)
|
||||||
num2, num2IsInt := ex2.(int)
|
num2, num2IsInt := ex2.(int)
|
||||||
@@ -485,11 +485,11 @@ func (c memoryExecutorContext) math_IntSub(arguments []interface{}, row RowType)
|
|||||||
return num1 - num2
|
return num1 - num2
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_IntMod(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_IntMod(arguments []interface{}) interface{} {
|
||||||
exItem1 := arguments[0].(parsers.SelectItem)
|
exItem1 := arguments[0].(parsers.SelectItem)
|
||||||
exItem2 := arguments[1].(parsers.SelectItem)
|
exItem2 := arguments[1].(parsers.SelectItem)
|
||||||
ex1 := c.getFieldValue(exItem1, row)
|
ex1 := r.resolveSelectItem(exItem1)
|
||||||
ex2 := c.getFieldValue(exItem2, row)
|
ex2 := r.resolveSelectItem(exItem2)
|
||||||
|
|
||||||
num1, num1IsInt := ex1.(int)
|
num1, num1IsInt := ex1.(int)
|
||||||
num2, num2IsInt := ex2.(int)
|
num2, num2IsInt := ex2.(int)
|
||||||
@@ -502,11 +502,11 @@ func (c memoryExecutorContext) math_IntMod(arguments []interface{}, row RowType)
|
|||||||
return num1 % num2
|
return num1 % num2
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Power(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Power(arguments []interface{}) interface{} {
|
||||||
exItem1 := arguments[0].(parsers.SelectItem)
|
exItem1 := arguments[0].(parsers.SelectItem)
|
||||||
exItem2 := arguments[1].(parsers.SelectItem)
|
exItem2 := arguments[1].(parsers.SelectItem)
|
||||||
ex1 := c.getFieldValue(exItem1, row)
|
ex1 := r.resolveSelectItem(exItem1)
|
||||||
ex2 := c.getFieldValue(exItem2, row)
|
ex2 := r.resolveSelectItem(exItem2)
|
||||||
|
|
||||||
base, baseIsNumber := numToFloat64(ex1)
|
base, baseIsNumber := numToFloat64(ex1)
|
||||||
exponent, exponentIsNumber := numToFloat64(ex2)
|
exponent, exponentIsNumber := numToFloat64(ex2)
|
||||||
@@ -519,14 +519,14 @@ func (c memoryExecutorContext) math_Power(arguments []interface{}, row RowType)
|
|||||||
return math.Pow(base, exponent)
|
return math.Pow(base, exponent)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Log(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_Log(arguments []interface{}) interface{} {
|
||||||
exItem1 := arguments[0].(parsers.SelectItem)
|
exItem1 := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem1, row)
|
ex := r.resolveSelectItem(exItem1)
|
||||||
|
|
||||||
var base float64 = math.E
|
var base float64 = math.E
|
||||||
if len(arguments) > 1 {
|
if len(arguments) > 1 {
|
||||||
exItem2 := arguments[1].(parsers.SelectItem)
|
exItem2 := arguments[1].(parsers.SelectItem)
|
||||||
baseValueObject := c.getFieldValue(exItem2, row)
|
baseValueObject := r.resolveSelectItem(exItem2)
|
||||||
baseValue, baseValueIsNumber := numToFloat64(baseValueObject)
|
baseValue, baseValueIsNumber := numToFloat64(baseValueObject)
|
||||||
|
|
||||||
if !baseValueIsNumber {
|
if !baseValueIsNumber {
|
||||||
@@ -551,15 +551,15 @@ func (c memoryExecutorContext) math_Log(arguments []interface{}, row RowType) in
|
|||||||
return math.Log(num) / math.Log(base)
|
return math.Log(num) / math.Log(base)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_NumberBin(arguments []interface{}, row RowType) interface{} {
|
func (r rowContext) math_NumberBin(arguments []interface{}) interface{} {
|
||||||
exItem1 := arguments[0].(parsers.SelectItem)
|
exItem1 := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem1, row)
|
ex := r.resolveSelectItem(exItem1)
|
||||||
|
|
||||||
binSize := 1.0
|
binSize := 1.0
|
||||||
|
|
||||||
if len(arguments) > 1 {
|
if len(arguments) > 1 {
|
||||||
exItem2 := arguments[1].(parsers.SelectItem)
|
exItem2 := arguments[1].(parsers.SelectItem)
|
||||||
binSizeValueObject := c.getFieldValue(exItem2, row)
|
binSizeValueObject := r.resolveSelectItem(exItem2)
|
||||||
binSizeValue, binSizeValueIsNumber := numToFloat64(binSizeValueObject)
|
binSizeValue, binSizeValueIsNumber := numToFloat64(binSizeValueObject)
|
||||||
|
|
||||||
if !binSizeValueIsNumber {
|
if !binSizeValueIsNumber {
|
||||||
@@ -584,11 +584,11 @@ func (c memoryExecutorContext) math_NumberBin(arguments []interface{}, row RowTy
|
|||||||
return math.Floor(num/binSize) * binSize
|
return math.Floor(num/binSize) * binSize
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Pi() interface{} {
|
func (r rowContext) math_Pi() interface{} {
|
||||||
return math.Pi
|
return math.Pi
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) math_Rand() interface{} {
|
func (r rowContext) math_Rand() interface{} {
|
||||||
return rand.Float64()
|
return rand.Float64()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -4,11 +4,11 @@ import (
|
|||||||
"github.com/pikami/cosmium/parsers"
|
"github.com/pikami/cosmium/parsers"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c memoryExecutorContext) misc_In(arguments []interface{}, row RowType) bool {
|
func (r rowContext) misc_In(arguments []interface{}) bool {
|
||||||
value := c.getFieldValue(arguments[0].(parsers.SelectItem), row)
|
value := r.resolveSelectItem(arguments[0].(parsers.SelectItem))
|
||||||
|
|
||||||
for i := 1; i < len(arguments); i++ {
|
for i := 1; i < len(arguments); i++ {
|
||||||
compareValue := c.getFieldValue(arguments[i].(parsers.SelectItem), row)
|
compareValue := r.resolveSelectItem(arguments[i].(parsers.SelectItem))
|
||||||
if compareValues(value, compareValue) == 0 {
|
if compareValues(value, compareValue) == 0 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ func testQueryExecute(
|
|||||||
data []memoryexecutor.RowType,
|
data []memoryexecutor.RowType,
|
||||||
expectedData []memoryexecutor.RowType,
|
expectedData []memoryexecutor.RowType,
|
||||||
) {
|
) {
|
||||||
result := memoryexecutor.Execute(query, data)
|
result := memoryexecutor.ExecuteQuery(query, data)
|
||||||
|
|
||||||
if !reflect.DeepEqual(result, expectedData) {
|
if !reflect.DeepEqual(result, expectedData) {
|
||||||
t.Errorf("execution result does not match expected data.\nExpected: %+v\nGot: %+v", expectedData, result)
|
t.Errorf("execution result does not match expected data.\nExpected: %+v\nGot: %+v", expectedData, result)
|
||||||
@@ -25,8 +25,20 @@ func Test_Execute(t *testing.T) {
|
|||||||
mockData := []memoryexecutor.RowType{
|
mockData := []memoryexecutor.RowType{
|
||||||
map[string]interface{}{"id": "12345", "pk": 123, "_self": "self1", "_rid": "rid1", "_ts": 123456, "isCool": false},
|
map[string]interface{}{"id": "12345", "pk": 123, "_self": "self1", "_rid": "rid1", "_ts": 123456, "isCool": false},
|
||||||
map[string]interface{}{"id": "67890", "pk": 456, "_self": "self2", "_rid": "rid2", "_ts": 789012, "isCool": true},
|
map[string]interface{}{"id": "67890", "pk": 456, "_self": "self2", "_rid": "rid2", "_ts": 789012, "isCool": true},
|
||||||
map[string]interface{}{"id": "456", "pk": 456, "_self": "self2", "_rid": "rid2", "_ts": 789012, "isCool": true},
|
map[string]interface{}{
|
||||||
map[string]interface{}{"id": "123", "pk": 456, "_self": "self2", "_rid": "rid2", "_ts": 789012, "isCool": true},
|
"id": "456", "pk": 456, "_self": "self2", "_rid": "rid2", "_ts": 789012, "isCool": true,
|
||||||
|
"tags": []map[string]interface{}{
|
||||||
|
{"name": "tag-a"},
|
||||||
|
{"name": "tag-b"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"id": "123", "pk": 456, "_self": "self2", "_rid": "rid2", "_ts": 789012, "isCool": true,
|
||||||
|
"tags": []map[string]interface{}{
|
||||||
|
{"name": "tag-b"},
|
||||||
|
{"name": "tag-c"},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Should execute SELECT with ORDER BY", func(t *testing.T) {
|
t.Run("Should execute SELECT with ORDER BY", func(t *testing.T) {
|
||||||
@@ -124,4 +136,31 @@ func Test_Execute(t *testing.T) {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("Should execute IN selector", func(t *testing.T) {
|
||||||
|
testQueryExecute(
|
||||||
|
t,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{
|
||||||
|
Path: []string{"c", "name"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{
|
||||||
|
Value: "c",
|
||||||
|
SelectItem: parsers.SelectItem{
|
||||||
|
Path: []string{"c", "tags"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mockData,
|
||||||
|
[]memoryexecutor.RowType{
|
||||||
|
map[string]interface{}{"name": "tag-a"},
|
||||||
|
map[string]interface{}{"name": "tag-b"},
|
||||||
|
map[string]interface{}{"name": "tag-b"},
|
||||||
|
map[string]interface{}{"name": "tag-c"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import (
|
|||||||
"github.com/pikami/cosmium/parsers"
|
"github.com/pikami/cosmium/parsers"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c memoryExecutorContext) strings_StringEquals(arguments []interface{}, row RowType) bool {
|
func (r rowContext) strings_StringEquals(arguments []interface{}) bool {
|
||||||
str1 := c.parseString(arguments[0], row)
|
str1 := r.parseString(arguments[0])
|
||||||
str2 := c.parseString(arguments[1], row)
|
str2 := r.parseString(arguments[1])
|
||||||
ignoreCase := c.getBoolFlag(arguments, row)
|
ignoreCase := r.getBoolFlag(arguments)
|
||||||
|
|
||||||
if ignoreCase {
|
if ignoreCase {
|
||||||
return strings.EqualFold(str1, str2)
|
return strings.EqualFold(str1, str2)
|
||||||
@@ -20,10 +20,10 @@ func (c memoryExecutorContext) strings_StringEquals(arguments []interface{}, row
|
|||||||
return str1 == str2
|
return str1 == str2
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) strings_Contains(arguments []interface{}, row RowType) bool {
|
func (r rowContext) strings_Contains(arguments []interface{}) bool {
|
||||||
str1 := c.parseString(arguments[0], row)
|
str1 := r.parseString(arguments[0])
|
||||||
str2 := c.parseString(arguments[1], row)
|
str2 := r.parseString(arguments[1])
|
||||||
ignoreCase := c.getBoolFlag(arguments, row)
|
ignoreCase := r.getBoolFlag(arguments)
|
||||||
|
|
||||||
if ignoreCase {
|
if ignoreCase {
|
||||||
str1 = strings.ToLower(str1)
|
str1 = strings.ToLower(str1)
|
||||||
@@ -33,10 +33,10 @@ func (c memoryExecutorContext) strings_Contains(arguments []interface{}, row Row
|
|||||||
return strings.Contains(str1, str2)
|
return strings.Contains(str1, str2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) strings_EndsWith(arguments []interface{}, row RowType) bool {
|
func (r rowContext) strings_EndsWith(arguments []interface{}) bool {
|
||||||
str1 := c.parseString(arguments[0], row)
|
str1 := r.parseString(arguments[0])
|
||||||
str2 := c.parseString(arguments[1], row)
|
str2 := r.parseString(arguments[1])
|
||||||
ignoreCase := c.getBoolFlag(arguments, row)
|
ignoreCase := r.getBoolFlag(arguments)
|
||||||
|
|
||||||
if ignoreCase {
|
if ignoreCase {
|
||||||
str1 = strings.ToLower(str1)
|
str1 = strings.ToLower(str1)
|
||||||
@@ -46,10 +46,10 @@ func (c memoryExecutorContext) strings_EndsWith(arguments []interface{}, row Row
|
|||||||
return strings.HasSuffix(str1, str2)
|
return strings.HasSuffix(str1, str2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) strings_StartsWith(arguments []interface{}, row RowType) bool {
|
func (r rowContext) strings_StartsWith(arguments []interface{}) bool {
|
||||||
str1 := c.parseString(arguments[0], row)
|
str1 := r.parseString(arguments[0])
|
||||||
str2 := c.parseString(arguments[1], row)
|
str2 := r.parseString(arguments[1])
|
||||||
ignoreCase := c.getBoolFlag(arguments, row)
|
ignoreCase := r.getBoolFlag(arguments)
|
||||||
|
|
||||||
if ignoreCase {
|
if ignoreCase {
|
||||||
str1 = strings.ToLower(str1)
|
str1 = strings.ToLower(str1)
|
||||||
@@ -59,12 +59,12 @@ func (c memoryExecutorContext) strings_StartsWith(arguments []interface{}, row R
|
|||||||
return strings.HasPrefix(str1, str2)
|
return strings.HasPrefix(str1, str2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) strings_Concat(arguments []interface{}, row RowType) string {
|
func (r rowContext) strings_Concat(arguments []interface{}) string {
|
||||||
result := ""
|
result := ""
|
||||||
|
|
||||||
for _, arg := range arguments {
|
for _, arg := range arguments {
|
||||||
if selectItem, ok := arg.(parsers.SelectItem); ok {
|
if selectItem, ok := arg.(parsers.SelectItem); ok {
|
||||||
value := c.getFieldValue(selectItem, row)
|
value := r.resolveSelectItem(selectItem)
|
||||||
result += convertToString(value)
|
result += convertToString(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,13 +72,13 @@ func (c memoryExecutorContext) strings_Concat(arguments []interface{}, row RowTy
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) strings_IndexOf(arguments []interface{}, row RowType) int {
|
func (r rowContext) strings_IndexOf(arguments []interface{}) int {
|
||||||
str1 := c.parseString(arguments[0], row)
|
str1 := r.parseString(arguments[0])
|
||||||
str2 := c.parseString(arguments[1], row)
|
str2 := r.parseString(arguments[1])
|
||||||
|
|
||||||
start := 0
|
start := 0
|
||||||
if len(arguments) > 2 && arguments[2] != nil {
|
if len(arguments) > 2 && arguments[2] != nil {
|
||||||
if startPos, ok := c.getFieldValue(arguments[2].(parsers.SelectItem), row).(int); ok {
|
if startPos, ok := r.resolveSelectItem(arguments[2].(parsers.SelectItem)).(int); ok {
|
||||||
start = startPos
|
start = startPos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,26 +97,26 @@ func (c memoryExecutorContext) strings_IndexOf(arguments []interface{}, row RowT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) strings_ToString(arguments []interface{}, row RowType) string {
|
func (r rowContext) strings_ToString(arguments []interface{}) string {
|
||||||
value := c.getFieldValue(arguments[0].(parsers.SelectItem), row)
|
value := r.resolveSelectItem(arguments[0].(parsers.SelectItem))
|
||||||
return convertToString(value)
|
return convertToString(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) strings_Upper(arguments []interface{}, row RowType) string {
|
func (r rowContext) strings_Upper(arguments []interface{}) string {
|
||||||
value := c.getFieldValue(arguments[0].(parsers.SelectItem), row)
|
value := r.resolveSelectItem(arguments[0].(parsers.SelectItem))
|
||||||
return strings.ToUpper(convertToString(value))
|
return strings.ToUpper(convertToString(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) strings_Lower(arguments []interface{}, row RowType) string {
|
func (r rowContext) strings_Lower(arguments []interface{}) string {
|
||||||
value := c.getFieldValue(arguments[0].(parsers.SelectItem), row)
|
value := r.resolveSelectItem(arguments[0].(parsers.SelectItem))
|
||||||
return strings.ToLower(convertToString(value))
|
return strings.ToLower(convertToString(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) strings_Left(arguments []interface{}, row RowType) string {
|
func (r rowContext) strings_Left(arguments []interface{}) string {
|
||||||
var ok bool
|
var ok bool
|
||||||
var length int
|
var length int
|
||||||
str := c.parseString(arguments[0], row)
|
str := r.parseString(arguments[0])
|
||||||
lengthEx := c.getFieldValue(arguments[1].(parsers.SelectItem), row)
|
lengthEx := r.resolveSelectItem(arguments[1].(parsers.SelectItem))
|
||||||
|
|
||||||
if length, ok = lengthEx.(int); !ok {
|
if length, ok = lengthEx.(int); !ok {
|
||||||
logger.Error("strings_Left - got parameters of wrong type")
|
logger.Error("strings_Left - got parameters of wrong type")
|
||||||
@@ -134,28 +134,28 @@ func (c memoryExecutorContext) strings_Left(arguments []interface{}, row RowType
|
|||||||
return str[:length]
|
return str[:length]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) strings_Length(arguments []interface{}, row RowType) int {
|
func (r rowContext) strings_Length(arguments []interface{}) int {
|
||||||
str := c.parseString(arguments[0], row)
|
str := r.parseString(arguments[0])
|
||||||
return len(str)
|
return len(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) strings_LTrim(arguments []interface{}, row RowType) string {
|
func (r rowContext) strings_LTrim(arguments []interface{}) string {
|
||||||
str := c.parseString(arguments[0], row)
|
str := r.parseString(arguments[0])
|
||||||
return strings.TrimLeft(str, " ")
|
return strings.TrimLeft(str, " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) strings_Replace(arguments []interface{}, row RowType) string {
|
func (r rowContext) strings_Replace(arguments []interface{}) string {
|
||||||
str := c.parseString(arguments[0], row)
|
str := r.parseString(arguments[0])
|
||||||
oldStr := c.parseString(arguments[1], row)
|
oldStr := r.parseString(arguments[1])
|
||||||
newStr := c.parseString(arguments[2], row)
|
newStr := r.parseString(arguments[2])
|
||||||
return strings.Replace(str, oldStr, newStr, -1)
|
return strings.Replace(str, oldStr, newStr, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) strings_Replicate(arguments []interface{}, row RowType) string {
|
func (r rowContext) strings_Replicate(arguments []interface{}) string {
|
||||||
var ok bool
|
var ok bool
|
||||||
var times int
|
var times int
|
||||||
str := c.parseString(arguments[0], row)
|
str := r.parseString(arguments[0])
|
||||||
timesEx := c.getFieldValue(arguments[1].(parsers.SelectItem), row)
|
timesEx := r.resolveSelectItem(arguments[1].(parsers.SelectItem))
|
||||||
|
|
||||||
if times, ok = timesEx.(int); !ok {
|
if times, ok = timesEx.(int); !ok {
|
||||||
logger.Error("strings_Replicate - got parameters of wrong type")
|
logger.Error("strings_Replicate - got parameters of wrong type")
|
||||||
@@ -173,8 +173,8 @@ func (c memoryExecutorContext) strings_Replicate(arguments []interface{}, row Ro
|
|||||||
return strings.Repeat(str, times)
|
return strings.Repeat(str, times)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) strings_Reverse(arguments []interface{}, row RowType) string {
|
func (r rowContext) strings_Reverse(arguments []interface{}) string {
|
||||||
str := c.parseString(arguments[0], row)
|
str := r.parseString(arguments[0])
|
||||||
runes := []rune(str)
|
runes := []rune(str)
|
||||||
|
|
||||||
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
|
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
|
||||||
@@ -184,11 +184,11 @@ func (c memoryExecutorContext) strings_Reverse(arguments []interface{}, row RowT
|
|||||||
return string(runes)
|
return string(runes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) strings_Right(arguments []interface{}, row RowType) string {
|
func (r rowContext) strings_Right(arguments []interface{}) string {
|
||||||
var ok bool
|
var ok bool
|
||||||
var length int
|
var length int
|
||||||
str := c.parseString(arguments[0], row)
|
str := r.parseString(arguments[0])
|
||||||
lengthEx := c.getFieldValue(arguments[1].(parsers.SelectItem), row)
|
lengthEx := r.resolveSelectItem(arguments[1].(parsers.SelectItem))
|
||||||
|
|
||||||
if length, ok = lengthEx.(int); !ok {
|
if length, ok = lengthEx.(int); !ok {
|
||||||
logger.Error("strings_Right - got parameters of wrong type")
|
logger.Error("strings_Right - got parameters of wrong type")
|
||||||
@@ -206,18 +206,18 @@ func (c memoryExecutorContext) strings_Right(arguments []interface{}, row RowTyp
|
|||||||
return str[len(str)-length:]
|
return str[len(str)-length:]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) strings_RTrim(arguments []interface{}, row RowType) string {
|
func (r rowContext) strings_RTrim(arguments []interface{}) string {
|
||||||
str := c.parseString(arguments[0], row)
|
str := r.parseString(arguments[0])
|
||||||
return strings.TrimRight(str, " ")
|
return strings.TrimRight(str, " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) strings_Substring(arguments []interface{}, row RowType) string {
|
func (r rowContext) strings_Substring(arguments []interface{}) string {
|
||||||
var ok bool
|
var ok bool
|
||||||
var startPos int
|
var startPos int
|
||||||
var length int
|
var length int
|
||||||
str := c.parseString(arguments[0], row)
|
str := r.parseString(arguments[0])
|
||||||
startPosEx := c.getFieldValue(arguments[1].(parsers.SelectItem), row)
|
startPosEx := r.resolveSelectItem(arguments[1].(parsers.SelectItem))
|
||||||
lengthEx := c.getFieldValue(arguments[2].(parsers.SelectItem), row)
|
lengthEx := r.resolveSelectItem(arguments[2].(parsers.SelectItem))
|
||||||
|
|
||||||
if startPos, ok = startPosEx.(int); !ok {
|
if startPos, ok = startPosEx.(int); !ok {
|
||||||
logger.Error("strings_Substring - got start parameters of wrong type")
|
logger.Error("strings_Substring - got start parameters of wrong type")
|
||||||
@@ -240,16 +240,16 @@ func (c memoryExecutorContext) strings_Substring(arguments []interface{}, row Ro
|
|||||||
return str[startPos:endPos]
|
return str[startPos:endPos]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) strings_Trim(arguments []interface{}, row RowType) string {
|
func (r rowContext) strings_Trim(arguments []interface{}) string {
|
||||||
str := c.parseString(arguments[0], row)
|
str := r.parseString(arguments[0])
|
||||||
return strings.TrimSpace(str)
|
return strings.TrimSpace(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) getBoolFlag(arguments []interface{}, row RowType) bool {
|
func (r rowContext) getBoolFlag(arguments []interface{}) bool {
|
||||||
ignoreCase := false
|
ignoreCase := false
|
||||||
if len(arguments) > 2 && arguments[2] != nil {
|
if len(arguments) > 2 && arguments[2] != nil {
|
||||||
ignoreCaseItem := arguments[2].(parsers.SelectItem)
|
ignoreCaseItem := arguments[2].(parsers.SelectItem)
|
||||||
if value, ok := c.getFieldValue(ignoreCaseItem, row).(bool); ok {
|
if value, ok := r.resolveSelectItem(ignoreCaseItem).(bool); ok {
|
||||||
ignoreCase = value
|
ignoreCase = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -257,9 +257,9 @@ func (c memoryExecutorContext) getBoolFlag(arguments []interface{}, row RowType)
|
|||||||
return ignoreCase
|
return ignoreCase
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) parseString(argument interface{}, row RowType) string {
|
func (r rowContext) parseString(argument interface{}) string {
|
||||||
exItem := argument.(parsers.SelectItem)
|
exItem := argument.(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
if str1, ok := ex.(string); ok {
|
if str1, ok := ex.(string); ok {
|
||||||
return str1
|
return str1
|
||||||
}
|
}
|
||||||
|
|||||||
155
query_executors/memory_executor/subquery_test.go
Normal file
155
query_executors/memory_executor/subquery_test.go
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
package memoryexecutor_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/pikami/cosmium/parsers"
|
||||||
|
memoryexecutor "github.com/pikami/cosmium/query_executors/memory_executor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Execute_SubQuery(t *testing.T) {
|
||||||
|
mockData := []memoryexecutor.RowType{
|
||||||
|
map[string]interface{}{"id": "123", "info": map[string]interface{}{"name": "row-1"}},
|
||||||
|
map[string]interface{}{
|
||||||
|
"id": "456",
|
||||||
|
"info": map[string]interface{}{"name": "row-2"},
|
||||||
|
"tags": []map[string]interface{}{
|
||||||
|
{"name": "tag-a"},
|
||||||
|
{"name": "tag-b"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"id": "789",
|
||||||
|
"info": map[string]interface{}{"name": "row-3"},
|
||||||
|
"tags": []map[string]interface{}{
|
||||||
|
{"name": "tag-b"},
|
||||||
|
{"name": "tag-c"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("Should execute FROM subquery", func(t *testing.T) {
|
||||||
|
testQueryExecute(
|
||||||
|
t,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{Path: []string{"c", "name"}},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{
|
||||||
|
Value: "c",
|
||||||
|
SelectItem: parsers.SelectItem{
|
||||||
|
Alias: "c",
|
||||||
|
Type: parsers.SelectItemTypeSubQuery,
|
||||||
|
Value: parsers.SelectStmt{
|
||||||
|
Table: parsers.Table{Value: "cc"},
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{Path: []string{"cc", "info"}, IsTopLevel: true},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mockData,
|
||||||
|
[]memoryexecutor.RowType{
|
||||||
|
map[string]interface{}{"name": "row-1"},
|
||||||
|
map[string]interface{}{"name": "row-2"},
|
||||||
|
map[string]interface{}{"name": "row-3"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should execute JOIN subquery", func(t *testing.T) {
|
||||||
|
testQueryExecute(
|
||||||
|
t,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{Path: []string{"c", "id"}},
|
||||||
|
{Path: []string{"cc", "name"}},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{
|
||||||
|
Value: "c",
|
||||||
|
},
|
||||||
|
JoinItems: []parsers.JoinItem{
|
||||||
|
{
|
||||||
|
Table: parsers.Table{
|
||||||
|
Value: "cc",
|
||||||
|
},
|
||||||
|
SelectItem: parsers.SelectItem{
|
||||||
|
Alias: "cc",
|
||||||
|
Type: parsers.SelectItemTypeSubQuery,
|
||||||
|
Value: parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{Path: []string{"tag", "name"}},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{
|
||||||
|
Value: "tag",
|
||||||
|
SelectItem: parsers.SelectItem{
|
||||||
|
Path: []string{"c", "tags"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mockData,
|
||||||
|
[]memoryexecutor.RowType{
|
||||||
|
map[string]interface{}{"id": "456", "name": "tag-a"},
|
||||||
|
map[string]interface{}{"id": "456", "name": "tag-b"},
|
||||||
|
map[string]interface{}{"id": "789", "name": "tag-b"},
|
||||||
|
map[string]interface{}{"id": "789", "name": "tag-c"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should execute JOIN EXISTS subquery", func(t *testing.T) {
|
||||||
|
testQueryExecute(
|
||||||
|
t,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{Path: []string{"c", "id"}},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{
|
||||||
|
Value: "c",
|
||||||
|
},
|
||||||
|
JoinItems: []parsers.JoinItem{
|
||||||
|
{
|
||||||
|
Table: parsers.Table{Value: "hasTags"},
|
||||||
|
SelectItem: parsers.SelectItem{
|
||||||
|
Alias: "hasTags",
|
||||||
|
Type: parsers.SelectItemTypeSubQuery,
|
||||||
|
Value: parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{
|
||||||
|
IsTopLevel: true,
|
||||||
|
Type: parsers.SelectItemTypeSubQuery,
|
||||||
|
Value: parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{Path: []string{"tag", "name"}},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{
|
||||||
|
Value: "tag",
|
||||||
|
SelectItem: parsers.SelectItem{
|
||||||
|
Path: []string{"c", "tags"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Exists: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Filters: parsers.SelectItem{
|
||||||
|
Path: []string{"hasTags"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mockData,
|
||||||
|
[]memoryexecutor.RowType{
|
||||||
|
map[string]interface{}{"id": "456"},
|
||||||
|
map[string]interface{}{"id": "789"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -6,32 +6,32 @@ import (
|
|||||||
"github.com/pikami/cosmium/parsers"
|
"github.com/pikami/cosmium/parsers"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c memoryExecutorContext) typeChecking_IsDefined(arguments []interface{}, row RowType) bool {
|
func (r rowContext) typeChecking_IsDefined(arguments []interface{}) bool {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
return ex != nil
|
return ex != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) typeChecking_IsArray(arguments []interface{}, row RowType) bool {
|
func (r rowContext) typeChecking_IsArray(arguments []interface{}) bool {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
_, isArray := ex.([]interface{})
|
_, isArray := ex.([]interface{})
|
||||||
return isArray
|
return isArray
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) typeChecking_IsBool(arguments []interface{}, row RowType) bool {
|
func (r rowContext) typeChecking_IsBool(arguments []interface{}) bool {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
_, isBool := ex.(bool)
|
_, isBool := ex.(bool)
|
||||||
return isBool
|
return isBool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) typeChecking_IsFiniteNumber(arguments []interface{}, row RowType) bool {
|
func (r rowContext) typeChecking_IsFiniteNumber(arguments []interface{}) bool {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
switch num := ex.(type) {
|
switch num := ex.(type) {
|
||||||
case int:
|
case int:
|
||||||
@@ -43,41 +43,41 @@ func (c memoryExecutorContext) typeChecking_IsFiniteNumber(arguments []interface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) typeChecking_IsInteger(arguments []interface{}, row RowType) bool {
|
func (r rowContext) typeChecking_IsInteger(arguments []interface{}) bool {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
_, isInt := ex.(int)
|
_, isInt := ex.(int)
|
||||||
return isInt
|
return isInt
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) typeChecking_IsNull(arguments []interface{}, row RowType) bool {
|
func (r rowContext) typeChecking_IsNull(arguments []interface{}) bool {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
return ex == nil
|
return ex == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) typeChecking_IsNumber(arguments []interface{}, row RowType) bool {
|
func (r rowContext) typeChecking_IsNumber(arguments []interface{}) bool {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
_, isFloat := ex.(float64)
|
_, isFloat := ex.(float64)
|
||||||
_, isInt := ex.(int)
|
_, isInt := ex.(int)
|
||||||
return isFloat || isInt
|
return isFloat || isInt
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) typeChecking_IsObject(arguments []interface{}, row RowType) bool {
|
func (r rowContext) typeChecking_IsObject(arguments []interface{}) bool {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
_, isObject := ex.(map[string]interface{})
|
_, isObject := ex.(map[string]interface{})
|
||||||
return isObject
|
return isObject
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) typeChecking_IsPrimitive(arguments []interface{}, row RowType) bool {
|
func (r rowContext) typeChecking_IsPrimitive(arguments []interface{}) bool {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
switch ex.(type) {
|
switch ex.(type) {
|
||||||
case bool, string, float64, int, nil:
|
case bool, string, float64, int, nil:
|
||||||
@@ -87,9 +87,9 @@ func (c memoryExecutorContext) typeChecking_IsPrimitive(arguments []interface{},
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c memoryExecutorContext) typeChecking_IsString(arguments []interface{}, row RowType) bool {
|
func (r rowContext) typeChecking_IsString(arguments []interface{}) bool {
|
||||||
exItem := arguments[0].(parsers.SelectItem)
|
exItem := arguments[0].(parsers.SelectItem)
|
||||||
ex := c.getFieldValue(exItem, row)
|
ex := r.resolveSelectItem(exItem)
|
||||||
|
|
||||||
_, isStr := ex.(string)
|
_, isStr := ex.(string)
|
||||||
return isStr
|
return isStr
|
||||||
|
|||||||
Reference in New Issue
Block a user