convert :timezone option into two new ones
:database_timezone - the timezone (:utc or :local) Mysql2 will assume time/datetime fields are stored in the db. This modifies what initial timezone your Time objects will be in when creating them from libmysql in C and :application_timezone - the timezone (:utc or :local) you'd finally like the Time objects converted to before you get them
This commit is contained in:
parent
1bdf44ce7f
commit
ad34357e57
@ -8,9 +8,10 @@ VALUE cMysql2Result;
|
||||
VALUE cBigDecimal, cDate, cDateTime;
|
||||
extern VALUE mMysql2, cMysql2Client, cMysql2Error;
|
||||
static VALUE intern_encoding_from_charset;
|
||||
static ID intern_new, intern_utc, intern_local, intern_encoding_from_charset_code;
|
||||
static ID sym_symbolize_keys, sym_as, sym_array, sym_timezone, sym_local, sym_utc,
|
||||
sym_cast_booleans;
|
||||
static ID intern_new, intern_utc, intern_local, intern_encoding_from_charset_code,
|
||||
intern_localtime;
|
||||
static ID sym_symbolize_keys, sym_as, sym_array, sym_database_timezone, sym_application_timezone,
|
||||
sym_local, sym_utc, sym_cast_booleans;
|
||||
static ID intern_merge;
|
||||
|
||||
static void rb_mysql_result_mark(void * wrapper) {
|
||||
@ -87,7 +88,7 @@ static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, short int
|
||||
return rb_field;
|
||||
}
|
||||
|
||||
static VALUE rb_mysql_result_fetch_row(VALUE self, ID timezone, int symbolizeKeys, int asArray, int castBool) {
|
||||
static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezone, int symbolizeKeys, int asArray, int castBool) {
|
||||
VALUE rowVal;
|
||||
mysql2_result_wrapper * wrapper;
|
||||
MYSQL_ROW row;
|
||||
@ -154,7 +155,14 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID timezone, int symbolizeKey
|
||||
case MYSQL_TYPE_TIME: { // TIME field
|
||||
int hour, min, sec, tokens;
|
||||
tokens = sscanf(row[i], "%2d:%2d:%2d", &hour, &min, &sec);
|
||||
val = rb_funcall(rb_cTime, timezone, 6, INT2NUM(2000), INT2NUM(1), INT2NUM(1), INT2NUM(hour), INT2NUM(min), INT2NUM(sec));
|
||||
val = rb_funcall(rb_cTime, db_timezone, 6, INT2NUM(2000), INT2NUM(1), INT2NUM(1), INT2NUM(hour), INT2NUM(min), INT2NUM(sec));
|
||||
if (!NIL_P(app_timezone)) {
|
||||
if (app_timezone == intern_local) {
|
||||
val = rb_funcall(val, intern_localtime, 0);
|
||||
} else { // utc
|
||||
val = rb_funcall(val, intern_utc, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_TIMESTAMP: // TIMESTAMP field
|
||||
@ -168,7 +176,14 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID timezone, int symbolizeKey
|
||||
rb_raise(cMysql2Error, "Invalid date: %s", row[i]);
|
||||
val = Qnil;
|
||||
} else {
|
||||
val = rb_funcall(rb_cTime, timezone, 6, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec));
|
||||
val = rb_funcall(rb_cTime, db_timezone, 6, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec));
|
||||
if (!NIL_P(app_timezone)) {
|
||||
if (app_timezone == intern_local) {
|
||||
val = rb_funcall(val, intern_localtime, 0);
|
||||
} else { // utc
|
||||
val = rb_funcall(val, intern_utc, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -267,8 +282,8 @@ static VALUE rb_mysql_result_fetch_fields(VALUE self) {
|
||||
}
|
||||
|
||||
static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
|
||||
VALUE defaults, opts, block, timezoneVal;
|
||||
ID timezone;
|
||||
VALUE defaults, opts, block;
|
||||
ID db_timezone, app_timezone, dbTz, appTz;
|
||||
mysql2_result_wrapper * wrapper;
|
||||
unsigned long i;
|
||||
int symbolizeKeys = 0, asArray = 0, castBool = 0;
|
||||
@ -294,14 +309,28 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
|
||||
castBool = 1;
|
||||
}
|
||||
|
||||
timezoneVal = rb_hash_aref(opts, sym_timezone);
|
||||
if (timezoneVal == sym_local) {
|
||||
timezone = intern_local;
|
||||
} else if (timezoneVal == sym_utc) {
|
||||
timezone = intern_utc;
|
||||
dbTz = rb_hash_aref(opts, sym_database_timezone);
|
||||
if (dbTz == sym_local) {
|
||||
db_timezone = intern_local;
|
||||
} else if (dbTz == sym_utc) {
|
||||
db_timezone = intern_utc;
|
||||
} else {
|
||||
rb_warn(":timezone config option must be :utc or :local - defaulting to :local");
|
||||
timezone = intern_local;
|
||||
if (!NIL_P(dbTz)) {
|
||||
rb_warn(":database_timezone option must be :utc or :local - defaulting to :local");
|
||||
}
|
||||
db_timezone = intern_local;
|
||||
}
|
||||
|
||||
appTz = rb_hash_aref(opts, sym_application_timezone);
|
||||
if (appTz == sym_local) {
|
||||
app_timezone = intern_local;
|
||||
} else if (appTz == sym_utc) {
|
||||
app_timezone = intern_utc;
|
||||
} else {
|
||||
if (!NIL_P(appTz)) {
|
||||
rb_warn(":application_timezone option must be :utc or :local - defaulting to :local");
|
||||
}
|
||||
app_timezone = intern_local;
|
||||
}
|
||||
|
||||
if (wrapper->lastRowProcessed == 0) {
|
||||
@ -327,7 +356,7 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
|
||||
if (i < rowsProcessed) {
|
||||
row = rb_ary_entry(wrapper->rows, i);
|
||||
} else {
|
||||
row = rb_mysql_result_fetch_row(self, timezone, symbolizeKeys, asArray, castBool);
|
||||
row = rb_mysql_result_fetch_row(self, db_timezone, app_timezone, symbolizeKeys, asArray, castBool);
|
||||
rb_ary_store(wrapper->rows, i, row);
|
||||
wrapper->lastRowProcessed++;
|
||||
}
|
||||
@ -379,18 +408,20 @@ void init_mysql2_result() {
|
||||
intern_encoding_from_charset = rb_intern("encoding_from_charset");
|
||||
intern_encoding_from_charset_code = rb_intern("encoding_from_charset_code");
|
||||
|
||||
intern_new = rb_intern("new");
|
||||
intern_utc = rb_intern("utc");
|
||||
intern_local = rb_intern("local");
|
||||
intern_merge = rb_intern("merge");
|
||||
intern_new = rb_intern("new");
|
||||
intern_utc = rb_intern("utc");
|
||||
intern_local = rb_intern("local");
|
||||
intern_merge = rb_intern("merge");
|
||||
intern_localtime = rb_intern("localtime");
|
||||
|
||||
sym_symbolize_keys = ID2SYM(rb_intern("symbolize_keys"));
|
||||
sym_as = ID2SYM(rb_intern("as"));
|
||||
sym_array = ID2SYM(rb_intern("array"));
|
||||
sym_timezone = ID2SYM(rb_intern("timezone"));
|
||||
sym_local = ID2SYM(rb_intern("local"));
|
||||
sym_utc = ID2SYM(rb_intern("utc"));
|
||||
sym_cast_booleans = ID2SYM(rb_intern("cast_booleans"));
|
||||
sym_database_timezone = ID2SYM(rb_intern("database_timezone"));
|
||||
sym_application_timezone = ID2SYM(rb_intern("application_timezone"));
|
||||
|
||||
#ifdef HAVE_RUBY_ENCODING_H
|
||||
binaryEncoding = rb_enc_find("binary");
|
||||
|
@ -2,11 +2,12 @@ module Mysql2
|
||||
class Client
|
||||
attr_reader :query_options
|
||||
@@default_query_options = {
|
||||
:symbolize_keys => false,
|
||||
:async => false,
|
||||
:as => :hash,
|
||||
:timezone => :local,
|
||||
:cast_booleans => false
|
||||
:async => false,
|
||||
:cast_booleans => false,
|
||||
:symbolize_keys => false,
|
||||
:database_timezone => :local, # timezone Mysql2 will assume datetime objects are stored in
|
||||
:application_timezone => :local # timezone Mysql2 will convert to before handing the object back to the caller
|
||||
}
|
||||
|
||||
def initialize(opts = {})
|
||||
|
Loading…
Reference in New Issue
Block a user