motto-mysql 0.1.0
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/README.txt +266 -0
- data/ext/extconf.rb +114 -0
- data/ext/motto_mysql.c +667 -0
- data/ext/motto_mysql.h +61 -0
- data/setup.rb +1585 -0
- metadata +57 -0
data/README.txt
ADDED
@@ -0,0 +1,266 @@
|
|
1
|
+
= Motto-Mysql README
|
2
|
+
|
3
|
+
Release: 0.1.0
|
4
|
+
|
5
|
+
copyright(c) 2008 kuwata-lab.com all rights reserved.
|
6
|
+
|
7
|
+
* website: http://motto-mysql.rubyforge.org/
|
8
|
+
* download: http://rubyforge.org/projects/motto-mysql/
|
9
|
+
* repository: http://github.com/kwatch/motto-mysql/
|
10
|
+
* bug reports: http://kuwata-lab-products.googlegroups.com/
|
11
|
+
|
12
|
+
|
13
|
+
== About
|
14
|
+
|
15
|
+
'Motto-Mysql' is a complementary library to enhance 'mysql-ruby'.
|
16
|
+
It adds some methods into Mysql::Result and Mysql::Stmt classes.
|
17
|
+
|
18
|
+
Motto-mysql requires mysql-ruby 2.7.4 or later (recommended 2.7.5 or later).
|
19
|
+
|
20
|
+
|
21
|
+
== Features
|
22
|
+
|
23
|
+
* Add 'fetch_as_{hash,array,object}()' and 'fetch_all_as_{hashes,arrays,objects}()'
|
24
|
+
methods into Mysql::Result and Mysql::Stmt classes.
|
25
|
+
These methods returns proper data instead of String.
|
26
|
+
For example, you can get 123 instead of "123", true/false instead of "1"/"0".
|
27
|
+
|
28
|
+
* Time object will be returned instead of Mysql::Time.
|
29
|
+
|
30
|
+
* True or false will be returned instead of 1 or 0 if column type is tinyint.
|
31
|
+
|
32
|
+
* 3.14 will be returned, while Mysql::Stmt.fetch() returns 3.14000010490417.
|
33
|
+
|
34
|
+
|
35
|
+
== Install
|
36
|
+
|
37
|
+
(1) Be sure that header files of Ruby and MySQL are installed.
|
38
|
+
(2) Install mysql-ruby (>= 2.7.4) if not installed yet.
|
39
|
+
(3) Install Motto-Mysql by RubyGems or 'setup.rb'.
|
40
|
+
|
41
|
+
The following is an example of steps to install by 'setup.rb'.
|
42
|
+
|
43
|
+
### install mysql-ruby (if not installed yet)
|
44
|
+
$ tar xzf mysql-ruby-2.8.tar.gz
|
45
|
+
$ cd mysql-ruby-2.8/
|
46
|
+
$ which mysql_config
|
47
|
+
/usr/local/mysql/bin/mysql_config
|
48
|
+
$ ruby extconf.rb --with-mysql-config
|
49
|
+
$ make
|
50
|
+
$ sudo make install
|
51
|
+
$ cd ..
|
52
|
+
### install motto-mysql
|
53
|
+
$ tar xzf motto-mysql-0.1.0.tar.gz
|
54
|
+
$ cd motto-mysql-0.1.0
|
55
|
+
$ which mysql_config
|
56
|
+
/usr/local/mysql/bin/mysql_config
|
57
|
+
$ sudo ruby setup.rb
|
58
|
+
|
59
|
+
|
60
|
+
== Example
|
61
|
+
|
62
|
+
require 'mysql'
|
63
|
+
require 'motto_mysql'
|
64
|
+
|
65
|
+
conn = Mysql.connect('localhost', 'username', 'password', 'dbname')
|
66
|
+
sql = 'select * from items';
|
67
|
+
|
68
|
+
### Mysql::Result#fetch_as_hash() vs. Mysql::Result#fetch_as_hash()
|
69
|
+
result = conn.query(sql)
|
70
|
+
p result.fetch_as_hash() #=> {"id"=>"1", "name"=>"foo", "price"=>"3.14",
|
71
|
+
# "created_at"=>#<Mysql::Time>, "flag"=>"1" }
|
72
|
+
result.free()
|
73
|
+
result = conn.query(sql)
|
74
|
+
p result.fetch_as_hash #=> {"id"=>1, "name"=>"foo", "price"=>3.14,
|
75
|
+
# "created_at"=>#<Time>, "flag"=>true }
|
76
|
+
result.free() #=> Mysql::Error ("Mysql::Result object is freed.")
|
77
|
+
|
78
|
+
### Mysql::Result#fetch_row() vs. Mysql::Result#fetch_as_array()
|
79
|
+
result = conn.query(sql)
|
80
|
+
p result.fetch_row #=> {"1", "foo", "3.14", #<Mysql::Time>, "1" }
|
81
|
+
result.free()
|
82
|
+
result = conn.query(sql)
|
83
|
+
p result.fetch_as_hash #=> {1, "foo", 3.14, #<Time>, true }
|
84
|
+
result.free() #=> Mysql::Error ("Mysql::Result object is freed.")
|
85
|
+
|
86
|
+
### Mysql::Result#fetch_as()
|
87
|
+
class MyObject
|
88
|
+
end
|
89
|
+
result = conn.query(sql)
|
90
|
+
result.fetch_as(MyClass) #=> #<MyClass @id=1, @name="foo", @price=>3.14,
|
91
|
+
@created_at=>#<Time>, @flag=>true>
|
92
|
+
result.free() #=> Mysql::Error ("Mysql::Result object is freed.")
|
93
|
+
|
94
|
+
### Mysql::Result#fetch_all_as_hashes()
|
95
|
+
result = conn.query(sql)
|
96
|
+
p result.fetch_all_as_hashes #=> [ {"id"=>1, "name"=>"foo", ... },
|
97
|
+
# {"id"=>2, "name"=>"bar", ... }, ]
|
98
|
+
# or result.fetch_all_as_hashes {|hash| p hash }
|
99
|
+
|
100
|
+
### Mysql::Result#fetch_all_as_arrays()
|
101
|
+
result = conn.query(sql)
|
102
|
+
p result.fetch_all_as_arrays #=> [ [1, "foo", 3.14, ...],
|
103
|
+
# [2, "bar", 3.15, ...], ]
|
104
|
+
# or result.fetch_all_as_arrays {|array| p array }
|
105
|
+
|
106
|
+
### Mysql::Result#fetch_all_as()
|
107
|
+
result = conn.query(sql)
|
108
|
+
p result.fetch_all_as(MyClass) #=> [ #<MyObject @id=1, @name="foo", ...>,
|
109
|
+
# #<MyObject @id=2, @name="bar", ...>, ]
|
110
|
+
# or result.fetch_all_as(MyClass) {|object| p object }
|
111
|
+
|
112
|
+
|
113
|
+
== API
|
114
|
+
|
115
|
+
=== class Mysql::Result
|
116
|
+
|
117
|
+
: Mysql::Result#fetch_as_hash()
|
118
|
+
Similar to Mysql::Result#fetch_as_hash(), but values are converted
|
119
|
+
into proper class and Mysql::Result#free() is called automatically.
|
120
|
+
For example, Mysql::Result#fetch_as_hash() returns
|
121
|
+
(({ {'id'=>1, 'float'=>3.14, 'date'=>Time.mktime(2008, 1, 1), 'flag'=>true} }))
|
122
|
+
while Mysql::Result#fetch_as_hash() returns
|
123
|
+
(({ {'id'=>"1", 'float'=>"3.14", 'date'=>"2008-01-01", 'flag'=>"1"} }))
|
124
|
+
.
|
125
|
+
|
126
|
+
: Mysql::Result#fetch_as_hash!()
|
127
|
+
Same as Mysql::Result#fetch_as_hash() but this doesn't call
|
128
|
+
Mysql::Result#free() automatically.
|
129
|
+
|
130
|
+
: Mysql::Result#fetch_as_array()
|
131
|
+
Similar to Mysql::Result#fetch_row(), but values are converted
|
132
|
+
into proper class and Mysql::Result#free() is called automatically.
|
133
|
+
For example, Mysql::Result#fetch_as_array() returns
|
134
|
+
(({ {1, 3.14, Time.mktime(2008, 1, 1), true} }))
|
135
|
+
while Mysql::Result#fetch_row() returns
|
136
|
+
(({ {"1", "3.14", "2008-01-01", "1"} }))
|
137
|
+
.
|
138
|
+
|
139
|
+
: Mysql::Result#fetch_as_array!()
|
140
|
+
Same as Mysql::Result#fetch_as_array() but this doesn't call
|
141
|
+
Mysql::Result#free() automatically.
|
142
|
+
|
143
|
+
: Mysql::Result#fetch_as_object(class), Mysql::Result#fetch_as(class)
|
144
|
+
Similar to Mysql::Result#fetch_as_hash(), but instance object
|
145
|
+
of ClassObject is returned instead of hash object.
|
146
|
+
Column data are set as instance variables of the object.
|
147
|
+
|
148
|
+
: Mysql::Result#fetch_as_object!(class), Mysql::Result#fetch_as!(class)
|
149
|
+
Same as Mysql::Result#fetch_as_object() but this doesn't call
|
150
|
+
Mysql::Result#free() automatically.
|
151
|
+
|
152
|
+
|
153
|
+
: Mysql::Result#fetch_all_as_hashes()
|
154
|
+
Fetch all records by Result#fetch_as_hash().
|
155
|
+
If block is given, it is called with each fetched hash object.
|
156
|
+
If block is not given, just returns an array of fetched hash objects.
|
157
|
+
Mysql::Result#free() is called automatically.
|
158
|
+
|
159
|
+
: Mysql::Result#fetch_all_as_hashes!()
|
160
|
+
Same as Mysql::Result#fetch_all_as_hashes() but this doesn't call
|
161
|
+
Mysql::Result#free() automatically.
|
162
|
+
|
163
|
+
: Mysql::Result#fetch_all_as_arrays()
|
164
|
+
Fetch all records by Result#fetch_as_array().
|
165
|
+
If block is given, it is called with each fetched array object.
|
166
|
+
If block is not given, just returns an array of fetched array objects.
|
167
|
+
Mysql::Result#free() is called automatically.
|
168
|
+
|
169
|
+
: Mysql::Result#fetch_all_as_arrays!()
|
170
|
+
Same as Mysql::Result#fetch_all_as_arrays() but this doesn't call
|
171
|
+
Mysql::Result#free() automatically.
|
172
|
+
|
173
|
+
: Mysql::Result#fetch_all_as_objects(class), Mysql::Result#fetch_all_as(class)
|
174
|
+
Fetch all records by Result#fetch_as_object().
|
175
|
+
If block is given, it is called with each fetched object.
|
176
|
+
If block is not given, just returns an array of fetched objects.
|
177
|
+
Mysql::Result#free() is called automatically.
|
178
|
+
|
179
|
+
: Mysql::Result#fetch_all_as_objects!(class), Mysql::Result#fetch_all_as!(class)
|
180
|
+
Same as Mysql::Result#fetch_all_as_objects() but this doesn't call
|
181
|
+
Mysql::Result#free() automatically.
|
182
|
+
|
183
|
+
|
184
|
+
=== class Mysql::Stmt
|
185
|
+
|
186
|
+
: Mysql::Stmt#fetch_as_hash()
|
187
|
+
Equivarent to Mysql::Resutl#fetch_as_hash().
|
188
|
+
Mysql::Stmt#free_result() and Mysql::Stmt#close() are called automatically.
|
189
|
+
|
190
|
+
: Mysql::Stmt#fetch_as_hash!()
|
191
|
+
Same as Mysql::Stmt#fetch_as_hash() but this doesn't call
|
192
|
+
Mysql::Stmt#free_result() and Mysql::Stmt#close().
|
193
|
+
|
194
|
+
: Mysql::Stmt#fetch_as_array()
|
195
|
+
Equivarent to Mysql::Resutl#fetch_as_array().
|
196
|
+
Mysql::Stmt#free_result() and Mysql::Stmt#close() are called automatically.
|
197
|
+
|
198
|
+
: Mysql::Stmt#fetch_as_array!()
|
199
|
+
Same as Mysql::Stmt#fetch_as_array() but this doesn't call
|
200
|
+
Mysql::Stmt#free_result() and Mysql::Stmt#close().
|
201
|
+
|
202
|
+
: Mysql::Stmt#fetch_as_object(class), Mysql::Stmt#fetch_as(class)
|
203
|
+
Equivarent to Mysql::Result#fetch_as_object().
|
204
|
+
Mysql::Stmt#free_result() and Mysql::Stmt#close() are called automatically.
|
205
|
+
|
206
|
+
: Mysql::Stmt#fetch_as_object!(class), Mysql::Stmt#fetch_as!(class)
|
207
|
+
Same as Mysql::Stmt#fetch_as_object() but this doesn't call
|
208
|
+
Mysql::Stmt#free_result() and Mysql::Stmt#close().
|
209
|
+
|
210
|
+
|
211
|
+
: Mysql::Stmt#fetch_all_as_hashes()
|
212
|
+
Equivarent to Mysql::Result#fetch_all_as_hashes().
|
213
|
+
Mysql::Stmt#free_result() and Mysql::Stmt#close() are called automatically.
|
214
|
+
|
215
|
+
: Mysql::Stmt#fetch_all_as_hashes!()
|
216
|
+
Same as Mysql::Result#fetch_all_as_hashes() but this doesn't call
|
217
|
+
Mysql::Stmt#free_result() and Mysql::Stmt#close() automatically.
|
218
|
+
|
219
|
+
|
220
|
+
: Mysql::Stmt#fetch_all_as_arrays()
|
221
|
+
Equivarent to Mysql::Result#fetch_all_as_arrays().
|
222
|
+
Mysql::Stmt#free_result() and Mysql::Stmt#close() are called automatically.
|
223
|
+
|
224
|
+
: Mysql::Stmt#fetch_all_as_arrays!()
|
225
|
+
Same as Mysql::Result#fetch_all_as_arrays() but this doesn't call
|
226
|
+
Mysql::Stmt#free_result() and Mysql::Stmt#close() automatically.
|
227
|
+
|
228
|
+
: Mysql::Stmt#fetch_all_as_objects(class), Mysql::Stmt#fetch_all_as(class)
|
229
|
+
Equivarent to Mysql::Result#fetch_all_as_objects().
|
230
|
+
Mysql::Stmt#free_result() and Mysql::Stmt#close() are called automatically.
|
231
|
+
|
232
|
+
: Mysql::Stmt#fetch_all_as_objects!(class), Mysql::Stmt#fetch_all_as!(class)
|
233
|
+
Same as Mysql::Result#fetch_all_as_objects() but this doesn't call
|
234
|
+
Mysql::Stmt#free_result() and Mysql::Stmt#close() automatically.
|
235
|
+
|
236
|
+
|
237
|
+
|
238
|
+
== Tips
|
239
|
+
|
240
|
+
=== Timestamp class
|
241
|
+
|
242
|
+
If column type is timestamp, fetch_as_xxx() and fetch_all_as_xxx() methods
|
243
|
+
in Mysql::Result and Mysql::Stmt classes returns:
|
244
|
+
|
245
|
+
* Time object when 1970 <= year < 2038
|
246
|
+
* DateTime object when year < 1970 or 2038 <= year
|
247
|
+
|
248
|
+
Because Ruby's Time class causes ArgumentError when year < 1970 or 2038 <= year.
|
249
|
+
|
250
|
+
(Notice that this is for 32bit environment. If you are in 64 bit environment,
|
251
|
+
Ruby's Time object will be returned everytime.)
|
252
|
+
|
253
|
+
|
254
|
+
== License
|
255
|
+
|
256
|
+
Ruby's license
|
257
|
+
|
258
|
+
|
259
|
+
== Author
|
260
|
+
|
261
|
+
makoto kuwata <kwa(at)kuwata-lab.com>
|
262
|
+
|
263
|
+
|
264
|
+
== Bug reports
|
265
|
+
|
266
|
+
If you have bugs or questions, join http://kuwata-lab-products.googlegroups.com.
|
data/ext/extconf.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
def die(msg)
|
2
|
+
$stderr.puts "**** ERROR: #{msg}"
|
3
|
+
exit 1
|
4
|
+
end
|
5
|
+
|
6
|
+
# rewrite MYSQL_RUBY_VERSION in motto_mysql.h
|
7
|
+
require 'mysql.so'
|
8
|
+
unless Mysql::VERSION >= 20704
|
9
|
+
die "mysql-ruby is too old (required >= 2.7.4)."
|
10
|
+
end
|
11
|
+
filename = 'motto_mysql.h'
|
12
|
+
s = File.open(filename) {|f| f.read }
|
13
|
+
s.sub! /^(\#define MYSQL_RUBY_VERSION\s+).*?$/, "\\1#{Mysql::VERSION}"
|
14
|
+
File.open(filename, 'wb') {|f| f.write s }
|
15
|
+
|
16
|
+
|
17
|
+
require 'mkmf'
|
18
|
+
|
19
|
+
if /mswin32/ =~ RUBY_PLATFORM
|
20
|
+
inc, lib = dir_config('mysql')
|
21
|
+
have_library("libmysql") or die "can't find libmysql."
|
22
|
+
elsif mc = with_config('mysql-config') then
|
23
|
+
mc = 'mysql_config' if mc == true
|
24
|
+
cflags = `#{mc} --cflags`.chomp ; $? == 0 or die "can't detect cflags."
|
25
|
+
libs = `#{mc} --libs`.chomp ; $? == 0 or die "can't detect libs."
|
26
|
+
$CPPFLAGS += ' ' + cflags
|
27
|
+
$libs = libs + " " + $libs
|
28
|
+
else
|
29
|
+
$stderr.puts "Trying to detect MySQL configuration with mysql_config..."
|
30
|
+
if (cflags = `mysql_config --cflags`.strip) && $? == 0 &&
|
31
|
+
(libs = `mysql_config --libs`.strip) && $? == 0
|
32
|
+
$stderr.puts "Succeeded to detect MySQL configuration with mysql_config."
|
33
|
+
$CPPFLAGS += ' ' + cflags.strip
|
34
|
+
$libs = libs.strip + " " + $libs
|
35
|
+
else
|
36
|
+
$stderr.puts "Failed to detect MySQL configuration with mysql_config."
|
37
|
+
$stderr.puts "Trying to detect MySQL client library..."
|
38
|
+
inc, lib = dir_config('mysql', '/usr/local')
|
39
|
+
libs = ['m', 'z', 'socket', 'nsl', 'mygcc']
|
40
|
+
while not find_library('mysqlclient', 'mysql_query', lib, "#{lib}/mysql") do
|
41
|
+
die "can't find mysql client library." if libs.empty?
|
42
|
+
have_library(libs.shift)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
have_func('mysql_ssl_set')
|
48
|
+
have_func('rb_str_set_len')
|
49
|
+
|
50
|
+
|
51
|
+
## define HAVE_MYSQL_H if mysql.h is found
|
52
|
+
have_header('mysql.h') or have_header('mysql/mysql.h') or die "can't find 'mysql.h'."
|
53
|
+
|
54
|
+
|
55
|
+
#if have_header('mysql.h') then
|
56
|
+
# src = "#include <errmsg.h>\n#include <mysqld_error.h>\n"
|
57
|
+
#elsif have_header('mysql/mysql.h') then
|
58
|
+
# src = "#include <mysql/errmsg.h>\n#include <mysql/mysqld_error.h>\n"
|
59
|
+
#else
|
60
|
+
# die "can't find 'mysql.h'."
|
61
|
+
#end
|
62
|
+
|
63
|
+
## make mysql constant
|
64
|
+
#File.open("conftest.c", "w") do |f|
|
65
|
+
# f.puts src
|
66
|
+
#end
|
67
|
+
#
|
68
|
+
#if defined? cpp_command then
|
69
|
+
# cpp = Config.expand(cpp_command(''))
|
70
|
+
#else
|
71
|
+
# cpp = Config.expand sprintf(CPP, $CPPFLAGS, $CFLAGS, '')
|
72
|
+
#end
|
73
|
+
#if /mswin32/ =~ RUBY_PLATFORM && !/-E/.match(cpp)
|
74
|
+
# cpp << " -E"
|
75
|
+
#end
|
76
|
+
#unless system "#{cpp} > confout" then
|
77
|
+
# die "can't compile test source."
|
78
|
+
#end
|
79
|
+
#
|
80
|
+
## add '#define ulong unsigned long' to mysql.c on MacOS X
|
81
|
+
#if /darwin/ =~ RUBY_PLATFORM && /i686/ =~ RUBY_PLATFORM
|
82
|
+
# definition = "#define ulong unsigned long\n"
|
83
|
+
# s = File.open('mysql.c') {|f| f.read }
|
84
|
+
# unless s.index(definition)
|
85
|
+
# print "add '#{definition.chomp}' to mysql.c..."
|
86
|
+
# File.open('mysql.c', 'w') {|f| f.write(definition + s) }
|
87
|
+
# puts "done."
|
88
|
+
# end
|
89
|
+
#end
|
90
|
+
#
|
91
|
+
#File.unlink "conftest.c"
|
92
|
+
#
|
93
|
+
#error_syms = []
|
94
|
+
#IO.foreach('confout') do |l|
|
95
|
+
# next unless l =~ /errmsg\.h|mysqld_error\.h/
|
96
|
+
# fn = l.split(/\"/)[1]
|
97
|
+
# IO.foreach(fn) do |m|
|
98
|
+
# if m =~ /^#define\s+([CE]R_[0-9A-Z_]+)/ then
|
99
|
+
# error_syms << $1
|
100
|
+
# end
|
101
|
+
# end
|
102
|
+
#end
|
103
|
+
#File.unlink 'confout'
|
104
|
+
#error_syms.uniq!
|
105
|
+
#
|
106
|
+
#File.open('error_const.h', 'w') do |f|
|
107
|
+
# error_syms.each do |s|
|
108
|
+
# f.puts " rb_define_mysql_const(#{s});"
|
109
|
+
# end
|
110
|
+
#end
|
111
|
+
#
|
112
|
+
#create_makefile("mysql")
|
113
|
+
|
114
|
+
create_makefile("motto_mysql")
|
data/ext/motto_mysql.c
ADDED
@@ -0,0 +1,667 @@
|
|
1
|
+
/**
|
2
|
+
** $Rev$
|
3
|
+
** $Release: 0.1.0 $
|
4
|
+
** copyright(c) 2008 kuwata-lab.com all rights reserved.
|
5
|
+
** License: Ruby's license
|
6
|
+
**/
|
7
|
+
|
8
|
+
#include "ruby.h"
|
9
|
+
#include "version.h"
|
10
|
+
|
11
|
+
#ifdef HAVE_MYSQL_H
|
12
|
+
#include <mysql.h>
|
13
|
+
#include <errmsg.h>
|
14
|
+
#include <mysqld_error.h>
|
15
|
+
#else
|
16
|
+
#include <mysql/mysql.h>
|
17
|
+
#include <mysql/errmsg.h>
|
18
|
+
#include <mysql/mysqld_error.h>
|
19
|
+
#endif
|
20
|
+
|
21
|
+
#include <time.h>
|
22
|
+
#include <assert.h>
|
23
|
+
#include <alloca.h>
|
24
|
+
|
25
|
+
extern VALUE cMysqlRes;
|
26
|
+
extern VALUE cMysqlStmt;
|
27
|
+
extern VALUE cMysqlTime;
|
28
|
+
extern VALUE eMysql;
|
29
|
+
extern VALUE cMysql;
|
30
|
+
static VALUE cDate; /* require 'date' */
|
31
|
+
static VALUE cDateTime; /* require 'date' */
|
32
|
+
|
33
|
+
#include "motto_mysql.h"
|
34
|
+
|
35
|
+
char *MOTTO_MYSQL_VERSION = "0.1.0";
|
36
|
+
|
37
|
+
#define MAX_IVAR_LENGTH 31
|
38
|
+
|
39
|
+
ID id_new;
|
40
|
+
ID id_initialize;
|
41
|
+
ID id_create_timestamp;
|
42
|
+
ID id_create_datetime;
|
43
|
+
ID id_create_date;
|
44
|
+
ID id_create_time;
|
45
|
+
ID id_close;
|
46
|
+
ID id_mktime;
|
47
|
+
ID id_free;
|
48
|
+
ID id_free_result;
|
49
|
+
|
50
|
+
|
51
|
+
static VALUE create_ruby_timestamp(VALUE obj, VALUE year, VALUE month, VALUE mday,
|
52
|
+
VALUE hour, VALUE min, VALUE sec,
|
53
|
+
VALUE neg, VALUE arg)
|
54
|
+
{
|
55
|
+
return rb_funcall(rb_cTime, id_mktime, 6,
|
56
|
+
year, month, mday, hour, min, sec);
|
57
|
+
}
|
58
|
+
|
59
|
+
/*
|
60
|
+
static VALUE create_mysql_timestamp(VALUE obj, VALUE year, VALUE month, VALUE mday,
|
61
|
+
VALUE hour, VALUE min, VALUE sec,
|
62
|
+
VALUE neg, VALUE arg)
|
63
|
+
{
|
64
|
+
VALUE val = rb_obj_alloc(cMysqlTime);
|
65
|
+
rb_funcall(val, id_initialize, 8,
|
66
|
+
year, month, mday, hour, min, sec, neg, arg);
|
67
|
+
return val;
|
68
|
+
}
|
69
|
+
*/
|
70
|
+
|
71
|
+
static VALUE create_ruby_datetime(VALUE obj, VALUE year, VALUE month, VALUE mday,
|
72
|
+
VALUE hour, VALUE min, VALUE sec,
|
73
|
+
VALUE neg, VALUE arg)
|
74
|
+
{
|
75
|
+
return rb_funcall(cDateTime, id_new, 6,
|
76
|
+
year, month, mday, hour, min, sec);
|
77
|
+
}
|
78
|
+
|
79
|
+
/*
|
80
|
+
static VALUE create_mysql_datetime(VALUE obj, VALUE year, VALUE month, VALUE mday,
|
81
|
+
VALUE hour, VALUE min, VALUE sec,
|
82
|
+
VALUE neg, VALUE arg)
|
83
|
+
{
|
84
|
+
VALUE val = rb_obj_alloc(cMysqlTime);
|
85
|
+
rb_funcall(val, id_initialize, 8,
|
86
|
+
year, month, mday, hour, min, sec, neg, arg);
|
87
|
+
return val;
|
88
|
+
}
|
89
|
+
*/
|
90
|
+
|
91
|
+
static VALUE create_ruby_date(VALUE obj, VALUE year, VALUE month, VALUE mday,
|
92
|
+
VALUE neg, VALUE arg)
|
93
|
+
{
|
94
|
+
return rb_funcall(cDate, id_new, 3,
|
95
|
+
year, month, mday);
|
96
|
+
}
|
97
|
+
|
98
|
+
/*
|
99
|
+
static VALUE create_mysql_date(VALUE obj, VALUE year, VALUE month, VALUE mday,
|
100
|
+
VALUE neg, VALUE arg)
|
101
|
+
{
|
102
|
+
VALUE val = rb_obj_alloc(cMysqlTime);
|
103
|
+
rb_funcall(val, id_initialize, 8,
|
104
|
+
year, month, mday, Qnil, Qnil, Qnil, neg, arg);
|
105
|
+
return val;
|
106
|
+
}
|
107
|
+
*/
|
108
|
+
|
109
|
+
static VALUE create_ruby_time(VALUE obj, VALUE hour, VALUE min, VALUE sec,
|
110
|
+
VALUE neg, VALUE arg)
|
111
|
+
{
|
112
|
+
return rb_funcall(rb_cTime, id_mktime, 6,
|
113
|
+
INT2FIX(1970), INT2FIX(1), INT2FIX(1), hour, min, sec);
|
114
|
+
}
|
115
|
+
|
116
|
+
/*
|
117
|
+
static VALUE create_mysql_time(VALUE obj, VALUE hour, VALUE min, VALUE sec,
|
118
|
+
VALUE neg, VALUE arg)
|
119
|
+
{
|
120
|
+
VALUE val = rb_obj_alloc(cMysqlTime);
|
121
|
+
rb_funcall(val, id_initialize, 8,
|
122
|
+
Qnil, Qnil, Qnil, hour, min, sec, neg, arg);
|
123
|
+
return val;
|
124
|
+
}
|
125
|
+
*/
|
126
|
+
|
127
|
+
static VALUE create_ruby_timestamp_or_datetime(VALUE obj,
|
128
|
+
VALUE year, VALUE month, VALUE mday,
|
129
|
+
VALUE hour, VALUE min, VALUE sec,
|
130
|
+
VALUE neg, VALUE arg)
|
131
|
+
{
|
132
|
+
int y = FIX2INT(year);
|
133
|
+
return 1970 <= y && y < 2038
|
134
|
+
? create_ruby_timestamp(obj, year, month, mday, hour, min, sec, neg, arg)
|
135
|
+
: create_ruby_datetime(obj, year, month, mday, hour, min, sec, neg, arg);
|
136
|
+
}
|
137
|
+
|
138
|
+
|
139
|
+
static VALUE _result_get_value(char *str, unsigned int length, int type)
|
140
|
+
{
|
141
|
+
if (str == NULL)
|
142
|
+
return Qnil;
|
143
|
+
assert(str != NULL);
|
144
|
+
fflush(stderr);
|
145
|
+
VALUE string;
|
146
|
+
struct time_object *tobj;
|
147
|
+
struct tm t;
|
148
|
+
switch (type) {
|
149
|
+
case MYSQL_TYPE_VAR_STRING:
|
150
|
+
case MYSQL_TYPE_STRING:
|
151
|
+
string = rb_tainted_str_new(str, length);
|
152
|
+
return string;
|
153
|
+
case MYSQL_TYPE_LONG:
|
154
|
+
case MYSQL_TYPE_SHORT:
|
155
|
+
case MYSQL_TYPE_INT24:
|
156
|
+
string = rb_tainted_str_new(str, length);
|
157
|
+
return rb_Integer(string);
|
158
|
+
case MYSQL_TYPE_LONGLONG:
|
159
|
+
string = rb_tainted_str_new(str, length);
|
160
|
+
return rb_Integer(string);
|
161
|
+
case MYSQL_TYPE_FLOAT:
|
162
|
+
case MYSQL_TYPE_DOUBLE:
|
163
|
+
string = rb_tainted_str_new(str, length);
|
164
|
+
return rb_Float(string);
|
165
|
+
case MYSQL_TYPE_TINY:
|
166
|
+
if (length == 1) {
|
167
|
+
return str[0] == '1' ? Qtrue : Qfalse;
|
168
|
+
} else {
|
169
|
+
string = rb_tainted_str_new(str, length);
|
170
|
+
return rb_Integer(string);
|
171
|
+
}
|
172
|
+
case MYSQL_TYPE_TIMESTAMP:
|
173
|
+
strptime(str, "%Y-%m-%d %H:%M:%S", &t);
|
174
|
+
return rb_funcall(cMysql, id_create_timestamp, 8,
|
175
|
+
INT2FIX(t.tm_year+1900), INT2FIX(t.tm_mon+1), INT2FIX(t.tm_mday),
|
176
|
+
INT2FIX(t.tm_hour), INT2FIX(t.tm_min), INT2FIX(t.tm_sec),
|
177
|
+
Qnil, Qnil);
|
178
|
+
case MYSQL_TYPE_DATETIME:
|
179
|
+
strptime(str, "%Y-%m-%d %H:%M:%S", &t);
|
180
|
+
return rb_funcall(cMysql, id_create_datetime, 8,
|
181
|
+
INT2FIX(t.tm_year+1900), INT2FIX(t.tm_mon+1), INT2FIX(t.tm_mday),
|
182
|
+
INT2FIX(t.tm_hour), INT2FIX(t.tm_min), INT2FIX(t.tm_sec),
|
183
|
+
Qnil, Qnil);
|
184
|
+
case MYSQL_TYPE_DATE:
|
185
|
+
strptime(str, "%Y-%m-%d", &t);
|
186
|
+
return rb_funcall(cMysql, id_create_date, 5,
|
187
|
+
INT2FIX(t.tm_year+1900), INT2FIX(t.tm_mon+1), INT2FIX(t.tm_mday),
|
188
|
+
Qnil, Qnil);
|
189
|
+
case MYSQL_TYPE_TIME:
|
190
|
+
strptime(str, "%H:%M:%S", &t);
|
191
|
+
return rb_funcall(cMysql, id_create_time, 5,
|
192
|
+
INT2FIX(t.tm_hour), INT2FIX(t.tm_min), INT2FIX(t.tm_sec),
|
193
|
+
Qnil, Qnil);
|
194
|
+
/*case MYSQL_TYPE_BLOB:*/
|
195
|
+
default:
|
196
|
+
string = rb_tainted_str_new(str, length);
|
197
|
+
return string;
|
198
|
+
}
|
199
|
+
}
|
200
|
+
|
201
|
+
static VALUE _result_fetch(VALUE obj_result, VALUE klass, int flag_fetch_one, int flag_free)
|
202
|
+
{
|
203
|
+
check_free(obj_result);
|
204
|
+
MYSQL_RES* res = GetMysqlRes(obj_result);
|
205
|
+
int n = mysql_num_fields(res);
|
206
|
+
MYSQL_FIELD *fields = mysql_fetch_fields(res);
|
207
|
+
/* fetch data */
|
208
|
+
MYSQL_ROW row;
|
209
|
+
VALUE ret;
|
210
|
+
int i;
|
211
|
+
if (flag_fetch_one) {
|
212
|
+
row = mysql_fetch_row(res);
|
213
|
+
if (row == NULL) {
|
214
|
+
ret = Qnil;
|
215
|
+
}
|
216
|
+
else {
|
217
|
+
unsigned long *lengths = mysql_fetch_lengths(res);
|
218
|
+
/* fetch_as_hash */
|
219
|
+
if (klass == rb_cHash) {
|
220
|
+
VALUE hash = rb_hash_new();
|
221
|
+
for (i = 0; i < n; i++) {
|
222
|
+
VALUE key = rb_tainted_str_new2(fields[i].name);
|
223
|
+
//VALUE val = row[i] ? _result_get_value(row[i], lengths[i], fields[i].type) : Qnil;
|
224
|
+
VALUE val = _result_get_value(row[i], lengths[i], fields[i].type);
|
225
|
+
rb_hash_aset(hash, key, val);
|
226
|
+
}
|
227
|
+
ret = hash;
|
228
|
+
}
|
229
|
+
/* fetch_as_array */
|
230
|
+
else if (klass == rb_cArray) {
|
231
|
+
VALUE arr = rb_ary_new2(n);
|
232
|
+
for (i = 0; i < n; i++) {
|
233
|
+
//VALUE val = row[i] ? _result_get_value(row[i], lengths[i], fields[i].type) : Qnil;
|
234
|
+
VALUE val = _result_get_value(row[i], lengths[i], fields[i].type);
|
235
|
+
rb_ary_push(arr, val);
|
236
|
+
}
|
237
|
+
ret = arr;
|
238
|
+
}
|
239
|
+
/* fetch_as_object */
|
240
|
+
else {
|
241
|
+
VALUE obj = rb_funcall(klass, id_new, 0);
|
242
|
+
char buf[MAX_IVAR_LENGTH + 1];
|
243
|
+
buf[0] = '@';
|
244
|
+
buf[MAX_IVAR_LENGTH] = '\0';
|
245
|
+
for (i = 0; i < n; i++) {
|
246
|
+
//VALUE val = row[i] ? _result_get_value(row[i], lengths[i], fields[i].type) : Qnil;
|
247
|
+
VALUE val = _result_get_value(row[i], lengths[i], fields[i].type);
|
248
|
+
//rb_ivar_set(obj, rb_intern(fields[i].name), val);
|
249
|
+
strncpy(buf+1, fields[i].name, MAX_IVAR_LENGTH - 1);
|
250
|
+
rb_ivar_set(obj, rb_intern(buf), val);
|
251
|
+
}
|
252
|
+
ret = obj;
|
253
|
+
}
|
254
|
+
}
|
255
|
+
}
|
256
|
+
else {
|
257
|
+
VALUE list;
|
258
|
+
int has_block = rb_block_given_p() == Qtrue;
|
259
|
+
list = has_block ? Qnil : rb_ary_new();
|
260
|
+
/* fetch_all_as_hashes */
|
261
|
+
if (klass == rb_cHash) {
|
262
|
+
VALUE *keys = alloca(n * sizeof(VALUE));
|
263
|
+
for (i = 0; i < n; i++)
|
264
|
+
keys[i] = rb_tainted_str_new2(fields[i].name);
|
265
|
+
while ((row = mysql_fetch_row(res)) != NULL) {
|
266
|
+
unsigned long* lengths = mysql_fetch_lengths(res);
|
267
|
+
VALUE hash = rb_hash_new();
|
268
|
+
for (i = 0; i < n; i++) {
|
269
|
+
VALUE val = row[i] ? _result_get_value(row[i], lengths[i], fields[i].type) : Qnil;
|
270
|
+
rb_hash_aset(hash, keys[i], val);
|
271
|
+
}
|
272
|
+
has_block ? rb_yield(hash) : rb_ary_push(list, hash);
|
273
|
+
}
|
274
|
+
}
|
275
|
+
/* fetch_all_as_arrays */
|
276
|
+
else if (klass == rb_cArray) {
|
277
|
+
while ((row = mysql_fetch_row(res)) != NULL) {
|
278
|
+
unsigned long* lengths = mysql_fetch_lengths(res);
|
279
|
+
VALUE arr = rb_ary_new2(n);
|
280
|
+
for (i = 0; i < n; i++) {
|
281
|
+
VALUE val = row[i] ? _result_get_value(row[i], lengths[i], fields[i].type) : Qnil;
|
282
|
+
rb_ary_push(arr, val);
|
283
|
+
}
|
284
|
+
has_block ? rb_yield(arr) : rb_ary_push(list, arr);
|
285
|
+
}
|
286
|
+
}
|
287
|
+
/* fetch_all_as_objects */
|
288
|
+
else {
|
289
|
+
char buf[MAX_IVAR_LENGTH + 1];
|
290
|
+
buf[0] = '@';
|
291
|
+
buf[MAX_IVAR_LENGTH] = '\0';
|
292
|
+
VALUE *names = alloca(n * sizeof(VALUE));
|
293
|
+
for (i = 0; i < n; i++) {
|
294
|
+
strncpy(buf+1, fields[i].name, MAX_IVAR_LENGTH - 1);
|
295
|
+
names[i] = rb_intern(buf);
|
296
|
+
}
|
297
|
+
ID id_new_ = id_new;
|
298
|
+
while ((row = mysql_fetch_row(res)) != NULL) {
|
299
|
+
unsigned long* lengths = mysql_fetch_lengths(res);
|
300
|
+
VALUE obj = rb_funcall(klass, id_new_, 0);
|
301
|
+
for (i = 0; i < n; i++) {
|
302
|
+
//VALUE val = row[i] ? _result_get_value(row[i], lengths[i], fields[i].type) : Qnil;
|
303
|
+
VALUE val = _result_get_value(row[i], lengths[i], fields[i].type);
|
304
|
+
rb_ivar_set(obj, names[i], val);
|
305
|
+
}
|
306
|
+
has_block ? rb_yield(obj) : rb_ary_push(list, obj);
|
307
|
+
}
|
308
|
+
}
|
309
|
+
ret = list;
|
310
|
+
}
|
311
|
+
/*res_free(obj_result);*/
|
312
|
+
if (flag_free) {
|
313
|
+
rb_funcall(obj_result, id_free, 0);
|
314
|
+
}
|
315
|
+
return ret;
|
316
|
+
}
|
317
|
+
|
318
|
+
static VALUE result_fetch_as_hash (VALUE obj_result) { return _result_fetch(obj_result, rb_cHash, 1, 1); }
|
319
|
+
static VALUE result_fetch_as_hash2(VALUE obj_result) { return _result_fetch(obj_result, rb_cHash, 1, 0); }
|
320
|
+
static VALUE result_fetch_all_as_hashes (VALUE obj_result) { return _result_fetch(obj_result, rb_cHash, 0, 1); }
|
321
|
+
static VALUE result_fetch_all_as_hashes2(VALUE obj_result) { return _result_fetch(obj_result, rb_cHash, 0, 0); }
|
322
|
+
|
323
|
+
static VALUE result_fetch_as_array (VALUE obj_result) { return _result_fetch(obj_result, rb_cArray, 1, 1); }
|
324
|
+
static VALUE result_fetch_as_array2(VALUE obj_result) { return _result_fetch(obj_result, rb_cArray, 1, 0); }
|
325
|
+
static VALUE result_fetch_all_as_arrays (VALUE obj_result) { return _result_fetch(obj_result, rb_cArray, 0, 1); }
|
326
|
+
static VALUE result_fetch_all_as_arrays2(VALUE obj_result) { return _result_fetch(obj_result, rb_cArray, 0, 0); }
|
327
|
+
|
328
|
+
static VALUE result_fetch_as_object (VALUE obj_result, VALUE klass) { return _result_fetch(obj_result, klass, 1, 1); }
|
329
|
+
static VALUE result_fetch_as_object2(VALUE obj_result, VALUE klass) { return _result_fetch(obj_result, klass, 1, 0); }
|
330
|
+
static VALUE result_fetch_all_as_objects (VALUE obj_result, VALUE klass) { return _result_fetch(obj_result, klass, 0, 1); }
|
331
|
+
static VALUE result_fetch_all_as_objects2(VALUE obj_result, VALUE klass) { return _result_fetch(obj_result, klass, 0, 0); }
|
332
|
+
|
333
|
+
|
334
|
+
|
335
|
+
static VALUE _stmt_get_value(struct mysql_stmt *s, int i, int buffer_type)
|
336
|
+
{
|
337
|
+
if (s->result.is_null[i])
|
338
|
+
return Qnil;
|
339
|
+
VALUE val;
|
340
|
+
MYSQL_TIME *t;
|
341
|
+
MYSQL_BIND *bind = &(s->result.bind[i]);
|
342
|
+
/*switch (bind->buffer_type) {*/
|
343
|
+
switch (buffer_type) {
|
344
|
+
#if MYSQL_RUBY_VERSION == 20704
|
345
|
+
case MYSQL_TYPE_STRING:
|
346
|
+
return rb_tainted_str_new(bind->buffer, s->result.length[i]);
|
347
|
+
case MYSQL_TYPE_LONG:
|
348
|
+
return INT2NUM(*(long*)bind->buffer);
|
349
|
+
case MYSQL_TYPE_LONGLONG:
|
350
|
+
return rb_ll2inum(*(LONG_LONG*)bind->buffer);
|
351
|
+
case MYSQL_TYPE_DOUBLE:
|
352
|
+
/*return rb_float_new(*(double*)bind->buffer);*/
|
353
|
+
return rb_Float(rb_tainted_str_new(bind->buffer, s->result.length[i]));
|
354
|
+
#elif MYSQL_RUBY_VERSION >= 20705
|
355
|
+
case MYSQL_TYPE_STRING:
|
356
|
+
case MYSQL_TYPE_VAR_STRING:
|
357
|
+
return rb_tainted_str_new(bind->buffer, s->result.length[i]);
|
358
|
+
case MYSQL_TYPE_INT24:
|
359
|
+
case MYSQL_TYPE_LONG:
|
360
|
+
return (bind->is_unsigned) ? UINT2NUM(*(unsigned int *)bind->buffer)
|
361
|
+
: INT2NUM(*(signed int *)bind->buffer);
|
362
|
+
case MYSQL_TYPE_LONGLONG:
|
363
|
+
return (bind->is_unsigned) ? ULL2NUM(*(unsigned long long *)bind->buffer)
|
364
|
+
: LL2NUM(*(signed long long *)bind->buffer);
|
365
|
+
case MYSQL_TYPE_FLOAT:
|
366
|
+
//return rb_float_new((double)(*(float *)bind->buffer));
|
367
|
+
return rb_Float(rb_tainted_str_new(bind->buffer, s->result.length[i]));
|
368
|
+
case MYSQL_TYPE_DOUBLE:
|
369
|
+
return rb_float_new(*(double *)bind->buffer);
|
370
|
+
//return rb_Float(rb_tainted_str_new(bind->buffer, s->result.length[i]));
|
371
|
+
case MYSQL_TYPE_TINY:
|
372
|
+
if (s->result.length[i] == 1) {
|
373
|
+
return ((char *)bind->buffer)[0] == 1 ? Qtrue : Qfalse;
|
374
|
+
} else {
|
375
|
+
return (bind->is_unsigned) ? UINT2NUM(*(unsigned char *)bind->buffer)
|
376
|
+
: INT2NUM(*(signed char *)bind->buffer);
|
377
|
+
}
|
378
|
+
#endif
|
379
|
+
/*
|
380
|
+
case MYSQL_TYPE_TIMESTAMP:
|
381
|
+
case MYSQL_TYPE_DATE:
|
382
|
+
case MYSQL_TYPE_TIME:
|
383
|
+
case MYSQL_TYPE_DATETIME:
|
384
|
+
t = (MYSQL_TIME*)bind->buffer;
|
385
|
+
val = rb_obj_alloc(cMysqlTime);
|
386
|
+
rb_funcall(val, id_initialize, 8,
|
387
|
+
INT2FIX(t->year), INT2FIX(t->month),
|
388
|
+
INT2FIX(t->day), INT2FIX(t->hour),
|
389
|
+
INT2FIX(t->minute), INT2FIX(t->second),
|
390
|
+
(t->neg ? Qtrue : Qfalse),
|
391
|
+
INT2FIX(t->second_part));
|
392
|
+
*/
|
393
|
+
case MYSQL_TYPE_TIMESTAMP:
|
394
|
+
t = (MYSQL_TIME*)bind->buffer;
|
395
|
+
return rb_funcall(cMysql, id_create_timestamp, 8,
|
396
|
+
INT2FIX(t->year), INT2FIX(t->month), INT2FIX(t->day),
|
397
|
+
INT2FIX(t->hour), INT2FIX(t->minute), INT2FIX(t->second),
|
398
|
+
(t->neg ? Qtrue : Qfalse), INT2FIX(t->second_part));
|
399
|
+
case MYSQL_TYPE_DATETIME:
|
400
|
+
t = (MYSQL_TIME*)bind->buffer;
|
401
|
+
return rb_funcall(cMysql, id_create_datetime, 8,
|
402
|
+
INT2FIX(t->year), INT2FIX(t->month), INT2FIX(t->day),
|
403
|
+
INT2FIX(t->hour), INT2FIX(t->minute), INT2FIX(t->second),
|
404
|
+
(t->neg ? Qtrue : Qfalse), INT2FIX(t->second_part));
|
405
|
+
case MYSQL_TYPE_DATE:
|
406
|
+
t = (MYSQL_TIME*)bind->buffer;
|
407
|
+
return rb_funcall(cMysql, id_create_date, 5,
|
408
|
+
INT2FIX(t->year), INT2FIX(t->month), INT2FIX(t->day),
|
409
|
+
(t->neg ? Qtrue : Qfalse), INT2FIX(t->second_part));
|
410
|
+
case MYSQL_TYPE_TIME:
|
411
|
+
t = (MYSQL_TIME*)bind->buffer;
|
412
|
+
return rb_funcall(cMysql, id_create_time, 5,
|
413
|
+
INT2FIX(t->hour), INT2FIX(t->minute), INT2FIX(t->second),
|
414
|
+
(t->neg ? Qtrue : Qfalse), INT2FIX(t->second_part));
|
415
|
+
#if MYSQL_RUBY_VERSION == 20704
|
416
|
+
case MYSQL_TYPE_BLOB:
|
417
|
+
return rb_tainted_str_new(bind->buffer, s->result.length[i]);
|
418
|
+
#elif MYSQL_RUBY_VERSION >= 20705
|
419
|
+
case MYSQL_TYPE_SHORT:
|
420
|
+
case MYSQL_TYPE_YEAR:
|
421
|
+
return (bind->is_unsigned) ? UINT2NUM(*(unsigned short *)bind->buffer)
|
422
|
+
: INT2NUM(*(signed short *)bind->buffer);
|
423
|
+
case MYSQL_TYPE_DECIMAL:
|
424
|
+
case MYSQL_TYPE_BLOB:
|
425
|
+
case MYSQL_TYPE_TINY_BLOB:
|
426
|
+
case MYSQL_TYPE_MEDIUM_BLOB:
|
427
|
+
case MYSQL_TYPE_LONG_BLOB:
|
428
|
+
#if MYSQL_VERSION_ID >= 50003
|
429
|
+
case MYSQL_TYPE_NEWDECIMAL:
|
430
|
+
case MYSQL_TYPE_BIT:
|
431
|
+
#endif
|
432
|
+
return rb_tainted_str_new(bind->buffer, s->result.length[i]);
|
433
|
+
#endif
|
434
|
+
default:
|
435
|
+
rb_raise(rb_eTypeError, "unknown buffer_type: %d", bind->buffer_type);
|
436
|
+
}
|
437
|
+
/* unreachable */
|
438
|
+
return Qnil;
|
439
|
+
}
|
440
|
+
|
441
|
+
static VALUE _stmt_fetch(VALUE obj_stmt, VALUE klass, int flag_fetch_one, int flag_free)
|
442
|
+
{
|
443
|
+
check_stmt_closed(obj_stmt);
|
444
|
+
struct mysql_stmt* s = DATA_PTR(obj_stmt);
|
445
|
+
MYSQL_RES* res = s->res;
|
446
|
+
int n = mysql_num_fields(res);
|
447
|
+
/* to avoid rounding error, change field type to string if it is double or float */
|
448
|
+
int *buffer_types = alloca(n * sizeof(int));
|
449
|
+
int i;
|
450
|
+
for (i = 0; i < n; i++) {
|
451
|
+
int t = buffer_types[i] = s->result.bind[i].buffer_type;
|
452
|
+
#if MYSQL_RUBY_VERSION == 20704
|
453
|
+
if (t == MYSQL_TYPE_DOUBLE || t == MYSQL_TYPE_FLOAT) {
|
454
|
+
#elif MYSQL_RUBY_VERSION >= 20705
|
455
|
+
if (t == MYSQL_TYPE_FLOAT) {
|
456
|
+
#endif
|
457
|
+
s->result.bind[i].buffer_type = MYSQL_TYPE_STRING;
|
458
|
+
}
|
459
|
+
}
|
460
|
+
if (mysql_stmt_bind_result(s->stmt, s->result.bind))
|
461
|
+
mysql_stmt_raise(s->stmt);
|
462
|
+
/* fetch data */
|
463
|
+
VALUE ret;
|
464
|
+
int r;
|
465
|
+
if (flag_fetch_one) {
|
466
|
+
r = mysql_stmt_fetch(s->stmt);
|
467
|
+
if (r == MYSQL_NO_DATA) {
|
468
|
+
ret = Qnil;
|
469
|
+
}
|
470
|
+
else if (r == 1) {
|
471
|
+
ret = Qnil; /* dummy */
|
472
|
+
mysql_stmt_raise(s->stmt);
|
473
|
+
}
|
474
|
+
/* fetch_as_hash */
|
475
|
+
else if (klass == rb_cHash) {
|
476
|
+
MYSQL_FIELD *fields = mysql_fetch_fields(res);
|
477
|
+
VALUE hash = rb_hash_new();
|
478
|
+
for (i = 0; i < n; i++) {
|
479
|
+
VALUE key = rb_tainted_str_new2(fields[i].name);
|
480
|
+
VALUE val = _stmt_get_value(s, i, buffer_types[i]);
|
481
|
+
rb_hash_aset(hash, key, val);
|
482
|
+
}
|
483
|
+
ret = hash;
|
484
|
+
}
|
485
|
+
/* fetch_as_array */
|
486
|
+
else if (klass == rb_cArray) {
|
487
|
+
VALUE arr = rb_ary_new();
|
488
|
+
for (i = 0; i < n; i++) {
|
489
|
+
VALUE val = _stmt_get_value(s, i, buffer_types[i]);
|
490
|
+
rb_ary_push(arr, val);
|
491
|
+
}
|
492
|
+
ret = arr;
|
493
|
+
}
|
494
|
+
/* fetch_as_object */
|
495
|
+
else {
|
496
|
+
MYSQL_FIELD *fields = mysql_fetch_fields(res);
|
497
|
+
VALUE obj = rb_funcall(klass, id_new, 0);
|
498
|
+
char buf[MAX_IVAR_LENGTH + 1];
|
499
|
+
buf[0] = '@';
|
500
|
+
buf[MAX_IVAR_LENGTH] = '\0';
|
501
|
+
for (i = 0; i < n; i++) {
|
502
|
+
VALUE val = _stmt_get_value(s, i, buffer_types[i]);
|
503
|
+
strncpy(buf+1, fields[i].name, MAX_IVAR_LENGTH - 1);
|
504
|
+
rb_ivar_set(obj, rb_intern(buf), val);
|
505
|
+
}
|
506
|
+
ret = obj;
|
507
|
+
}
|
508
|
+
}
|
509
|
+
else {
|
510
|
+
VALUE list;
|
511
|
+
int has_block = rb_block_given_p() == Qtrue;
|
512
|
+
list = has_block ? Qnil : rb_ary_new();
|
513
|
+
/* fetch_all_as_hashes */
|
514
|
+
if (klass == rb_cHash) {
|
515
|
+
MYSQL_FIELD *fields = mysql_fetch_fields(res);
|
516
|
+
VALUE *keys = alloca(n * sizeof(VALUE));
|
517
|
+
for (i = 0; i < n; i++) {
|
518
|
+
keys[i] = rb_tainted_str_new2(fields[i].name);
|
519
|
+
}
|
520
|
+
while ((r = mysql_stmt_fetch(s->stmt)) != MYSQL_NO_DATA && r != 1) {
|
521
|
+
VALUE hash = rb_hash_new();
|
522
|
+
for (i = 0; i < n; i++) {
|
523
|
+
//VALUE val = s->result.is_null[i] ? Qnil : _stmt_get_value(s, i, buffer_types[i]);
|
524
|
+
VALUE val = _stmt_get_value(s, i, buffer_types[i]);
|
525
|
+
rb_hash_aset(hash, keys[i], val);
|
526
|
+
}
|
527
|
+
has_block ? rb_yield(hash) : rb_ary_push(list, hash);
|
528
|
+
}
|
529
|
+
}
|
530
|
+
/* fetch_all_as_arrays */
|
531
|
+
else if (klass == rb_cArray) {
|
532
|
+
while ((r = mysql_stmt_fetch(s->stmt)) != MYSQL_NO_DATA && r != 1) {
|
533
|
+
VALUE arr = rb_ary_new2(n);
|
534
|
+
for (i = 0; i < n; i++) {
|
535
|
+
//VALUE val = s->result.is_null[i] ? Qnil : _stmt_get_value(s, i, buffer_types[i]);
|
536
|
+
VALUE val = _stmt_get_value(s, i, buffer_types[i]);
|
537
|
+
rb_ary_push(arr, val);
|
538
|
+
}
|
539
|
+
has_block ? rb_yield(arr) : rb_ary_push(list, arr);
|
540
|
+
}
|
541
|
+
}
|
542
|
+
/* fetch_all_as_objects */
|
543
|
+
else {
|
544
|
+
MYSQL_FIELD *fields = mysql_fetch_fields(res);
|
545
|
+
char buf[MAX_IVAR_LENGTH + 1];
|
546
|
+
buf[0] = '@';
|
547
|
+
buf[MAX_IVAR_LENGTH] = '\0';
|
548
|
+
VALUE *names = alloca(n * sizeof(VALUE));
|
549
|
+
for (i = 0; i < n; i++) {
|
550
|
+
strncpy(buf+1, fields[i].name, MAX_IVAR_LENGTH - 1);
|
551
|
+
names[i] = rb_intern(buf);
|
552
|
+
}
|
553
|
+
ID id_new_ = id_new;
|
554
|
+
while ((r = mysql_stmt_fetch(s->stmt)) != MYSQL_NO_DATA && r != 1) {
|
555
|
+
VALUE obj = rb_funcall(klass, id_new_, 0);
|
556
|
+
for (i = 0; i < n; i++) {
|
557
|
+
VALUE val = _stmt_get_value(s, i, buffer_types[i]);
|
558
|
+
rb_ivar_set(obj, names[i], val);
|
559
|
+
}
|
560
|
+
has_block ? rb_yield(obj) : rb_ary_push(list, obj);
|
561
|
+
}
|
562
|
+
}
|
563
|
+
if (r == 1)
|
564
|
+
mysql_stmt_raise(s->stmt);
|
565
|
+
ret = list;
|
566
|
+
}
|
567
|
+
/*
|
568
|
+
stmt_free_result(obj_stmt);
|
569
|
+
stmt_close(obj_stmt);
|
570
|
+
*/
|
571
|
+
if (flag_free) {
|
572
|
+
rb_funcall(obj_stmt, id_free_result, 0);
|
573
|
+
rb_funcall(obj_stmt, id_close, 0);
|
574
|
+
}
|
575
|
+
return ret;
|
576
|
+
}
|
577
|
+
|
578
|
+
static VALUE stmt_fetch_as_hash (VALUE obj_stmt) { return _stmt_fetch(obj_stmt, rb_cHash, 1, 1); }
|
579
|
+
static VALUE stmt_fetch_as_hash2(VALUE obj_stmt) { return _stmt_fetch(obj_stmt, rb_cHash, 1, 0); }
|
580
|
+
static VALUE stmt_fetch_all_as_hashes (VALUE obj_stmt) { return _stmt_fetch(obj_stmt, rb_cHash, 0, 1); }
|
581
|
+
static VALUE stmt_fetch_all_as_hashes2(VALUE obj_stmt) { return _stmt_fetch(obj_stmt, rb_cHash, 0, 0); }
|
582
|
+
|
583
|
+
static VALUE stmt_fetch_as_array (VALUE obj_stmt) { return _stmt_fetch(obj_stmt, rb_cArray, 1, 1); }
|
584
|
+
static VALUE stmt_fetch_as_array2(VALUE obj_stmt) { return _stmt_fetch(obj_stmt, rb_cArray, 1, 0); }
|
585
|
+
static VALUE stmt_fetch_all_as_arrays (VALUE obj_stmt) { return _stmt_fetch(obj_stmt, rb_cArray, 0, 1); }
|
586
|
+
static VALUE stmt_fetch_all_as_arrays2(VALUE obj_stmt) { return _stmt_fetch(obj_stmt, rb_cArray, 0, 0); }
|
587
|
+
|
588
|
+
static VALUE stmt_fetch_as_object (VALUE obj_stmt, VALUE klass) { return _stmt_fetch(obj_stmt, klass, 1, 1); }
|
589
|
+
static VALUE stmt_fetch_as_object2(VALUE obj_stmt, VALUE klass) { return _stmt_fetch(obj_stmt, klass, 1, 0); }
|
590
|
+
static VALUE stmt_fetch_all_as_objects (VALUE obj_stmt, VALUE klass) { return _stmt_fetch(obj_stmt, klass, 0, 1); }
|
591
|
+
static VALUE stmt_fetch_all_as_objects2(VALUE obj_stmt, VALUE klass) { return _stmt_fetch(obj_stmt, klass, 0, 0); }
|
592
|
+
|
593
|
+
|
594
|
+
|
595
|
+
void Init_motto_mysql(void)
|
596
|
+
{
|
597
|
+
id_new = rb_intern("new");
|
598
|
+
id_initialize = rb_intern("initialize");
|
599
|
+
id_create_timestamp = rb_intern("create_timestamp");
|
600
|
+
id_create_datetime = rb_intern("create_datetime");
|
601
|
+
id_create_date = rb_intern("create_date");
|
602
|
+
id_create_time = rb_intern("create_time");
|
603
|
+
id_close = rb_intern("close");
|
604
|
+
id_mktime = rb_intern("mktime");
|
605
|
+
id_free = rb_intern("free");
|
606
|
+
id_free_result = rb_intern("free_result");
|
607
|
+
|
608
|
+
rb_define_const(cMysql, "MOTTO_MYSQL_VERSION", rb_str_freeze(rb_str_new2(MOTTO_MYSQL_VERSION)));
|
609
|
+
|
610
|
+
/* require 'date' */
|
611
|
+
rb_require("date");
|
612
|
+
cDate = rb_const_get(rb_cObject, rb_intern("Date"));
|
613
|
+
cDateTime = rb_const_get(rb_cObject, rb_intern("DateTime"));
|
614
|
+
|
615
|
+
|
616
|
+
/* Mysql::create_{timestamp,datetime,date,time,timestamp_or_datetime} */
|
617
|
+
if (sizeof(time_t) == 8) {
|
618
|
+
rb_define_singleton_method(cMysql, "create_timestamp", create_ruby_timestamp, 8);
|
619
|
+
} else {
|
620
|
+
rb_define_singleton_method(cMysql, "create_timestamp", create_ruby_timestamp_or_datetime, 8);
|
621
|
+
}
|
622
|
+
rb_define_singleton_method(cMysql, "create_datetime", create_ruby_datetime, 8);
|
623
|
+
rb_define_singleton_method(cMysql, "create_date", create_ruby_date, 5);
|
624
|
+
rb_define_singleton_method(cMysql, "create_time", create_ruby_time, 5);
|
625
|
+
rb_define_singleton_method(cMysql, "create_timestamp_or_datetime", create_ruby_timestamp_or_datetime, 8);
|
626
|
+
|
627
|
+
|
628
|
+
/* Mysql::Result */
|
629
|
+
rb_define_method(cMysqlRes, "fetch_as_hash", result_fetch_as_hash, 0);
|
630
|
+
rb_define_method(cMysqlRes, "fetch_as_array", result_fetch_as_array, 0);
|
631
|
+
rb_define_method(cMysqlRes, "fetch_as_object", result_fetch_as_object, 1);
|
632
|
+
rb_define_method(cMysqlRes, "fetch_as", result_fetch_as_object, 1);
|
633
|
+
rb_define_method(cMysqlRes, "fetch_all_as_hashes", result_fetch_all_as_hashes, 0);
|
634
|
+
rb_define_method(cMysqlRes, "fetch_all_as_arrays", result_fetch_all_as_arrays, 0);
|
635
|
+
rb_define_method(cMysqlRes, "fetch_all_as_objects", result_fetch_all_as_objects, 1);
|
636
|
+
rb_define_method(cMysqlRes, "fetch_all_as", result_fetch_all_as_objects, 1);
|
637
|
+
|
638
|
+
rb_define_method(cMysqlRes, "fetch_as_hash!", result_fetch_as_hash2, 0);
|
639
|
+
rb_define_method(cMysqlRes, "fetch_as_array!", result_fetch_as_array2, 0);
|
640
|
+
rb_define_method(cMysqlRes, "fetch_as_object!", result_fetch_as_object2, 1);
|
641
|
+
rb_define_method(cMysqlRes, "fetch_as!", result_fetch_as_object2, 1);
|
642
|
+
rb_define_method(cMysqlRes, "fetch_all_as_hashes!", result_fetch_all_as_hashes2, 0);
|
643
|
+
rb_define_method(cMysqlRes, "fetch_all_as_arrays!", result_fetch_all_as_arrays2, 0);
|
644
|
+
rb_define_method(cMysqlRes, "fetch_all_as_objects!", result_fetch_all_as_objects2, 1);
|
645
|
+
rb_define_method(cMysqlRes, "fetch_all_as!", result_fetch_all_as_objects2, 1);
|
646
|
+
|
647
|
+
|
648
|
+
/* Mysql::Stmt */
|
649
|
+
rb_define_method(cMysqlStmt, "fetch_as_hash", stmt_fetch_as_hash, 0);
|
650
|
+
rb_define_method(cMysqlStmt, "fetch_as_array", stmt_fetch_as_array, 0);
|
651
|
+
rb_define_method(cMysqlStmt, "fetch_as_object", stmt_fetch_as_object, 1);
|
652
|
+
rb_define_method(cMysqlStmt, "fetch_as", stmt_fetch_as_object, 1);
|
653
|
+
rb_define_method(cMysqlStmt, "fetch_all_as_hashes", stmt_fetch_all_as_hashes, 0);
|
654
|
+
rb_define_method(cMysqlStmt, "fetch_all_as_arrays", stmt_fetch_all_as_arrays, 0);
|
655
|
+
rb_define_method(cMysqlStmt, "fetch_all_as_objects", stmt_fetch_all_as_objects, 1);
|
656
|
+
rb_define_method(cMysqlStmt, "fetch_all_as", stmt_fetch_all_as_objects, 1);
|
657
|
+
|
658
|
+
rb_define_method(cMysqlStmt, "fetch_as_hash!", stmt_fetch_as_hash2, 0);
|
659
|
+
rb_define_method(cMysqlStmt, "fetch_as_array!", stmt_fetch_as_array2, 0);
|
660
|
+
rb_define_method(cMysqlStmt, "fetch_as_object!", stmt_fetch_as_object2, 1);
|
661
|
+
rb_define_method(cMysqlStmt, "fetch_as!", stmt_fetch_as_object2, 1);
|
662
|
+
rb_define_method(cMysqlStmt, "fetch_all_as_hashes!", stmt_fetch_all_as_hashes2, 0);
|
663
|
+
rb_define_method(cMysqlStmt, "fetch_all_as_arrays!", stmt_fetch_all_as_arrays2, 0);
|
664
|
+
rb_define_method(cMysqlStmt, "fetch_all_as_objects!", stmt_fetch_all_as_objects2, 1);
|
665
|
+
rb_define_method(cMysqlStmt, "fetch_all_as!", stmt_fetch_all_as_objects2, 1);
|
666
|
+
|
667
|
+
}
|