+ } else {
+ for (i = 2; i < ctx->argc; i++) {
+ const struct ovsdb_idl_row *row;
+
+ row = get_row(ctx, table, ctx->argv[i], must_exist);
+ if (row) {
+ ovsdb_idl_txn_delete(row);
+ }
+ }
+ }
+ vsctl_context_invalidate_cache(ctx);
+}
+
+#define RELOPS \
+ RELOP(RELOP_EQ, "=") \
+ RELOP(RELOP_NE, "!=") \
+ RELOP(RELOP_LT, "<") \
+ RELOP(RELOP_GT, ">") \
+ RELOP(RELOP_LE, "<=") \
+ RELOP(RELOP_GE, ">=") \
+ RELOP(RELOP_SET_EQ, "{=}") \
+ RELOP(RELOP_SET_NE, "{!=}") \
+ RELOP(RELOP_SET_LT, "{<}") \
+ RELOP(RELOP_SET_GT, "{>}") \
+ RELOP(RELOP_SET_LE, "{<=}") \
+ RELOP(RELOP_SET_GE, "{>=}")
+
+enum relop {
+#define RELOP(ENUM, STRING) ENUM,
+ RELOPS
+#undef RELOP
+};
+
+static bool
+is_set_operator(enum relop op)
+{
+ 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:
+ OVS_NOT_REACHED();