@Override
  public SelType binaryOps(SelOp op, SelType rhs) {
    if (rhs.type() != SelTypes.NULL && (op == SelOp.EQUAL || op == SelOp.NOT_EQUAL)) {
      SelTypeUtil.checkTypeMatch(this.type(), rhs.type());
    }

    switch (op) {
      case ADD:
        return new SelString(this.val + rhs.getInternalVal());
      case EQUAL:
        return SelBoolean.of(Objects.equals(this.val, rhs.getInternalVal()));
      case NOT_EQUAL:
        return SelBoolean.of(!Objects.equals(this.val, rhs.getInternalVal()));
      default:
        throw new UnsupportedOperationException(
            type() + " DO NOT support expression operation " + op);
    }
  }
@Test
  public void testBinaryOps() {
    SelString obj = SelString.of("foo");
    SelType res = obj.binaryOps(SelOp.ADD, SelString.of("bar"));
    assertEquals("foobar", res.toString());
    res = obj.binaryOps(SelOp.NOT_EQUAL, SelString.of("foobar"));
    assertEquals("BOOLEAN: true", res.type() + ": " + res.toString());
    res = obj.binaryOps(SelOp.EQUAL, SelString.of("foo"));
    assertEquals("BOOLEAN: true", res.type() + ": " + res.toString());
  }