Compare commits
23 Commits
Author | SHA1 | Date |
---|---|---|
John Bintz | b99e0a057a | |
Brian Lopez | 52f62c8b44 | |
Brian Lopez | 66f595a406 | |
dan sinclair | 5f6ff0d4a8 | |
Brian Lopez | 80697d11b2 | |
dan sinclair | dac2f02c9b | |
dan sinclair | 9d49728c30 | |
dj2 | c2e2f0c46c | |
Youhei Kondou | 550c68cade | |
Brian Lopez | d48846f13b | |
Brian Lopez | 99766a2303 | |
Brian Lopez | badc5e04e3 | |
Brian Lopez | 974a5658d6 | |
Brian Lopez | 60b8d061ac | |
Brian Lopez | 2b37ace3dc | |
Brian Lopez | 1057f976d0 | |
Brian Lopez | 90ddb63e52 | |
Brian Lopez | 426cff8adc | |
Brian Lopez | f79bf6261e | |
Brian Lopez | 05df9e312d | |
Brian Lopez | 60fd02ebe6 | |
Brian Lopez | 7e75f5ed4c | |
Anko painting | e7dcf37bd4 |
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -1,5 +1,17 @@
|
|||
# Changelog
|
||||
|
||||
## 0.2.6 (October 19th, 2010)
|
||||
* version bump since the 0.2.5 win32 binary gems were broken
|
||||
|
||||
## 0.2.5 (October 19th, 2010)
|
||||
* fixes for easier Win32 binary gem deployment for targeting 1.8 and 1.9 in the same gem
|
||||
* refactor of connection checks and management to avoid race conditions with the GC/threading to prevent the unexpected loss of connections
|
||||
* update the default flags during connection
|
||||
* add support for setting wait_timeout on AR adapter
|
||||
* upgrade to rspec2
|
||||
* bugfix for an edge case where the GC would clean up a Mysql2::Client object before the underlying MYSQL pointer had been initialized
|
||||
* fix to CFLAGS to allow compilation on SPARC with sunstudio compiler - Anko painting <anko.com+github@gmail.com>
|
||||
|
||||
## 0.2.4 (September 17th, 2010)
|
||||
* a few patches for win32 support from Luis Lavena - thanks man!
|
||||
* bugfix from Eric Wong to avoid a potential stack overflow during Mysql2::Client#escape
|
||||
|
|
|
@ -76,7 +76,7 @@ static void rb_mysql_client_mark(void * wrapper) {
|
|||
|
||||
static VALUE rb_raise_mysql2_error(MYSQL *client) {
|
||||
VALUE e = rb_exc_new2(cMysql2Error, mysql_error(client));
|
||||
rb_funcall(e, intern_error_number_eql, 1, INT2NUM(mysql_errno(client)));
|
||||
rb_funcall(e, intern_error_number_eql, 1, UINT2NUM(mysql_errno(client)));
|
||||
rb_funcall(e, intern_sql_state_eql, 1, rb_tainted_str_new2(mysql_sqlstate(client)));
|
||||
rb_exc_raise(e);
|
||||
return Qnil;
|
||||
|
@ -264,7 +264,7 @@ static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
|
|||
fd_set fdset;
|
||||
int fd, retval;
|
||||
int async = 0;
|
||||
VALUE opts, defaults;
|
||||
VALUE opts, defaults, read_timeout;
|
||||
GET_CLIENT(self);
|
||||
|
||||
REQUIRE_OPEN_DB(wrapper);
|
||||
|
@ -290,6 +290,7 @@ static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
|
|||
opts = defaults;
|
||||
}
|
||||
|
||||
Check_Type(args.sql, T_STRING);
|
||||
#ifdef HAVE_RUBY_ENCODING_H
|
||||
rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding);
|
||||
// ensure the string is in the encoding the connection is expecting
|
||||
|
@ -302,6 +303,23 @@ static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
|
|||
return rb_raise_mysql2_error(wrapper->client);
|
||||
}
|
||||
|
||||
read_timeout = rb_iv_get(self, "@read_timeout");
|
||||
struct timeval tv;
|
||||
struct timeval* tvp = NULL;
|
||||
if (!NIL_P(read_timeout)) {
|
||||
Check_Type(read_timeout, T_FIXNUM);
|
||||
tvp = &tv;
|
||||
long int sec = FIX2INT(read_timeout);
|
||||
// TODO: support partial seconds?
|
||||
// also, this check is here for sanity, we also check up in Ruby
|
||||
if (sec >= 0) {
|
||||
tvp->tv_sec = sec;
|
||||
} else {
|
||||
rb_raise(cMysql2Error, "read_timeout must be a positive integer, you passed %ld", sec);
|
||||
}
|
||||
tvp->tv_usec = 0;
|
||||
}
|
||||
|
||||
if (!async) {
|
||||
// the below code is largely from do_mysql
|
||||
// http://github.com/datamapper/do
|
||||
|
@ -310,7 +328,11 @@ static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
|
|||
FD_ZERO(&fdset);
|
||||
FD_SET(fd, &fdset);
|
||||
|
||||
retval = rb_thread_select(fd + 1, &fdset, NULL, NULL, NULL);
|
||||
retval = rb_thread_select(fd + 1, &fdset, NULL, NULL, tvp);
|
||||
|
||||
if (retval == 0) {
|
||||
rb_raise(cMysql2Error, "Timeout waiting for a response from the last query. (waited %d seconds)", FIX2INT(read_timeout));
|
||||
}
|
||||
|
||||
if (retval < 0) {
|
||||
rb_sys_fail(0);
|
||||
|
@ -516,20 +538,6 @@ static VALUE init_connection(VALUE self) {
|
|||
return self;
|
||||
}
|
||||
|
||||
/* call-seq: client.create_statement # => Mysql2::Statement
|
||||
*
|
||||
* Create a new prepared statement.
|
||||
*/
|
||||
static VALUE create_statement(VALUE self) {
|
||||
MYSQL * client;
|
||||
MYSQL_STMT * stmt;
|
||||
|
||||
Data_Get_Struct(self, MYSQL, client);
|
||||
stmt = mysql_stmt_init(client);
|
||||
|
||||
return Data_Wrap_Struct(cMysql2Statement, 0, mysql_stmt_close, stmt);
|
||||
}
|
||||
|
||||
void init_mysql2_client() {
|
||||
cMysql2Client = rb_define_class_under(mMysql2, "Client", rb_cObject);
|
||||
|
||||
|
@ -544,7 +552,6 @@ void init_mysql2_client() {
|
|||
rb_define_method(cMysql2Client, "async_result", rb_mysql_client_async_result, 0);
|
||||
rb_define_method(cMysql2Client, "last_id", rb_mysql_client_last_id, 0);
|
||||
rb_define_method(cMysql2Client, "affected_rows", rb_mysql_client_affected_rows, 0);
|
||||
rb_define_method(cMysql2Client, "create_statement", create_statement, 0);
|
||||
|
||||
rb_define_private_method(cMysql2Client, "reconnect=", set_reconnect, 1);
|
||||
rb_define_private_method(cMysql2Client, "connect_timeout=", set_connect_timeout, 1);
|
||||
|
|
|
@ -33,8 +33,8 @@ void init_mysql2_client();
|
|||
|
||||
typedef struct {
|
||||
VALUE encoding;
|
||||
short int active;
|
||||
short int closed;
|
||||
char active;
|
||||
char closed;
|
||||
MYSQL *client;
|
||||
} mysql_client_wrapper;
|
||||
|
||||
|
|
|
@ -57,9 +57,13 @@ end
|
|||
asplode h unless have_header h
|
||||
end
|
||||
|
||||
unless RUBY_PLATFORM =~ /mswin/
|
||||
unless RUBY_PLATFORM =~ /mswin/ or RUBY_PLATFORM =~ /sparc/
|
||||
$CFLAGS << ' -Wall -funroll-loops'
|
||||
end
|
||||
# $CFLAGS << ' -O0 -ggdb3 -Wextra'
|
||||
|
||||
if hard_mysql_path = $libs[%r{-L(/[^ ]+)}, 1]
|
||||
$LDFLAGS << " -Wl,-rpath,#{hard_mysql_path}"
|
||||
end
|
||||
|
||||
create_makefile('mysql2/mysql2')
|
||||
|
|
|
@ -2,21 +2,6 @@
|
|||
|
||||
VALUE mMysql2, cMysql2Error;
|
||||
|
||||
/* call-seq: client.create_statement # => Mysql2::Statement
|
||||
*
|
||||
* Create a new prepared statement.
|
||||
*/
|
||||
static VALUE create_statement(VALUE self)
|
||||
{
|
||||
MYSQL * client;
|
||||
MYSQL_STMT * stmt;
|
||||
|
||||
Data_Get_Struct(self, MYSQL, client);
|
||||
stmt = mysql_stmt_init(client);
|
||||
|
||||
return Data_Wrap_Struct(cMysql2Statement, 0, mysql_stmt_close, stmt);
|
||||
}
|
||||
|
||||
/* Ruby Extension initializer */
|
||||
void Init_mysql2() {
|
||||
mMysql2 = rb_define_module("Mysql2");
|
||||
|
@ -24,5 +9,4 @@ void Init_mysql2() {
|
|||
|
||||
init_mysql2_client();
|
||||
init_mysql2_result();
|
||||
init_mysql2_statement();
|
||||
}
|
||||
|
|
|
@ -4,6 +4,12 @@
|
|||
#include <ruby.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef HAVE_UINT
|
||||
#define HAVE_UINT
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned int uint;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MYSQL_H
|
||||
#include <mysql.h>
|
||||
#include <mysql_com.h>
|
||||
|
@ -28,6 +34,5 @@
|
|||
|
||||
#include <client.h>
|
||||
#include <result.h>
|
||||
#include <statement.h>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -248,7 +248,7 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
|
|||
val = rb_str_new(row[i], fieldLengths[i]);
|
||||
#ifdef HAVE_RUBY_ENCODING_H
|
||||
// if binary flag is set, respect it's wishes
|
||||
if (fields[i].flags & BINARY_FLAG) {
|
||||
if (fields[i].flags & BINARY_FLAG && fields[i].charsetnr == 63) {
|
||||
rb_enc_associate(val, binaryEncoding);
|
||||
} else {
|
||||
// lookup the encoding configured on this field
|
||||
|
|
|
@ -8,10 +8,10 @@ typedef struct {
|
|||
VALUE fields;
|
||||
VALUE rows;
|
||||
VALUE encoding;
|
||||
long numberOfFields;
|
||||
unsigned int numberOfFields;
|
||||
unsigned long numberOfRows;
|
||||
unsigned long lastRowProcessed;
|
||||
short int resultFreed;
|
||||
char resultFreed;
|
||||
MYSQL_RES *result;
|
||||
} mysql2_result_wrapper;
|
||||
|
||||
|
|
|
@ -1,203 +0,0 @@
|
|||
#include <mysql2_ext.h>
|
||||
|
||||
VALUE cMysql2Statement;
|
||||
extern VALUE mMysql2, cMysql2Error;
|
||||
|
||||
/* call-seq: stmt.prepare(sql)
|
||||
*
|
||||
* Prepare +sql+ for execution
|
||||
*/
|
||||
static VALUE prepare(VALUE self, VALUE sql)
|
||||
{
|
||||
MYSQL_STMT * stmt;
|
||||
Data_Get_Struct(self, MYSQL_STMT, stmt);
|
||||
|
||||
if(mysql_stmt_prepare(stmt, StringValuePtr(sql), RSTRING_LEN(sql))) {
|
||||
rb_raise(cMysql2Error, "%s", mysql_stmt_error(stmt));
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/* call-seq: stmt.param_count # => 2
|
||||
*
|
||||
* Returns the number of parameters the prepared statement expects.
|
||||
*/
|
||||
static VALUE param_count(VALUE self)
|
||||
{
|
||||
MYSQL_STMT * stmt;
|
||||
Data_Get_Struct(self, MYSQL_STMT, stmt);
|
||||
|
||||
return ULL2NUM(mysql_stmt_param_count(stmt));
|
||||
}
|
||||
|
||||
/* call-seq: stmt.field_count # => 2
|
||||
*
|
||||
* Returns the number of fields the prepared statement returns.
|
||||
*/
|
||||
static VALUE field_count(VALUE self)
|
||||
{
|
||||
MYSQL_STMT * stmt;
|
||||
Data_Get_Struct(self, MYSQL_STMT, stmt);
|
||||
|
||||
return UINT2NUM(mysql_stmt_field_count(stmt));
|
||||
}
|
||||
|
||||
/* call-seq: stmt.execute
|
||||
*
|
||||
* Executes the current prepared statement, returns +stmt+.
|
||||
*/
|
||||
static VALUE execute(VALUE self)
|
||||
{
|
||||
MYSQL_STMT * stmt;
|
||||
Data_Get_Struct(self, MYSQL_STMT, stmt);
|
||||
|
||||
if(mysql_stmt_execute(stmt))
|
||||
rb_raise(cMysql2Error, "%s", mysql_stmt_error(stmt));
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/* call-seq: stmt.fields -> array
|
||||
*
|
||||
* Returns a list of fields that will be returned by this statement.
|
||||
*/
|
||||
static VALUE fields(VALUE self)
|
||||
{
|
||||
MYSQL_STMT * stmt;
|
||||
MYSQL_FIELD * fields;
|
||||
MYSQL_RES * metadata;
|
||||
unsigned int field_count;
|
||||
unsigned int i;
|
||||
VALUE field_list;
|
||||
VALUE cMysql2Field;
|
||||
|
||||
Data_Get_Struct(self, MYSQL_STMT, stmt);
|
||||
metadata = mysql_stmt_result_metadata(stmt);
|
||||
fields = mysql_fetch_fields(metadata);
|
||||
field_count = mysql_stmt_field_count(stmt);
|
||||
field_list = rb_ary_new2((long)field_count);
|
||||
|
||||
cMysql2Field = rb_const_get(mMysql2, rb_intern("Field"));
|
||||
|
||||
for(i = 0; i < field_count; i++) {
|
||||
VALUE argv[2];
|
||||
VALUE field;
|
||||
|
||||
/* FIXME: encoding. Also, can this return null? */
|
||||
argv[0] = rb_str_new2(fields[i].name);
|
||||
argv[1] = INT2NUM(fields[i].type);
|
||||
|
||||
field = rb_class_new_instance(2, argv, cMysql2Field);
|
||||
|
||||
rb_ary_store(field_list, (long)i, field);
|
||||
}
|
||||
|
||||
return field_list;
|
||||
}
|
||||
|
||||
static VALUE each(VALUE self)
|
||||
{
|
||||
MYSQL_STMT * stmt;
|
||||
MYSQL_FIELD * fields;
|
||||
MYSQL_RES * metadata;
|
||||
|
||||
MYSQL_BIND * binds;
|
||||
my_bool * is_null;
|
||||
my_bool * error;
|
||||
unsigned long * length;
|
||||
int int_data;
|
||||
MYSQL_TIME ts;
|
||||
|
||||
unsigned int field_count;
|
||||
unsigned int i;
|
||||
VALUE block;
|
||||
|
||||
Data_Get_Struct(self, MYSQL_STMT, stmt);
|
||||
|
||||
block = rb_block_proc();
|
||||
metadata = mysql_stmt_result_metadata(stmt);
|
||||
fields = mysql_fetch_fields(metadata);
|
||||
field_count = mysql_stmt_field_count(stmt);
|
||||
|
||||
binds = xcalloc(field_count, sizeof(MYSQL_BIND));
|
||||
is_null = xcalloc(field_count, sizeof(my_bool));
|
||||
error = xcalloc(field_count, sizeof(my_bool));
|
||||
length = xcalloc(field_count, sizeof(unsigned long));
|
||||
|
||||
for(i = 0; i < field_count; i++) {
|
||||
switch(fields[i].type) {
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
binds[i].buffer_type = MYSQL_TYPE_LONG;
|
||||
binds[i].buffer = (char *)&int_data;
|
||||
break;
|
||||
case MYSQL_TYPE_DATETIME:
|
||||
binds[i].buffer_type = MYSQL_TYPE_DATETIME;
|
||||
binds[i].buffer = (char *)&ts;
|
||||
break;
|
||||
default:
|
||||
rb_raise(cMysql2Error, "unhandled mysql type: %d", fields[i].type);
|
||||
}
|
||||
|
||||
binds[i].is_null = &is_null[i];
|
||||
binds[i].length = &length[i];
|
||||
binds[i].error = &error[i];
|
||||
}
|
||||
|
||||
if(mysql_stmt_bind_result(stmt, binds)) {
|
||||
xfree(binds);
|
||||
xfree(is_null);
|
||||
xfree(error);
|
||||
xfree(length);
|
||||
rb_raise(cMysql2Error, "%s", mysql_stmt_error(stmt));
|
||||
}
|
||||
|
||||
while(!mysql_stmt_fetch(stmt)) {
|
||||
VALUE row = rb_ary_new2((long)field_count);
|
||||
|
||||
for(i = 0; i < field_count; i++) {
|
||||
VALUE column = Qnil;
|
||||
switch(binds[i].buffer_type) {
|
||||
case MYSQL_TYPE_LONG:
|
||||
column = INT2NUM(int_data);
|
||||
break;
|
||||
/* FIXME: maybe we want to return a datetime in this case? */
|
||||
case MYSQL_TYPE_DATETIME:
|
||||
column = rb_funcall(rb_cTime,
|
||||
rb_intern("mktime"), 6,
|
||||
UINT2NUM(ts.year),
|
||||
UINT2NUM(ts.month),
|
||||
UINT2NUM(ts.day),
|
||||
UINT2NUM(ts.hour),
|
||||
UINT2NUM(ts.minute),
|
||||
UINT2NUM(ts.second));
|
||||
break;
|
||||
default:
|
||||
rb_raise(cMysql2Error, "unhandled buffer type: %d",
|
||||
binds[i].buffer_type);
|
||||
break;
|
||||
}
|
||||
rb_ary_store(row, (long)i, column);
|
||||
}
|
||||
rb_yield(row);
|
||||
}
|
||||
|
||||
xfree(binds);
|
||||
xfree(is_null);
|
||||
xfree(error);
|
||||
xfree(length);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void init_mysql2_statement()
|
||||
{
|
||||
cMysql2Statement = rb_define_class_under(mMysql2, "Statement", rb_cObject);
|
||||
|
||||
rb_define_method(cMysql2Statement, "prepare", prepare, 1);
|
||||
rb_define_method(cMysql2Statement, "param_count", param_count, 0);
|
||||
rb_define_method(cMysql2Statement, "field_count", field_count, 0);
|
||||
rb_define_method(cMysql2Statement, "execute", execute, 0);
|
||||
rb_define_method(cMysql2Statement, "each", each, 0);
|
||||
rb_define_method(cMysql2Statement, "fields", fields, 0);
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
#ifndef MYSQL2_STATEMENT_H
|
||||
#define MYSQL2_STATEMENT_H
|
||||
|
||||
extern VALUE cMysql2Statement;
|
||||
|
||||
void init_mysql2_statement();
|
||||
|
||||
#endif
|
|
@ -35,7 +35,6 @@ module Mysql2
|
|||
results = @client.async_result
|
||||
@deferable.succeed(results)
|
||||
rescue Exception => e
|
||||
puts e.backtrace.join("\n\t")
|
||||
@deferable.fail(e)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,6 +18,9 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
module ConnectionAdapters
|
||||
class Mysql2IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths) #:nodoc:
|
||||
end
|
||||
|
||||
class Mysql2Column < Column
|
||||
BOOL = "tinyint(1)"
|
||||
def extract_default(default)
|
||||
|
@ -447,7 +450,7 @@ module ActiveRecord
|
|||
if current_index != row[:Key_name]
|
||||
next if row[:Key_name] == PRIMARY # skip the primary key
|
||||
current_index = row[:Key_name]
|
||||
indexes << IndexDefinition.new(row[:Table], row[:Key_name], row[:Non_unique] == 0, [], [])
|
||||
indexes << Mysql2IndexDefinition.new(row[:Table], row[:Key_name], row[:Non_unique] == 0, [], [])
|
||||
end
|
||||
|
||||
indexes.last.columns << row[:Column_name]
|
||||
|
@ -622,8 +625,9 @@ module ActiveRecord
|
|||
variable_assignments << "NAMES '#{encoding}'" if encoding
|
||||
|
||||
# increase timeout so mysql server doesn't disconnect us
|
||||
wait_timeout = @config[:wait_timeout] || 2592000
|
||||
variable_assignments << "@@wait_timeout = #{wait_timeout}" if wait_timeout.is_a?(Fixnum)
|
||||
wait_timeout = @config[:wait_timeout]
|
||||
wait_timeout = 2592000 unless wait_timeout.is_a?(Fixnum)
|
||||
variable_assignments << "@@wait_timeout = #{wait_timeout}"
|
||||
|
||||
execute("SET #{variable_assignments.join(', ')}", :skip_logging)
|
||||
end
|
||||
|
|
|
@ -7,11 +7,10 @@ require 'mysql2/error'
|
|||
require 'mysql2/mysql2'
|
||||
require 'mysql2/client'
|
||||
require 'mysql2/result'
|
||||
require 'mysql2/field'
|
||||
|
||||
# = Mysql2
|
||||
#
|
||||
# A modern, simple and very fast Mysql library for Ruby - binding to libmysql
|
||||
module Mysql2
|
||||
VERSION = "0.2.4"
|
||||
VERSION = "0.2.6"
|
||||
end
|
||||
|
|
|
@ -24,6 +24,11 @@ module Mysql2
|
|||
# force the encoding to utf8
|
||||
self.charset_name = opts[:encoding] || 'utf8'
|
||||
|
||||
@read_timeout = opts[:read_timeout]
|
||||
if @read_timeout and @read_timeout < 0
|
||||
raise Mysql2::Error, "read_timeout must be a positive integer, you passed #{@read_timeout}"
|
||||
end
|
||||
|
||||
ssl_set(*opts.values_at(:sslkey, :sslcert, :sslca, :sslcapath, :sslciper))
|
||||
|
||||
user = opts[:username]
|
||||
|
|
|
@ -23,10 +23,14 @@ module Mysql2
|
|||
end
|
||||
|
||||
def query(sql, opts={})
|
||||
super(sql, opts.merge(:async => true))
|
||||
deferable = ::EM::DefaultDeferrable.new
|
||||
::EM.watch(self.socket, Watcher, self, deferable).notify_readable = true
|
||||
deferable
|
||||
if ::EM.reactor_running?
|
||||
super(sql, opts.merge(:async => true))
|
||||
deferable = ::EM::DefaultDeferrable.new
|
||||
::EM.watch(self.socket, Watcher, self, deferable).notify_readable = true
|
||||
deferable
|
||||
else
|
||||
super(sql, opts)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
# encoding: utf-8
|
||||
|
||||
require 'mysql2/em'
|
||||
require 'fiber'
|
||||
|
||||
module Mysql2
|
||||
module EM
|
||||
module Fiber
|
||||
class Client < ::Mysql2::EM::Client
|
||||
def query(sql, opts={})
|
||||
if ::EM.reactor_running?
|
||||
deferable = super(sql, opts)
|
||||
|
||||
fiber = ::Fiber.current
|
||||
deferable.callback do |result|
|
||||
fiber.resume(result)
|
||||
end
|
||||
deferable.errback do |err|
|
||||
fiber.resume(err)
|
||||
end
|
||||
::Fiber.yield
|
||||
else
|
||||
super(sql, opts)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,4 +0,0 @@
|
|||
module Mysql2
|
||||
class Field < Struct.new(:name, :type)
|
||||
end
|
||||
end
|
|
@ -5,11 +5,11 @@
|
|||
|
||||
Gem::Specification.new do |s|
|
||||
s.name = %q{mysql2}
|
||||
s.version = "0.2.4"
|
||||
s.version = "0.2.6"
|
||||
|
||||
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
||||
s.authors = ["Brian Lopez"]
|
||||
s.date = %q{2010-10-18}
|
||||
s.date = %q{2010-10-19}
|
||||
s.email = %q{seniorlopez@gmail.com}
|
||||
s.extensions = ["ext/mysql2/extconf.rb"]
|
||||
s.extra_rdoc_files = [
|
||||
|
@ -46,6 +46,7 @@ Gem::Specification.new do |s|
|
|||
"lib/mysql2.rb",
|
||||
"lib/mysql2/client.rb",
|
||||
"lib/mysql2/em.rb",
|
||||
"lib/mysql2/em_fiber.rb",
|
||||
"lib/mysql2/error.rb",
|
||||
"lib/mysql2/result.rb",
|
||||
"mysql2.gemspec",
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
# encoding: UTF-8
|
||||
if defined? EventMachine && defined? Fiber
|
||||
require 'spec_helper'
|
||||
require 'mysql2/em_fiber'
|
||||
|
||||
describe Mysql2::EM::Fiber::Client do
|
||||
it 'should support queries' do
|
||||
results = []
|
||||
EM.run do
|
||||
Fiber.new {
|
||||
client1 = Mysql2::EM::Fiber::Client.new
|
||||
results = client1.query "SELECT sleep(0.1) as first_query"
|
||||
EM.stop_event_loop
|
||||
}.resume
|
||||
end
|
||||
|
||||
results.first.keys.should include("first_query")
|
||||
end
|
||||
end
|
||||
else
|
||||
puts "Either EventMachine or Fibers not available. Skipping tests that use them."
|
||||
end
|
|
@ -85,7 +85,19 @@ describe Mysql2::Client do
|
|||
@client.should respond_to(:query)
|
||||
end
|
||||
|
||||
it "should expect read_timeout to be a positive integer" do
|
||||
lambda {
|
||||
Mysql2::Client.new(:read_timeout => -1)
|
||||
}.should raise_error(Mysql2::Error)
|
||||
end
|
||||
|
||||
context "#query" do
|
||||
it "should only accept strings as the query parameter" do
|
||||
lambda {
|
||||
@client.query ["SELECT 'not right'"]
|
||||
}.should raise_error(TypeError)
|
||||
end
|
||||
|
||||
it "should accept an options hash that inherits from Mysql2::Client.default_query_options" do
|
||||
@client.query "SELECT 1", :something => :else
|
||||
@client.query_options.should eql(@client.query_options.merge(:something => :else))
|
||||
|
@ -118,6 +130,13 @@ describe Mysql2::Client do
|
|||
}.should raise_error(Mysql2::Error)
|
||||
end
|
||||
|
||||
it "should timeout if we wait longer than :read_timeout" do
|
||||
client = Mysql2::Client.new(:read_timeout => 1)
|
||||
lambda {
|
||||
client.query("SELECT sleep(2)")
|
||||
}.should raise_error(Mysql2::Error)
|
||||
end
|
||||
|
||||
# XXX this test is not deterministic (because Unix signal handling is not)
|
||||
# and may fail on a loaded system
|
||||
if RUBY_PLATFORM !~ /mingw|mswin/
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
# encoding: UTF-8
|
||||
require 'spec_helper'
|
||||
|
||||
describe Mysql2::Statement do
|
||||
before :each do
|
||||
@client = Mysql2::Client.new :host => "localhost", :username => "root"
|
||||
end
|
||||
|
||||
it "should create a statement" do
|
||||
stmt = @client.create_statement
|
||||
stmt.should be_kind_of Mysql2::Statement
|
||||
end
|
||||
|
||||
it "prepares some sql" do
|
||||
stmt = @client.create_statement
|
||||
lambda { stmt.prepare 'SELECT 1' }.should_not raise_error
|
||||
end
|
||||
|
||||
it "return self when prepare some sql" do
|
||||
stmt = @client.create_statement
|
||||
stmt.prepare('SELECT 1').should == stmt
|
||||
end
|
||||
|
||||
it "should raise an exception when server disconnects" do
|
||||
stmt = @client.create_statement
|
||||
@client.close
|
||||
lambda { stmt.prepare 'SELECT 1' }.should raise_error(Mysql2::Error)
|
||||
end
|
||||
|
||||
it "should tell us the param count" do
|
||||
stmt = @client.create_statement
|
||||
stmt.prepare 'SELECT ?, ?'
|
||||
stmt.param_count.should == 2
|
||||
|
||||
stmt.prepare 'SELECT 1'
|
||||
stmt.param_count.should == 0
|
||||
end
|
||||
|
||||
it "should tell us the field count" do
|
||||
stmt = @client.create_statement
|
||||
stmt.prepare 'SELECT ?, ?'
|
||||
stmt.field_count.should == 2
|
||||
|
||||
stmt.prepare 'SELECT 1'
|
||||
stmt.field_count.should == 1
|
||||
end
|
||||
|
||||
it "should let us execute our statement" do
|
||||
stmt = @client.create_statement
|
||||
stmt.prepare 'SELECT 1'
|
||||
stmt.execute.should == stmt
|
||||
end
|
||||
|
||||
it "should raise an exception on error" do
|
||||
stmt = @client.create_statement
|
||||
lambda { stmt.execute }.should raise_error(Mysql2::Error)
|
||||
end
|
||||
|
||||
it "should raise an exception without a block" do
|
||||
stmt = @client.create_statement
|
||||
stmt.prepare 'SELECT 1'
|
||||
stmt.execute
|
||||
lambda { stmt.each }.should raise_error
|
||||
end
|
||||
|
||||
it "should let us iterate over results" do
|
||||
stmt = @client.create_statement
|
||||
stmt.prepare 'SELECT 1'
|
||||
stmt.execute
|
||||
rows = []
|
||||
stmt.each { |row| rows << row }
|
||||
rows.should == [[1]]
|
||||
end
|
||||
|
||||
it "should select dates" do
|
||||
stmt = @client.create_statement
|
||||
stmt.prepare 'SELECT NOW()'
|
||||
stmt.execute
|
||||
rows = []
|
||||
stmt.each { |row| rows << row }
|
||||
rows.first.first.should be_kind_of Time
|
||||
end
|
||||
|
||||
it "should tell us about the fields" do
|
||||
stmt = @client.create_statement
|
||||
stmt.prepare 'SELECT 1 as foo, 2'
|
||||
stmt.execute
|
||||
list = stmt.fields
|
||||
list.length.should == 2
|
||||
list.first.name.should == 'foo'
|
||||
list[1].name.should == '2'
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue