Skip to content

Commit bb9bc49

Browse files
committed
Merge branch '0.2.x'
2 parents 9602840 + 0f0a5ad commit bb9bc49

File tree

4 files changed

+77
-40
lines changed

4 files changed

+77
-40
lines changed

.rspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
--format documentation
22
--colour
3+
--fail-fast

ext/mysql2/client.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ static VALUE allocate(VALUE klass) {
171171
return obj;
172172
}
173173

174-
static VALUE rb_mysql_client_escape(VALUE klass, VALUE str) {
174+
static VALUE rb_mysql_client_escape(RB_MYSQL_UNUSED VALUE klass, VALUE str) {
175175
unsigned char *newStr;
176176
VALUE rb_str;
177177
unsigned long newLen, oldLen;

ext/mysql2/result.c

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,46 @@
44
static rb_encoding *binaryEncoding;
55
#endif
66

7-
#if SIZEOF_INT < SIZEOF_LONG
8-
/**
9-
* on 64bit platforms we can handle dates way outside 2038-01-19T03:14:07
10-
* because of how I'm performing the math below, this will allow a maximum
11-
* timestamp of 9846-12-12T11:5999:59
12-
*/
13-
#define MYSQL2_MAX_YEAR 9999
7+
#if (SIZEOF_INT < SIZEOF_LONG) || defined(HAVE_RUBY_ENCODING_H)
8+
/* on 64bit platforms we can handle dates way outside 2038-01-19T03:14:07
9+
*
10+
* (9999*31557600) + (12*2592000) + (31*86400) + (11*3600) + (59*60) + 59
11+
*/
12+
#define MYSQL2_MAX_TIME 315578267999ULL
1413
#else
1514
/**
16-
* on 32bit platforms the maximum date the Time class can handle is 2038-01-19T03:14:07
17-
* 2082 = 2038+1+19+3+14+7
15+
* On 32bit platforms the maximum date the Time class can handle is 2038-01-19T03:14:07
16+
* 2038 years + 1 month + 19 days + 3 hours + 14 minutes + 7 seconds = 64318634047 seconds
17+
*
18+
* (2038*31557600) + (1*2592000) + (19*86400) + (3*3600) + (14*60) + 7
1819
*/
19-
#define MYSQL2_MAX_YEAR 2082
20+
#define MYSQL2_MAX_TIME 64318634047ULL
2021
#endif
2122

22-
#ifdef NEGATIVE_TIME_T
23-
/* 1901-12-13 20:45:52 UTC : The oldest time in 32-bit signed time_t. */
24-
#define MYSQL2_MIN_YEAR 1902
23+
#if defined(HAVE_RUBY_ENCODING_H)
24+
/* 0000-1-1 00:00:00 UTC
25+
*
26+
* (0*31557600) + (1*2592000) + (1*86400) + (0*3600) + (0*60) + 0
27+
*/
28+
#define MYSQL2_MIN_TIME 2678400ULL
29+
#elif SIZEOF_INT < SIZEOF_LONG // 64bit Ruby 1.8
30+
/* 0139-1-1 00:00:00 UTC
31+
*
32+
* (139*31557600) + (1*2592000) + (1*86400) + (0*3600) + (0*60) + 0
33+
*/
34+
#define MYSQL2_MIN_TIME 4389184800ULL
35+
#elif defined(NEGATIVE_TIME_T)
36+
/* 1901-12-13 20:45:52 UTC : The oldest time in 32-bit signed time_t.
37+
*
38+
* (1901*31557600) + (12*2592000) + (13*86400) + (20*3600) + (45*60) + 52
39+
*/
40+
#define MYSQL2_MIN_TIME 60023299552ULL
2541
#else
26-
/* 1970-01-01 00:00:00 UTC : The Unix epoch - the oldest time in portable time_t. */
27-
#define MYSQL2_MIN_YEAR 1970
42+
/* 1970-01-01 00:00:01 UTC : The Unix epoch - the oldest time in portable time_t.
43+
*
44+
* (1970*31557600) + (1*2592000) + (1*86400) + (0*3600) + (0*60) + 1
45+
*/
46+
#define MYSQL2_MIN_TIME 62171150401ULL
2847
#endif
2948

3049
static VALUE cMysql2Result;
@@ -244,16 +263,20 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
244263
}
245264
case MYSQL_TYPE_TIMESTAMP: // TIMESTAMP field
246265
case MYSQL_TYPE_DATETIME: { // DATETIME field
247-
int year, month, day, hour, min, sec, tokens;
266+
unsigned int year, month, day, hour, min, sec, tokens;
267+
uint64_t seconds;
268+
248269
tokens = sscanf(row[i], "%4d-%2d-%2d %2d:%2d:%2d", &year, &month, &day, &hour, &min, &sec);
249-
if (year+month+day+hour+min+sec == 0) {
270+
seconds = (year*31557600ULL) + (month*2592000ULL) + (day*86400ULL) + (hour*3600ULL) + (min*60ULL) + sec;
271+
272+
if (seconds == 0) {
250273
val = Qnil;
251274
} else {
252275
if (month < 1 || day < 1) {
253276
rb_raise(cMysql2Error, "Invalid date: %s", row[i]);
254277
val = Qnil;
255278
} else {
256-
if (year < MYSQL2_MIN_YEAR || year+month+day+hour+min+sec > MYSQL2_MAX_YEAR) { // use DateTime instead
279+
if (seconds < MYSQL2_MIN_TIME || seconds > MYSQL2_MAX_TIME) { // use DateTime instead
257280
VALUE offset = INT2NUM(0);
258281
if (db_timezone == intern_local) {
259282
offset = rb_funcall(cMysql2Client, intern_local_offset, 0);

spec/mysql2/result_spec.rb

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -181,37 +181,50 @@
181181
@test_result['date_time_test'].strftime("%F %T").should eql('2010-04-04 11:44:00')
182182
end
183183

184-
it "should return DateTime for a DATETIME value when outside the supported range, Time if otherwise" do
185-
if RUBY_PLATFORM =~ /mswin/
186-
inside_year = 1970
187-
outside_year = inside_year-1
184+
if 1.size == 4 # 32bit
185+
if RUBY_VERSION =~ /1.9/
186+
klass = Time
188187
else
189-
inside_year = 1902
190-
outside_year = inside_year-1
191-
end
192-
r = @client.query("SELECT CAST('#{inside_year}-1-1 01:01:01' AS DATETIME) as test")
193-
if defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /rbx/
194188
klass = DateTime
195-
else
196-
klass = Time
197189
end
198-
r.first['test'].class.should eql(klass)
199190

200-
r = @client.query("SELECT CAST('#{outside_year}-1-1 01:01:01' AS DATETIME) as test")
201-
r.first['test'].class.should eql(DateTime)
202-
end
191+
it "should return DateTime when timestamp is < 1901-12-13 20:45:52" do
192+
# 1901-12-13T20:45:52 is the min for 32bit Ruby 1.8
193+
r = @client.query("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test")
194+
r.first['test'].class.should eql(klass)
195+
end
203196

204-
if 1.size == 4 # 32bit
205197
it "should return DateTime when timestamp is > 2038-01-19T03:14:07" do
206198
# 2038-01-19T03:14:07 is the max for 32bit Ruby 1.8
207199
r = @client.query("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test")
208-
r.first['test'].class.should eql(DateTime)
200+
r.first['test'].class.should eql(klass)
209201
end
210202
elsif 1.size == 8 # 64bit
211-
it "should return Time when timestamp is > 2038-01-19T03:14:07" do
212-
# 2038-01-19 03:14:07 is the max for 32bit Ruby 1.8
213-
r = @client.query("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test")
214-
r.first['test'].class.should eql(Time)
203+
if RUBY_VERSION =~ /1.9/
204+
it "should return Time when timestamp is < 1901-12-13 20:45:52" do
205+
r = @client.query("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test")
206+
r.first['test'].class.should eql(Time)
207+
end
208+
209+
it "should return Time when timestamp is > 2038-01-19T03:14:07" do
210+
r = @client.query("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test")
211+
r.first['test'].class.should eql(Time)
212+
end
213+
else
214+
it "should return Time when timestamp is > 0138-12-31 11:59:59" do
215+
r = @client.query("SELECT CAST('0139-1-1 00:00:00' AS DATETIME) as test")
216+
r.first['test'].class.should eql(Time)
217+
end
218+
219+
it "should return DateTime when timestamp is < 0139-1-1T00:00:00" do
220+
r = @client.query("SELECT CAST('0138-12-31 11:59:59' AS DATETIME) as test")
221+
r.first['test'].class.should eql(DateTime)
222+
end
223+
224+
it "should return Time when timestamp is > 2038-01-19T03:14:07" do
225+
r = @client.query("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test")
226+
r.first['test'].class.should eql(Time)
227+
end
215228
end
216229
end
217230

0 commit comments

Comments
 (0)