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);
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -12,5 +12,5 @@ require 'mysql2/result'
|
|||
#
|
||||
# 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
|
|
@ -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/
|
||||
|
|
Loading…
Reference in New Issue