VALUE db_sqlite3_statement_execute(int argc, VALUE *argv, VALUE self) { int expect, n; VALUE bind, result; Statement *s = db_sqlite3_statement_handle_safe(self); sqlite3_reset(s->s); sqlite3_clear_bindings(s->s); rb_scan_args(argc, argv, "00*", &bind); expect = sqlite3_bind_parameter_count(s->s); if (expect != RARRAY_LEN(bind)) rb_raise(eSwiftArgumentError, "expected %d bind values got %d", expect, (int)RARRAY_LEN(bind)); rb_gc_register_address(&bind); for (n = 0; n < expect; n++) { VALUE value = rb_ary_entry(bind, n); if (NIL_P(value)) sqlite3_bind_null(s->s, n + 1); else { VALUE text = typecast_to_string(value); sqlite3_bind_text(s->s, n + 1, RSTRING_PTR(text), RSTRING_LEN(text), 0); } } result = db_sqlite3_result_allocate(cDSR); db_sqlite3_result_initialize(result, self); db_sqlite3_result_consume(result); rb_gc_unregister_address(&bind); return result; }
VALUE db_postgres_statement_execute(int argc, VALUE *argv, VALUE self) { PGresult *result; PGconn *connection; char **bind_args_data = 0; int n, *bind_args_size = 0, *bind_args_fmt = 0; VALUE bind, data, typecast_bind; Statement *s = db_postgres_statement_handle_safe(self); connection = db_postgres_adapter_handle_safe(s->adapter)->connection; rb_scan_args(argc, argv, "00*", &bind); typecast_bind = rb_ary_new(); rb_gc_register_address(&typecast_bind); rb_gc_register_address(&bind); if (RARRAY_LEN(bind) > 0) { bind_args_size = (int *) malloc(sizeof(int) * RARRAY_LEN(bind)); bind_args_fmt = (int *) malloc(sizeof(int) * RARRAY_LEN(bind)); bind_args_data = (char **) malloc(sizeof(char *) * RARRAY_LEN(bind)); for (n = 0; n < RARRAY_LEN(bind); n++) { data = rb_ary_entry(bind, n); if (NIL_P(data)) { bind_args_size[n] = 0; bind_args_data[n] = 0; bind_args_fmt[n] = 0; } else { if (rb_obj_is_kind_of(data, rb_cIO) || rb_obj_is_kind_of(data, cStringIO)) bind_args_fmt[n] = 1; else bind_args_fmt[n] = 0; data = typecast_to_string(data); rb_ary_push(typecast_bind, data); bind_args_size[n] = RSTRING_LEN(data); bind_args_data[n] = RSTRING_PTR(data); } } Query q = { .connection = connection, .command = s->id, .n_args = RARRAY_LEN(bind), .data = bind_args_data, .size = bind_args_size, .format = bind_args_fmt }; result = (PGresult *)GVL_NOLOCK(nogvl_pq_exec_prepared, &q, RUBY_UBF_IO, 0); free(bind_args_fmt); free(bind_args_size); free(bind_args_data); } else {
VALUE db_postgres_adapter_execute(int argc, VALUE *argv, VALUE self) { char **bind_args_data = 0; int n, *bind_args_size = 0, *bind_args_fmt = 0; PGresult *result; VALUE sql, bind, data; Adapter *a = db_postgres_adapter_handle_safe(self); rb_scan_args(argc, argv, "10*", &sql, &bind); if (!a->native) sql = db_postgres_normalized_sql(sql); if (RARRAY_LEN(bind) > 0) { bind_args_size = (int *) malloc(sizeof(int) * RARRAY_LEN(bind)); bind_args_fmt = (int *) malloc(sizeof(int) * RARRAY_LEN(bind)); bind_args_data = (char **) malloc(sizeof(char *) * RARRAY_LEN(bind)); rb_gc_register_address(&bind); for (n = 0; n < RARRAY_LEN(bind); n++) { data = rb_ary_entry(bind, n); if (NIL_P(data)) { bind_args_size[n] = 0; bind_args_data[n] = 0; bind_args_fmt[n] = 0; } else { if (rb_obj_is_kind_of(data, rb_cIO) || rb_obj_is_kind_of(data, cStringIO)) bind_args_fmt[n] = 1; else bind_args_fmt[n] = 0; data = typecast_to_string(data); bind_args_size[n] = RSTRING_LEN(data); bind_args_data[n] = RSTRING_PTR(data); } } Query q = { .connection = a->connection, .command = CSTRING(sql), .n_args = RARRAY_LEN(bind), .data = bind_args_data, .size = bind_args_size, .format = bind_args_fmt }; result = (PGresult *)rb_thread_blocking_region(nogvl_pq_exec_params, &q, RUBY_UBF_IO, 0); rb_gc_unregister_address(&bind); free(bind_args_size); free(bind_args_data); free(bind_args_fmt); } else {
/* NOTE: very naive, no regex etc. */ VALUE db_mysql_bind_sql(VALUE adapter, VALUE sql, VALUE bind) { VALUE value; size_t size = 4096; char *ptr, *buffer; size_t i = 0, j = 0, n = 0; buffer = (char *)malloc(size); ptr = RSTRING_PTR(sql); while (i < (size_t)RSTRING_LEN(sql)) { if (*ptr == '?') { if (n < (size_t)RARRAY_LEN(bind)) { value = rb_ary_entry(bind, n++); if (NIL_P(value)) { size = db_mysql_buffer_adjust(&buffer, size, j, 4); j += sprintf(buffer + j, "NULL"); } else { value = db_mysql_adapter_escape(adapter, typecast_to_string(value)); size = db_mysql_buffer_adjust(&buffer, size, j, RSTRING_LEN(value) + 2); j += sprintf(buffer + j, "'%s'", RSTRING_PTR(value)); } } else { buffer[j++] = *ptr; n++; } } else { buffer[j++] = *ptr; } i++; ptr++; if (j >= size) buffer = realloc(buffer, size += 4096); } sql = rb_str_new(buffer, j); free(buffer); if (n != (size_t)RARRAY_LEN(bind)) rb_raise(eSwiftArgumentError, "expected %d bind arguments got %d instead", n, RARRAY_LEN(bind)); return sql; }