This is an automated email from the ASF dual-hosted git repository.

ako pushed a commit to branch ageviewer_go
in repository https://gitbox.apache.org/repos/asf/age.git


The following commit(s) were added to refs/heads/ageviewer_go by this push:
     new 8a3406a9 [Ageviewer_go_Desktop] Added functionalities to read query 
response dynamically (#836)
8a3406a9 is described below

commit 8a3406a99b418c79a6647b90765eaf3088555631
Author: Kamlesh Kumar <[email protected]>
AuthorDate: Fri Apr 28 09:19:15 2023 +0500

    [Ageviewer_go_Desktop] Added functionalities to read query response 
dynamically (#836)
    
    * Function to disconnect database add to backend
    
    * Added functionalities to read query response dynamically
---
 backend/miscellaneous/cypher.go  | 40 ++++++++++++++++++++++++++++
 backend/miscellaneous/results.go |  7 +++++
 backend/models/graph.go          | 14 +++++++---
 backend/routes/query.go          | 56 ++++++++++++++++++----------------------
 4 files changed, 82 insertions(+), 35 deletions(-)

diff --git a/backend/miscellaneous/cypher.go b/backend/miscellaneous/cypher.go
new file mode 100644
index 00000000..2bad06bc
--- /dev/null
+++ b/backend/miscellaneous/cypher.go
@@ -0,0 +1,40 @@
+package miscellaneous
+
+import (
+       "database/sql"
+)
+
+func CypherCall(db *sql.DB, q map[string]string, c chan<- ChannelResults) {
+       data := ChannelResults{}
+       results := []interface{}{}
+       rows, err := db.Query(q["query"])
+       if err != nil {
+               data.Err = err
+               c <- data
+               return
+       }
+       cols, _ := rows.ColumnTypes()
+       if len(cols) == 1 && cols[0].DatabaseTypeName() == "VOID" {
+               data.Msg = map[string]string{
+                       "status": "success",
+               }
+               c <- data
+               return
+       }
+
+       for rows.Next() {
+               rawData := make([]any, len(cols))
+               for i := 0; i < len(cols); i++ {
+                       rawData[i] = new(string)
+               }
+
+               err := rows.Scan(rawData...)
+               if err != nil {
+                       data.Err = err
+                       break
+               }
+               results = append(results, rawData)
+       }
+       data.Res = results
+       c <- data
+}
diff --git a/backend/miscellaneous/results.go b/backend/miscellaneous/results.go
new file mode 100644
index 00000000..963fd404
--- /dev/null
+++ b/backend/miscellaneous/results.go
@@ -0,0 +1,7 @@
+package miscellaneous
+
+type ChannelResults struct {
+       Res any
+       Msg map[string]string
+       Err error
+}
diff --git a/backend/models/graph.go b/backend/models/graph.go
index 61380faf..cb5df677 100644
--- a/backend/models/graph.go
+++ b/backend/models/graph.go
@@ -15,15 +15,21 @@ type Graph struct {
 GetMetaData returns the metadata for a given graph instance g, based on the 
version of the database.
 and returns a set of rows and an error (if any)
 */
-func (g *Graph) GetMetaData(conn *sql.DB, v int) (*sql.Rows, error) {
+func (g *Graph) GetMetaData(conn *sql.DB, v int, dataChan chan<- *sql.Rows, 
errorChan chan<- error) {
 
        defer conn.Close()
+       var data *sql.Rows
+       var err error
+
        switch v {
        case 11:
-               return conn.Query(db.META_DATA_11, g.Name)
+               data, err = conn.Query(db.META_DATA_11, g.Name)
        case 12:
-               return conn.Query(db.META_DATA_12, g.Name)
+               data, err = conn.Query(db.META_DATA_12, g.Name)
        default:
-               return nil, errors.New("unsupported version")
+               err = errors.New("unsupported version")
        }
+
+       errorChan <- err
+       dataChan <- data
 }
diff --git a/backend/routes/query.go b/backend/routes/query.go
index dea66cb9..39aedf3b 100644
--- a/backend/routes/query.go
+++ b/backend/routes/query.go
@@ -32,19 +32,19 @@ func CypherMiddleWare(next echo.HandlerFunc) 
echo.HandlerFunc {
                if err != nil {
                        return echo.NewHTTPError(400, err.Error())
                }
-               if err = conn.Ping(); err != nil { // check if the connection 
is still valid
+               if err = conn.Ping(); err != nil {
                        return echo.NewHTTPError(400, err.Error())
                }
                if !user.GraphInit {
-                       _, err = conn.Exec(db.INIT_EXTENSION) // initialize the 
AGE extension, if it is not already
+                       _, err = conn.Exec(db.INIT_EXTENSION)
                        if err != nil {
                                msg := fmt.Sprintf("could not communicate with 
db\nerror: %s", err.Error())
                                return echo.NewHTTPError(400, msg)
                        }
-                       user.GraphInit = true // set the flag to true, so that 
the extension is not initialized again
+                       user.GraphInit = true
                }
                if user.Version == 0 {
-                       rows, err := conn.Query(db.PG_VERSION) // get the 
version of the database, if Version in User connection struct is 0.
+                       rows, err := conn.Query(db.PG_VERSION)
                        if err != nil {
                                fmt.Print(err.Error())
                        }
@@ -65,17 +65,15 @@ func CypherMiddleWare(next echo.HandlerFunc) 
echo.HandlerFunc {
 }
 
 /*
- Cypher function processes Cypher queries in a context object, The function 
extracts
- the query from the context object, executes it on a database connection, and 
returns
- the results as a JSON response. It also handles errors that may arise during 
the query execution.
+Cypher function processes Cypher queries in a context object, The function 
extracts
+the query from the context object, executes it on a database connection, and 
returns
+the results as a JSON response. It also handles errors that may arise during 
the query execution.
 */
-
 func Cypher(ctx echo.Context) error {
        q := map[string]string{}
-       results := []interface{}{}
        var err error
 
-       err = ctx.Bind(&q) // extract the query from the request body
+       err = ctx.Bind(&q)
        if err != nil {
                e := m.ErrorHandle{
                        Msg: "unable to parse query",
@@ -83,28 +81,22 @@ func Cypher(ctx echo.Context) error {
                }
                return ctx.JSON(400, e.JSON())
        }
-       conn := ctx.Get("conn").(*sql.DB)   // get the database connection from 
the context object
-       rows, err := conn.Query(q["query"]) // execute the query on the database
-
+       conn := ctx.Get("conn").(*sql.DB)
+       c := make(chan m.ChannelResults, 1)
+       m.CypherCall(conn, q, c)
+       data := <-c
+       err = data.Err
+       res := data.Res
+       msg := data.Msg
        if err != nil {
                return echo.NewHTTPError(400, fmt.Sprintf("unable to process 
query. error: %s", err.Error()))
        }
 
-       cols, _ := rows.ColumnTypes()
-       if len(cols) == 1 && cols[0].DatabaseTypeName() == "VOID" { // if the 
query is a DDL query(Data Definition Language), return a 204 status code
-               return ctx.JSON(204, map[string]string{
-                       "status": "success",
-               })
-       }
-       for rows.Next() { // iterate over the rows returned by the query
-               data := []any{}
-               err := rows.Scan(&data)
-               if err != nil {
-                       print(fmt.Sprintf("\n\nerror: %s", err.Error()))
-               }
-               results = append(results, data)
+       if _, ok := msg["status"]; ok {
+               return ctx.JSON(204, msg)
        }
-       return ctx.JSON(200, results)
+
+       return ctx.JSON(200, res)
 }
 
 /*
@@ -113,20 +105,22 @@ which graph to query, and the user object to determine 
the database version. The
 then organized into two lists: one for nodes and one for edges, before being 
returned as a JSON response.
 */
 func GraphMetaData(c echo.Context) error {
+       dataChan := make(chan *sql.Rows, 1)
+       errChan := make(chan error, 1)
 
-       user := c.Get("user").(models.Connection) // get the user object from 
the context object
+       user := c.Get("user").(models.Connection)
        conn := c.Get("conn").(*sql.DB)
        graph := models.Graph{}
-       c.Bind(&graph) // extract the graph object from the request body
+       c.Bind(&graph)
        conn.Exec(db.ANALYZE)
-       data, err := graph.GetMetaData(conn, user.Version) // get the metadata 
for the graph according to the version.
+       go graph.GetMetaData(conn, user.Version, dataChan, errChan)
+       data, err := <-dataChan, <-errChan
 
        if err != nil {
                return echo.NewHTTPError(400, err.Error())
        }
        results := models.MetaDataContainer{}
 
-       // organize the metadata into two lists: one for nodes and one for edges
        for data.Next() {
                row := models.MetaData{}
                err := data.Scan(&row.Label, &row.Cnt, &row.Kind)

Reply via email to