in sources/cg_c.c [4811:4971]
static void cg_bound_sql_statement(CSTR stmt_name, ast_node *stmt, int32_t cg_flags) {
list_item *vars = NULL;
CSTR amp = "&";
cur_bound_statement++;
cur_fragment_predicate = 0;
max_fragment_predicate = 0;
prev_variable_count = 0;
cur_variable_count = 0;
bytebuf_open(&shared_fragment_strings);
if (stmt_name && !strcmp("_result", stmt_name)) {
// predefined out argument
amp = "";
}
cg_classify_fragments(stmt);
if (has_conditional_fragments) {
bprintf(cg_main_output, "memset(&_preds_%d[0], 0, sizeof(_preds_%d));\n",
cur_bound_statement,
cur_bound_statement);
if (has_variables) {
bprintf(cg_main_output, "memset(&_vpreds_%d[0], 0, sizeof(_vpreds_%d));\n",
cur_bound_statement,
cur_bound_statement);
}
}
bool_t minify_aliases = !!(cg_flags & CG_MINIFY_ALIASES);
bool_t exec_only = !!(cg_flags & CG_EXEC);
gen_sql_callbacks callbacks;
init_gen_sql_callbacks(&callbacks);
callbacks.variables_callback = cg_capture_variables;
callbacks.variables_context = &vars;
callbacks.star_callback = cg_expand_star;
callbacks.minify_casts = 1;
callbacks.minify_aliases = minify_aliases;
callbacks.long_to_int_conv = true;
callbacks.cte_proc_callback = cg_call_in_cte;
callbacks.cte_suppress_callback = cg_suppress_cte;
callbacks.table_rename_callback = cg_table_rename;
callbacks.inline_func_callback = cg_inline_func;
CHARBUF_OPEN(temp);
gen_set_output_buffer(&temp);
gen_statement_with_callbacks(stmt, &callbacks);
// whether or not there is a prepare statement
bool_t has_prepare_stmt = !exec_only || vars;
uint32_t count = 0;
for (list_item *item = vars; item; item = item->next, count++) ;
if (stmt_name == NULL && has_prepare_stmt) {
ensure_temp_statement();
stmt_name = "_temp";
}
// take care of what's left in the buffer after the other fragments have been emitted
if (has_shared_fragments) {
cg_emit_one_frag(&temp);
}
if (!has_shared_fragments && options.compress) {
bprintf(cg_main_output, "/* ");
CHARBUF_OPEN(t2);
cg_pretty_quote_plaintext(temp.ptr, &t2, PRETTY_QUOTE_C | PRETTY_QUOTE_MULTI_LINE);
cg_remove_slash_star_and_star_slash(&t2); // internal "*/" is fatal. "/*" can also be under certain compilation flags
bprintf(cg_main_output, "%s", t2.ptr);
CHARBUF_CLOSE(t2);
bprintf(cg_main_output, " */\n");
if (!has_prepare_stmt) {
bprintf(cg_main_output, "_rc_ = cql_exec_frags(_db_,\n");
}
else {
bprintf(cg_main_output, "_rc_ = cql_prepare_frags(_db_, %s%s_stmt,\n ", amp, stmt_name);
}
bprintf(cg_main_output, "_pieces_, ");
cg_statement_pieces(temp.ptr, cg_main_output);
bprintf(cg_main_output, ");\n");
}
else {
CSTR suffix = has_shared_fragments ? "_var" : "";
if (!has_prepare_stmt) {
bprintf(cg_main_output, "_rc_ = cql_exec%s(_db_,\n ", suffix);
}
else {
bprintf(cg_main_output, "_rc_ = cql_prepare%s(_db_, %s%s_stmt,\n ", suffix, amp, stmt_name);
}
if (!has_shared_fragments) {
cg_pretty_quote_plaintext(temp.ptr, cg_main_output, PRETTY_QUOTE_C | PRETTY_QUOTE_MULTI_LINE);
}
else {
int32_t scount = cg_fragment_count();
// declare the predicate variables if needed
if (has_conditional_fragments) {
bprintf(cg_main_output, "%d, _preds_%d,\n", scount, cur_bound_statement);
bprintf(cg_declarations_output, "char _preds_%d[%d];\n", cur_bound_statement, scount);
if (has_variables) {
bprintf(cg_declarations_output, "char _vpreds_%d[%d];\n", cur_bound_statement, cur_variable_count);
}
}
else {
bprintf(cg_main_output, "%d, NULL,\n", scount);
}
CSTR *strs = (CSTR *)(shared_fragment_strings.ptr);
for (size_t i = 0; i < scount; i++) {
cg_pretty_quote_plaintext(strs[i], cg_main_output, PRETTY_QUOTE_C | PRETTY_QUOTE_MULTI_LINE);
if (i + 1 < scount) {
bprintf(cg_main_output, ",\n");
}
else {
bprintf(cg_main_output, "\n");
}
}
}
bprintf(cg_main_output, ");\n");
}
CHARBUF_CLOSE(temp);
reverse_list(&vars);
if (count) {
if (has_conditional_fragments) {
bprintf(cg_main_output, "cql_multibind_var(&_rc_, _db_, %s%s_stmt, %d, _vpreds_%d", amp, stmt_name, count, cur_bound_statement);
}
else {
bprintf(cg_main_output, "cql_multibind(&_rc_, _db_, %s%s_stmt, %d", amp, stmt_name, count);
}
// Now emit the binding args for each variable
for (list_item *item = vars; item; item = item->next) {
Contract(item->ast->sem->name);
bprintf(cg_main_output, ",\n ");
cg_bind_column(item->ast->sem->sem_type, item->ast->sem->name);
}
bprintf(cg_main_output, ");\n");
}
cg_error_on_not_sqlite_ok();
if (exec_only && vars) {
bprintf(cg_main_output, "_rc_ = sqlite3_step(%s_stmt);\n", stmt_name);
cg_error_on_rc_notequal("SQLITE_DONE");
bprintf(cg_main_output, "cql_finalize_stmt(&%s_stmt);\n", stmt_name);
}
// vars is pool allocated, so we don't need to free it
bytebuf_close(&shared_fragment_strings);
}