in sources/cg_c.c [993:1068]
static void cg_binary_compare(ast_node *ast, CSTR op, charbuf *is_null, charbuf *value, int32_t pri, int32_t pri_new) {
sem_t sem_type_result = ast->sem->sem_type;
sem_t sem_type_left = ast->left->sem->sem_type;
sem_t sem_type_right = ast->right->sem->sem_type;
bool_t is_text_op = is_text(sem_type_left) && is_text(sem_type_right);
bool_t is_blob_op = is_blob(sem_type_left) && is_blob(sem_type_right);
if (is_blob_op) {
// we want to make sure blob is only supported for certain operation
// even though we already have the semantic analysis for this.
Invariant(is_ast_eq(ast) || is_ast_ne(ast));
}
if (!is_text_op && !is_blob_op) {
// for numeric, the usual binary processing works
cg_binary(ast, op, is_null, value, pri, pri_new);
return;
}
// Both sides are text/blob or null; already verified compatible in semantic phase.
CHARBUF_OPEN(comparison);
if (needs_paren(ast, pri_new, pri)) {
bprintf(&comparison, "(");
}
ast_node *l = ast->left;
ast_node *r = ast->right;
CG_RESERVE_RESULT_VAR(ast, sem_type_result);
CG_PUSH_EVAL(l, pri_new);
CG_PUSH_EVAL(r, pri_new);
if (is_ast_like(ast)) {
// like not allowed semantically for blob type
Invariant(!is_blob_op);
bprintf(&comparison, "%s(%s, %s) == 0", rt->cql_string_like, l_value.ptr, r_value.ptr);
}
else if (is_ast_not_like(ast)) {
// like not allowed semantically for blob type
Invariant(!is_blob_op);
bprintf(&comparison, "%s(%s, %s) != 0", rt->cql_string_like, l_value.ptr, r_value.ptr);
}
else if (is_blob_op) {
bool_t logical_not = is_ast_ne(ast) || is_ast_is_not(ast);
if (logical_not) {
bprintf(&comparison, "%s", "!");
}
bprintf(&comparison, "%s(%s, %s)", rt->cql_blob_equal, l_value.ptr, r_value.ptr);
}
else {
// otherwise other string comparisons
bprintf(&comparison, "%s(%s, %s) %s 0", rt->cql_string_compare, l_value.ptr, r_value.ptr, op);
}
if (needs_paren(ast, pri_new, pri)) {
bprintf(&comparison, ")");
}
if (is_not_nullable(sem_type_left) && is_not_nullable(sem_type_right)) {
bprintf(value, "%s", comparison.ptr);
bprintf(is_null, "0");
}
else {
CG_USE_RESULT_VAR();
cg_combine_nullables(cg_main_output, result_var.ptr, l_is_null.ptr, r_is_null.ptr, comparison.ptr);
}
CG_POP_EVAL(r);
CG_POP_EVAL(l);
CG_CLEANUP_RESULT_VAR();
CHARBUF_CLOSE(comparison);
}