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);
}