// runExecute is the code that implements the execute command. func runExecute(cmd *cobra.Command, args []string) error { cmd.Printf("Executing View : Name[%s]\n", execute.viewName) // Validate the input parameters. if execute.viewName == "" || execute.itemKey == "" { return fmt.Errorf("view name and item key must be specified") } // Ready the view parameters. viewParams := wire.ViewParams{ ViewName: execute.viewName, ItemKey: execute.itemKey, ResultsCollection: execute.resultsCollection, BufferLimit: execute.bufferLimit, } // Execute the view. results, err := wire.Execute("", mgoDB, graphDB, &viewParams) if err != nil { return err } // Prepare the results for printing. data, err := json.MarshalIndent(results, "", " ") if err != nil { return err } cmd.Printf("\n%s\n\n", string(data)) cmd.Println("\n", "Executing View : Executed") return nil }
// materializeView executes a view, creates a temporary collection for the view, and // modifies the query to query the temporary collection. func materializeView(context interface{}, db *db.DB, q *query.Query, vars map[string]string) (string, error) { // Make sure we have a valid connection to the graph. graph, err := db.GraphHandle(context) if err != nil { return "", err } // Make sure we have the information we need to execute the view. viewName, ok := vars["view"] if !ok { return "", fmt.Errorf("Vars does not include \"view\".") } itemKey, ok := vars["item"] if !ok { return "", fmt.Errorf("Vars does not include \"item\".") } // Generate a unique name for the collection. viewCol := uuid.New() // Prepare the parameters for executing the view. viewParams := wire.ViewParams{ ViewName: viewName, ItemKey: itemKey, ResultsCollection: viewCol, } // Execute the view. if _, err := wire.Execute(context, db, graph, &viewParams); err != nil { return viewCol, err } // Provide the query with the temporary collection name. q.Collection = viewCol return viewCol, nil }
// TestExecuteViews tests the execution of different views. func TestExecuteViews(t *testing.T) { db, store := setup(t) defer teardown(t, db, store) // Build our table of the different test sets. execViews := []struct { typ string views []execView }{ {typ: "Positive", views: getPosViews()}, {typ: "Negative", views: getNegViews()}, } // Iterate over all the different test view. for _, ev := range execViews { t.Logf("Given the need to execute %s view tests.", ev.typ) { for _, vw := range ev.views { // Setup a sub-test for each test view. tf := func(t *testing.T) { t.Logf("\tWhen using the view named %s", vw.viewName) { // Form the view parameters. viewParams := wire.ViewParams{ ViewName: wirePrefix + vw.viewName, ItemKey: wirePrefix + vw.itemKey, ResultsCollection: vw.collection, BufferLimit: vw.bufferLimit, } // Generate the view. result, err := wire.Execute(tests.Context, db, store, &viewParams) if err != nil && !vw.fail { t.Fatalf("\t%s\tShould be able to execute the view", tests.Failed) } t.Logf("\t%s\tShould be able to execute the view.", tests.Success) if err != nil && vw.fail { errDoc, ok := result.Results.(bson.M) if !ok || len(errDoc["error"].(string)) == 0 { t.Fatalf("\t%s\tShould return a single error document : %s", tests.Failed, err) } t.Logf("\t%s\tShould return a single error document.", tests.Success) return } // Process the results in mongo if the view is persisted. var viewItems []bson.M if len(vw.collection) > 0 { // Check the result message. msg, ok := result.Results.(bson.M) if !ok || msg["number_of_results"] != vw.number { t.Fatalf("\t%s\tShould be able to get %d items in the view", tests.Failed, vw.number) } t.Logf("\t%s\tShould be able to get %d items in the view.", tests.Success, vw.number) // Query the output collection. f := func(c *mgo.Collection) error { return c.Find(nil).All(&viewItems) } if err := db.ExecuteMGO(tests.Context, "testcollection", f); err != nil { t.Fatalf("\t%s\tShould be able to query the output collection : %s", tests.Failed, err) } t.Logf("\t%s\tShould be able to query the output collection.", tests.Success) // Verify that we get the same number of items back. if len(viewItems) != vw.number { t.Fatalf("\t%s\tShould be able to get %d items from the output collection", tests.Failed, vw.number) } t.Logf("\t%s\tShould be able to get %d items from the output collection.", tests.Success, vw.number) // Delete the persisted collection to clean up. f = func(c *mgo.Collection) error { return c.DropCollection() } if err := db.ExecuteMGO(tests.Context, vw.collection, f); err != nil { t.Fatalf("\t%s\tShould be able to drop the output collection : %s", tests.Failed, err) } t.Logf("\t%s\tShould be able to drop the output collection.", tests.Success) } // Otherwise, get the items directly from the result. var ok bool if vw.collection == "" { viewItems, ok = result.Results.([]bson.M) if !ok || len(viewItems) != vw.number { t.Fatalf("\t%s\tShould be able to get %d items in the view", tests.Failed, vw.number) } t.Logf("\t%s\tShould be able to get %d items in the view.", tests.Success, vw.number) } // Check the content of the items returned. commonData := wire.Result{ Results: viewItems, } data, err := json.Marshal(commonData) if err != nil { t.Errorf("\t%s\tShould be able to marshal the result : %s", tests.Failed, err) return } t.Logf("\t%s\tShould be able to marshal the result.", tests.Success) for _, rslt := range vw.results { // We just need to find the string inside the result. if !strings.Contains(string(data), rslt) { t.Log("\t\tRsl:", string(data)) for _, rslt := range vw.results { t.Log("\t\tExp:", rslt) } t.Errorf("\t%s\tShould have the correct result.", tests.Failed) return } } t.Logf("\t%s\tShould have the correct result", tests.Success) return } } t.Run(vw.viewName, tf) } } } }