ovsdb: Check ovsdb_mutation_set_execute() return value in transactions.
authorBen Pfaff <blp@nicira.com>
Tue, 31 May 2011 19:50:57 +0000 (12:50 -0700)
committerBen Pfaff <blp@nicira.com>
Tue, 31 May 2011 20:52:03 +0000 (13:52 -0700)
Errors from this function were being ignored, which meant that transactions
could use "mutate" to bypass number-of-elements constraints on sets and
maps.  This fixes the problem and adds a test to prevent the problem from
recurring.

Bug #5781.

ovsdb/execution.c
ovsdb/mutation.h
tests/ovsdb-execution.at

index 708cc60..ae17607 100644 (file)
@@ -451,6 +451,7 @@ struct mutate_row_cbdata {
     size_t n_matches;
     struct ovsdb_txn *txn;
     const struct ovsdb_mutation_set *mutations;
+    struct ovsdb_error **error;
 };
 
 static bool
@@ -459,10 +460,9 @@ mutate_row_cb(const struct ovsdb_row *row, void *mr_)
     struct mutate_row_cbdata *mr = mr_;
 
     mr->n_matches++;
-    ovsdb_mutation_set_execute(ovsdb_txn_row_modify(mr->txn, row),
-                               mr->mutations);
-
-    return true;
+    *mr->error = ovsdb_mutation_set_execute(ovsdb_txn_row_modify(mr->txn, row),
+                                            mr->mutations);
+    return *mr->error == NULL;
 }
 
 struct ovsdb_error *
@@ -494,6 +494,7 @@ ovsdb_execute_mutate(struct ovsdb_execution *x, struct ovsdb_parser *parser,
         mr.n_matches = 0;
         mr.txn = x->txn;
         mr.mutations = &mutations;
+        mr.error = &error;
         ovsdb_query(table, &condition, mutate_row_cb, &mr);
         json_object_put(result, "count", json_integer_create(mr.n_matches));
     }
index 57fd965..86de6f2 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010 Nicira Networks
+/* Copyright (c) 2009, 2010, 2011 Nicira Networks
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -67,6 +67,6 @@ struct ovsdb_error *ovsdb_mutation_set_from_json(
 struct json *ovsdb_mutation_set_to_json(const struct ovsdb_mutation_set *);
 void ovsdb_mutation_set_destroy(struct ovsdb_mutation_set *);
 struct ovsdb_error *ovsdb_mutation_set_execute(
-    struct ovsdb_row *, const struct ovsdb_mutation_set *);
+    struct ovsdb_row *, const struct ovsdb_mutation_set *) WARN_UNUSED_RESULT;
 
 #endif /* ovsdb/mutation.h */
index ebf1186..54ff0ae 100644 (file)
@@ -26,7 +26,8 @@ m4_define([CONSTRAINT_SCHEMA],
            "b2a": {"type": {"key": {"type": "uuid", "refTable": "a"},
                             "min": 0, "max": "unlimited"}},
            "b2b": {"type": {"key": {"type": "uuid", "refTable": "b"},
-                            "min": 0, "max": "unlimited"}}}},
+                            "min": 0, "max": "unlimited"}},
+           "x": {"type": {"key": "integer", "min": 1, "max": 2}}}},
        "constrained": {
          "columns": {
            "positive": {"type": {"key": {"type": "integer",
@@ -575,6 +576,12 @@ OVSDB_CHECK_EXECUTION([referential integrity -- simple],
       {"op": "delete",
        "table": "b",
        "where": []}]]],
+dnl Check that "mutate" honors number-of-elements constraints on sets and maps.
+   [[["constraints",
+      {"op": "mutate",
+       "table": "b",
+       "where": [],
+       "mutations": [["x", "delete", 0]]}]]],
    [[["constraints",
       {"op": "delete",
        "table": "a",
@@ -601,6 +608,7 @@ OVSDB_CHECK_EXECUTION([referential integrity -- simple],
        "where": []}]]]],
   [[[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]},{"uuid":["uuid","<2>"]},{"uuid":["uuid","<3>"]}]
 [{"count":1},{"details":"cannot delete b row <0> because of 3 remaining reference(s)","error":"referential integrity violation"}]
+[{"details":"Attempted to store 0 elements in set of 1 to 2 integers.","error":"constraint violation"}]
 [{"count":1}]
 [{"count":1},{"details":"cannot delete b row <0> because of 2 remaining reference(s)","error":"referential integrity violation"}]
 [{"count":1}]