mysql2 0.3.18-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,23 @@
1
+ #ifndef MYSQL2_RESULT_H
2
+ #define MYSQL2_RESULT_H
3
+
4
+ void init_mysql2_result();
5
+ VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_RES *r);
6
+
7
+ typedef struct {
8
+ VALUE fields;
9
+ VALUE rows;
10
+ VALUE client;
11
+ VALUE encoding;
12
+ unsigned int numberOfFields;
13
+ unsigned long numberOfRows;
14
+ unsigned long lastRowProcessed;
15
+ char streamingComplete;
16
+ char resultFreed;
17
+ MYSQL_RES *result;
18
+ mysql_client_wrapper *client_wrapper;
19
+ } mysql2_result_wrapper;
20
+
21
+ #define GetMysql2Result(obj, sval) (sval = (mysql2_result_wrapper*)DATA_PTR(obj));
22
+
23
+ #endif
@@ -0,0 +1,36 @@
1
+ /*
2
+ * backwards compatibility for pre-1.9.3 C API
3
+ *
4
+ * Ruby 1.9.3 provides this API which allows the use of ppoll() on Linux
5
+ * to minimize select() and malloc() overhead on high-numbered FDs.
6
+ */
7
+ #ifdef HAVE_RB_WAIT_FOR_SINGLE_FD
8
+ # include <ruby/io.h>
9
+ #else
10
+ # define RB_WAITFD_IN 0x001
11
+ # define RB_WAITFD_PRI 0x002
12
+ # define RB_WAITFD_OUT 0x004
13
+
14
+ static int my_wait_for_single_fd(int fd, int events, struct timeval *tvp)
15
+ {
16
+ fd_set fdset;
17
+ fd_set *rfds = NULL;
18
+ fd_set *wfds = NULL;
19
+ fd_set *efds = NULL;
20
+
21
+ FD_ZERO(&fdset);
22
+ FD_SET(fd, &fdset);
23
+
24
+ if (events & RB_WAITFD_IN)
25
+ rfds = &fdset;
26
+ if (events & RB_WAITFD_OUT)
27
+ wfds = &fdset;
28
+ if (events & RB_WAITFD_PRI)
29
+ efds = &fdset;
30
+
31
+ return rb_thread_select(fd + 1, rfds, wfds, efds, tvp);
32
+ }
33
+
34
+ #define rb_wait_for_single_fd(fd,events,tvp) \
35
+ my_wait_for_single_fd((fd),(events),(tvp))
36
+ #endif
@@ -0,0 +1,64 @@
1
+ # encoding: UTF-8
2
+ require 'date'
3
+ require 'bigdecimal'
4
+ require 'rational' unless RUBY_VERSION >= '1.9.2'
5
+
6
+ # Load libmysql.dll before requiring mysql2/mysql2.so
7
+ # This gives a chance to be flexible about the load path
8
+ # Or to bomb out with a clear error message instead of a linker crash
9
+ if RUBY_PLATFORM =~ /mswin|mingw/
10
+ dll_path = if ENV['RUBY_MYSQL2_LIBMYSQL_DLL']
11
+ # If this environment variable is set, it overrides any other paths
12
+ # The user is advised to use backslashes not forward slashes
13
+ ENV['RUBY_MYSQL2_LIBMYSQL_DLL'].dup
14
+ elsif File.exist?(File.expand_path('../vendor/libmysql.dll', File.dirname(__FILE__)))
15
+ # Use vendor/libmysql.dll if it exists, convert slashes for Win32 LoadLibrary
16
+ File.expand_path('../vendor/libmysql.dll', File.dirname(__FILE__)).gsub('/', '\\')
17
+ else
18
+ # This will use default / system library paths
19
+ 'libmysql.dll'
20
+ end
21
+
22
+ require 'Win32API'
23
+ LoadLibrary = Win32API.new('Kernel32', 'LoadLibrary', ['P'], 'I')
24
+ if 0 == LoadLibrary.call(dll_path)
25
+ abort "Failed to load libmysql.dll from #{dll_path}"
26
+ end
27
+ end
28
+
29
+ require 'mysql2/version' unless defined? Mysql2::VERSION
30
+ require 'mysql2/error'
31
+ require 'mysql2/mysql2'
32
+ require 'mysql2/result'
33
+ require 'mysql2/client'
34
+
35
+ # = Mysql2
36
+ #
37
+ # A modern, simple and very fast Mysql library for Ruby - binding to libmysql
38
+ module Mysql2
39
+ end
40
+
41
+ if defined?(ActiveRecord::VERSION::STRING) && ActiveRecord::VERSION::STRING < "3.1"
42
+ begin
43
+ require 'active_record/connection_adapters/mysql2_adapter'
44
+ rescue LoadError
45
+ warn "============= WARNING FROM mysql2 ============="
46
+ warn "This version of mysql2 (#{Mysql2::VERSION}) doesn't ship with the ActiveRecord adapter."
47
+ warn "In Rails version 3.1.0 and up, the mysql2 ActiveRecord adapter is included with rails."
48
+ warn "If you want to use the mysql2 gem with Rails <= 3.0.x, please use the latest mysql2 in the 0.2.x series."
49
+ warn "============= END WARNING FROM mysql2 ============="
50
+ end
51
+ end
52
+
53
+ # For holding utility methods
54
+ module Mysql2::Util
55
+
56
+ #
57
+ # Rekey a string-keyed hash with equivalent symbols.
58
+ #
59
+ def self.key_hash_as_symbols(hash)
60
+ return nil unless hash
61
+ Hash[hash.map { |k,v| [k.to_sym, v] }]
62
+ end
63
+
64
+ end
Binary file
Binary file
@@ -0,0 +1,90 @@
1
+ module Mysql2
2
+ class Client
3
+ attr_reader :query_options, :read_timeout
4
+ @@default_query_options = {
5
+ :as => :hash, # the type of object you want each row back as; also supports :array (an array of values)
6
+ :async => false, # don't wait for a result after sending the query, you'll have to monitor the socket yourself then eventually call Mysql2::Client#async_result
7
+ :cast_booleans => false, # cast tinyint(1) fields as true/false in ruby
8
+ :symbolize_keys => false, # return field names as symbols instead of strings
9
+ :database_timezone => :local, # timezone Mysql2 will assume datetime objects are stored in
10
+ :application_timezone => nil, # timezone Mysql2 will convert to before handing the object back to the caller
11
+ :cache_rows => true, # tells Mysql2 to use it's internal row cache for results
12
+ :connect_flags => REMEMBER_OPTIONS | LONG_PASSWORD | LONG_FLAG | TRANSACTIONS | PROTOCOL_41 | SECURE_CONNECTION,
13
+ :cast => true,
14
+ :default_file => nil,
15
+ :default_group => nil
16
+ }
17
+
18
+ def initialize(opts = {})
19
+ opts = Mysql2::Util.key_hash_as_symbols( opts )
20
+ @read_timeout = nil
21
+ @query_options = @@default_query_options.dup
22
+ @query_options.merge! opts
23
+
24
+ initialize_ext
25
+
26
+ # Set default connect_timeout to avoid unlimited retries from signal interruption
27
+ opts[:connect_timeout] = 120 unless opts.key?(:connect_timeout)
28
+
29
+ [:reconnect, :connect_timeout, :local_infile, :read_timeout, :write_timeout, :default_file, :default_group, :secure_auth, :init_command].each do |key|
30
+ next unless opts.key?(key)
31
+ case key
32
+ when :reconnect, :local_infile, :secure_auth
33
+ send(:"#{key}=", !!opts[key])
34
+ when :connect_timeout, :read_timeout, :write_timeout
35
+ send(:"#{key}=", opts[key].to_i)
36
+ else
37
+ send(:"#{key}=", opts[key])
38
+ end
39
+ end
40
+
41
+ # force the encoding to utf8
42
+ self.charset_name = opts[:encoding] || 'utf8'
43
+
44
+ ssl_options = opts.values_at(:sslkey, :sslcert, :sslca, :sslcapath, :sslcipher)
45
+ ssl_set(*ssl_options) if ssl_options.any?
46
+
47
+ if [:user,:pass,:hostname,:dbname,:db,:sock].any?{|k| @query_options.has_key?(k) }
48
+ warn "============= WARNING FROM mysql2 ============="
49
+ warn "The options :user, :pass, :hostname, :dbname, :db, and :sock will be deprecated at some point in the future."
50
+ warn "Instead, please use :username, :password, :host, :port, :database, :socket, :flags for the options."
51
+ warn "============= END WARNING FROM mysql2 ========="
52
+ end
53
+
54
+ user = opts[:username] || opts[:user]
55
+ pass = opts[:password] || opts[:pass]
56
+ host = opts[:host] || opts[:hostname]
57
+ port = opts[:port]
58
+ database = opts[:database] || opts[:dbname] || opts[:db]
59
+ socket = opts[:socket] || opts[:sock]
60
+ flags = opts[:flags] ? opts[:flags] | @query_options[:connect_flags] : @query_options[:connect_flags]
61
+
62
+ # Correct the data types before passing these values down to the C level
63
+ user = user.to_s unless user.nil?
64
+ pass = pass.to_s unless pass.nil?
65
+ host = host.to_s unless host.nil?
66
+ port = port.to_i unless port.nil?
67
+ database = database.to_s unless database.nil?
68
+ socket = socket.to_s unless socket.nil?
69
+
70
+ connect user, pass, host, port, database, socket, flags
71
+ end
72
+
73
+ def self.default_query_options
74
+ @@default_query_options
75
+ end
76
+
77
+ def query_info
78
+ info = query_info_string
79
+ return {} unless info
80
+ info_hash = {}
81
+ info.split.each_slice(2) { |s| info_hash[s[0].downcase.delete(':').to_sym] = s[1].to_i }
82
+ info_hash
83
+ end
84
+
85
+ private
86
+ def self.local_offset
87
+ ::Time.local(2010).utc_offset.to_r / 86400
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,5 @@
1
+ # Loaded by script/console. Land helpers here.
2
+
3
+ Pry.config.prompt = lambda do |context, nesting, pry|
4
+ "[mysql2] #{context}> "
5
+ end
@@ -0,0 +1,56 @@
1
+ # encoding: utf-8
2
+
3
+ require 'eventmachine'
4
+ require 'mysql2'
5
+
6
+ module Mysql2
7
+ module EM
8
+ class Client < ::Mysql2::Client
9
+ module Watcher
10
+ def initialize(client, deferable)
11
+ @client = client
12
+ @deferable = deferable
13
+ @is_watching = true
14
+ end
15
+
16
+ def notify_readable
17
+ detach
18
+ begin
19
+ result = @client.async_result
20
+ rescue Exception => e
21
+ @deferable.fail(e)
22
+ else
23
+ @deferable.succeed(result)
24
+ end
25
+ end
26
+
27
+ def watching?
28
+ @is_watching
29
+ end
30
+
31
+ def unbind
32
+ @is_watching = false
33
+ end
34
+ end
35
+
36
+ def close(*args)
37
+ if @watch
38
+ @watch.detach if @watch.watching?
39
+ end
40
+ super(*args)
41
+ end
42
+
43
+ def query(sql, opts={})
44
+ if ::EM.reactor_running?
45
+ super(sql, opts.merge(:async => true))
46
+ deferable = ::EM::DefaultDeferrable.new
47
+ @watch = ::EM.watch(self.socket, Watcher, self, deferable)
48
+ @watch.notify_readable = true
49
+ deferable
50
+ else
51
+ super(sql, opts)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,80 @@
1
+ # encoding: UTF-8
2
+
3
+ module Mysql2
4
+ class Error < StandardError
5
+ REPLACEMENT_CHAR = '?'
6
+ ENCODE_OPTS = {:undef => :replace, :invalid => :replace, :replace => REPLACEMENT_CHAR}
7
+
8
+ attr_accessor :error_number
9
+ attr_reader :sql_state
10
+ attr_writer :server_version
11
+
12
+ # Mysql gem compatibility
13
+ alias_method :errno, :error_number
14
+ alias_method :error, :message
15
+
16
+ def initialize(msg, server_version=nil)
17
+ self.server_version = server_version
18
+
19
+ super(clean_message(msg))
20
+ end
21
+
22
+ def sql_state=(state)
23
+ @sql_state = ''.respond_to?(:encode) ? state.encode(ENCODE_OPTS) : state
24
+ end
25
+
26
+ private
27
+
28
+ # In MySQL 5.5+ error messages are always constructed server-side as UTF-8
29
+ # then returned in the encoding set by the `character_set_results` system
30
+ # variable.
31
+ #
32
+ # See http://dev.mysql.com/doc/refman/5.5/en/charset-errors.html for
33
+ # more contetx.
34
+ #
35
+ # Before MySQL 5.5 error message template strings are in whatever encoding
36
+ # is associated with the error message language.
37
+ # See http://dev.mysql.com/doc/refman/5.1/en/error-message-language.html
38
+ # for more information.
39
+ #
40
+ # The issue is that the user-data inserted in the message could potentially
41
+ # be in any encoding MySQL supports and is insert into the latin1, euckr or
42
+ # koi8r string raw. Meaning there's a high probability the string will be
43
+ # corrupt encoding-wise.
44
+ #
45
+ # See http://dev.mysql.com/doc/refman/5.1/en/charset-errors.html for
46
+ # more information.
47
+ #
48
+ # So in an attempt to make sure the error message string is always in a valid
49
+ # encoding, we'll assume UTF-8 and clean the string of anything that's not a
50
+ # valid UTF-8 character.
51
+ #
52
+ # Except for if we're on 1.8, where we'll do nothing ;)
53
+ #
54
+ # Returns a valid UTF-8 string in Ruby 1.9+, the original string on Ruby 1.8
55
+ def clean_message(message)
56
+ return message if !message.respond_to?(:encoding)
57
+
58
+ if @server_version && @server_version > 50500
59
+ message.encode(ENCODE_OPTS)
60
+ else
61
+ if message.respond_to? :scrub
62
+ message.scrub(REPLACEMENT_CHAR).encode(ENCODE_OPTS)
63
+ else
64
+ # This is ugly as hell but Ruby 1.9 doesn't provide a way to clean a string
65
+ # and retain it's valid UTF-8 characters, that I know of.
66
+
67
+ new_message = "".force_encoding(Encoding::UTF_8)
68
+ message.chars.each do |char|
69
+ if char.valid_encoding?
70
+ new_message << char
71
+ else
72
+ new_message << REPLACEMENT_CHAR
73
+ end
74
+ end
75
+ new_message.encode(ENCODE_OPTS)
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,2 @@
1
+ RUBY_VERSION =~ /(\d+.\d+)/
2
+ require "mysql2/#{$1}/mysql2"
@@ -0,0 +1,5 @@
1
+ module Mysql2
2
+ class Result
3
+ include Enumerable
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module Mysql2
2
+ VERSION = "0.3.18"
3
+ end
@@ -0,0 +1,17 @@
1
+ root:
2
+ host: localhost
3
+ username: root
4
+ password:
5
+ database: test
6
+
7
+ user:
8
+ host: localhost
9
+ username: LOCALUSERNAME
10
+ password:
11
+ database: mysql2_test
12
+
13
+ numericuser:
14
+ host: localhost
15
+ username: LOCALUSERNAME
16
+ password:
17
+ database: 12345
@@ -0,0 +1,135 @@
1
+ # encoding: UTF-8
2
+ require 'spec_helper'
3
+ begin
4
+ require 'eventmachine'
5
+ require 'mysql2/em'
6
+
7
+ describe Mysql2::EM::Client do
8
+ it "should support async queries" do
9
+ results = []
10
+ EM.run do
11
+ client1 = Mysql2::EM::Client.new DatabaseCredentials['root']
12
+ defer1 = client1.query "SELECT sleep(0.1) as first_query"
13
+ defer1.callback do |result|
14
+ results << result.first
15
+ client1.close
16
+ EM.stop_event_loop
17
+ end
18
+
19
+ client2 = Mysql2::EM::Client.new DatabaseCredentials['root']
20
+ defer2 = client2.query "SELECT sleep(0.025) second_query"
21
+ defer2.callback do |result|
22
+ results << result.first
23
+ client2.close
24
+ end
25
+ end
26
+
27
+ results[0].keys.should include("second_query")
28
+ results[1].keys.should include("first_query")
29
+ end
30
+
31
+ it "should support queries in callbacks" do
32
+ results = []
33
+ EM.run do
34
+ client = Mysql2::EM::Client.new DatabaseCredentials['root']
35
+ defer1 = client.query "SELECT sleep(0.025) as first_query"
36
+ defer1.callback do |result|
37
+ results << result.first
38
+ defer2 = client.query "SELECT sleep(0.025) as second_query"
39
+ defer2.callback do |r|
40
+ results << r.first
41
+ client.close
42
+ EM.stop_event_loop
43
+ end
44
+ end
45
+ end
46
+
47
+ results[0].keys.should include("first_query")
48
+ results[1].keys.should include("second_query")
49
+ end
50
+
51
+ it "should not swallow exceptions raised in callbacks" do
52
+ lambda {
53
+ EM.run do
54
+ client = Mysql2::EM::Client.new DatabaseCredentials['root']
55
+ defer = client.query "SELECT sleep(0.1) as first_query"
56
+ defer.callback do |result|
57
+ client.close
58
+ raise 'some error'
59
+ end
60
+ defer.errback do |err|
61
+ # This _shouldn't_ be run, but it needed to prevent the specs from
62
+ # freezing if this test fails.
63
+ EM.stop_event_loop
64
+ end
65
+ end
66
+ }.should raise_error
67
+ end
68
+
69
+ context 'when an exception is raised by the client' do
70
+ let(:client) { Mysql2::EM::Client.new DatabaseCredentials['root'] }
71
+ let(:error) { StandardError.new('some error') }
72
+ before { client.stub(:async_result).and_raise(error) }
73
+
74
+ it "should swallow exceptions raised in by the client" do
75
+ errors = []
76
+ EM.run do
77
+ defer = client.query "SELECT sleep(0.1) as first_query"
78
+ defer.callback do |result|
79
+ # This _shouldn't_ be run, but it is needed to prevent the specs from
80
+ # freezing if this test fails.
81
+ EM.stop_event_loop
82
+ end
83
+ defer.errback do |err|
84
+ errors << err
85
+ EM.stop_event_loop
86
+ end
87
+ end
88
+ errors.should == [error]
89
+ end
90
+
91
+ it "should fail the deferrable" do
92
+ callbacks_run = []
93
+ EM.run do
94
+ defer = client.query "SELECT sleep(0.025) as first_query"
95
+ EM.add_timer(0.1) do
96
+ defer.callback do |result|
97
+ callbacks_run << :callback
98
+ # This _shouldn't_ be run, but it is needed to prevent the specs from
99
+ # freezing if this test fails.
100
+ EM.stop_event_loop
101
+ end
102
+ defer.errback do |err|
103
+ callbacks_run << :errback
104
+ EM.stop_event_loop
105
+ end
106
+ end
107
+ end
108
+ callbacks_run.should == [:errback]
109
+ end
110
+ end
111
+
112
+ it "should not raise error when closing client with no query running" do
113
+ callbacks_run = []
114
+ EM.run do
115
+ client = Mysql2::EM::Client.new DatabaseCredentials['root']
116
+ defer = client.query("select sleep(0.025)")
117
+ defer.callback do |result|
118
+ callbacks_run << :callback
119
+ end
120
+ defer.errback do |err|
121
+ callbacks_run << :errback
122
+ end
123
+ EM.add_timer(0.1) do
124
+ callbacks_run.should == [:callback]
125
+ lambda {
126
+ client.close
127
+ }.should_not raise_error(/invalid binding to detach/)
128
+ EM.stop_event_loop
129
+ end
130
+ end
131
+ end
132
+ end
133
+ rescue LoadError
134
+ puts "EventMachine not installed, skipping the specs that use it"
135
+ end