mirror of
https://github.com/pikami/cosmium.git
synced 2026-04-20 21:38:47 +01:00
Compare commits
3 Commits
v0.1.12
...
d86bac7d79
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d86bac7d79 | ||
|
|
69b76c1c3e | ||
|
|
8e3db3e44d |
@@ -22,3 +22,97 @@ func (h *Handlers) GetAllStoredProcedures(c *gin.Context) {
|
|||||||
|
|
||||||
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Unknown error"})
|
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Unknown error"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Handlers) GetStoredProcedure(c *gin.Context) {
|
||||||
|
databaseId := c.Param("databaseId")
|
||||||
|
collectionId := c.Param("collId")
|
||||||
|
spId := c.Param("spId")
|
||||||
|
|
||||||
|
sp, status := h.repository.GetStoredProcedure(databaseId, collectionId, spId)
|
||||||
|
|
||||||
|
if status == repositorymodels.StatusOk {
|
||||||
|
c.IndentedJSON(http.StatusOK, sp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if status == repositorymodels.StatusNotFound {
|
||||||
|
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "NotFound"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Unknown error"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handlers) DeleteStoredProcedure(c *gin.Context) {
|
||||||
|
databaseId := c.Param("databaseId")
|
||||||
|
collectionId := c.Param("collId")
|
||||||
|
spId := c.Param("spId")
|
||||||
|
|
||||||
|
status := h.repository.DeleteStoredProcedure(databaseId, collectionId, spId)
|
||||||
|
if status == repositorymodels.StatusOk {
|
||||||
|
c.Status(http.StatusNoContent)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if status == repositorymodels.StatusNotFound {
|
||||||
|
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "NotFound"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Unknown error"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handlers) ReplaceStoredProcedure(c *gin.Context) {
|
||||||
|
databaseId := c.Param("databaseId")
|
||||||
|
collectionId := c.Param("collId")
|
||||||
|
spId := c.Param("spId")
|
||||||
|
|
||||||
|
var sp repositorymodels.StoredProcedure
|
||||||
|
if err := c.BindJSON(&sp); err != nil {
|
||||||
|
c.IndentedJSON(http.StatusBadRequest, gin.H{"message": "Invalid body"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
status := h.repository.DeleteStoredProcedure(databaseId, collectionId, spId)
|
||||||
|
if status == repositorymodels.StatusNotFound {
|
||||||
|
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "NotFound"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
createdSP, status := h.repository.CreateStoredProcedure(databaseId, collectionId, sp)
|
||||||
|
if status == repositorymodels.Conflict {
|
||||||
|
c.IndentedJSON(http.StatusConflict, gin.H{"message": "Conflict"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if status == repositorymodels.StatusOk {
|
||||||
|
c.IndentedJSON(http.StatusOK, createdSP)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Unknown error"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handlers) CreateStoredProcedure(c *gin.Context) {
|
||||||
|
databaseId := c.Param("databaseId")
|
||||||
|
collectionId := c.Param("collId")
|
||||||
|
|
||||||
|
var sp repositorymodels.StoredProcedure
|
||||||
|
if err := c.BindJSON(&sp); err != nil {
|
||||||
|
c.IndentedJSON(http.StatusBadRequest, gin.H{"message": "Invalid body"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
createdSP, status := h.repository.CreateStoredProcedure(databaseId, collectionId, sp)
|
||||||
|
if status == repositorymodels.Conflict {
|
||||||
|
c.IndentedJSON(http.StatusConflict, gin.H{"message": "Conflict"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if status == repositorymodels.StatusOk {
|
||||||
|
c.IndentedJSON(http.StatusCreated, createdSP)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Unknown error"})
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,3 +22,97 @@ func (h *Handlers) GetAllTriggers(c *gin.Context) {
|
|||||||
|
|
||||||
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Unknown error"})
|
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Unknown error"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Handlers) GetTrigger(c *gin.Context) {
|
||||||
|
databaseId := c.Param("databaseId")
|
||||||
|
collectionId := c.Param("collId")
|
||||||
|
triggerId := c.Param("triggerId")
|
||||||
|
|
||||||
|
trigger, status := h.repository.GetTrigger(databaseId, collectionId, triggerId)
|
||||||
|
|
||||||
|
if status == repositorymodels.StatusOk {
|
||||||
|
c.IndentedJSON(http.StatusOK, trigger)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if status == repositorymodels.StatusNotFound {
|
||||||
|
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "NotFound"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Unknown error"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handlers) DeleteTrigger(c *gin.Context) {
|
||||||
|
databaseId := c.Param("databaseId")
|
||||||
|
collectionId := c.Param("collId")
|
||||||
|
triggerId := c.Param("triggerId")
|
||||||
|
|
||||||
|
status := h.repository.DeleteTrigger(databaseId, collectionId, triggerId)
|
||||||
|
if status == repositorymodels.StatusOk {
|
||||||
|
c.Status(http.StatusNoContent)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if status == repositorymodels.StatusNotFound {
|
||||||
|
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "NotFound"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Unknown error"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handlers) ReplaceTrigger(c *gin.Context) {
|
||||||
|
databaseId := c.Param("databaseId")
|
||||||
|
collectionId := c.Param("collId")
|
||||||
|
triggerId := c.Param("triggerId")
|
||||||
|
|
||||||
|
var trigger repositorymodels.Trigger
|
||||||
|
if err := c.BindJSON(&trigger); err != nil {
|
||||||
|
c.IndentedJSON(http.StatusBadRequest, gin.H{"message": "Invalid body"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
status := h.repository.DeleteTrigger(databaseId, collectionId, triggerId)
|
||||||
|
if status == repositorymodels.StatusNotFound {
|
||||||
|
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "NotFound"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
createdTrigger, status := h.repository.CreateTrigger(databaseId, collectionId, trigger)
|
||||||
|
if status == repositorymodels.Conflict {
|
||||||
|
c.IndentedJSON(http.StatusConflict, gin.H{"message": "Conflict"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if status == repositorymodels.StatusOk {
|
||||||
|
c.IndentedJSON(http.StatusOK, createdTrigger)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Unknown error"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handlers) CreateTrigger(c *gin.Context) {
|
||||||
|
databaseId := c.Param("databaseId")
|
||||||
|
collectionId := c.Param("collId")
|
||||||
|
|
||||||
|
var trigger repositorymodels.Trigger
|
||||||
|
if err := c.BindJSON(&trigger); err != nil {
|
||||||
|
c.IndentedJSON(http.StatusBadRequest, gin.H{"message": "Invalid body"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
createdTrigger, status := h.repository.CreateTrigger(databaseId, collectionId, trigger)
|
||||||
|
if status == repositorymodels.Conflict {
|
||||||
|
c.IndentedJSON(http.StatusConflict, gin.H{"message": "Conflict"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if status == repositorymodels.StatusOk {
|
||||||
|
c.IndentedJSON(http.StatusCreated, createdTrigger)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Unknown error"})
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,3 +22,97 @@ func (h *Handlers) GetAllUserDefinedFunctions(c *gin.Context) {
|
|||||||
|
|
||||||
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Unknown error"})
|
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Unknown error"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Handlers) GetUserDefinedFunction(c *gin.Context) {
|
||||||
|
databaseId := c.Param("databaseId")
|
||||||
|
collectionId := c.Param("collId")
|
||||||
|
udfId := c.Param("udfId")
|
||||||
|
|
||||||
|
udf, status := h.repository.GetUserDefinedFunction(databaseId, collectionId, udfId)
|
||||||
|
|
||||||
|
if status == repositorymodels.StatusOk {
|
||||||
|
c.IndentedJSON(http.StatusOK, udf)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if status == repositorymodels.StatusNotFound {
|
||||||
|
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "NotFound"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Unknown error"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handlers) DeleteUserDefinedFunction(c *gin.Context) {
|
||||||
|
databaseId := c.Param("databaseId")
|
||||||
|
collectionId := c.Param("collId")
|
||||||
|
udfId := c.Param("udfId")
|
||||||
|
|
||||||
|
status := h.repository.DeleteUserDefinedFunction(databaseId, collectionId, udfId)
|
||||||
|
if status == repositorymodels.StatusOk {
|
||||||
|
c.Status(http.StatusNoContent)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if status == repositorymodels.StatusNotFound {
|
||||||
|
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "NotFound"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Unknown error"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handlers) ReplaceUserDefinedFunction(c *gin.Context) {
|
||||||
|
databaseId := c.Param("databaseId")
|
||||||
|
collectionId := c.Param("collId")
|
||||||
|
udfId := c.Param("udfId")
|
||||||
|
|
||||||
|
var udf repositorymodels.UserDefinedFunction
|
||||||
|
if err := c.BindJSON(&udf); err != nil {
|
||||||
|
c.IndentedJSON(http.StatusBadRequest, gin.H{"message": "Invalid body"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
status := h.repository.DeleteUserDefinedFunction(databaseId, collectionId, udfId)
|
||||||
|
if status == repositorymodels.StatusNotFound {
|
||||||
|
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "NotFound"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
createdUdf, status := h.repository.CreateUserDefinedFunction(databaseId, collectionId, udf)
|
||||||
|
if status == repositorymodels.Conflict {
|
||||||
|
c.IndentedJSON(http.StatusConflict, gin.H{"message": "Conflict"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if status == repositorymodels.StatusOk {
|
||||||
|
c.IndentedJSON(http.StatusOK, createdUdf)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Unknown error"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handlers) CreateUserDefinedFunction(c *gin.Context) {
|
||||||
|
databaseId := c.Param("databaseId")
|
||||||
|
collectionId := c.Param("collId")
|
||||||
|
|
||||||
|
var udf repositorymodels.UserDefinedFunction
|
||||||
|
if err := c.BindJSON(&udf); err != nil {
|
||||||
|
c.IndentedJSON(http.StatusBadRequest, gin.H{"message": "Invalid body"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
createdUdf, status := h.repository.CreateUserDefinedFunction(databaseId, collectionId, udf)
|
||||||
|
if status == repositorymodels.Conflict {
|
||||||
|
c.IndentedJSON(http.StatusConflict, gin.H{"message": "Conflict"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if status == repositorymodels.StatusOk {
|
||||||
|
c.IndentedJSON(http.StatusCreated, createdUdf)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Unknown error"})
|
||||||
|
}
|
||||||
|
|||||||
@@ -50,9 +50,23 @@ func (s *ApiServer) CreateRouter(repository *repositories.DataRepository) {
|
|||||||
router.GET("/dbs/:databaseId", routeHandlers.GetDatabase)
|
router.GET("/dbs/:databaseId", routeHandlers.GetDatabase)
|
||||||
router.DELETE("/dbs/:databaseId", routeHandlers.DeleteDatabase)
|
router.DELETE("/dbs/:databaseId", routeHandlers.DeleteDatabase)
|
||||||
|
|
||||||
router.GET("/dbs/:databaseId/colls/:collId/udfs", routeHandlers.GetAllUserDefinedFunctions)
|
router.POST("/dbs/:databaseId/colls/:collId/triggers", routeHandlers.CreateTrigger)
|
||||||
router.GET("/dbs/:databaseId/colls/:collId/sprocs", routeHandlers.GetAllStoredProcedures)
|
|
||||||
router.GET("/dbs/:databaseId/colls/:collId/triggers", routeHandlers.GetAllTriggers)
|
router.GET("/dbs/:databaseId/colls/:collId/triggers", routeHandlers.GetAllTriggers)
|
||||||
|
router.GET("/dbs/:databaseId/colls/:collId/triggers/:triggerId", routeHandlers.GetTrigger)
|
||||||
|
router.PUT("/dbs/:databaseId/colls/:collId/triggers/:triggerId", routeHandlers.ReplaceTrigger)
|
||||||
|
router.DELETE("/dbs/:databaseId/colls/:collId/triggers/:triggerId", routeHandlers.DeleteTrigger)
|
||||||
|
|
||||||
|
router.POST("/dbs/:databaseId/colls/:collId/sprocs", routeHandlers.CreateStoredProcedure)
|
||||||
|
router.GET("/dbs/:databaseId/colls/:collId/sprocs", routeHandlers.GetAllStoredProcedures)
|
||||||
|
router.GET("/dbs/:databaseId/colls/:collId/sprocs/:sprocId", routeHandlers.GetStoredProcedure)
|
||||||
|
router.PUT("/dbs/:databaseId/colls/:collId/sprocs/:sprocId", routeHandlers.ReplaceStoredProcedure)
|
||||||
|
router.DELETE("/dbs/:databaseId/colls/:collId/sprocs/:sprocId", routeHandlers.DeleteStoredProcedure)
|
||||||
|
|
||||||
|
router.POST("/dbs/:databaseId/colls/:collId/udfs", routeHandlers.CreateUserDefinedFunction)
|
||||||
|
router.GET("/dbs/:databaseId/colls/:collId/udfs", routeHandlers.GetAllUserDefinedFunctions)
|
||||||
|
router.GET("/dbs/:databaseId/colls/:collId/udfs/:udfId", routeHandlers.GetUserDefinedFunction)
|
||||||
|
router.PUT("/dbs/:databaseId/colls/:collId/udfs/:udfId", routeHandlers.ReplaceUserDefinedFunction)
|
||||||
|
router.DELETE("/dbs/:databaseId/colls/:collId/udfs/:udfId", routeHandlers.DeleteUserDefinedFunction)
|
||||||
|
|
||||||
router.GET("/offers", handlers.GetOffers)
|
router.GET("/offers", handlers.GetOffers)
|
||||||
router.GET("/", routeHandlers.GetServerInfo)
|
router.GET("/", routeHandlers.GetServerInfo)
|
||||||
|
|||||||
@@ -65,9 +65,9 @@ Cosmium strives to support the core features of Cosmos DB, including:
|
|||||||
| Function | Implemented |
|
| Function | Implemented |
|
||||||
| ------------------ | ----------- |
|
| ------------------ | ----------- |
|
||||||
| ARRAY_CONCAT | Yes |
|
| ARRAY_CONCAT | Yes |
|
||||||
| ARRAY_CONTAINS | No |
|
| ARRAY_CONTAINS | Yes |
|
||||||
| ARRAY_CONTAINS_ANY | No |
|
| ARRAY_CONTAINS_ANY | Yes |
|
||||||
| ARRAY_CONTAINS_ALL | No |
|
| ARRAY_CONTAINS_ALL | Yes |
|
||||||
| ARRAY_LENGTH | Yes |
|
| ARRAY_LENGTH | Yes |
|
||||||
| ARRAY_SLICE | Yes |
|
| ARRAY_SLICE | Yes |
|
||||||
| CHOOSE | No |
|
| CHOOSE | No |
|
||||||
|
|||||||
@@ -77,6 +77,9 @@ func (r *DataRepository) CreateCollection(databaseId string, newCollection repos
|
|||||||
|
|
||||||
r.storeState.Collections[databaseId][newCollection.ID] = newCollection
|
r.storeState.Collections[databaseId][newCollection.ID] = newCollection
|
||||||
r.storeState.Documents[databaseId][newCollection.ID] = make(map[string]repositorymodels.Document)
|
r.storeState.Documents[databaseId][newCollection.ID] = make(map[string]repositorymodels.Document)
|
||||||
|
r.storeState.Triggers[databaseId][newCollection.ID] = make(map[string]repositorymodels.Trigger)
|
||||||
|
r.storeState.StoredProcedures[databaseId][newCollection.ID] = make(map[string]repositorymodels.StoredProcedure)
|
||||||
|
r.storeState.UserDefinedFunctions[databaseId][newCollection.ID] = make(map[string]repositorymodels.UserDefinedFunction)
|
||||||
|
|
||||||
return newCollection, repositorymodels.StatusOk
|
return newCollection, repositorymodels.StatusOk
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ func (r *DataRepository) CreateDatabase(newDatabase repositorymodels.Database) (
|
|||||||
r.storeState.Databases[newDatabase.ID] = newDatabase
|
r.storeState.Databases[newDatabase.ID] = newDatabase
|
||||||
r.storeState.Collections[newDatabase.ID] = make(map[string]repositorymodels.Collection)
|
r.storeState.Collections[newDatabase.ID] = make(map[string]repositorymodels.Collection)
|
||||||
r.storeState.Documents[newDatabase.ID] = make(map[string]map[string]repositorymodels.Document)
|
r.storeState.Documents[newDatabase.ID] = make(map[string]map[string]repositorymodels.Document)
|
||||||
|
r.storeState.Triggers[newDatabase.ID] = make(map[string]map[string]repositorymodels.Trigger)
|
||||||
|
r.storeState.StoredProcedures[newDatabase.ID] = make(map[string]map[string]repositorymodels.StoredProcedure)
|
||||||
|
r.storeState.UserDefinedFunctions[newDatabase.ID] = make(map[string]map[string]repositorymodels.UserDefinedFunction)
|
||||||
|
|
||||||
return newDatabase, repositorymodels.StatusOk
|
return newDatabase, repositorymodels.StatusOk
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,6 @@ package repositories
|
|||||||
import repositorymodels "github.com/pikami/cosmium/internal/repository_models"
|
import repositorymodels "github.com/pikami/cosmium/internal/repository_models"
|
||||||
|
|
||||||
type DataRepository struct {
|
type DataRepository struct {
|
||||||
storedProcedures []repositorymodels.StoredProcedure
|
|
||||||
triggers []repositorymodels.Trigger
|
|
||||||
userDefinedFunctions []repositorymodels.UserDefinedFunction
|
|
||||||
storeState repositorymodels.State
|
storeState repositorymodels.State
|
||||||
|
|
||||||
initialDataFilePath string
|
initialDataFilePath string
|
||||||
@@ -19,13 +16,13 @@ type RepositoryOptions struct {
|
|||||||
|
|
||||||
func NewDataRepository(options RepositoryOptions) *DataRepository {
|
func NewDataRepository(options RepositoryOptions) *DataRepository {
|
||||||
repository := &DataRepository{
|
repository := &DataRepository{
|
||||||
storedProcedures: []repositorymodels.StoredProcedure{},
|
|
||||||
triggers: []repositorymodels.Trigger{},
|
|
||||||
userDefinedFunctions: []repositorymodels.UserDefinedFunction{},
|
|
||||||
storeState: repositorymodels.State{
|
storeState: repositorymodels.State{
|
||||||
Databases: make(map[string]repositorymodels.Database),
|
Databases: make(map[string]repositorymodels.Database),
|
||||||
Collections: make(map[string]map[string]repositorymodels.Collection),
|
Collections: make(map[string]map[string]repositorymodels.Collection),
|
||||||
Documents: make(map[string]map[string]map[string]repositorymodels.Document),
|
Documents: make(map[string]map[string]map[string]repositorymodels.Document),
|
||||||
|
Triggers: make(map[string]map[string]map[string]repositorymodels.Trigger),
|
||||||
|
StoredProcedures: make(map[string]map[string]map[string]repositorymodels.StoredProcedure),
|
||||||
|
UserDefinedFunctions: make(map[string]map[string]map[string]repositorymodels.UserDefinedFunction),
|
||||||
},
|
},
|
||||||
initialDataFilePath: options.InitialDataFilePath,
|
initialDataFilePath: options.InitialDataFilePath,
|
||||||
persistDataFilePath: options.PersistDataFilePath,
|
persistDataFilePath: options.PersistDataFilePath,
|
||||||
|
|||||||
@@ -64,6 +64,9 @@ func (r *DataRepository) LoadStateJSON(jsonData string) error {
|
|||||||
logger.Infof("Databases: %d\n", getLength(r.storeState.Databases))
|
logger.Infof("Databases: %d\n", getLength(r.storeState.Databases))
|
||||||
logger.Infof("Collections: %d\n", getLength(r.storeState.Collections))
|
logger.Infof("Collections: %d\n", getLength(r.storeState.Collections))
|
||||||
logger.Infof("Documents: %d\n", getLength(r.storeState.Documents))
|
logger.Infof("Documents: %d\n", getLength(r.storeState.Documents))
|
||||||
|
logger.Infof("Triggers: %d\n", getLength(r.storeState.Triggers))
|
||||||
|
logger.Infof("Stored procedures: %d\n", getLength(r.storeState.StoredProcedures))
|
||||||
|
logger.Infof("User defined functions: %d\n", getLength(r.storeState.UserDefinedFunctions))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -84,6 +87,9 @@ func (r *DataRepository) SaveStateFS(filePath string) {
|
|||||||
logger.Infof("Databases: %d\n", getLength(r.storeState.Databases))
|
logger.Infof("Databases: %d\n", getLength(r.storeState.Databases))
|
||||||
logger.Infof("Collections: %d\n", getLength(r.storeState.Collections))
|
logger.Infof("Collections: %d\n", getLength(r.storeState.Collections))
|
||||||
logger.Infof("Documents: %d\n", getLength(r.storeState.Documents))
|
logger.Infof("Documents: %d\n", getLength(r.storeState.Documents))
|
||||||
|
logger.Infof("Triggers: %d\n", getLength(r.storeState.Triggers))
|
||||||
|
logger.Infof("Stored procedures: %d\n", getLength(r.storeState.StoredProcedures))
|
||||||
|
logger.Infof("User defined functions: %d\n", getLength(r.storeState.UserDefinedFunctions))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *DataRepository) GetState() (string, error) {
|
func (r *DataRepository) GetState() (string, error) {
|
||||||
@@ -103,7 +109,10 @@ func getLength(v interface{}) int {
|
|||||||
switch v.(type) {
|
switch v.(type) {
|
||||||
case repositorymodels.Database,
|
case repositorymodels.Database,
|
||||||
repositorymodels.Collection,
|
repositorymodels.Collection,
|
||||||
repositorymodels.Document:
|
repositorymodels.Document,
|
||||||
|
repositorymodels.Trigger,
|
||||||
|
repositorymodels.StoredProcedure,
|
||||||
|
repositorymodels.UserDefinedFunction:
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,6 +146,18 @@ func (r *DataRepository) ensureStoreStateNoNullReferences() {
|
|||||||
r.storeState.Documents = make(map[string]map[string]map[string]repositorymodels.Document)
|
r.storeState.Documents = make(map[string]map[string]map[string]repositorymodels.Document)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if r.storeState.Triggers == nil {
|
||||||
|
r.storeState.Triggers = make(map[string]map[string]map[string]repositorymodels.Trigger)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.storeState.StoredProcedures == nil {
|
||||||
|
r.storeState.StoredProcedures = make(map[string]map[string]map[string]repositorymodels.StoredProcedure)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.storeState.UserDefinedFunctions == nil {
|
||||||
|
r.storeState.UserDefinedFunctions = make(map[string]map[string]map[string]repositorymodels.UserDefinedFunction)
|
||||||
|
}
|
||||||
|
|
||||||
for database := range r.storeState.Databases {
|
for database := range r.storeState.Databases {
|
||||||
if r.storeState.Collections[database] == nil {
|
if r.storeState.Collections[database] == nil {
|
||||||
r.storeState.Collections[database] = make(map[string]repositorymodels.Collection)
|
r.storeState.Collections[database] = make(map[string]repositorymodels.Collection)
|
||||||
@@ -146,6 +167,18 @@ func (r *DataRepository) ensureStoreStateNoNullReferences() {
|
|||||||
r.storeState.Documents[database] = make(map[string]map[string]repositorymodels.Document)
|
r.storeState.Documents[database] = make(map[string]map[string]repositorymodels.Document)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if r.storeState.Triggers[database] == nil {
|
||||||
|
r.storeState.Triggers[database] = make(map[string]map[string]repositorymodels.Trigger)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.storeState.StoredProcedures[database] == nil {
|
||||||
|
r.storeState.StoredProcedures[database] = make(map[string]map[string]repositorymodels.StoredProcedure)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.storeState.UserDefinedFunctions[database] == nil {
|
||||||
|
r.storeState.UserDefinedFunctions[database] = make(map[string]map[string]repositorymodels.UserDefinedFunction)
|
||||||
|
}
|
||||||
|
|
||||||
for collection := range r.storeState.Collections[database] {
|
for collection := range r.storeState.Collections[database] {
|
||||||
if r.storeState.Documents[database][collection] == nil {
|
if r.storeState.Documents[database][collection] == nil {
|
||||||
r.storeState.Documents[database][collection] = make(map[string]repositorymodels.Document)
|
r.storeState.Documents[database][collection] = make(map[string]repositorymodels.Document)
|
||||||
@@ -156,6 +189,18 @@ func (r *DataRepository) ensureStoreStateNoNullReferences() {
|
|||||||
delete(r.storeState.Documents[database][collection], document)
|
delete(r.storeState.Documents[database][collection], document)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if r.storeState.Triggers[database][collection] == nil {
|
||||||
|
r.storeState.Triggers[database][collection] = make(map[string]repositorymodels.Trigger)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.storeState.StoredProcedures[database][collection] == nil {
|
||||||
|
r.storeState.StoredProcedures[database][collection] = make(map[string]repositorymodels.StoredProcedure)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.storeState.UserDefinedFunctions[database][collection] == nil {
|
||||||
|
r.storeState.UserDefinedFunctions[database][collection] = make(map[string]repositorymodels.UserDefinedFunction)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,91 @@
|
|||||||
package repositories
|
package repositories
|
||||||
|
|
||||||
import repositorymodels "github.com/pikami/cosmium/internal/repository_models"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
repositorymodels "github.com/pikami/cosmium/internal/repository_models"
|
||||||
|
"github.com/pikami/cosmium/internal/resourceid"
|
||||||
|
"golang.org/x/exp/maps"
|
||||||
|
)
|
||||||
|
|
||||||
func (r *DataRepository) GetAllStoredProcedures(databaseId string, collectionId string) ([]repositorymodels.StoredProcedure, repositorymodels.RepositoryStatus) {
|
func (r *DataRepository) GetAllStoredProcedures(databaseId string, collectionId string) ([]repositorymodels.StoredProcedure, repositorymodels.RepositoryStatus) {
|
||||||
return r.storedProcedures, repositorymodels.StatusOk
|
r.storeState.RLock()
|
||||||
|
defer r.storeState.RUnlock()
|
||||||
|
|
||||||
|
return maps.Values(r.storeState.StoredProcedures[databaseId][collectionId]), repositorymodels.StatusOk
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *DataRepository) GetStoredProcedure(databaseId string, collectionId string, spId string) (repositorymodels.StoredProcedure, repositorymodels.RepositoryStatus) {
|
||||||
|
r.storeState.RLock()
|
||||||
|
defer r.storeState.RUnlock()
|
||||||
|
|
||||||
|
if _, ok := r.storeState.Databases[databaseId]; !ok {
|
||||||
|
return repositorymodels.StoredProcedure{}, repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := r.storeState.Collections[databaseId][collectionId]; !ok {
|
||||||
|
return repositorymodels.StoredProcedure{}, repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if sp, ok := r.storeState.StoredProcedures[databaseId][collectionId][spId]; ok {
|
||||||
|
return sp, repositorymodels.StatusOk
|
||||||
|
}
|
||||||
|
|
||||||
|
return repositorymodels.StoredProcedure{}, repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *DataRepository) DeleteStoredProcedure(databaseId string, collectionId string, spId string) repositorymodels.RepositoryStatus {
|
||||||
|
r.storeState.Lock()
|
||||||
|
defer r.storeState.Unlock()
|
||||||
|
|
||||||
|
if _, ok := r.storeState.Databases[databaseId]; !ok {
|
||||||
|
return repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := r.storeState.Collections[databaseId][collectionId]; !ok {
|
||||||
|
return repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := r.storeState.StoredProcedures[databaseId][collectionId][spId]; !ok {
|
||||||
|
return repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(r.storeState.StoredProcedures[databaseId][collectionId], spId)
|
||||||
|
|
||||||
|
return repositorymodels.StatusOk
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *DataRepository) CreateStoredProcedure(databaseId string, collectionId string, sp repositorymodels.StoredProcedure) (repositorymodels.StoredProcedure, repositorymodels.RepositoryStatus) {
|
||||||
|
r.storeState.Lock()
|
||||||
|
defer r.storeState.Unlock()
|
||||||
|
|
||||||
|
var ok bool
|
||||||
|
var database repositorymodels.Database
|
||||||
|
var collection repositorymodels.Collection
|
||||||
|
if sp.ID == "" {
|
||||||
|
return repositorymodels.StoredProcedure{}, repositorymodels.BadRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
if database, ok = r.storeState.Databases[databaseId]; !ok {
|
||||||
|
return repositorymodels.StoredProcedure{}, repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if collection, ok = r.storeState.Collections[databaseId][collectionId]; !ok {
|
||||||
|
return repositorymodels.StoredProcedure{}, repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok = r.storeState.StoredProcedures[databaseId][collectionId][sp.ID]; ok {
|
||||||
|
return repositorymodels.StoredProcedure{}, repositorymodels.Conflict
|
||||||
|
}
|
||||||
|
|
||||||
|
sp.TimeStamp = time.Now().Unix()
|
||||||
|
sp.ResourceID = resourceid.NewCombined(database.ResourceID, collection.ResourceID, resourceid.New())
|
||||||
|
sp.ETag = fmt.Sprintf("\"%s\"", uuid.New())
|
||||||
|
sp.Self = fmt.Sprintf("dbs/%s/colls/%s/sprocs/%s/", database.ResourceID, collection.ResourceID, sp.ResourceID)
|
||||||
|
|
||||||
|
r.storeState.StoredProcedures[databaseId][collectionId][sp.ID] = sp
|
||||||
|
|
||||||
|
return sp, repositorymodels.StatusOk
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,91 @@
|
|||||||
package repositories
|
package repositories
|
||||||
|
|
||||||
import repositorymodels "github.com/pikami/cosmium/internal/repository_models"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
repositorymodels "github.com/pikami/cosmium/internal/repository_models"
|
||||||
|
"github.com/pikami/cosmium/internal/resourceid"
|
||||||
|
"golang.org/x/exp/maps"
|
||||||
|
)
|
||||||
|
|
||||||
func (r *DataRepository) GetAllTriggers(databaseId string, collectionId string) ([]repositorymodels.Trigger, repositorymodels.RepositoryStatus) {
|
func (r *DataRepository) GetAllTriggers(databaseId string, collectionId string) ([]repositorymodels.Trigger, repositorymodels.RepositoryStatus) {
|
||||||
return r.triggers, repositorymodels.StatusOk
|
r.storeState.RLock()
|
||||||
|
defer r.storeState.RUnlock()
|
||||||
|
|
||||||
|
return maps.Values(r.storeState.Triggers[databaseId][collectionId]), repositorymodels.StatusOk
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *DataRepository) GetTrigger(databaseId string, collectionId string, triggerId string) (repositorymodels.Trigger, repositorymodels.RepositoryStatus) {
|
||||||
|
r.storeState.RLock()
|
||||||
|
defer r.storeState.RUnlock()
|
||||||
|
|
||||||
|
if _, ok := r.storeState.Databases[databaseId]; !ok {
|
||||||
|
return repositorymodels.Trigger{}, repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := r.storeState.Collections[databaseId][collectionId]; !ok {
|
||||||
|
return repositorymodels.Trigger{}, repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if trigger, ok := r.storeState.Triggers[databaseId][collectionId][triggerId]; ok {
|
||||||
|
return trigger, repositorymodels.StatusOk
|
||||||
|
}
|
||||||
|
|
||||||
|
return repositorymodels.Trigger{}, repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *DataRepository) DeleteTrigger(databaseId string, collectionId string, triggerId string) repositorymodels.RepositoryStatus {
|
||||||
|
r.storeState.Lock()
|
||||||
|
defer r.storeState.Unlock()
|
||||||
|
|
||||||
|
if _, ok := r.storeState.Databases[databaseId]; !ok {
|
||||||
|
return repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := r.storeState.Collections[databaseId][collectionId]; !ok {
|
||||||
|
return repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := r.storeState.Triggers[databaseId][collectionId][triggerId]; !ok {
|
||||||
|
return repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(r.storeState.Triggers[databaseId][collectionId], triggerId)
|
||||||
|
|
||||||
|
return repositorymodels.StatusOk
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *DataRepository) CreateTrigger(databaseId string, collectionId string, trigger repositorymodels.Trigger) (repositorymodels.Trigger, repositorymodels.RepositoryStatus) {
|
||||||
|
r.storeState.Lock()
|
||||||
|
defer r.storeState.Unlock()
|
||||||
|
|
||||||
|
var ok bool
|
||||||
|
var database repositorymodels.Database
|
||||||
|
var collection repositorymodels.Collection
|
||||||
|
if trigger.ID == "" {
|
||||||
|
return repositorymodels.Trigger{}, repositorymodels.BadRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
if database, ok = r.storeState.Databases[databaseId]; !ok {
|
||||||
|
return repositorymodels.Trigger{}, repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if collection, ok = r.storeState.Collections[databaseId][collectionId]; !ok {
|
||||||
|
return repositorymodels.Trigger{}, repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok = r.storeState.Triggers[databaseId][collectionId][trigger.ID]; ok {
|
||||||
|
return repositorymodels.Trigger{}, repositorymodels.Conflict
|
||||||
|
}
|
||||||
|
|
||||||
|
trigger.TimeStamp = time.Now().Unix()
|
||||||
|
trigger.ResourceID = resourceid.NewCombined(database.ResourceID, collection.ResourceID, resourceid.New())
|
||||||
|
trigger.ETag = fmt.Sprintf("\"%s\"", uuid.New())
|
||||||
|
trigger.Self = fmt.Sprintf("dbs/%s/colls/%s/triggers/%s/", database.ResourceID, collection.ResourceID, trigger.ResourceID)
|
||||||
|
|
||||||
|
r.storeState.Triggers[databaseId][collectionId][trigger.ID] = trigger
|
||||||
|
|
||||||
|
return trigger, repositorymodels.StatusOk
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,91 @@
|
|||||||
package repositories
|
package repositories
|
||||||
|
|
||||||
import repositorymodels "github.com/pikami/cosmium/internal/repository_models"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
repositorymodels "github.com/pikami/cosmium/internal/repository_models"
|
||||||
|
"github.com/pikami/cosmium/internal/resourceid"
|
||||||
|
"golang.org/x/exp/maps"
|
||||||
|
)
|
||||||
|
|
||||||
func (r *DataRepository) GetAllUserDefinedFunctions(databaseId string, collectionId string) ([]repositorymodels.UserDefinedFunction, repositorymodels.RepositoryStatus) {
|
func (r *DataRepository) GetAllUserDefinedFunctions(databaseId string, collectionId string) ([]repositorymodels.UserDefinedFunction, repositorymodels.RepositoryStatus) {
|
||||||
return r.userDefinedFunctions, repositorymodels.StatusOk
|
r.storeState.RLock()
|
||||||
|
defer r.storeState.RUnlock()
|
||||||
|
|
||||||
|
return maps.Values(r.storeState.UserDefinedFunctions[databaseId][collectionId]), repositorymodels.StatusOk
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *DataRepository) GetUserDefinedFunction(databaseId string, collectionId string, udfId string) (repositorymodels.UserDefinedFunction, repositorymodels.RepositoryStatus) {
|
||||||
|
r.storeState.RLock()
|
||||||
|
defer r.storeState.RUnlock()
|
||||||
|
|
||||||
|
if _, ok := r.storeState.Databases[databaseId]; !ok {
|
||||||
|
return repositorymodels.UserDefinedFunction{}, repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := r.storeState.Collections[databaseId][collectionId]; !ok {
|
||||||
|
return repositorymodels.UserDefinedFunction{}, repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if udf, ok := r.storeState.UserDefinedFunctions[databaseId][collectionId][udfId]; ok {
|
||||||
|
return udf, repositorymodels.StatusOk
|
||||||
|
}
|
||||||
|
|
||||||
|
return repositorymodels.UserDefinedFunction{}, repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *DataRepository) DeleteUserDefinedFunction(databaseId string, collectionId string, udfId string) repositorymodels.RepositoryStatus {
|
||||||
|
r.storeState.Lock()
|
||||||
|
defer r.storeState.Unlock()
|
||||||
|
|
||||||
|
if _, ok := r.storeState.Databases[databaseId]; !ok {
|
||||||
|
return repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := r.storeState.Collections[databaseId][collectionId]; !ok {
|
||||||
|
return repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := r.storeState.UserDefinedFunctions[databaseId][collectionId][udfId]; !ok {
|
||||||
|
return repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(r.storeState.UserDefinedFunctions[databaseId][collectionId], udfId)
|
||||||
|
|
||||||
|
return repositorymodels.StatusOk
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *DataRepository) CreateUserDefinedFunction(databaseId string, collectionId string, udf repositorymodels.UserDefinedFunction) (repositorymodels.UserDefinedFunction, repositorymodels.RepositoryStatus) {
|
||||||
|
r.storeState.Lock()
|
||||||
|
defer r.storeState.Unlock()
|
||||||
|
|
||||||
|
var ok bool
|
||||||
|
var database repositorymodels.Database
|
||||||
|
var collection repositorymodels.Collection
|
||||||
|
if udf.ID == "" {
|
||||||
|
return repositorymodels.UserDefinedFunction{}, repositorymodels.BadRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
if database, ok = r.storeState.Databases[databaseId]; !ok {
|
||||||
|
return repositorymodels.UserDefinedFunction{}, repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if collection, ok = r.storeState.Collections[databaseId][collectionId]; !ok {
|
||||||
|
return repositorymodels.UserDefinedFunction{}, repositorymodels.StatusNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := r.storeState.UserDefinedFunctions[databaseId][collectionId][udf.ID]; ok {
|
||||||
|
return repositorymodels.UserDefinedFunction{}, repositorymodels.Conflict
|
||||||
|
}
|
||||||
|
|
||||||
|
udf.TimeStamp = time.Now().Unix()
|
||||||
|
udf.ResourceID = resourceid.NewCombined(database.ResourceID, collection.ResourceID, resourceid.New())
|
||||||
|
udf.ETag = fmt.Sprintf("\"%s\"", uuid.New())
|
||||||
|
udf.Self = fmt.Sprintf("dbs/%s/colls/%s/udfs/%s/", database.ResourceID, collection.ResourceID, udf.ResourceID)
|
||||||
|
|
||||||
|
r.storeState.UserDefinedFunctions[databaseId][collectionId][udf.ID] = udf
|
||||||
|
|
||||||
|
return udf, repositorymodels.StatusOk
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,22 @@ const (
|
|||||||
BadRequest = 4
|
BadRequest = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type TriggerOperation string
|
||||||
|
|
||||||
|
const (
|
||||||
|
All TriggerOperation = "All"
|
||||||
|
Create TriggerOperation = "Create"
|
||||||
|
Delete TriggerOperation = "Delete"
|
||||||
|
Replace TriggerOperation = "Replace"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TriggerType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
Pre TriggerType = "Pre"
|
||||||
|
Post TriggerType = "Post"
|
||||||
|
)
|
||||||
|
|
||||||
type Collection struct {
|
type Collection struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
IndexingPolicy CollectionIndexingPolicy `json:"indexingPolicy"`
|
IndexingPolicy CollectionIndexingPolicy `json:"indexingPolicy"`
|
||||||
@@ -60,29 +76,29 @@ type UserDefinedFunction struct {
|
|||||||
Body string `json:"body"`
|
Body string `json:"body"`
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
ResourceID string `json:"_rid"`
|
ResourceID string `json:"_rid"`
|
||||||
TimeStamp int `json:"_ts"`
|
TimeStamp int64 `json:"_ts"`
|
||||||
Self string `json:"_self"`
|
Self string `json:"_self"`
|
||||||
Etag string `json:"_etag"`
|
ETag string `json:"_etag"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type StoredProcedure struct {
|
type StoredProcedure struct {
|
||||||
Body string `json:"body"`
|
Body string `json:"body"`
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
ResourceID string `json:"_rid"`
|
ResourceID string `json:"_rid"`
|
||||||
TimeStamp int `json:"_ts"`
|
TimeStamp int64 `json:"_ts"`
|
||||||
Self string `json:"_self"`
|
Self string `json:"_self"`
|
||||||
Etag string `json:"_etag"`
|
ETag string `json:"_etag"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Trigger struct {
|
type Trigger struct {
|
||||||
Body string `json:"body"`
|
Body string `json:"body"`
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
TriggerOperation string `json:"triggerOperation"`
|
TriggerOperation TriggerOperation `json:"triggerOperation"`
|
||||||
TriggerType string `json:"triggerType"`
|
TriggerType TriggerType `json:"triggerType"`
|
||||||
ResourceID string `json:"_rid"`
|
ResourceID string `json:"_rid"`
|
||||||
TimeStamp int `json:"_ts"`
|
TimeStamp int64 `json:"_ts"`
|
||||||
Self string `json:"_self"`
|
Self string `json:"_self"`
|
||||||
Etag string `json:"_etag"`
|
ETag string `json:"_etag"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Document map[string]interface{}
|
type Document map[string]interface{}
|
||||||
@@ -113,4 +129,13 @@ type State struct {
|
|||||||
|
|
||||||
// Map databaseId -> collectionId -> documentId -> Documents
|
// Map databaseId -> collectionId -> documentId -> Documents
|
||||||
Documents map[string]map[string]map[string]Document `json:"documents"`
|
Documents map[string]map[string]map[string]Document `json:"documents"`
|
||||||
|
|
||||||
|
// Map databaseId -> collectionId -> triggerId -> Trigger
|
||||||
|
Triggers map[string]map[string]map[string]Trigger `json:"triggers"`
|
||||||
|
|
||||||
|
// Map databaseId -> collectionId -> spId -> StoredProcedure
|
||||||
|
StoredProcedures map[string]map[string]map[string]StoredProcedure `json:"sprocs"`
|
||||||
|
|
||||||
|
// Map databaseId -> collectionId -> udfId -> UserDefinedFunction
|
||||||
|
UserDefinedFunctions map[string]map[string]map[string]UserDefinedFunction `json:"udfs"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,6 +124,9 @@ const (
|
|||||||
FunctionCallIsString FunctionCallType = "IsString"
|
FunctionCallIsString FunctionCallType = "IsString"
|
||||||
|
|
||||||
FunctionCallArrayConcat FunctionCallType = "ArrayConcat"
|
FunctionCallArrayConcat FunctionCallType = "ArrayConcat"
|
||||||
|
FunctionCallArrayContains FunctionCallType = "ArrayContains"
|
||||||
|
FunctionCallArrayContainsAny FunctionCallType = "ArrayContainsAny"
|
||||||
|
FunctionCallArrayContainsAll FunctionCallType = "ArrayContainsAll"
|
||||||
FunctionCallArrayLength FunctionCallType = "ArrayLength"
|
FunctionCallArrayLength FunctionCallType = "ArrayLength"
|
||||||
FunctionCallArraySlice FunctionCallType = "ArraySlice"
|
FunctionCallArraySlice FunctionCallType = "ArraySlice"
|
||||||
FunctionCallSetIntersect FunctionCallType = "SetIntersect"
|
FunctionCallSetIntersect FunctionCallType = "SetIntersect"
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pikami/cosmium/parsers"
|
"github.com/pikami/cosmium/parsers"
|
||||||
|
testutils "github.com/pikami/cosmium/test_utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_Parse_ArrayFunctions(t *testing.T) {
|
func Test_Parse_ArrayFunctions(t *testing.T) {
|
||||||
@@ -36,6 +37,119 @@ func Test_Parse_ArrayFunctions(t *testing.T) {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("Should parse function ARRAY_CONTAINS()", func(t *testing.T) {
|
||||||
|
testQueryParse(
|
||||||
|
t,
|
||||||
|
`SELECT ARRAY_CONTAINS(c.a1, "value") FROM c`,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayContains,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
parsers.SelectItem{
|
||||||
|
Path: []string{"c", "a1"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
testutils.SelectItem_Constant_String("value"),
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{Value: "c"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should parse function ARRAY_CONTAINS() with partial match", func(t *testing.T) {
|
||||||
|
testQueryParse(
|
||||||
|
t,
|
||||||
|
`SELECT ARRAY_CONTAINS(["a", "b"], "value", true) FROM c`,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayContains,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
parsers.SelectItem{
|
||||||
|
Type: parsers.SelectItemTypeArray,
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
testutils.SelectItem_Constant_String("a"),
|
||||||
|
testutils.SelectItem_Constant_String("b"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
testutils.SelectItem_Constant_String("value"),
|
||||||
|
testutils.SelectItem_Constant_Bool(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{Value: "c"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should parse function ARRAY_CONTAINS_ANY()", func(t *testing.T) {
|
||||||
|
testQueryParse(
|
||||||
|
t,
|
||||||
|
`SELECT ARRAY_CONTAINS_ANY(["a", "b"], "value", true) FROM c`,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayContainsAny,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
parsers.SelectItem{
|
||||||
|
Type: parsers.SelectItemTypeArray,
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
testutils.SelectItem_Constant_String("a"),
|
||||||
|
testutils.SelectItem_Constant_String("b"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
testutils.SelectItem_Constant_String("value"),
|
||||||
|
testutils.SelectItem_Constant_Bool(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{Value: "c"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should parse function ARRAY_CONTAINS_ALL()", func(t *testing.T) {
|
||||||
|
testQueryParse(
|
||||||
|
t,
|
||||||
|
`SELECT ARRAY_CONTAINS_ALL(["a", "b"], "value", true) FROM c`,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayContainsAll,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
parsers.SelectItem{
|
||||||
|
Type: parsers.SelectItemTypeArray,
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
testutils.SelectItem_Constant_String("a"),
|
||||||
|
testutils.SelectItem_Constant_String("b"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
testutils.SelectItem_Constant_String("value"),
|
||||||
|
testutils.SelectItem_Constant_Bool(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{Value: "c"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("Should parse function ARRAY_LENGTH()", func(t *testing.T) {
|
t.Run("Should parse function ARRAY_LENGTH()", func(t *testing.T) {
|
||||||
testQueryParse(
|
testQueryParse(
|
||||||
t,
|
t,
|
||||||
@@ -75,20 +189,8 @@ func Test_Parse_ArrayFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "array"},
|
Path: []string{"c", "array"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_Int(0),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
testutils.SelectItem_Constant_Int(2),
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeInteger,
|
|
||||||
Value: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parsers.SelectItem{
|
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeInteger,
|
|
||||||
Value: 2,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/pikami/cosmium/parsers"
|
"github.com/pikami/cosmium/parsers"
|
||||||
"github.com/pikami/cosmium/parsers/nosql"
|
"github.com/pikami/cosmium/parsers/nosql"
|
||||||
|
testutils "github.com/pikami/cosmium/test_utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// For Parser Debugging
|
// For Parser Debugging
|
||||||
@@ -102,20 +103,8 @@ func Test_Parse(t *testing.T) {
|
|||||||
Path: []string{"c", "id"},
|
Path: []string{"c", "id"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_String("123"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
testutils.SelectItem_Constant_String("456"),
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: "123",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parsers.SelectItem{
|
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: "456",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -457,6 +457,9 @@ AggregateFunctions <- AvgAggregateExpression
|
|||||||
/ SumAggregateExpression
|
/ SumAggregateExpression
|
||||||
|
|
||||||
ArrayFunctions <- ArrayConcatExpression
|
ArrayFunctions <- ArrayConcatExpression
|
||||||
|
/ ArrayContainsExpression
|
||||||
|
/ ArrayContainsAnyExpression
|
||||||
|
/ ArrayContainsAllExpression
|
||||||
/ ArrayLengthExpression
|
/ ArrayLengthExpression
|
||||||
/ ArraySliceExpression
|
/ ArraySliceExpression
|
||||||
/ SetIntersectExpression
|
/ SetIntersectExpression
|
||||||
@@ -626,6 +629,18 @@ ArrayConcatExpression <- "ARRAY_CONCAT"i ws "(" ws arrays:SelectItem others:(ws
|
|||||||
return createFunctionCall(parsers.FunctionCallArrayConcat, append([]interface{}{arrays}, others.([]interface{})...))
|
return createFunctionCall(parsers.FunctionCallArrayConcat, append([]interface{}{arrays}, others.([]interface{})...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArrayContainsExpression <- "ARRAY_CONTAINS"i ws "(" ws array:SelectItem ws "," ws item:SelectItem partialMatch:(ws "," ws ex:SelectItem { return ex, nil })? ws ")" {
|
||||||
|
return createFunctionCall(parsers.FunctionCallArrayContains, []interface{}{array, item, partialMatch})
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayContainsAnyExpression <- "ARRAY_CONTAINS_ANY"i ws "(" ws array:SelectItem items:(ws "," ws ex:SelectItem { return ex, nil })+ ws ")" {
|
||||||
|
return createFunctionCall(parsers.FunctionCallArrayContainsAny, append([]interface{}{array}, items.([]interface{})...))
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayContainsAllExpression <- "ARRAY_CONTAINS_ALL"i ws "(" ws array:SelectItem items:(ws "," ws ex:SelectItem { return ex, nil })+ ws ")" {
|
||||||
|
return createFunctionCall(parsers.FunctionCallArrayContainsAll, append([]interface{}{array}, items.([]interface{})...))
|
||||||
|
}
|
||||||
|
|
||||||
ArrayLengthExpression <- "ARRAY_LENGTH"i ws "(" ws array:SelectItem ws ")" {
|
ArrayLengthExpression <- "ARRAY_LENGTH"i ws "(" ws array:SelectItem ws ")" {
|
||||||
return createFunctionCall(parsers.FunctionCallArrayLength, []interface{}{array})
|
return createFunctionCall(parsers.FunctionCallArrayLength, []interface{}{array})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pikami/cosmium/parsers"
|
"github.com/pikami/cosmium/parsers"
|
||||||
|
testutils "github.com/pikami/cosmium/test_utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_Execute_StringFunctions(t *testing.T) {
|
func Test_Execute_StringFunctions(t *testing.T) {
|
||||||
@@ -23,20 +24,8 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "id"},
|
Path: []string{"c", "id"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_String("123"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
testutils.SelectItem_Constant_Bool(true),
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: "123",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parsers.SelectItem{
|
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeBoolean,
|
|
||||||
Value: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -61,13 +50,7 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "id"},
|
Path: []string{"c", "id"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_String("123"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: "123",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -93,13 +76,7 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "id"},
|
Path: []string{"c", "id"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_String("123"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: "123",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parsers.SelectItem{
|
parsers.SelectItem{
|
||||||
Path: []string{"c", "pk"},
|
Path: []string{"c", "pk"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
@@ -128,20 +105,8 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "id"},
|
Path: []string{"c", "id"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_String("123"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
testutils.SelectItem_Constant_Bool(true),
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: "123",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parsers.SelectItem{
|
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeBoolean,
|
|
||||||
Value: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -166,20 +131,8 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "id"},
|
Path: []string{"c", "id"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_String("123"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
testutils.SelectItem_Constant_Bool(true),
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: "123",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parsers.SelectItem{
|
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeBoolean,
|
|
||||||
Value: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -204,20 +157,8 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "id"},
|
Path: []string{"c", "id"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_String("123"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
testutils.SelectItem_Constant_Bool(true),
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: "123",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parsers.SelectItem{
|
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeBoolean,
|
|
||||||
Value: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -242,20 +183,8 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "id"},
|
Path: []string{"c", "id"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_String("2"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
testutils.SelectItem_Constant_Int(1),
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: "2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parsers.SelectItem{
|
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeInteger,
|
|
||||||
Value: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -352,13 +281,7 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "id"},
|
Path: []string{"c", "id"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_Int(5),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeInteger,
|
|
||||||
Value: 5,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -431,20 +354,8 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "id"},
|
Path: []string{"c", "id"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_String("old"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
testutils.SelectItem_Constant_String("new"),
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: "old",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parsers.SelectItem{
|
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: "new",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -469,13 +380,7 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "id"},
|
Path: []string{"c", "id"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_Int(3),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeInteger,
|
|
||||||
Value: 3,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -524,13 +429,7 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "id"},
|
Path: []string{"c", "id"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_Int(3),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeInteger,
|
|
||||||
Value: 3,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -579,20 +478,8 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "id"},
|
Path: []string{"c", "id"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_Int(1),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
testutils.SelectItem_Constant_Int(5),
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeInteger,
|
|
||||||
Value: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parsers.SelectItem{
|
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeInteger,
|
|
||||||
Value: 5,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pikami/cosmium/parsers"
|
"github.com/pikami/cosmium/parsers"
|
||||||
|
testutils "github.com/pikami/cosmium/test_utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_Parse_Were(t *testing.T) {
|
func Test_Parse_Were(t *testing.T) {
|
||||||
@@ -22,10 +23,7 @@ func Test_Parse_Were(t *testing.T) {
|
|||||||
Filters: parsers.ComparisonExpression{
|
Filters: parsers.ComparisonExpression{
|
||||||
Operation: "=",
|
Operation: "=",
|
||||||
Left: parsers.SelectItem{Path: []string{"c", "isCool"}},
|
Left: parsers.SelectItem{Path: []string{"c", "isCool"}},
|
||||||
Right: parsers.SelectItem{
|
Right: testutils.SelectItem_Constant_Bool(true),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{Type: parsers.ConstantTypeBoolean, Value: true},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -51,18 +49,12 @@ func Test_Parse_Were(t *testing.T) {
|
|||||||
parsers.ComparisonExpression{
|
parsers.ComparisonExpression{
|
||||||
Operation: "=",
|
Operation: "=",
|
||||||
Left: parsers.SelectItem{Path: []string{"c", "id"}},
|
Left: parsers.SelectItem{Path: []string{"c", "id"}},
|
||||||
Right: parsers.SelectItem{
|
Right: testutils.SelectItem_Constant_String("12345"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{Type: parsers.ConstantTypeString, Value: "12345"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
parsers.ComparisonExpression{
|
parsers.ComparisonExpression{
|
||||||
Operation: "=",
|
Operation: "=",
|
||||||
Left: parsers.SelectItem{Path: []string{"c", "pk"}},
|
Left: parsers.SelectItem{Path: []string{"c", "pk"}},
|
||||||
Right: parsers.SelectItem{
|
Right: testutils.SelectItem_Constant_Int(123),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{Type: parsers.ConstantTypeInteger, Value: 123},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -87,10 +79,7 @@ func Test_Parse_Were(t *testing.T) {
|
|||||||
parsers.ComparisonExpression{
|
parsers.ComparisonExpression{
|
||||||
Operation: "=",
|
Operation: "=",
|
||||||
Left: parsers.SelectItem{Path: []string{"c", "isCool"}},
|
Left: parsers.SelectItem{Path: []string{"c", "isCool"}},
|
||||||
Right: parsers.SelectItem{
|
Right: testutils.SelectItem_Constant_Bool(true),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{Type: parsers.ConstantTypeBoolean, Value: true},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
parsers.LogicalExpression{
|
parsers.LogicalExpression{
|
||||||
Operation: parsers.LogicalExpressionTypeOr,
|
Operation: parsers.LogicalExpressionTypeOr,
|
||||||
@@ -98,18 +87,12 @@ func Test_Parse_Were(t *testing.T) {
|
|||||||
parsers.ComparisonExpression{
|
parsers.ComparisonExpression{
|
||||||
Operation: "=",
|
Operation: "=",
|
||||||
Left: parsers.SelectItem{Path: []string{"c", "id"}},
|
Left: parsers.SelectItem{Path: []string{"c", "id"}},
|
||||||
Right: parsers.SelectItem{
|
Right: testutils.SelectItem_Constant_String("123"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{Type: parsers.ConstantTypeString, Value: "123"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
parsers.ComparisonExpression{
|
parsers.ComparisonExpression{
|
||||||
Operation: "=",
|
Operation: "=",
|
||||||
Left: parsers.SelectItem{Path: []string{"c", "id"}},
|
Left: parsers.SelectItem{Path: []string{"c", "id"}},
|
||||||
Right: parsers.SelectItem{
|
Right: testutils.SelectItem_Constant_String("456"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{Type: parsers.ConstantTypeString, Value: "456"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -136,42 +119,27 @@ func Test_Parse_Were(t *testing.T) {
|
|||||||
Expressions: []interface{}{
|
Expressions: []interface{}{
|
||||||
parsers.ComparisonExpression{
|
parsers.ComparisonExpression{
|
||||||
Left: parsers.SelectItem{Path: []string{"c", "boolean"}},
|
Left: parsers.SelectItem{Path: []string{"c", "boolean"}},
|
||||||
Right: parsers.SelectItem{
|
Right: testutils.SelectItem_Constant_Bool(true),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{Type: parsers.ConstantTypeBoolean, Value: true},
|
|
||||||
},
|
|
||||||
Operation: "=",
|
Operation: "=",
|
||||||
},
|
},
|
||||||
parsers.ComparisonExpression{
|
parsers.ComparisonExpression{
|
||||||
Left: parsers.SelectItem{Path: []string{"c", "integer"}},
|
Left: parsers.SelectItem{Path: []string{"c", "integer"}},
|
||||||
Right: parsers.SelectItem{
|
Right: testutils.SelectItem_Constant_Int(1),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{Type: parsers.ConstantTypeInteger, Value: 1},
|
|
||||||
},
|
|
||||||
Operation: "=",
|
Operation: "=",
|
||||||
},
|
},
|
||||||
parsers.ComparisonExpression{
|
parsers.ComparisonExpression{
|
||||||
Left: parsers.SelectItem{Path: []string{"c", "float"}},
|
Left: parsers.SelectItem{Path: []string{"c", "float"}},
|
||||||
Right: parsers.SelectItem{
|
Right: testutils.SelectItem_Constant_Float(6.9),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{Type: parsers.ConstantTypeFloat, Value: 6.9},
|
|
||||||
},
|
|
||||||
Operation: "=",
|
Operation: "=",
|
||||||
},
|
},
|
||||||
parsers.ComparisonExpression{
|
parsers.ComparisonExpression{
|
||||||
Left: parsers.SelectItem{Path: []string{"c", "string"}},
|
Left: parsers.SelectItem{Path: []string{"c", "string"}},
|
||||||
Right: parsers.SelectItem{
|
Right: testutils.SelectItem_Constant_String("hello"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{Type: parsers.ConstantTypeString, Value: "hello"},
|
|
||||||
},
|
|
||||||
Operation: "=",
|
Operation: "=",
|
||||||
},
|
},
|
||||||
parsers.ComparisonExpression{
|
parsers.ComparisonExpression{
|
||||||
Left: parsers.SelectItem{Path: []string{"c", "param"}},
|
Left: parsers.SelectItem{Path: []string{"c", "param"}},
|
||||||
Right: parsers.SelectItem{
|
Right: testutils.SelectItem_Constant_Parameter("@param_id1"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{Type: parsers.ConstantTypeParameterConstant, Value: "@param_id1"},
|
|
||||||
},
|
|
||||||
Operation: "=",
|
Operation: "=",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -16,6 +16,86 @@ func (r rowContext) array_Concat(arguments []interface{}) []interface{} {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r rowContext) array_Contains(arguments []interface{}) bool {
|
||||||
|
array := r.parseArray(arguments[0])
|
||||||
|
if array == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
exprToSearch := r.resolveSelectItem(arguments[1].(parsers.SelectItem))
|
||||||
|
|
||||||
|
partialSearch := false
|
||||||
|
if len(arguments) > 2 {
|
||||||
|
boolExpr := r.resolveSelectItem(arguments[2].(parsers.SelectItem))
|
||||||
|
if boolValue, ok := boolExpr.(bool); ok {
|
||||||
|
partialSearch = boolValue
|
||||||
|
} else {
|
||||||
|
logger.Error("array_Contains - got parameters of wrong type")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range array {
|
||||||
|
if partialSearch {
|
||||||
|
if r.partialMatch(item, exprToSearch) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if reflect.DeepEqual(item, exprToSearch) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r rowContext) array_Contains_Any(arguments []interface{}) bool {
|
||||||
|
array := r.parseArray(arguments[0])
|
||||||
|
if array == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
valueSelectItems := arguments[1:]
|
||||||
|
|
||||||
|
for _, valueSelectItem := range valueSelectItems {
|
||||||
|
value := r.resolveSelectItem(valueSelectItem.(parsers.SelectItem))
|
||||||
|
for _, item := range array {
|
||||||
|
if reflect.DeepEqual(item, value) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r rowContext) array_Contains_All(arguments []interface{}) bool {
|
||||||
|
array := r.parseArray(arguments[0])
|
||||||
|
if array == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
valueSelectItems := arguments[1:]
|
||||||
|
|
||||||
|
for _, valueSelectItem := range valueSelectItems {
|
||||||
|
value := r.resolveSelectItem(valueSelectItem.(parsers.SelectItem))
|
||||||
|
|
||||||
|
found := false
|
||||||
|
for _, item := range array {
|
||||||
|
if reflect.DeepEqual(item, value) {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (r rowContext) array_Length(arguments []interface{}) int {
|
func (r rowContext) array_Length(arguments []interface{}) int {
|
||||||
array := r.parseArray(arguments[0])
|
array := r.parseArray(arguments[0])
|
||||||
if array == nil {
|
if array == nil {
|
||||||
@@ -129,3 +209,21 @@ func (r rowContext) parseArray(argument interface{}) []interface{} {
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r rowContext) partialMatch(item interface{}, exprToSearch interface{}) bool {
|
||||||
|
itemValue := reflect.ValueOf(item)
|
||||||
|
exprValue := reflect.ValueOf(exprToSearch)
|
||||||
|
|
||||||
|
if itemValue.Kind() != reflect.Map || exprValue.Kind() != reflect.Map {
|
||||||
|
logger.Error("partialMatch got parameters of wrong type")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, key := range exprValue.MapKeys() {
|
||||||
|
if itemValue.MapIndex(key).Interface() != exprValue.MapIndex(key).Interface() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/pikami/cosmium/parsers"
|
"github.com/pikami/cosmium/parsers"
|
||||||
memoryexecutor "github.com/pikami/cosmium/query_executors/memory_executor"
|
memoryexecutor "github.com/pikami/cosmium/query_executors/memory_executor"
|
||||||
|
testutils "github.com/pikami/cosmium/test_utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_Execute_ArrayFunctions(t *testing.T) {
|
func Test_Execute_ArrayFunctions(t *testing.T) {
|
||||||
@@ -52,6 +53,286 @@ func Test_Execute_ArrayFunctions(t *testing.T) {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("Should execute function ARRAY_CONTAINS()", func(t *testing.T) {
|
||||||
|
testQueryExecute(
|
||||||
|
t,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
Parameters: map[string]interface{}{
|
||||||
|
"@categories": []interface{}{"coats", "jackets", "sweatshirts"},
|
||||||
|
"@objectArray": []interface{}{map[string]interface{}{"category": "shirts", "color": "blue"}},
|
||||||
|
"@fullMatchObject": map[string]interface{}{"category": "shirts", "color": "blue"},
|
||||||
|
"@partialMatchObject": map[string]interface{}{"category": "shirts"},
|
||||||
|
"@missingPartialMatchObject": map[string]interface{}{"category": "shorts", "color": "blue"},
|
||||||
|
},
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{
|
||||||
|
Alias: "ContainsItem",
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayContains,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
testutils.SelectItem_Constant_Parameter("@categories"),
|
||||||
|
testutils.SelectItem_Constant_String("coats"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Alias: "MissingItem",
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayContains,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
testutils.SelectItem_Constant_Parameter("@categories"),
|
||||||
|
testutils.SelectItem_Constant_String("hoodies"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Alias: "ContainsFullMatchObject",
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayContains,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
testutils.SelectItem_Constant_Parameter("@objectArray"),
|
||||||
|
testutils.SelectItem_Constant_Parameter("@fullMatchObject"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Alias: "MissingFullMatchObject",
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayContains,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
testutils.SelectItem_Constant_Parameter("@objectArray"),
|
||||||
|
testutils.SelectItem_Constant_Parameter("@partialMatchObject"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Alias: "ContainsPartialMatchObject",
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayContains,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
testutils.SelectItem_Constant_Parameter("@objectArray"),
|
||||||
|
testutils.SelectItem_Constant_Parameter("@partialMatchObject"),
|
||||||
|
testutils.SelectItem_Constant_Bool(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Alias: "MissingPartialMatchObject",
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayContains,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
testutils.SelectItem_Constant_Parameter("@objectArray"),
|
||||||
|
testutils.SelectItem_Constant_Parameter("@missingPartialMatchObject"),
|
||||||
|
testutils.SelectItem_Constant_Bool(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[]memoryexecutor.RowType{map[string]interface{}{"id": "123"}},
|
||||||
|
[]memoryexecutor.RowType{
|
||||||
|
map[string]interface{}{
|
||||||
|
"ContainsItem": true,
|
||||||
|
"MissingItem": false,
|
||||||
|
"ContainsFullMatchObject": true,
|
||||||
|
"MissingFullMatchObject": false,
|
||||||
|
"ContainsPartialMatchObject": true,
|
||||||
|
"MissingPartialMatchObject": false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should execute function ARRAY_CONTAINS_ANY()", func(t *testing.T) {
|
||||||
|
testQueryExecute(
|
||||||
|
t,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
Parameters: map[string]interface{}{
|
||||||
|
"@mixedArray": []interface{}{1, true, "3", []int{1, 2, 3}},
|
||||||
|
"@numbers": []interface{}{1, 2, 3, 4},
|
||||||
|
"@emptyArray": []interface{}{},
|
||||||
|
"@arr123": []interface{}{1, 2, 3},
|
||||||
|
},
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{
|
||||||
|
Alias: "matchesEntireArray",
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayContainsAny,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
testutils.SelectItem_Constant_Parameter("@mixedArray"),
|
||||||
|
testutils.SelectItem_Constant_Int(1),
|
||||||
|
testutils.SelectItem_Constant_Bool(true),
|
||||||
|
testutils.SelectItem_Constant_String("3"),
|
||||||
|
testutils.SelectItem_Constant_Parameter("@arr123"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Alias: "matchesSomeValues",
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayContainsAny,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
testutils.SelectItem_Constant_Parameter("@numbers"),
|
||||||
|
testutils.SelectItem_Constant_Int(2),
|
||||||
|
testutils.SelectItem_Constant_Int(3),
|
||||||
|
testutils.SelectItem_Constant_Int(4),
|
||||||
|
testutils.SelectItem_Constant_Int(5),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Alias: "matchSingleValue",
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayContainsAny,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
testutils.SelectItem_Constant_Parameter("@numbers"),
|
||||||
|
testutils.SelectItem_Constant_Int(1),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Alias: "noMatches",
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayContainsAny,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
testutils.SelectItem_Constant_Parameter("@numbers"),
|
||||||
|
testutils.SelectItem_Constant_Int(5),
|
||||||
|
testutils.SelectItem_Constant_Int(6),
|
||||||
|
testutils.SelectItem_Constant_Int(7),
|
||||||
|
testutils.SelectItem_Constant_Int(8),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Alias: "emptyArray",
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayContainsAny,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
testutils.SelectItem_Constant_Parameter("@emptyArray"),
|
||||||
|
testutils.SelectItem_Constant_Int(1),
|
||||||
|
testutils.SelectItem_Constant_Int(2),
|
||||||
|
testutils.SelectItem_Constant_Int(3),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[]memoryexecutor.RowType{map[string]interface{}{"id": "123"}},
|
||||||
|
[]memoryexecutor.RowType{
|
||||||
|
map[string]interface{}{
|
||||||
|
"matchesEntireArray": true,
|
||||||
|
"matchesSomeValues": true,
|
||||||
|
"matchSingleValue": true,
|
||||||
|
"noMatches": false,
|
||||||
|
"emptyArray": false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should execute function ARRAY_CONTAINS_ALL()", func(t *testing.T) {
|
||||||
|
testQueryExecute(
|
||||||
|
t,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
Parameters: map[string]interface{}{
|
||||||
|
"@mixedArray": []interface{}{1, true, "3", []interface{}{1, 2, 3}},
|
||||||
|
"@numbers": []interface{}{1, 2, 3, 4},
|
||||||
|
"@emptyArray": []interface{}{},
|
||||||
|
"@arr123": []interface{}{1, 2, 3},
|
||||||
|
},
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{
|
||||||
|
Alias: "matchesEntireArray",
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayContainsAll,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
testutils.SelectItem_Constant_Parameter("@mixedArray"),
|
||||||
|
testutils.SelectItem_Constant_Int(1),
|
||||||
|
testutils.SelectItem_Constant_Bool(true),
|
||||||
|
testutils.SelectItem_Constant_String("3"),
|
||||||
|
testutils.SelectItem_Constant_Parameter("@arr123"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Alias: "matchesSomeValues",
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayContainsAll,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
testutils.SelectItem_Constant_Parameter("@numbers"),
|
||||||
|
testutils.SelectItem_Constant_Int(2),
|
||||||
|
testutils.SelectItem_Constant_Int(3),
|
||||||
|
testutils.SelectItem_Constant_Int(4),
|
||||||
|
testutils.SelectItem_Constant_Int(5),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Alias: "matchSingleValue",
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayContainsAll,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
testutils.SelectItem_Constant_Parameter("@numbers"),
|
||||||
|
testutils.SelectItem_Constant_Int(1),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Alias: "noMatches",
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayContainsAll,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
testutils.SelectItem_Constant_Parameter("@numbers"),
|
||||||
|
testutils.SelectItem_Constant_Int(5),
|
||||||
|
testutils.SelectItem_Constant_Int(6),
|
||||||
|
testutils.SelectItem_Constant_Int(7),
|
||||||
|
testutils.SelectItem_Constant_Int(8),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Alias: "emptyArray",
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayContainsAll,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
testutils.SelectItem_Constant_Parameter("@emptyArray"),
|
||||||
|
testutils.SelectItem_Constant_Int(1),
|
||||||
|
testutils.SelectItem_Constant_Int(2),
|
||||||
|
testutils.SelectItem_Constant_Int(3),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[]memoryexecutor.RowType{map[string]interface{}{"id": "123"}},
|
||||||
|
[]memoryexecutor.RowType{
|
||||||
|
map[string]interface{}{
|
||||||
|
"matchesEntireArray": true,
|
||||||
|
"matchesSomeValues": false,
|
||||||
|
"matchSingleValue": true,
|
||||||
|
"noMatches": false,
|
||||||
|
"emptyArray": false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("Should execute function ARRAY_LENGTH()", func(t *testing.T) {
|
t.Run("Should execute function ARRAY_LENGTH()", func(t *testing.T) {
|
||||||
testQueryExecute(
|
testQueryExecute(
|
||||||
t,
|
t,
|
||||||
@@ -105,20 +386,8 @@ func Test_Execute_ArrayFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "arr2"},
|
Path: []string{"c", "arr2"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_Int(1),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
testutils.SelectItem_Constant_Int(2),
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeInteger,
|
|
||||||
Value: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parsers.SelectItem{
|
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeInteger,
|
|
||||||
Value: 2,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -470,6 +470,12 @@ func (r rowContext) selectItem_SelectItemTypeFunctionCall(functionCall parsers.F
|
|||||||
|
|
||||||
case parsers.FunctionCallArrayConcat:
|
case parsers.FunctionCallArrayConcat:
|
||||||
return r.array_Concat(functionCall.Arguments)
|
return r.array_Concat(functionCall.Arguments)
|
||||||
|
case parsers.FunctionCallArrayContains:
|
||||||
|
return r.array_Contains(functionCall.Arguments)
|
||||||
|
case parsers.FunctionCallArrayContainsAny:
|
||||||
|
return r.array_Contains_Any(functionCall.Arguments)
|
||||||
|
case parsers.FunctionCallArrayContainsAll:
|
||||||
|
return r.array_Contains_All(functionCall.Arguments)
|
||||||
case parsers.FunctionCallArrayLength:
|
case parsers.FunctionCallArrayLength:
|
||||||
return r.array_Length(functionCall.Arguments)
|
return r.array_Length(functionCall.Arguments)
|
||||||
case parsers.FunctionCallArraySlice:
|
case parsers.FunctionCallArraySlice:
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/pikami/cosmium/parsers"
|
"github.com/pikami/cosmium/parsers"
|
||||||
memoryexecutor "github.com/pikami/cosmium/query_executors/memory_executor"
|
memoryexecutor "github.com/pikami/cosmium/query_executors/memory_executor"
|
||||||
|
testutils "github.com/pikami/cosmium/test_utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func testQueryExecute(
|
func testQueryExecute(
|
||||||
@@ -111,20 +112,8 @@ func Test_Execute(t *testing.T) {
|
|||||||
Path: []string{"c", "id"},
|
Path: []string{"c", "id"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_String("123"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
testutils.SelectItem_Constant_String("456"),
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: "123",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parsers.SelectItem{
|
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: "456",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/pikami/cosmium/parsers"
|
"github.com/pikami/cosmium/parsers"
|
||||||
memoryexecutor "github.com/pikami/cosmium/query_executors/memory_executor"
|
memoryexecutor "github.com/pikami/cosmium/query_executors/memory_executor"
|
||||||
|
testutils "github.com/pikami/cosmium/test_utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_Execute_StringFunctions(t *testing.T) {
|
func Test_Execute_StringFunctions(t *testing.T) {
|
||||||
@@ -33,20 +34,8 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "pk"},
|
Path: []string{"c", "pk"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_String("aaa"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
testutils.SelectItem_Constant_Bool(true),
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: "aaa",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parsers.SelectItem{
|
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeBoolean,
|
|
||||||
Value: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -81,13 +70,7 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "pk"},
|
Path: []string{"c", "pk"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_String("aaa"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: "aaa",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -119,20 +102,8 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "id"},
|
Path: []string{"c", "id"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_String(" "),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
testutils.SelectItem_Constant_Int(123),
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: " ",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parsers.SelectItem{
|
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: 123,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parsers.SelectItem{
|
parsers.SelectItem{
|
||||||
Path: []string{"c", "pk"},
|
Path: []string{"c", "pk"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
@@ -171,20 +142,8 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "id"},
|
Path: []string{"c", "id"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_String("2"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
testutils.SelectItem_Constant_Bool(true),
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: "2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parsers.SelectItem{
|
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeBoolean,
|
|
||||||
Value: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -219,20 +178,8 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "id"},
|
Path: []string{"c", "id"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_String("3"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
testutils.SelectItem_Constant_Bool(true),
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: "3",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parsers.SelectItem{
|
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeBoolean,
|
|
||||||
Value: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -267,20 +214,8 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "id"},
|
Path: []string{"c", "id"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_String("1"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
testutils.SelectItem_Constant_Bool(true),
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: "1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parsers.SelectItem{
|
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeBoolean,
|
|
||||||
Value: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -315,20 +250,8 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "str"},
|
Path: []string{"c", "str"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_String("o"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
testutils.SelectItem_Constant_Int(4),
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: "o",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parsers.SelectItem{
|
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeInteger,
|
|
||||||
Value: 4,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -397,13 +320,7 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "str"},
|
Path: []string{"c", "str"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_Int(3),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeInteger,
|
|
||||||
Value: 3,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -506,20 +423,8 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "str"},
|
Path: []string{"c", "str"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_String("world"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
testutils.SelectItem_Constant_String("universe"),
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: "world",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parsers.SelectItem{
|
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeString,
|
|
||||||
Value: "universe",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -554,13 +459,7 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "str"},
|
Path: []string{"c", "str"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_Int(3),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeInteger,
|
|
||||||
Value: 3,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -629,13 +528,7 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "str"},
|
Path: []string{"c", "str"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_Int(3),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeInteger,
|
|
||||||
Value: 3,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -704,20 +597,8 @@ func Test_Execute_StringFunctions(t *testing.T) {
|
|||||||
Path: []string{"c", "str"},
|
Path: []string{"c", "str"},
|
||||||
Type: parsers.SelectItemTypeField,
|
Type: parsers.SelectItemTypeField,
|
||||||
},
|
},
|
||||||
parsers.SelectItem{
|
testutils.SelectItem_Constant_Int(2),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
testutils.SelectItem_Constant_Int(4),
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeInteger,
|
|
||||||
Value: 2,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parsers.SelectItem{
|
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{
|
|
||||||
Type: parsers.ConstantTypeInteger,
|
|
||||||
Value: 4,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/pikami/cosmium/parsers"
|
"github.com/pikami/cosmium/parsers"
|
||||||
memoryexecutor "github.com/pikami/cosmium/query_executors/memory_executor"
|
memoryexecutor "github.com/pikami/cosmium/query_executors/memory_executor"
|
||||||
|
testutils "github.com/pikami/cosmium/test_utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_Execute_Where(t *testing.T) {
|
func Test_Execute_Where(t *testing.T) {
|
||||||
@@ -26,10 +27,7 @@ func Test_Execute_Where(t *testing.T) {
|
|||||||
Filters: parsers.ComparisonExpression{
|
Filters: parsers.ComparisonExpression{
|
||||||
Operation: "=",
|
Operation: "=",
|
||||||
Left: parsers.SelectItem{Path: []string{"c", "isCool"}},
|
Left: parsers.SelectItem{Path: []string{"c", "isCool"}},
|
||||||
Right: parsers.SelectItem{
|
Right: testutils.SelectItem_Constant_Bool(true),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{Type: parsers.ConstantTypeBoolean, Value: true},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mockData,
|
mockData,
|
||||||
@@ -52,10 +50,7 @@ func Test_Execute_Where(t *testing.T) {
|
|||||||
Filters: parsers.ComparisonExpression{
|
Filters: parsers.ComparisonExpression{
|
||||||
Operation: "=",
|
Operation: "=",
|
||||||
Left: parsers.SelectItem{Path: []string{"c", "id"}},
|
Left: parsers.SelectItem{Path: []string{"c", "id"}},
|
||||||
Right: parsers.SelectItem{
|
Right: testutils.SelectItem_Constant_Parameter("@param_id"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{Type: parsers.ConstantTypeParameterConstant, Value: "@param_id"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
Parameters: map[string]interface{}{
|
Parameters: map[string]interface{}{
|
||||||
"@param_id": "456",
|
"@param_id": "456",
|
||||||
@@ -83,18 +78,12 @@ func Test_Execute_Where(t *testing.T) {
|
|||||||
parsers.ComparisonExpression{
|
parsers.ComparisonExpression{
|
||||||
Operation: "=",
|
Operation: "=",
|
||||||
Left: parsers.SelectItem{Path: []string{"c", "id"}},
|
Left: parsers.SelectItem{Path: []string{"c", "id"}},
|
||||||
Right: parsers.SelectItem{
|
Right: testutils.SelectItem_Constant_String("67890"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{Type: parsers.ConstantTypeString, Value: "67890"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
parsers.ComparisonExpression{
|
parsers.ComparisonExpression{
|
||||||
Operation: "=",
|
Operation: "=",
|
||||||
Left: parsers.SelectItem{Path: []string{"c", "pk"}},
|
Left: parsers.SelectItem{Path: []string{"c", "pk"}},
|
||||||
Right: parsers.SelectItem{
|
Right: testutils.SelectItem_Constant_Int(456),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{Type: parsers.ConstantTypeInteger, Value: 456},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -120,10 +109,7 @@ func Test_Execute_Where(t *testing.T) {
|
|||||||
parsers.ComparisonExpression{
|
parsers.ComparisonExpression{
|
||||||
Operation: "=",
|
Operation: "=",
|
||||||
Left: parsers.SelectItem{Path: []string{"c", "isCool"}},
|
Left: parsers.SelectItem{Path: []string{"c", "isCool"}},
|
||||||
Right: parsers.SelectItem{
|
Right: testutils.SelectItem_Constant_Bool(true),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{Type: parsers.ConstantTypeBoolean, Value: true},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
parsers.LogicalExpression{
|
parsers.LogicalExpression{
|
||||||
Operation: parsers.LogicalExpressionTypeOr,
|
Operation: parsers.LogicalExpressionTypeOr,
|
||||||
@@ -131,18 +117,12 @@ func Test_Execute_Where(t *testing.T) {
|
|||||||
parsers.ComparisonExpression{
|
parsers.ComparisonExpression{
|
||||||
Operation: "=",
|
Operation: "=",
|
||||||
Left: parsers.SelectItem{Path: []string{"c", "id"}},
|
Left: parsers.SelectItem{Path: []string{"c", "id"}},
|
||||||
Right: parsers.SelectItem{
|
Right: testutils.SelectItem_Constant_String("123"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{Type: parsers.ConstantTypeString, Value: "123"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
parsers.ComparisonExpression{
|
parsers.ComparisonExpression{
|
||||||
Operation: "=",
|
Operation: "=",
|
||||||
Left: parsers.SelectItem{Path: []string{"c", "id"}},
|
Left: parsers.SelectItem{Path: []string{"c", "id"}},
|
||||||
Right: parsers.SelectItem{
|
Right: testutils.SelectItem_Constant_String("456"),
|
||||||
Type: parsers.SelectItemTypeConstant,
|
|
||||||
Value: parsers.Constant{Type: parsers.ConstantTypeString, Value: "456"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
53
test_utils/parser_model_gen.go
Normal file
53
test_utils/parser_model_gen.go
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package testutils
|
||||||
|
|
||||||
|
import "github.com/pikami/cosmium/parsers"
|
||||||
|
|
||||||
|
func SelectItem_Constant_String(value string) parsers.SelectItem {
|
||||||
|
return parsers.SelectItem{
|
||||||
|
Type: parsers.SelectItemTypeConstant,
|
||||||
|
Value: parsers.Constant{
|
||||||
|
Type: parsers.ConstantTypeString,
|
||||||
|
Value: value,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SelectItem_Constant_Int(value int) parsers.SelectItem {
|
||||||
|
return parsers.SelectItem{
|
||||||
|
Type: parsers.SelectItemTypeConstant,
|
||||||
|
Value: parsers.Constant{
|
||||||
|
Type: parsers.ConstantTypeInteger,
|
||||||
|
Value: value,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SelectItem_Constant_Float(value float64) parsers.SelectItem {
|
||||||
|
return parsers.SelectItem{
|
||||||
|
Type: parsers.SelectItemTypeConstant,
|
||||||
|
Value: parsers.Constant{
|
||||||
|
Type: parsers.ConstantTypeFloat,
|
||||||
|
Value: value,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SelectItem_Constant_Bool(value bool) parsers.SelectItem {
|
||||||
|
return parsers.SelectItem{
|
||||||
|
Type: parsers.SelectItemTypeConstant,
|
||||||
|
Value: parsers.Constant{
|
||||||
|
Type: parsers.ConstantTypeBoolean,
|
||||||
|
Value: value,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SelectItem_Constant_Parameter(name string) parsers.SelectItem {
|
||||||
|
return parsers.SelectItem{
|
||||||
|
Type: parsers.SelectItemTypeConstant,
|
||||||
|
Value: parsers.Constant{
|
||||||
|
Type: parsers.ConstantTypeParameterConstant,
|
||||||
|
Value: name,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user