ext/adapter.cc in swift-0.13.0 vs ext/adapter.cc in swift-0.14.0

- old
+ new

@@ -1,6 +1,9 @@ +// vim:ts=2:sts=2:sw=2:expandtab + #include "adapter.h" +#include "sys/select.h" // Extend the default dbi::FieldSet class with some ruby love. class Fields : public dbi::FieldSet { public: Fields() : dbi::FieldSet(0) {} @@ -69,14 +72,26 @@ Close the connection. */ static VALUE adapter_close(VALUE self) { dbi::Handle *handle = adapter_handle(self); try { handle->close(); } CATCH_DBI_EXCEPTIONS(); + rb_iv_set(self, "@closed", true); return Qtrue; } + /* + Check if connection is closed. +*/ +static VALUE adapter_closed(VALUE self) { + return rb_iv_get(self, "@closed"); +} + + + + +/* Shallow copy of adapter. @note Currently not allowed. @see Object.clone */ @@ -164,11 +179,11 @@ if (RARRAY_LEN(bind_values) > 0) query_bind_values(&query, bind_values); if (dbi::_trace) dbi::logMessage(dbi::_trace_fd, dbi::formatParams(query.sql, query.bind)); if ((rows = rb_thread_blocking_region(((VALUE (*)(void*))query_execute), &query, RUBY_UBF_IO, 0)) == Qfalse) - rb_raise(eSwiftRuntimeError, "%s", query.error); + rb_raise(query.error_klass, "%s", query.error_message); VALUE result = result_wrap_handle(cSwiftResult, self, handle->conn()->result(), true); if (!NIL_P(scheme)) rb_iv_set(result, "@scheme", scheme); return rb_block_given_p() ? result_each(result) : result; @@ -179,11 +194,15 @@ /* Reestablish a connection. */ static VALUE adapter_reconnect(VALUE self) { dbi::Handle *handle = adapter_handle(self); - try { handle->reconnect(); } CATCH_DBI_EXCEPTIONS(); + try { + handle->reconnect(); + rb_iv_set(self, "@closed", false); + } + CATCH_DBI_EXCEPTIONS(); return Qtrue; } /* Setup a new DB connection. @@ -200,11 +219,10 @@ @option options [String] :db Name. @option options [String] :user (*nix login user) @option options [String] :password ('') @option options [String] :host ('localhost') @option options [Integer] :port (DB default) - @option options [String] :timezone (*nix TZ format) See http://en.wikipedia.org/wiki/List_of_tz_database_time_zones @return [Swift::Adapter] @see Swift::DB @see Swift::Adapter */ @@ -223,11 +241,10 @@ rb_hash_delete(extra, ID2SYM(rb_intern("driver"))); rb_hash_delete(extra, ID2SYM(rb_intern("user"))); rb_hash_delete(extra, ID2SYM(rb_intern("password"))); rb_hash_delete(extra, ID2SYM(rb_intern("host"))); rb_hash_delete(extra, ID2SYM(rb_intern("port"))); - rb_hash_delete(extra, ID2SYM(rb_intern("timezone"))); std::string extra_options_string = parse_extra_options(extra); try { DATA_PTR(self) = new dbi::Handle( @@ -241,11 +258,10 @@ ); } CATCH_DBI_EXCEPTIONS(); rb_iv_set(self, "@options", options); - rb_iv_set(self, "@timezone", rb_hash_aref(options, ID2SYM(rb_intern("timezone")))); return Qnil; } /* @@ -375,26 +391,89 @@ return SIZET2NUM(rows); } CATCH_DBI_EXCEPTIONS(); } +/* + Returns the socket fileno for the connection. + + @overload fileno() + @return [Fixnum] +*/ +VALUE adapter_fileno(VALUE self) { + dbi::Handle *handle = adapter_handle(self); + return INT2NUM(handle->conn()->socket()); +} + +/* + Executes a query asynchronously and returns the result instance. + + @example + + @overload async_execute(statement = '', *binds, &block) + @param [String] statement Query statement. + @param [*Object] binds Bind values. + @return [Swift::Result] +*/ +VALUE adapter_async_execute(int argc, VALUE *argv, VALUE self) { + VALUE statement, bind_values, block, scheme = Qnil, result; + + dbi::Handle *handle = adapter_handle(self); + rb_scan_args(argc, argv, "1*&", &statement, &bind_values, &block); + + if (TYPE(statement) == T_CLASS) { + scheme = statement; + statement = rb_ary_shift(bind_values); + } + + try { + dbi::AbstractResult *dbi_result; + if (RARRAY_LEN(bind_values) > 0) { + Query query; + query_bind_values(&query, bind_values); + dbi_result = handle->conn()->aexecute(CSTRING(statement), query.bind); + } + else + dbi_result = handle->conn()->aexecute(CSTRING(statement)); + + result = result_wrap_handle(cSwiftResult, self, dbi_result, true); + if (!NIL_P(scheme)) + rb_iv_set(result, "@scheme", scheme); + + // if block given, just use rb_thread_select + if (rb_block_given_p()) { + rb_thread_wait_fd(handle->socket()); + while (dbi_result->consumeResult()); + dbi_result->prepareResult(); + } + } + CATCH_DBI_EXCEPTIONS(); + + return rb_block_given_p() ? result_each(result) : result; +} + void init_swift_adapter() { VALUE mSwift = rb_define_module("Swift"); cSwiftAdapter = rb_define_class_under(mSwift, "Adapter", rb_cObject); rb_define_method(cSwiftAdapter, "begin", RUBY_METHOD_FUNC(adapter_begin), -1); rb_define_method(cSwiftAdapter, "clone", RUBY_METHOD_FUNC(adapter_clone), 0); rb_define_method(cSwiftAdapter, "close", RUBY_METHOD_FUNC(adapter_close), 0); + rb_define_method(cSwiftAdapter, "closed?", RUBY_METHOD_FUNC(adapter_closed), 0); rb_define_method(cSwiftAdapter, "commit", RUBY_METHOD_FUNC(adapter_commit), -1); rb_define_method(cSwiftAdapter, "dup", RUBY_METHOD_FUNC(adapter_dup), 0); rb_define_method(cSwiftAdapter, "escape", RUBY_METHOD_FUNC(adapter_escape), 1); rb_define_method(cSwiftAdapter, "execute", RUBY_METHOD_FUNC(adapter_execute), -1); rb_define_method(cSwiftAdapter, "initialize", RUBY_METHOD_FUNC(adapter_initialize), 1); rb_define_method(cSwiftAdapter, "prepare", RUBY_METHOD_FUNC(adapter_prepare), -1); rb_define_method(cSwiftAdapter, "rollback", RUBY_METHOD_FUNC(adapter_rollback), -1); rb_define_method(cSwiftAdapter, "transaction", RUBY_METHOD_FUNC(adapter_transaction), -1); rb_define_method(cSwiftAdapter, "write", RUBY_METHOD_FUNC(adapter_write), -1); rb_define_method(cSwiftAdapter, "reconnect", RUBY_METHOD_FUNC(adapter_reconnect), 0); + + // stuff you need for async + rb_define_method(cSwiftAdapter, "fileno", RUBY_METHOD_FUNC(adapter_fileno), 0); + rb_define_method(cSwiftAdapter, "async_execute", RUBY_METHOD_FUNC(adapter_async_execute), -1); rb_define_alloc_func(cSwiftAdapter, adapter_alloc); }