aboutsummaryrefslogtreecommitdiff
path: root/ovsdb
diff options
context:
space:
mode:
authorBen Pfaff <blp@nicira.com>2011-11-16 14:38:52 -0800
committerBen Pfaff <blp@nicira.com>2011-11-28 13:26:19 -0800
commit40f280c781639c24176e054abc20bb7270da9e7a (patch)
tree2e783bb28e3b66c9141970a97e5d5b1a30cddedc /ovsdb
parent2c8fcc9cd6a7bbb948f6c79879e89c7ed791c9b1 (diff)
ovsdb: Correctly implement conditions that include multiple clauses.
Multiple-clause conditions in OVSDB operations with "where" clauses are supposed to be conjunctions, that is, the condition is true only if every clause is true. In fact, the implementation only checked a single clause (not necessarily the first one) and ignored the rest. This fixes the problem and adds test coverage for multiple-clause conditions. Reported-by: Shih-Hao Li <shli@nicira.com>
Diffstat (limited to 'ovsdb')
-rw-r--r--ovsdb/condition.c93
1 files changed, 51 insertions, 42 deletions
diff --git a/ovsdb/condition.c b/ovsdb/condition.c
index 59f742c9..c57e4197 100644
--- a/ovsdb/condition.c
+++ b/ovsdb/condition.c
@@ -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.
@@ -217,6 +217,54 @@ ovsdb_condition_to_json(const struct ovsdb_condition *cnd)
return json_array_create(clauses, cnd->n_clauses);
}
+static bool
+ovsdb_clause_evaluate(const struct ovsdb_row *row,
+ const struct ovsdb_clause *c)
+{
+ const struct ovsdb_datum *field = &row->fields[c->column->index];
+ const struct ovsdb_datum *arg = &c->arg;
+ const struct ovsdb_type *type = &c->column->type;
+
+ if (ovsdb_type_is_scalar(type)) {
+ int cmp = ovsdb_atom_compare_3way(&field->keys[0], &arg->keys[0],
+ type->key.type);
+ switch (c->function) {
+ case OVSDB_F_LT:
+ return cmp < 0;
+ case OVSDB_F_LE:
+ return cmp <= 0;
+ case OVSDB_F_EQ:
+ case OVSDB_F_INCLUDES:
+ return cmp == 0;
+ case OVSDB_F_NE:
+ case OVSDB_F_EXCLUDES:
+ return cmp != 0;
+ case OVSDB_F_GE:
+ return cmp >= 0;
+ case OVSDB_F_GT:
+ return cmp > 0;
+ }
+ } else {
+ switch (c->function) {
+ case OVSDB_F_EQ:
+ return ovsdb_datum_equals(field, arg, type);
+ case OVSDB_F_NE:
+ return !ovsdb_datum_equals(field, arg, type);
+ case OVSDB_F_INCLUDES:
+ return ovsdb_datum_includes_all(arg, field, type);
+ case OVSDB_F_EXCLUDES:
+ return ovsdb_datum_excludes_all(arg, field, type);
+ case OVSDB_F_LT:
+ case OVSDB_F_LE:
+ case OVSDB_F_GE:
+ case OVSDB_F_GT:
+ NOT_REACHED();
+ }
+ }
+
+ NOT_REACHED();
+}
+
bool
ovsdb_condition_evaluate(const struct ovsdb_row *row,
const struct ovsdb_condition *cnd)
@@ -224,48 +272,9 @@ ovsdb_condition_evaluate(const struct ovsdb_row *row,
size_t i;
for (i = 0; i < cnd->n_clauses; i++) {
- const struct ovsdb_clause *c = &cnd->clauses[i];
- const struct ovsdb_datum *field = &row->fields[c->column->index];
- const struct ovsdb_datum *arg = &cnd->clauses[i].arg;
- const struct ovsdb_type *type = &c->column->type;
-
- if (ovsdb_type_is_scalar(type)) {
- int cmp = ovsdb_atom_compare_3way(&field->keys[0], &arg->keys[0],
- type->key.type);
- switch (c->function) {
- case OVSDB_F_LT:
- return cmp < 0;
- case OVSDB_F_LE:
- return cmp <= 0;
- case OVSDB_F_EQ:
- case OVSDB_F_INCLUDES:
- return cmp == 0;
- case OVSDB_F_NE:
- case OVSDB_F_EXCLUDES:
- return cmp != 0;
- case OVSDB_F_GE:
- return cmp >= 0;
- case OVSDB_F_GT:
- return cmp > 0;
- }
- } else {
- switch (c->function) {
- case OVSDB_F_EQ:
- return ovsdb_datum_equals(field, arg, type);
- case OVSDB_F_NE:
- return !ovsdb_datum_equals(field, arg, type);
- case OVSDB_F_INCLUDES:
- return ovsdb_datum_includes_all(arg, field, type);
- case OVSDB_F_EXCLUDES:
- return ovsdb_datum_excludes_all(arg, field, type);
- case OVSDB_F_LT:
- case OVSDB_F_LE:
- case OVSDB_F_GE:
- case OVSDB_F_GT:
- NOT_REACHED();
- }
+ if (!ovsdb_clause_evaluate(row, &cnd->clauses[i])) {
+ return false;
}
- NOT_REACHED();
}
return true;