+ return (op == RELOP_SET_EQ || op == RELOP_SET_NE ||
+ op == RELOP_SET_LT || op == RELOP_SET_GT ||
+ op == RELOP_SET_LE || op == RELOP_SET_GE);
+}
+
+static bool
+evaluate_relop(const struct ovsdb_datum *a, const struct ovsdb_datum *b,
+ const struct ovsdb_type *type, enum relop op)
+{
+ switch (op) {
+ case RELOP_EQ:
+ case RELOP_SET_EQ:
+ return ovsdb_datum_compare_3way(a, b, type) == 0;
+ case RELOP_NE:
+ case RELOP_SET_NE:
+ return ovsdb_datum_compare_3way(a, b, type) != 0;
+ case RELOP_LT:
+ return ovsdb_datum_compare_3way(a, b, type) < 0;
+ case RELOP_GT:
+ return ovsdb_datum_compare_3way(a, b, type) > 0;
+ case RELOP_LE:
+ return ovsdb_datum_compare_3way(a, b, type) <= 0;
+ case RELOP_GE:
+ return ovsdb_datum_compare_3way(a, b, type) >= 0;
+
+ case RELOP_SET_LT:
+ return b->n > a->n && ovsdb_datum_includes_all(a, b, type);
+ case RELOP_SET_GT:
+ return a->n > b->n && ovsdb_datum_includes_all(b, a, type);
+ case RELOP_SET_LE:
+ return ovsdb_datum_includes_all(a, b, type);
+ case RELOP_SET_GE:
+ return ovsdb_datum_includes_all(b, a, type);
+
+ default:
+ NOT_REACHED();
+ }
+}
+
+static bool
+is_condition_satisfied(const struct vsctl_table_class *table,
+ const struct ovsdb_idl_row *row, const char *arg,
+ struct ovsdb_symbol_table *symtab)
+{
+ static const char *operators[] = {
+#define RELOP(ENUM, STRING) STRING,
+ RELOPS
+#undef RELOP
+ };
+
+ const struct ovsdb_idl_column *column;
+ const struct ovsdb_datum *have_datum;
+ char *key_string, *value_string;
+ struct ovsdb_type type;
+ int operator;
+ bool retval;
+ char *error;
+
+ error = parse_column_key_value(arg, table, &column, &key_string,
+ &operator, operators, ARRAY_SIZE(operators),
+ &value_string);
+ die_if_error(error);
+ if (!value_string) {
+ vsctl_fatal("%s: missing value", arg);
+ }
+
+ type = column->type;
+ type.n_max = UINT_MAX;
+
+ have_datum = ovsdb_idl_read(row, column);
+ if (key_string) {
+ union ovsdb_atom want_key;
+ struct ovsdb_datum b;
+ unsigned int idx;
+
+ if (column->type.value.type == OVSDB_TYPE_VOID) {
+ vsctl_fatal("cannot specify key to check for non-map column %s",
+ column->name);
+ }
+
+ die_if_error(ovsdb_atom_from_string(&want_key, &column->type.key,
+ key_string, symtab));
+
+ type.key = type.value;
+ type.value.type = OVSDB_TYPE_VOID;
+ die_if_error(ovsdb_datum_from_string(&b, &type, value_string, symtab));
+
+ idx = ovsdb_datum_find_key(have_datum,
+ &want_key, column->type.key.type);
+ if (idx == UINT_MAX && !is_set_operator(operator)) {
+ retval = false;
+ } else {
+ struct ovsdb_datum a;
+
+ if (idx != UINT_MAX) {
+ a.n = 1;
+ a.keys = &have_datum->values[idx];
+ a.values = NULL;
+ } else {
+ a.n = 0;
+ a.keys = NULL;
+ a.values = NULL;
+ }
+
+ retval = evaluate_relop(&a, &b, &type, operator);
+ }
+
+ ovsdb_atom_destroy(&want_key, column->type.key.type);
+ ovsdb_datum_destroy(&b, &type);
+ } else {
+ struct ovsdb_datum want_datum;
+
+ die_if_error(ovsdb_datum_from_string(&want_datum, &column->type,
+ value_string, symtab));
+ retval = evaluate_relop(have_datum, &want_datum, &type, operator);
+ ovsdb_datum_destroy(&want_datum, &column->type);
+ }
+
+ free(key_string);
+ free(value_string);
+
+ return retval;