mysql2-cs-bind 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mysql2-cs-bind.gemspec
4
+ gemspec
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010-2011 Brian Lopez - http://github.com/brianmario
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # mysql-cs-bind
2
+
3
+ 'mysql-cs-bind' is extension of 'mysql2', to add method of client-side variable binding (pseudo prepared statement).
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'mysql2-cs-bind'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install mysql2-cs-bind
18
+
19
+ ## Usage
20
+
21
+ Require 'mysql2-cs-bind' instead of (or after) 'mysql2', you can use Mysql2::Client#xquery with bound variables like below:
22
+
23
+ use 'mysql2-cs-bind'
24
+ client = Mysql2::Client.new(...)
25
+ client.xquery('SELECT x,y,z FROM tbl WHERE x=? AND y=?', val1, val2) #=> Mysql2::Result
26
+
27
+ Mysql2::Client#xquery receives query, variables, and options(hash) for Mysql2::Client#query.
28
+
29
+ client.xquery(sql)
30
+ client.xquery(sql, :as => :array)
31
+ client.xquery(sql, val1, val2)
32
+ client.xquery(sql, [val1, val2])
33
+ client.xquery(sql, val1, val2, :as => :array)
34
+ client.xquery(sql, [val1, val2], :as => :array)
35
+
36
+ Mysql2::Client#xquery raises ArgumentError if mismatch found between placeholder number and arguments
37
+
38
+ client.xquery('SELECT x FROM tbl', 1) # ArgumentError
39
+ client.xquery('SELECT x FROM tbl WHERE x=? AND y=?', 1) # ArgumentError
40
+ client.xquery('SELECT x FROM tbl WHERE x=?', 1, 2) # ArgumentError
41
+
42
+ Formatting for nil and Time objects:
43
+
44
+ client.xquery('INSERT INTO tbl (val1,created_at) VALUES (?,?)', nil, Time.now)
45
+ #execute "INSERT INTO tbl (val1,created_at) VALUES (NULL,'2012-01-02 13:45:01')"
46
+
47
+ ### Type Conversion of Numbers
48
+
49
+ Mysql2::Client#xquery quotes any values as STRING. This may not be problems for almost all kind of queries, but sometimes you may be confused by return value types:
50
+
51
+ client.query('SELECT 1', :as => :array).first #=> [1]
52
+ client.xquery('SELECT ?', 1, :as => :array).first #=> ['1']
53
+
54
+ ## Contributing
55
+
56
+ 1. Fork it
57
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
58
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
59
+ 4. Push to the branch (`git push origin my-new-feature`)
60
+ 5. Create new Pull Request
61
+
62
+ ## Copyright
63
+
64
+ Copyright (c) 2012- TAGOMORI Satoshi (tagomoris)
65
+
66
+ ## License
67
+ MIT (see MIT-LICENSE)
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,43 @@
1
+ require 'mysql2'
2
+
3
+ class Mysql2::Client
4
+
5
+ def xquery(sql, *args)
6
+ options = if args.size > 0 and args[-1].is_a?(Hash)
7
+ args.pop
8
+ else
9
+ {}
10
+ end
11
+ if args.size < 1
12
+ query(sql, options)
13
+ else
14
+ query(pseudo_bind(sql, args.flatten), options)
15
+ end
16
+ end
17
+
18
+ private
19
+ def pseudo_bind(sql, values)
20
+ sql = sql.dup
21
+
22
+ placeholders = []
23
+ search_pos = 0
24
+ while pos = sql.index('?', search_pos)
25
+ placeholders.push(pos)
26
+ search_pos = pos + 1
27
+ end
28
+ raise ArgumentError, "mismatch between placeholders number and values arguments" if placeholders.length != values.length
29
+
30
+ while pos = placeholders.pop()
31
+ rawvalue = values.pop()
32
+ if rawvalue.nil?
33
+ sql[pos] = 'NULL'
34
+ elsif rawvalue.is_a?(Time)
35
+ sql[pos] = "'" + rawvalue.strftime('%Y-%m-%d %H:%M:%S') + "'"
36
+ else
37
+ sql[pos] = "'" + Mysql2::Client.escape(rawvalue.to_s) + "'"
38
+ end
39
+ end
40
+ sql
41
+ end
42
+
43
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = "mysql2-cs-bind"
5
+ gem.version = "0.0.1"
6
+ gem.authors = ["TAGOMORI Satoshi"]
7
+ gem.email = ["tagomoris@gmail.com"]
8
+ gem.homepage = "https://github.com/tagomoris/mysql2-cs-bind"
9
+ gem.summary = %q{extension for mysql2 to add client-side variable binding}
10
+ gem.description = %q{extension for mysql2 to add client-side variable binding, by adding method Mysql2::Client#xquery}
11
+
12
+ gem.files = `git ls-files`.split($\)
13
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ gem.require_paths = ["lib"]
16
+
17
+ gem.add_runtime_dependency "mysql2"
18
+
19
+ # tests
20
+ gem.add_development_dependency "mysql2"
21
+ gem.add_development_dependency 'eventmachine'
22
+ gem.add_development_dependency 'rake-compiler', "~> 0.7.7"
23
+ gem.add_development_dependency 'rake', '0.8.7' # NB: 0.8.7 required by rake-compiler 0.7.9
24
+ gem.add_development_dependency 'rspec'
25
+ end
@@ -0,0 +1,98 @@
1
+ # encoding: UTF-8
2
+ require 'spec_helper'
3
+
4
+ describe Mysql2::Client do
5
+ before(:each) do
6
+ @client = Mysql2::Client.new
7
+ end
8
+
9
+ it "should respond to #query" do
10
+ @client.should respond_to(:query)
11
+ end
12
+
13
+ context "#pseudo_bind" do
14
+ it "should return query just same as argument, if without any placeholders" do
15
+ @client.__send__(:pseudo_bind, "SELECT x,y,z FROM x WHERE x='1'", []).should eql("SELECT x,y,z FROM x WHERE x='1'")
16
+ end
17
+
18
+ it "should return replaced query if with placeholders" do
19
+ @client.__send__(:pseudo_bind, "SELECT x,y,z FROM x WHERE x=?", [1]).should eql("SELECT x,y,z FROM x WHERE x='1'")
20
+ @client.__send__(:pseudo_bind, "SELECT x,y,z FROM x WHERE x=? AND y=?", [1, 'X']).should eql("SELECT x,y,z FROM x WHERE x='1' AND y='X'")
21
+ end
22
+
23
+ it "should raise ArgumentError if mismatch exists between placeholders and arguments" do
24
+ expect {
25
+ @client.__send__(:pseudo_bind, "SELECT x,y,z FROM x", [1])
26
+ }.should raise_exception(ArgumentError)
27
+ expect {
28
+ @client.__send__(:pseudo_bind, "SELECT x,y,z FROM x WHERE x=?", [1,2])
29
+ }.should raise_exception(ArgumentError)
30
+ expect {
31
+ @client.__send__(:pseudo_bind, "SELECT x,y,z FROM x WHERE x=? AND y=?", [1])
32
+ }.should raise_exception(ArgumentError)
33
+ expect {
34
+ @client.__send__(:pseudo_bind, "SELECT x,y,z FROM x WHERE x=?", [])
35
+ }.should raise_exception(ArgumentError)
36
+ end
37
+
38
+ it "should replace placeholder with NULL about nil" do
39
+ @client.__send__(:pseudo_bind, "UPDATE x SET y=? WHERE x=?", [nil,1]).should eql("UPDATE x SET y=NULL WHERE x='1'")
40
+ end
41
+
42
+ it "should replace placeholder with formatted timestamp string about Time object" do
43
+ require 'time'
44
+ t = Time.strptime('2012/04/20 16:50:45', '%Y/%m/%d %H:%M:%S')
45
+ @client.__send__(:pseudo_bind, "UPDATE x SET y=? WHERE x=?", [t,1]).should eql("UPDATE x SET y='2012-04-20 16:50:45' WHERE x='1'")
46
+ end
47
+ end
48
+
49
+ context "#xquery" do
50
+ it "should let you query again if iterating is finished when streaming" do
51
+ @client.xquery("SELECT 1 UNION SELECT ?", 2, :stream => true, :cache_rows => false).each {}
52
+
53
+ expect {
54
+ @client.xquery("SELECT 1 UNION SELECT ?", 2, :stream => true, :cache_rows => false)
55
+ }.to_not raise_exception(Mysql2::Error)
56
+ end
57
+
58
+ it "should accept an options hash that inherits from Mysql2::Client.default_query_options" do
59
+ @client.xquery "SELECT ?", 1, :something => :else
60
+ @client.query_options.should eql(@client.query_options.merge(:something => :else))
61
+ end
62
+
63
+ it "should return results as a hash by default" do
64
+ @client.xquery("SELECT ?", 1).first.class.should eql(Hash)
65
+ end
66
+
67
+ it "should be able to return results as an array" do
68
+ @client.xquery("SELECT ?", 1, :as => :array).first.class.should eql(Array)
69
+ @client.xquery("SELECT ?", 1).each(:as => :array)
70
+ @client.query("SELECT 1").first.should eql([1])
71
+ @client.query("SELECT '1'").first.should eql(['1'])
72
+ @client.xquery("SELECT 1", :as => :array).first.should eql([1])
73
+ @client.xquery("SELECT ?", 1).first.should eql(['1'])
74
+ @client.xquery("SELECT ?+1", 1).first.should eql([2.0])
75
+ end
76
+
77
+ it "should be able to return results with symbolized keys" do
78
+ @client.xquery("SELECT 1", :symbolize_keys => true).first.keys[0].class.should eql(Symbol)
79
+ end
80
+
81
+ it "should require an open connection" do
82
+ @client.close
83
+ lambda {
84
+ @client.xquery "SELECT ?", 1
85
+ }.should raise_error(Mysql2::Error)
86
+ end
87
+ end
88
+
89
+ it "should respond to escape" do
90
+ Mysql2::Client.should respond_to(:escape)
91
+ end
92
+
93
+ if RUBY_VERSION =~ /1.9/
94
+ it "should respond to #encoding" do
95
+ @client.should respond_to(:encoding)
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,69 @@
1
+ # encoding: UTF-8
2
+ require 'spec_helper'
3
+
4
+ describe Mysql2::Error do
5
+ before(:each) do
6
+ @client = Mysql2::Client.new :encoding => "utf8"
7
+ begin
8
+ @client.query("HAHAHA")
9
+ rescue Mysql2::Error => e
10
+ @error = e
11
+ end
12
+
13
+ @client2 = Mysql2::Client.new :encoding => "big5"
14
+ begin
15
+ @client2.query("HAHAHA")
16
+ rescue Mysql2::Error => e
17
+ @error2 = e
18
+ end
19
+ end
20
+
21
+ it "should respond to #error_number" do
22
+ @error.should respond_to(:error_number)
23
+ end
24
+
25
+ it "should respond to #sql_state" do
26
+ @error.should respond_to(:sql_state)
27
+ end
28
+
29
+ # Mysql gem compatibility
30
+ it "should alias #error_number to #errno" do
31
+ @error.should respond_to(:errno)
32
+ end
33
+
34
+ it "should alias #message to #error" do
35
+ @error.should respond_to(:error)
36
+ end
37
+
38
+ if RUBY_VERSION =~ /1.9/
39
+ it "#message encoding should match the connection's encoding, or Encoding.default_internal if set" do
40
+ if Encoding.default_internal.nil?
41
+ @error.message.encoding.should eql(@client.encoding)
42
+ @error2.message.encoding.should eql(@client2.encoding)
43
+ else
44
+ @error.message.encoding.should eql(Encoding.default_internal)
45
+ @error2.message.encoding.should eql(Encoding.default_internal)
46
+ end
47
+ end
48
+
49
+ it "#error encoding should match the connection's encoding, or Encoding.default_internal if set" do
50
+ if Encoding.default_internal.nil?
51
+ @error.error.encoding.should eql(@client.encoding)
52
+ @error2.error.encoding.should eql(@client2.encoding)
53
+ else
54
+ @error.error.encoding.should eql(Encoding.default_internal)
55
+ @error2.error.encoding.should eql(Encoding.default_internal)
56
+ end
57
+ end
58
+
59
+ it "#sql_state encoding should match the connection's encoding, or Encoding.default_internal if set" do
60
+ if Encoding.default_internal.nil?
61
+ @error.sql_state.encoding.should eql(@client.encoding)
62
+ @error2.sql_state.encoding.should eql(@client2.encoding)
63
+ else
64
+ @error.sql_state.encoding.should eql(Encoding.default_internal)
65
+ @error2.sql_state.encoding.should eql(Encoding.default_internal)
66
+ end
67
+ end
68
+ end
69
+ end
data/spec/rcov.opts ADDED
@@ -0,0 +1,3 @@
1
+ --exclude spec,gem
2
+ --text-summary
3
+ --sort coverage --sort-reverse
@@ -0,0 +1,68 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'rspec'
4
+ # require 'mysql2'
5
+ require 'mysql2-cs-bind'
6
+ require 'timeout'
7
+
8
+ RSpec.configure do |config|
9
+ config.before(:all) do
10
+ client = Mysql2::Client.new :host => "localhost", :username => "root", :database => 'test'
11
+ client.query %[
12
+ CREATE TABLE IF NOT EXISTS mysql2_test (
13
+ id MEDIUMINT NOT NULL AUTO_INCREMENT,
14
+ null_test VARCHAR(10),
15
+ bit_test BIT(64),
16
+ tiny_int_test TINYINT,
17
+ bool_cast_test TINYINT(1),
18
+ small_int_test SMALLINT,
19
+ medium_int_test MEDIUMINT,
20
+ int_test INT,
21
+ big_int_test BIGINT,
22
+ float_test FLOAT(10,3),
23
+ float_zero_test FLOAT(10,3),
24
+ double_test DOUBLE(10,3),
25
+ decimal_test DECIMAL(10,3),
26
+ decimal_zero_test DECIMAL(10,3),
27
+ date_test DATE,
28
+ date_time_test DATETIME,
29
+ timestamp_test TIMESTAMP,
30
+ time_test TIME,
31
+ year_test YEAR(4),
32
+ char_test CHAR(10),
33
+ varchar_test VARCHAR(10),
34
+ binary_test BINARY(10),
35
+ varbinary_test VARBINARY(10),
36
+ tiny_blob_test TINYBLOB,
37
+ tiny_text_test TINYTEXT,
38
+ blob_test BLOB,
39
+ text_test TEXT,
40
+ medium_blob_test MEDIUMBLOB,
41
+ medium_text_test MEDIUMTEXT,
42
+ long_blob_test LONGBLOB,
43
+ long_text_test LONGTEXT,
44
+ enum_test ENUM('val1', 'val2'),
45
+ set_test SET('val1', 'val2'),
46
+ PRIMARY KEY (id)
47
+ )
48
+ ]
49
+ client.query "DELETE FROM mysql2_test;"
50
+ client.query %[
51
+ INSERT INTO mysql2_test (
52
+ null_test, bit_test, tiny_int_test, bool_cast_test, small_int_test, medium_int_test, int_test, big_int_test,
53
+ float_test, float_zero_test, double_test, decimal_test, decimal_zero_test, date_test, date_time_test, timestamp_test, time_test,
54
+ year_test, char_test, varchar_test, binary_test, varbinary_test, tiny_blob_test,
55
+ tiny_text_test, blob_test, text_test, medium_blob_test, medium_text_test,
56
+ long_blob_test, long_text_test, enum_test, set_test
57
+ )
58
+
59
+ VALUES (
60
+ NULL, b'101', 1, 1, 10, 10, 10, 10,
61
+ 10.3, 0, 10.3, 10.3, 0, '2010-4-4', '2010-4-4 11:44:00', '2010-4-4 11:44:00', '11:44:00',
62
+ 2009, "test", "test", "test", "test", "test",
63
+ "test", "test", "test", "test", "test",
64
+ "test", "test", 'val1', 'val1,val2'
65
+ )
66
+ ]
67
+ end
68
+ end
metadata ADDED
@@ -0,0 +1,157 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mysql2-cs-bind
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - TAGOMORI Satoshi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: mysql2
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: mysql2
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: eventmachine
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rake-compiler
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 0.7.7
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 0.7.7
78
+ - !ruby/object:Gem::Dependency
79
+ name: rake
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - '='
84
+ - !ruby/object:Gem::Version
85
+ version: 0.8.7
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - '='
92
+ - !ruby/object:Gem::Version
93
+ version: 0.8.7
94
+ - !ruby/object:Gem::Dependency
95
+ name: rspec
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ description: extension for mysql2 to add client-side variable binding, by adding method
111
+ Mysql2::Client#xquery
112
+ email:
113
+ - tagomoris@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - .gitignore
119
+ - Gemfile
120
+ - MIT-LICENSE
121
+ - README.md
122
+ - Rakefile
123
+ - lib/mysql2-cs-bind.rb
124
+ - mysql2-cs-bind.gemspec
125
+ - spec/mysql2/client_spec.rb
126
+ - spec/mysql2/error_spec.rb
127
+ - spec/rcov.opts
128
+ - spec/spec_helper.rb
129
+ homepage: https://github.com/tagomoris/mysql2-cs-bind
130
+ licenses: []
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ! '>='
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ none: false
143
+ requirements:
144
+ - - ! '>='
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ requirements: []
148
+ rubyforge_project:
149
+ rubygems_version: 1.8.21
150
+ signing_key:
151
+ specification_version: 3
152
+ summary: extension for mysql2 to add client-side variable binding
153
+ test_files:
154
+ - spec/mysql2/client_spec.rb
155
+ - spec/mysql2/error_spec.rb
156
+ - spec/rcov.opts
157
+ - spec/spec_helper.rb