ext/statement.cc in swift-0.6.1 vs ext/statement.cc in swift-0.7.0

- old
+ new

@@ -3,28 +3,49 @@ #include "result.h" #include "query.h" VALUE cSwiftStatement; -void statement_free(dbi::AbstractStatement *statement) { - if (statement) { - statement->cleanup(); - delete statement; +void statement_mark(StatementWrapper *handle) { + if (handle) + rb_gc_mark(handle->adapter); +} + +void statement_free(StatementWrapper *handle) { + if (handle) { + if (handle->free) { + handle->statement->cleanup(); + delete handle->statement; + } + delete handle; } } VALUE statement_alloc(VALUE klass) { - dbi::AbstractStatement *statement = 0; - return Data_Wrap_Struct(klass, 0, statement_free, statement); + StatementWrapper *handle = 0; + return Data_Wrap_Struct(klass, statement_mark, statement_free, handle); } +VALUE statement_wrap_handle(VALUE klass, VALUE adapter, dbi::AbstractStatement *statement) { + StatementWrapper *handle = new StatementWrapper; + handle->statement = statement; + handle->adapter = adapter; + handle->free = true; + + VALUE obj = Data_Wrap_Struct(klass, statement_mark, statement_free, handle); + if (!NIL_P(adapter)) + rb_iv_set(obj, "@timezone", rb_iv_get(adapter, "@timezone")); + + return obj; +} + dbi::AbstractStatement* statement_handle(VALUE self) { - dbi::AbstractStatement *handle; - Data_Get_Struct(self, dbi::AbstractStatement, handle); + StatementWrapper *handle; + Data_Get_Struct(self, StatementWrapper, handle); if (!handle) rb_raise(eSwiftRuntimeError, "Invalid object, did you forget to call #super?"); - return handle; + return handle->statement; } // TODO: Change bind_values to an array in the interface? Avoid array -> splat -> array. static VALUE statement_execute(int argc, VALUE *argv, VALUE self) { VALUE bind_values, block; @@ -32,11 +53,11 @@ dbi::AbstractStatement *statement = (dbi::AbstractStatement*)statement_handle(self); try { Query query; query.statement = statement; - if (RARRAY_LEN(bind_values) > 0) query_bind_values(&query, bind_values); + if (RARRAY_LEN(bind_values) > 0) query_bind_values(&query, bind_values, statement->driver()); if (dbi::_trace) dbi::logMessage(dbi::_trace_fd, dbi::formatParams(statement->command(), query.bind)); if (rb_thread_blocking_region(((VALUE (*)(void*))query_execute_statement), &query, RUBY_UBF_IO, 0) == Qfalse) rb_raise(eSwiftRuntimeError, "%s", query.error); } @@ -51,10 +72,16 @@ if (NIL_P(adapter)) rb_raise(eSwiftArgumentError, "Statement#new called without an Adapter instance."); if (NIL_P(sql)) rb_raise(eSwiftArgumentError, "Statement#new called without a command."); try { - DATA_PTR(self) = handle->conn()->prepare(CSTRING(sql)); + // needs to happen before wrapping in case it raises errors. + dbi::AbstractStatement *statement = handle->conn()->prepare(CSTRING(sql)); + StatementWrapper *statement_handle = new StatementWrapper; + statement_handle->statement = statement; + statement_handle->adapter = adapter; + statement_handle->free = true; + DATA_PTR(self) = statement_handle; } CATCH_DBI_EXCEPTIONS(); return Qnil; }