0
@@ -65,51 +65,51 @@ static VALUE eMysqlError;
0
// Figures out what we should cast a given mysql field type to
0
static char * ruby_type_from_mysql_type(MYSQL_FIELD *field) {
0
- case MYSQL_TYPE_NULL: {
0
- ruby_type_name = NULL;
0
- case MYSQL_TYPE_TINY: {
0
- ruby_type_name = "TrueClass";
0
- case MYSQL_TYPE_SHORT:
0
- case MYSQL_TYPE_INT24:
0
- case MYSQL_TYPE_LONGLONG:
0
- case MYSQL_TYPE_YEAR: {
0
- ruby_type_name = "Fixnum";
0
- case MYSQL_TYPE_DECIMAL:
0
- case MYSQL_TYPE_FLOAT:
0
- case MYSQL_TYPE_DOUBLE: {
0
- ruby_type_name = "BigDecimal";
0
- case MYSQL_TYPE_TIMESTAMP:
0
- case MYSQL_TYPE_DATETIME: {
0
- ruby_type_name = "DateTime";
0
- case MYSQL_TYPE_TIME: {
0
- ruby_type_name = "DateTime";
0
- case MYSQL_TYPE_DATE: {
0
- ruby_type_name = "Date";
0
- // printf("Falling to default: %s - %d\n", field->name, field->type);
0
- ruby_type_name = "String";
0
- return ruby_type_name;
0
+ case MYSQL_TYPE_NULL: {
0
+ ruby_type_name = NULL;
0
+ case MYSQL_TYPE_TINY: {
0
+ ruby_type_name = "TrueClass";
0
+ case MYSQL_TYPE_SHORT:
0
+ case MYSQL_TYPE_INT24:
0
+ case MYSQL_TYPE_LONGLONG:
0
+ case MYSQL_TYPE_YEAR: {
0
+ ruby_type_name = "Fixnum";
0
+ case MYSQL_TYPE_DECIMAL:
0
+ case MYSQL_TYPE_FLOAT:
0
+ case MYSQL_TYPE_DOUBLE: {
0
+ ruby_type_name = "BigDecimal";
0
+ case MYSQL_TYPE_TIMESTAMP:
0
+ case MYSQL_TYPE_DATETIME: {
0
+ ruby_type_name = "DateTime";
0
+ case MYSQL_TYPE_TIME: {
0
+ ruby_type_name = "DateTime";
0
+ case MYSQL_TYPE_DATE: {
0
+ ruby_type_name = "Date";
0
+ // printf("Falling to default: %s - %d\n", field->name, field->type);
0
+ ruby_type_name = "String";
0
+ return ruby_type_name;
0
// Find the greatest common denominator and reduce the provided numerator and denominator.
0
@@ -119,7 +119,7 @@ static void reduce( do_int64 *numerator, do_int64 *denominator ) {
0
-
c = a; a = b % a; b = c;
0
+
c = a; a = b % a; b = c;
0
*numerator = *numerator / b;
0
*denominator = *denominator / b;
0
@@ -129,8 +129,8 @@ static void reduce( do_int64 *numerator, do_int64 *denominator ) {
0
static int jd_from_date(int year, int month, int day) {
0
@@ -138,374 +138,375 @@ static int jd_from_date(int year, int month, int day) {
0
static VALUE seconds_to_offset(long seconds_offset) {
0
- do_int64 num = seconds_offset, den = 86400;
0
- return rb_funcall(rb_cRational, rb_intern("new!"), 2, rb_ll2inum(num), rb_ll2inum(den));
0
+ do_int64 num = seconds_offset, den = 86400;
0
+ return rb_funcall(rb_cRational, rb_intern("new!"), 2, rb_ll2inum(num), rb_ll2inum(den));
0
static VALUE parse_date(const char *date) {
0
-
sscanf(date, "%4d-%2d-%2d", &year, &month, &day);
0
+
sscanf(date, "%4d-%2d-%2d", &year, &month, &day);
0
-
jd = jd_from_date(year, month, day);
0
+
jd = jd_from_date(year, month, day);
0
- // Math from Date.jd_to_ajd
0
- rational = rb_funcall(rb_cRational, ID_NEW_RATIONAL, 2, INT2NUM(ajd), INT2NUM(2));
0
- return rb_funcall(rb_cDate, ID_NEW_DATE, 3, rational, INT2NUM(0), INT2NUM(2299161));
0
+ // Math from Date.jd_to_ajd
0
+ rational = rb_funcall(rb_cRational, ID_NEW_RATIONAL, 2, INT2NUM(ajd), INT2NUM(2));
0
+ return rb_funcall(rb_cDate, ID_NEW_DATE, 3, rational, INT2NUM(0), INT2NUM(2299161));
0
static VALUE parse_time(const char *date) {
0
- int year, month, day, hour, min, sec, usec;
0
+ int year, month, day, hour, min, sec, usec;
0
- if (0 != strchr(date, '.')) {
0
- // right padding usec with 0. e.g. '012' will become 12000 microsecond, since Time#local use microsecond
0
- sscanf(date, "%4d-%2d-%2d %2d:%2d:%2d.%s", &year, &month, &day, &hour, &min, &sec, subsec);
0
- sscanf(subsec, "%d", &usec);
0
- sscanf(date, "%4d-%2d-%2d %2d:%2d:%2d", &year, &month, &day, &hour, &min, &sec);
0
+ if (0 != strchr(date, '.')) {
0
+ // right padding usec with 0. e.g. '012' will become 12000 microsecond, since Time#local use microsecond
0
+ sscanf(date, "%4d-%2d-%2d %2d:%2d:%2d.%s", &year, &month, &day, &hour, &min, &sec, subsec);
0
+ sscanf(subsec, "%d", &usec);
0
+ sscanf(date, "%4d-%2d-%2d %2d:%2d:%2d", &year, &month, &day, &hour, &min, &sec);
0
-
return rb_funcall(rb_cTime, rb_intern("local"), 7, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec), INT2NUM(usec));
0
+
return rb_funcall(rb_cTime, rb_intern("local"), 7, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec), INT2NUM(usec));
0
static VALUE parse_date_time(const char *date_time) {
0
- int year, month, day, hour, min, sec;
0
+ int year, month, day, hour, min, sec;
0
- // Mysql date format: 2008-05-03 14:43:00
0
- sscanf(date_time, "%4d-%2d-%2d %2d:%2d:%2d", &year, &month, &day, &hour, &min, &sec);
0
+ // Mysql date format: 2008-05-03 14:43:00
0
+ sscanf(date_time, "%4d-%2d-%2d %2d:%2d:%2d", &year, &month, &day, &hour, &min, &sec);
0
-
jd = jd_from_date(year, month, day);
0
+
jd = jd_from_date(year, month, day);
0
- // Generate ajd with fractional days for the time
0
- // Extracted from Date#jd_to_ajd, Date#day_fraction_to_time, and Rational#+ and #-
0
- num = ((hour) * 1440) + ((min) * 24); // (Hour * Minutes in a day) + (minutes * 24)
0
+ // Generate ajd with fractional days for the time
0
+ // Extracted from Date#jd_to_ajd, Date#day_fraction_to_time, and Rational#+ and #-
0
+ num = ((hour) * 1440) + ((min) * 24); // (Hour * Minutes in a day) + (minutes * 24)
0
- timeinfo = localtime(&rawtime);
0
+ timeinfo = localtime(&rawtime);
0
- // TODO: Refactor the following few lines to do the calculation with the *seconds*
0
- // value instead of having to do the hour/minute math
0
- int hour_offset = abs(timeinfo->tm_gmtoff) / 3600;
0
- int minute_offset = abs(timeinfo->tm_gmtoff) % 3600 / 60;
0
+ // TODO: Refactor the following few lines to do the calculation with the *seconds*
0
+ // value instead of having to do the hour/minute math
0
+ int hour_offset = abs(timeinfo->tm_gmtoff) / 3600;
0
+ int minute_offset = abs(timeinfo->tm_gmtoff) % 3600 / 60;
0
- // Modify the numerator so when we apply the timezone everything works out
0
- if (timeinfo->tm_gmtoff < 0) {
0
- // If the Timezone is behind UTC, we need to add the time offset
0
- num += (hour_offset * 1440) + (minute_offset * 24);
0
- // If the Timezone is ahead of UTC, we need to subtract the time offset
0
- num -= (hour_offset * 1440) + (minute_offset * 24);
0
+ // Modify the numerator so when we apply the timezone everything works out
0
+ if (timeinfo->tm_gmtoff < 0) {
0
+ // If the Timezone is behind UTC, we need to add the time offset
0
+ num += (hour_offset * 1440) + (minute_offset * 24);
0
+ // If the Timezone is ahead of UTC, we need to subtract the time offset
0
+ num -= (hour_offset * 1440) + (minute_offset * 24);
0
- num = (num * 86400) + (sec * den);
0
+ num = (num * 86400) + (sec * den);
0
-
num = (jd * den) + num;
0
+
num = (jd * den) + num;
0
-
ajd = rb_funcall(rb_cRational, rb_intern("new!"), 2, rb_ull2inum(num), rb_ull2inum(den));
0
+
ajd = rb_funcall(rb_cRational, rb_intern("new!"), 2, rb_ull2inum(num), rb_ull2inum(den));
0
- // Calculate the offset using the seconds from GMT
0
- offset = seconds_to_offset(timeinfo->tm_gmtoff);
0
+ // Calculate the offset using the seconds from GMT
0
+ offset = seconds_to_offset(timeinfo->tm_gmtoff);
0
-
return rb_funcall(rb_cDateTime, ID_NEW_DATE, 3, ajd, offset, INT2NUM(2299161));
0
+
return rb_funcall(rb_cDateTime, ID_NEW_DATE, 3, ajd, offset, INT2NUM(2299161));
0
// Convert C-string to a Ruby instance of Ruby type "type"
0
static VALUE typecast(const char* value, char* type) {
0
- if ( strcmp(type, "Class") == 0) {
0
- return rb_funcall(mDO, rb_intern("find_const"), 1, TAINTED_STRING(value));
0
- } else if ( strcmp(type, "Integer") == 0 || strcmp(type, "Fixnum") == 0 || strcmp(type, "Bignum") == 0 ) {
0
- return rb_cstr2inum(value, 10);
0
- } else if (0 == strcmp("String", type)) {
0
- return TAINTED_STRING(value);
0
- } else if (0 == strcmp("Float", type) ) {
0
- return rb_float_new(rb_cstr_to_dbl(value, Qfalse));
0
- } else if (0 == strcmp("BigDecimal", type) ) {
0
- return rb_funcall(rb_cBigDecimal, ID_NEW, 1, TAINTED_STRING(value));
0
- } else if (0 == strcmp("TrueClass", type) || 0 == strcmp("FalseClass", type)) {
0
- return (0 == value || 0 == strcmp("0", value)) ? Qfalse : Qtrue;
0
- } else if (0 == strcmp("Date", type)) {
0
- return parse_date(value);
0
- } else if (0 == strcmp("DateTime", type)) {
0
- return parse_date_time(value);
0
- } else if (0 == strcmp("Time", type)) {
0
- return parse_time(value);
0
- return TAINTED_STRING(value);
0
+ if ( strcmp(type, "Class") == 0) {
0
+ return rb_funcall(mDO, rb_intern("find_const"), 1, TAINTED_STRING(value));
0
+ } else if ( strcmp(type, "Integer") == 0 || strcmp(type, "Fixnum") == 0 || strcmp(type, "Bignum") == 0 ) {
0
+ return rb_cstr2inum(value, 10);
0
+ } else if (0 == strcmp("String", type)) {
0
+ return TAINTED_STRING(value);
0
+ } else if (0 == strcmp("Float", type) ) {
0
+ return rb_float_new(rb_cstr_to_dbl(value, Qfalse));
0
+ } else if (0 == strcmp("BigDecimal", type) ) {
0
+ return rb_funcall(rb_cBigDecimal, ID_NEW, 1, TAINTED_STRING(value));
0
+ } else if (0 == strcmp("TrueClass", type) || 0 == strcmp("FalseClass", type)) {
0
+ return (0 == value || 0 == strcmp("0", value)) ? Qfalse : Qtrue;
0
+ } else if (0 == strcmp("Date", type)) {
0
+ return parse_date(value);
0
+ } else if (0 == strcmp("DateTime", type)) {
0
+ return parse_date_time(value);
0
+ } else if (0 == strcmp("Time", type)) {
0
+ return parse_time(value);
0
+ return TAINTED_STRING(value);
0
static void data_objects_debug(VALUE string) {
0
- VALUE logger = rb_funcall(mDOMysql, ID_LOGGER, 0);
0
- int log_level = NUM2INT(rb_funcall(logger, ID_LEVEL, 0));
0
+ VALUE logger = rb_funcall(mDOMysql, ID_LOGGER, 0);
0
+ int log_level = NUM2INT(rb_funcall(logger, ID_LEVEL, 0));
0
- rb_funcall(logger, ID_DEBUG, 1, string);
0
+ rb_funcall(logger, ID_DEBUG, 1, string);
0
static void flush_pool(VALUE connection) {
0
- if ( Qnil != connection ) {
0
- VALUE pool = rb_iv_get(connection, "@__pool");
0
- rb_funcall(pool, rb_intern("dispose"), 0);
0
+ if ( Qnil != connection ) {
0
+ VALUE pool = rb_iv_get(connection, "@__pool");
0
+ rb_funcall(pool, rb_intern("dispose"), 0);
0
// We can add custom information to error messages using this function
0
// if we think it matters
0
static void raise_mysql_error(VALUE connection, MYSQL *db, int mysql_error_code) {
0
- char *error_message = (char *)mysql_error(db);
0
- switch(mysql_error_code) {
0
- case CR_UNKNOWN_ERROR:
0
- case CR_SOCKET_CREATE_ERROR:
0
- case CR_CONNECTION_ERROR:
0
- case CR_CONN_HOST_ERROR:
0
- case CR_SERVER_GONE_ERROR:
0
- case CR_VERSION_ERROR:
0
- case CR_OUT_OF_MEMORY:
0
- case CR_WRONG_HOST_INFO:
0
- case CR_LOCALHOST_CONNECTION:
0
- case CR_TCP_CONNECTION:
0
- case CR_SERVER_HANDSHAKE_ERR:
0
- case CR_COMMANDS_OUT_OF_SYNC:
0
- case CR_NAMEDPIPE_CONNECTION:
0
- case CR_NAMEDPIPEWAIT_ERROR:
0
- case CR_NAMEDPIPEOPEN_ERROR:
0
- case CR_NAMEDPIPESETSTATE_ERROR:
0
- case CR_CANT_READ_CHARSET:
0
- case CR_NET_PACKET_TOO_LARGE:
0
- case CR_EMBEDDED_CONNECTION:
0
- case CR_PROBE_SLAVE_STATUS:
0
- case CR_PROBE_SLAVE_HOSTS:
0
- case CR_PROBE_SLAVE_CONNECT:
0
- case CR_PROBE_MASTER_CONNECT:
0
- case CR_SSL_CONNECTION_ERROR:
0
- case CR_MALFORMED_PACKET:
0
- case CR_WRONG_LICENSE:
0
- case CR_NO_PREPARE_STMT:
0
- case CR_PARAMS_NOT_BOUND:
0
- case CR_DATA_TRUNCATED:
0
- case CR_NO_PARAMETERS_EXISTS:
0
- case CR_INVALID_PARAMETER_NO:
0
- case CR_INVALID_BUFFER_USE:
0
- case CR_UNSUPPORTED_PARAM_TYPE:
0
- case CR_SHARED_MEMORY_CONNECTION:
0
- case CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR:
0
- case CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR:
0
- case CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR:
0
- case CR_SHARED_MEMORY_CONNECT_MAP_ERROR:
0
- case CR_SHARED_MEMORY_FILE_MAP_ERROR:
0
- case CR_SHARED_MEMORY_MAP_ERROR:
0
- case CR_SHARED_MEMORY_EVENT_ERROR:
0
- case CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR:
0
- case CR_SHARED_MEMORY_CONNECT_SET_ERROR:
0
- case CR_CONN_UNKNOW_PROTOCOL:
0
- case CR_INVALID_CONN_HANDLE:
0
- case CR_FETCH_CANCELED:
0
- case CR_NO_STMT_METADATA:
0
+ char *error_message = (char *)mysql_error(db);
0
+ switch(mysql_error_code) {
0
+ case CR_UNKNOWN_ERROR:
0
+ case CR_SOCKET_CREATE_ERROR:
0
+ case CR_CONNECTION_ERROR:
0
+ case CR_CONN_HOST_ERROR:
0
+ case CR_SERVER_GONE_ERROR:
0
+ case CR_VERSION_ERROR:
0
+ case CR_OUT_OF_MEMORY:
0
+ case CR_WRONG_HOST_INFO:
0
+ case CR_LOCALHOST_CONNECTION:
0
+ case CR_TCP_CONNECTION:
0
+ case CR_SERVER_HANDSHAKE_ERR:
0
+ case CR_COMMANDS_OUT_OF_SYNC:
0
+ case CR_NAMEDPIPE_CONNECTION:
0
+ case CR_NAMEDPIPEWAIT_ERROR:
0
+ case CR_NAMEDPIPEOPEN_ERROR:
0
+ case CR_NAMEDPIPESETSTATE_ERROR:
0
+ case CR_CANT_READ_CHARSET:
0
+ case CR_NET_PACKET_TOO_LARGE:
0
+ case CR_EMBEDDED_CONNECTION:
0
+ case CR_PROBE_SLAVE_STATUS:
0
+ case CR_PROBE_SLAVE_HOSTS:
0
+ case CR_PROBE_SLAVE_CONNECT:
0
+ case CR_PROBE_MASTER_CONNECT:
0
+ case CR_SSL_CONNECTION_ERROR:
0
+ case CR_MALFORMED_PACKET:
0
+ case CR_WRONG_LICENSE:
0
+ case CR_NO_PREPARE_STMT:
0
+ case CR_PARAMS_NOT_BOUND:
0
+ case CR_DATA_TRUNCATED:
0
+ case CR_NO_PARAMETERS_EXISTS:
0
+ case CR_INVALID_PARAMETER_NO:
0
+ case CR_INVALID_BUFFER_USE:
0
+ case CR_UNSUPPORTED_PARAM_TYPE:
0
+ case CR_SHARED_MEMORY_CONNECTION:
0
+ case CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR:
0
+ case CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR:
0
+ case CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR:
0
+ case CR_SHARED_MEMORY_CONNECT_MAP_ERROR:
0
+ case CR_SHARED_MEMORY_FILE_MAP_ERROR:
0
+ case CR_SHARED_MEMORY_MAP_ERROR:
0
+ case CR_SHARED_MEMORY_EVENT_ERROR:
0
+ case CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR:
0
+ case CR_SHARED_MEMORY_CONNECT_SET_ERROR:
0
+ case CR_CONN_UNKNOW_PROTOCOL:
0
+ case CR_INVALID_CONN_HANDLE:
0
+ case CR_FETCH_CANCELED:
0
+ case CR_NO_STMT_METADATA:
0
#if MYSQL_VERSION_ID >= 50000
0
- case CR_NO_RESULT_SET:
0
- case CR_NOT_IMPLEMENTED:
0
+ case CR_NO_RESULT_SET:
0
+ case CR_NOT_IMPLEMENTED:
0
- flush_pool(connection);
0
- rb_raise(eMysqlError, error_message);
0
+ flush_pool(connection);
0
+ rb_raise(eMysqlError, error_message);
0
// Pull an option out of a querystring-formmated option list using CGI::parse
0
static char * get_uri_option(VALUE querystring, char * key) {
0
-
VALUE options_hash, option_value;
0
+
VALUE options_hash, option_value;
0
- // Ensure that we're dealing with a string
0
- querystring = rb_funcall(querystring, ID_TO_S, 0);
0
+ // Ensure that we're dealing with a string
0
+ querystring = rb_funcall(querystring, ID_TO_S, 0);
0
-
options_hash = rb_funcall(rb_cCGI, ID_PARSE, 1, querystring);
0
+
options_hash = rb_funcall(rb_cCGI, ID_PARSE, 1, querystring);
0
- // TODO: rb_hash_aref always returns an array?
0
- option_value = rb_ary_entry(rb_hash_aref(options_hash, RUBY_STRING(key)), 0);
0
+ // TODO: rb_hash_aref always returns an array?
0
+ option_value = rb_ary_entry(rb_hash_aref(options_hash, RUBY_STRING(key)), 0);
0
- if (Qnil != option_value) {
0
- value = StringValuePtr(option_value);
0
+ if (Qnil != option_value) {
0
+ value = StringValuePtr(option_value);
0
static VALUE cConnection_initialize(VALUE self, VALUE uri) {
0
- VALUE r_host, r_user, r_password, r_path, r_options, r_port;
0
- char *host = "localhost", *user = "root", *password = NULL, *path;
0
- char *database = "", *socket = NULL;
0
- unsigned long client_flags = 0;
0
- MYSQL *db = 0, *result;
0
- db = (MYSQL *)mysql_init(NULL);
0
- rb_iv_set(self, "@using_socket", Qfalse);
0
- r_host = rb_funcall(uri, rb_intern("host"), 0);
0
- host = StringValuePtr(r_host);
0
- r_user = rb_funcall(uri, rb_intern("user"), 0);
0
- user = StringValuePtr(r_user);
0
- r_password = rb_funcall(uri, rb_intern("password"), 0);
0
- if (Qnil != r_password) {
0
- password = StringValuePtr(r_password);
0
- r_path = rb_funcall(uri, rb_intern("path"), 0);
0
- path = StringValuePtr(r_path);
0
- database = strtok(path, "/");
0
- if (NULL == database || 0 == strlen(database)) {
0
- rb_raise(eMysqlError, "Database must be specified");
0
- // Pull the querystring off the URI
0
- r_options = rb_funcall(uri, rb_intern("query"), 0);
0
- // Check to see if we're on the db machine. If so, try to use the socket
0
- if (0 == strcasecmp(host, "localhost")) {
0
- socket = get_uri_option(r_options, "socket");
0
- rb_iv_set(self, "@using_socket", Qtrue);
0
- r_port = rb_funcall(uri, rb_intern("port"), 0);
0
- port = NUM2INT(r_port);
0
- charset = get_uri_option(r_options, "charset");
0
- // mysql_ssl_set(db, key, cert, ca, capath, cipher)
0
- result = (MYSQL *)mysql_real_connect(
0
- raise_mysql_error(Qnil, db, -1);
0
- if (NULL == charset) {
0
- charset = (char*)calloc(5, sizeof(char));
0
- strcpy(charset, "utf8");
0
- // Set the connections character set
0
- charset_error = mysql_set_character_set(db, charset);
0
- if (0 != charset_error) {
0
- raise_mysql_error(Qnil, db, charset_error);
0
- rb_iv_set(self, "@uri", uri);
0
- rb_iv_set(self, "@connection", Data_Wrap_Struct(rb_cObject, 0, 0, db));
0
+ VALUE r_host, r_user, r_password, r_path, r_options, r_port;
0
+ char *host = "localhost", *user = "root", *password = NULL, *path;
0
+ char *database = "", *socket = NULL;
0
+ unsigned long client_flags = 0;
0
+ MYSQL *db = 0, *result;
0
+ db = (MYSQL *)mysql_init(NULL);
0
+ rb_iv_set(self, "@using_socket", Qfalse);
0
+ r_host = rb_funcall(uri, rb_intern("host"), 0);
0
+ host = StringValuePtr(r_host);
0
+ r_user = rb_funcall(uri, rb_intern("user"), 0);
0
+ user = StringValuePtr(r_user);
0
+ r_password = rb_funcall(uri, rb_intern("password"), 0);
0
+ if (Qnil != r_password) {
0
+ password = StringValuePtr(r_password);
0
+ r_path = rb_funcall(uri, rb_intern("path"), 0);
0
+ path = StringValuePtr(r_path);
0
+ database = strtok(path, "/");
0
+ if (NULL == database || 0 == strlen(database)) {
0
+ rb_raise(eMysqlError, "Database must be specified");
0
+ // Pull the querystring off the URI
0
+ r_options = rb_funcall(uri, rb_intern("query"), 0);
0
+ // Check to see if we're on the db machine. If so, try to use the socket
0
+ if (0 == strcasecmp(host, "localhost")) {
0
+ socket = get_uri_option(r_options, "socket");
0
+ rb_iv_set(self, "@using_socket", Qtrue);
0
+ r_port = rb_funcall(uri, rb_intern("port"), 0);
0
+ port = NUM2INT(r_port);
0
+ charset = get_uri_option(r_options, "charset");
0
+ // mysql_ssl_set(db, key, cert, ca, capath, cipher)
0
+ result = (MYSQL *)mysql_real_connect(
0
+ raise_mysql_error(Qnil, db, -1);
0
+ if (NULL == charset) {
0
+ charset = (char*)calloc(5, sizeof(char));
0
+ strcpy(charset, "utf8");
0
+ // Set the connections character set
0
+ charset_error = mysql_set_character_set(db, charset);
0
+ if (0 != charset_error) {
0
+ raise_mysql_error(Qnil, db, charset_error);
0
+ rb_iv_set(self, "@uri", uri);
0
+ rb_iv_set(self, "@connection", Data_Wrap_Struct(rb_cObject, 0, 0, db));
0
static VALUE cConnection_character_set(VALUE self) {
0
- VALUE connection_container = rb_iv_get(self, "@connection");
0
+ VALUE connection_container = rb_iv_get(self, "@connection");
0
- if (Qnil == connection_container)
0
+ if (Qnil == connection_container)
0
-
db = DATA_PTR(connection_container);
0
+
db = DATA_PTR(connection_container);
0
-
charset = mysql_character_set_name(db);
0
+
charset = mysql_character_set_name(db);
0
-
return RUBY_STRING(charset);
0
+
return RUBY_STRING(charset);
0
static VALUE cConnection_is_using_socket(VALUE self) {
0
-
return rb_iv_get(self, "@using_socket");
0
+
return rb_iv_get(self, "@using_socket");
0
static VALUE cConnection_dispose(VALUE self) {
0
-
VALUE connection_container = rb_iv_get(self, "@connection");
0
+
VALUE connection_container = rb_iv_get(self, "@connection");
0
- if (Qnil == connection_container)
0
+ if (Qnil == connection_container)
0
-
db = DATA_PTR(connection_container);
0
+
db = DATA_PTR(connection_container);
0
- rb_iv_set(self, "@connection", Qnil);
0
+ rb_iv_set(self, "@connection", Qnil);
0
@@ -513,305 +514,305 @@ Accepts an array of Ruby types (Fixnum, Float, String, etc...) and turns them
0
into Ruby-strings so we can easily typecast later
0
static VALUE cCommand_set_types(VALUE self, VALUE array) {
0
- VALUE type_strings = rb_ary_new();
0
+ VALUE type_strings = rb_ary_new();
0
- for (i = 0; i < RARRAY(array)->len; i++) {
0
- rb_ary_push(type_strings, RUBY_STRING(rb_class2name(rb_ary_entry(array, i))));
0
+ for (i = 0; i < RARRAY(array)->len; i++) {
0
+ rb_ary_push(type_strings, RUBY_STRING(rb_class2name(rb_ary_entry(array, i))));
0
-
rb_iv_set(self, "@field_types", type_strings);
0
+
rb_iv_set(self, "@field_types", type_strings);
0
VALUE cCommand_quote_time(VALUE self, VALUE value) {
0
-
return rb_funcall(value, ID_STRFTIME, 1, RUBY_STRING("'%Y-%m-%d %H:%M:%S'"));
0
+
return rb_funcall(value, ID_STRFTIME, 1, RUBY_STRING("'%Y-%m-%d %H:%M:%S'"));
0
VALUE cCommand_quote_date_time(VALUE self, VALUE value) {
0
- // TODO: Support non-local dates. we need to call #new_offset on the date to be
0
- // quoted and pass in the current locale's date offset (self.new_offset((hours * 3600).to_r / 86400)
0
- return rb_funcall(value, ID_STRFTIME, 1, RUBY_STRING("'%Y-%m-%d %H:%M:%S'"));
0
+ // TODO: Support non-local dates. we need to call #new_offset on the date to be
0
+ // quoted and pass in the current locale's date offset (self.new_offset((hours * 3600).to_r / 86400)
0
+ return rb_funcall(value, ID_STRFTIME, 1, RUBY_STRING("'%Y-%m-%d %H:%M:%S'"));
0
VALUE cCommand_quote_date(VALUE self, VALUE value) {
0
-
return rb_funcall(value, ID_STRFTIME, 1, RUBY_STRING("'%Y-%m-%d'"));
0
+
return rb_funcall(value, ID_STRFTIME, 1, RUBY_STRING("'%Y-%m-%d'"));
0
static VALUE cCommand_quote_string(VALUE self, VALUE string) {
0
- MYSQL *db = DATA_PTR(rb_iv_get(rb_iv_get(self, "@connection"), "@connection"));
0
- const char *source = StringValuePtr(string);
0
- int quoted_length = 0;
0
- // Allocate space for the escaped version of 'string'. Use + 3 allocate space for null term.
0
- // and the leading and trailing single-quotes.
0
- // Thanks to http://www.browardphp.com/mysql_manual_en/manual_MySQL_APIs.html#mysql_real_escape_string
0
- escaped = (char *)calloc(strlen(source) * 3 + 3, sizeof(char));
0
- // Escape 'source' using the current charset in use on the conection 'db'
0
- quoted_length = mysql_real_escape_string(db, escaped + 1, source, strlen(source));
0
- // Wrap the escaped string in single-quotes, this is DO's convention
0
- escaped[0] = escaped[quoted_length + 1] = '\'';
0
- result = rb_str_new(escaped, quoted_length + 2);
0
+ MYSQL *db = DATA_PTR(rb_iv_get(rb_iv_get(self, "@connection"), "@connection"));
0
+ const char *source = StringValuePtr(string);
0
+ int quoted_length = 0;
0
+ // Allocate space for the escaped version of 'string'. Use + 3 allocate space for null term.
0
+ // and the leading and trailing single-quotes.
0
+ // Thanks to http://www.browardphp.com/mysql_manual_en/manual_MySQL_APIs.html#mysql_real_escape_string
0
+ escaped = (char *)calloc(strlen(source) * 3 + 3, sizeof(char));
0
+ // Escape 'source' using the current charset in use on the conection 'db'
0
+ quoted_length = mysql_real_escape_string(db, escaped + 1, source, strlen(source));
0
+ // Wrap the escaped string in single-quotes, this is DO's convention
0
+ escaped[0] = escaped[quoted_length + 1] = '\'';
0
+ result = rb_str_new(escaped, quoted_length + 2);
0
static VALUE build_query_from_args(VALUE klass, int count, VALUE *args) {
0
- VALUE query = rb_iv_get(klass, "@text");
0
- VALUE array = rb_ary_new();
0
- for ( i = 0; i < count; i++) {
0
- rb_ary_push(array, (VALUE)args[i]);
0
- query = rb_funcall(klass, ID_ESCAPE_SQL, 1, array);
0
+ VALUE query = rb_iv_get(klass, "@text");
0
+ VALUE array = rb_ary_new();
0
+ for ( i = 0; i < count; i++) {
0
+ rb_ary_push(array, (VALUE)args[i]);
0
+ query = rb_funcall(klass, ID_ESCAPE_SQL, 1, array);
0
static VALUE cCommand_execute_non_query(int argc, VALUE *argv, VALUE self) {
0
- MYSQL_RES *response = 0;
0
+ MYSQL_RES *response = 0;
0
- my_ulonglong affected_rows;
0
- VALUE connection = rb_iv_get(self, "@connection");
0
- MYSQL *db = DATA_PTR(rb_iv_get(connection, "@connection"));
0
- query = build_query_from_args(self, argc, argv);
0
+ my_ulonglong affected_rows;
0
+ VALUE connection = rb_iv_get(self, "@connection");
0
+ MYSQL *db = DATA_PTR(rb_iv_get(connection, "@connection"));
0
+ query = build_query_from_args(self, argc, argv);
0
-
data_objects_debug(query);
0
+
data_objects_debug(query);
0
- query_result = mysql_query(db, StringValuePtr(query));
0
- CHECK_AND_RAISE(query_result);
0
+ query_result = mysql_query(db, StringValuePtr(query));
0
+ CHECK_AND_RAISE(query_result);
0
- response = (MYSQL_RES *)mysql_store_result(db);
0
- affected_rows = mysql_affected_rows(db);
0
- mysql_free_result(response);
0
+ response = (MYSQL_RES *)mysql_store_result(db);
0
+ affected_rows = mysql_affected_rows(db);
0
+ mysql_free_result(response);
0
- if (-1 == affected_rows)
0
+ if (-1 == affected_rows)
0
-
return rb_funcall(cResult, ID_NEW, 3, self, INT2NUM(affected_rows), INT2NUM(mysql_insert_id(db)));
0
+
return rb_funcall(cResult, ID_NEW, 3, self, INT2NUM(affected_rows), INT2NUM(mysql_insert_id(db)));
0
static VALUE cCommand_execute_reader(int argc, VALUE *argv, VALUE self) {
0
- VALUE field_names, field_types;
0
+ VALUE field_names, field_types;
0
- char guess_default_field_types = 0;
0
- VALUE connection = rb_iv_get(self, "@connection");
0
- MYSQL *db = DATA_PTR(rb_iv_get(connection, "@connection"));
0
+ char guess_default_field_types = 0;
0
+ VALUE connection = rb_iv_get(self, "@connection");
0
+ MYSQL *db = DATA_PTR(rb_iv_get(connection, "@connection"));
0
- MYSQL_RES *response = 0;
0
+ MYSQL_RES *response = 0;
0
- query = build_query_from_args(self, argc, argv);
0
- data_objects_debug(query);
0
+ query = build_query_from_args(self, argc, argv);
0
+ data_objects_debug(query);
0
- query_result = mysql_query(db, StringValuePtr(query));
0
- CHECK_AND_RAISE(query_result);
0
+ query_result = mysql_query(db, StringValuePtr(query));
0
+ CHECK_AND_RAISE(query_result);
0
-
response = (MYSQL_RES *)mysql_use_result(db);
0
+
response = (MYSQL_RES *)mysql_use_result(db);
0
-
field_count = (int)mysql_field_count(db);
0
+
field_count = (int)mysql_field_count(db);
0
- reader = rb_funcall(cReader, ID_NEW, 0);
0
- rb_iv_set(reader, "@reader", Data_Wrap_Struct(rb_cObject, 0, 0, response));
0
- rb_iv_set(reader, "@opened", Qtrue);
0
- rb_iv_set(reader, "@field_count", INT2NUM(field_count));
0
+ reader = rb_funcall(cReader, ID_NEW, 0);
0
+ rb_iv_set(reader, "@reader", Data_Wrap_Struct(rb_cObject, 0, 0, response));
0
+ rb_iv_set(reader, "@opened", Qtrue);
0
+ rb_iv_set(reader, "@field_count", INT2NUM(field_count));
0
- field_names = rb_ary_new();
0
- field_types = rb_iv_get(self, "@field_types");
0
+ field_names = rb_ary_new();
0
+ field_types = rb_iv_get(self, "@field_types");
0
- if ( field_types == Qnil || 0 == RARRAY(field_types)->len ) {
0
- field_types = rb_ary_new();
0
- guess_default_field_types = 1;
0
- } else if (RARRAY(field_types)->len != field_count) {
0
- // Whoops... wrong number of types passed to set_types. Close the reader and raise
0
- rb_funcall(reader, rb_intern("close"), 0);
0
- flush_pool(connection);
0
- rb_raise(eMysqlError, "Field-count mismatch. Expected %d fields, but the query yielded %d", RARRAY(field_types)->len, field_count);
0
+ if ( field_types == Qnil || 0 == RARRAY(field_types)->len ) {
0
+ field_types = rb_ary_new();
0
+ guess_default_field_types = 1;
0
+ } else if (RARRAY(field_types)->len != field_count) {
0
+ // Whoops... wrong number of types passed to set_types. Close the reader and raise
0
+ rb_funcall(reader, rb_intern("close"), 0);
0
+ flush_pool(connection);
0
+ rb_raise(eMysqlError, "Field-count mismatch. Expected %d fields, but the query yielded %d", RARRAY(field_types)->len, field_count);
0
- for(i = 0; i < field_count; i++) {
0
- field = mysql_fetch_field_direct(response, i);
0
- rb_ary_push(field_names, RUBY_STRING(field->name));
0
+ for(i = 0; i < field_count; i++) {
0
+ field = mysql_fetch_field_direct(response, i);
0
+ rb_ary_push(field_names, RUBY_STRING(field->name));
0
- if (1 == guess_default_field_types) {
0
- VALUE field_ruby_type_name = RUBY_STRING(ruby_type_from_mysql_type(field));
0
- rb_ary_push(field_types, field_ruby_type_name);
0
+ if (1 == guess_default_field_types) {
0
+ VALUE field_ruby_type_name = RUBY_STRING(ruby_type_from_mysql_type(field));
0
+ rb_ary_push(field_types, field_ruby_type_name);
0
- rb_iv_set(reader, "@fields", field_names);
0
- rb_iv_set(reader, "@field_types", field_types);
0
+ rb_iv_set(reader, "@fields", field_names);
0
+ rb_iv_set(reader, "@field_types", field_types);
0
- if (rb_block_given_p()) {
0
- rb_funcall(reader, rb_intern("close"), 0);
0
+ if (rb_block_given_p()) {
0
+ rb_funcall(reader, rb_intern("close"), 0);
0
// This should be called to ensure that the internal result reader is freed
0
static VALUE cReader_close(VALUE self) {
0
- // Get the reader from the instance variable, maybe refactor this?
0
- VALUE reader_container = rb_iv_get(self, "@reader");
0
+ // Get the reader from the instance variable, maybe refactor this?
0
+ VALUE reader_container = rb_iv_get(self, "@reader");
0
- if (Qnil == reader_container)
0
+ if (Qnil == reader_container)
0
-
reader = DATA_PTR(reader_container);
0
+
reader = DATA_PTR(reader_container);
0
- mysql_free_result(reader);
0
- rb_iv_set(self, "@reader", Qnil);
0
+ mysql_free_result(reader);
0
+ rb_iv_set(self, "@reader", Qnil);
0
// Retrieve a single row
0
static VALUE cReader_next(VALUE self) {
0
- // Get the reader from the instance variable, maybe refactor this?
0
- VALUE reader_container = rb_iv_get(self, "@reader");
0
- VALUE ruby_field_type_strings, row;
0
+ // Get the reader from the instance variable, maybe refactor this?
0
+ VALUE reader_container = rb_iv_get(self, "@reader");
0
+ VALUE ruby_field_type_strings, row;
0
- if (Qnil == reader_container)
0
+ if (Qnil == reader_container)
0
-
reader = DATA_PTR(reader_container);
0
+
reader = DATA_PTR(reader_container);
0
- ruby_field_type_strings = rb_iv_get(self, "@field_types");
0
- result = (MYSQL_ROW)mysql_fetch_row(reader);
0
+ ruby_field_type_strings = rb_iv_get(self, "@field_types");
0
+ result = (MYSQL_ROW)mysql_fetch_row(reader);
0
-
rb_iv_set(self, "@state", result ? Qtrue : Qfalse);
0
+
rb_iv_set(self, "@state", result ? Qtrue : Qfalse);
0
- for (i = 0; i < reader->field_count; i++) {
0
- // The field_type data could be cached in a c-array
0
- field_type = RSTRING(rb_ary_entry(ruby_field_type_strings, i))->ptr;
0
- rb_ary_push(row, typecast(result[i], field_type));
0
+ for (i = 0; i < reader->field_count; i++) {
0
+ // The field_type data could be cached in a c-array
0
+ field_type = RSTRING(rb_ary_entry(ruby_field_type_strings, i))->ptr;
0
+ rb_ary_push(row, typecast(result[i], field_type));
0
-
rb_iv_set(self, "@values", row);
0
+
rb_iv_set(self, "@values", row);
0
static VALUE cReader_values(VALUE self) {
0
- VALUE state = rb_iv_get(self, "@state");
0
- if ( state == Qnil || state == Qfalse ) {
0
- rb_raise(eMysqlError, "Reader is not initialized");
0
- return rb_iv_get(self, "@values");
0
+ VALUE state = rb_iv_get(self, "@state");
0
+ if ( state == Qnil || state == Qfalse ) {
0
+ rb_raise(eMysqlError, "Reader is not initialized");
0
+ return rb_iv_get(self, "@values");
0
static VALUE cReader_fields(VALUE self) {
0
-
return rb_iv_get(self, "@fields");
0
+
return rb_iv_get(self, "@fields");
0
void Init_do_mysql_ext() {
0
- rb_require("rubygems");
0
- rb_require("bigdecimal");
0
+ rb_require("rubygems");
0
+ rb_require("bigdecimal");
0
rb_funcall(rb_mKernel, rb_intern("require"), 1, RUBY_STRING("data_objects"));
0
- ID_TO_I = rb_intern("to_i");
0
- ID_TO_F = rb_intern("to_f");
0
- ID_TO_S = rb_intern("to_s");
0
- ID_PARSE = rb_intern("parse");
0
- ID_TO_TIME = rb_intern("to_time");
0
- ID_NEW = rb_intern("new");
0
- ID_NEW_RATIONAL = rb_intern("new!");
0
- ID_NEW_DATE = RUBY_VERSION_CODE < 186 ? rb_intern("new0") : rb_intern("new!");
0
- ID_CONST_GET = rb_intern("const_get");
0
- ID_UTC = rb_intern("utc");
0
- ID_ESCAPE_SQL = rb_intern("escape_sql");
0
- ID_STRFTIME = rb_intern("strftime");
0
- ID_LOGGER = rb_intern("logger");
0
- ID_DEBUG = rb_intern("debug");
0
- ID_LEVEL = rb_intern("level");
0
- // Store references to a few helpful clases that aren't in Ruby Core
0
- rb_cDate = RUBY_CLASS("Date");
0
- rb_cDateTime = RUBY_CLASS("DateTime");
0
- rb_cRational = RUBY_CLASS("Rational");
0
- rb_cBigDecimal = RUBY_CLASS("BigDecimal");
0
- rb_cCGI = RUBY_CLASS("CGI");
0
- // Get references to the DataObjects module and its classes
0
- mDO = CONST_GET(rb_mKernel, "DataObjects");
0
- cDO_Quoting = CONST_GET(mDO, "Quoting");
0
- cDO_Connection = CONST_GET(mDO, "Connection");
0
- cDO_Command = CONST_GET(mDO, "Command");
0
- cDO_Result = CONST_GET(mDO, "Result");
0
- cDO_Reader = CONST_GET(mDO, "Reader");
0
- // Top Level Module that all the classes live under
0
- mDOMysql = rb_define_module_under(mDO, "Mysql");
0
- eMysqlError = rb_define_class("MysqlError", rb_eStandardError);
0
- cConnection = DRIVER_CLASS("Connection", cDO_Connection);
0
- rb_define_method(cConnection, "initialize", cConnection_initialize, 1);
0
- rb_define_method(cConnection, "using_socket?", cConnection_is_using_socket, 0);
0
- rb_define_method(cConnection, "character_set", cConnection_character_set , 0);
0
- rb_define_method(cConnection, "dispose", cConnection_dispose, 0);
0
- cCommand = DRIVER_CLASS("Command", cDO_Command);
0
- rb_include_module(cCommand, cDO_Quoting);
0
- rb_define_method(cCommand, "set_types", cCommand_set_types, 1);
0
- rb_define_method(cCommand, "execute_non_query", cCommand_execute_non_query, -1);
0
- rb_define_method(cCommand, "execute_reader", cCommand_execute_reader, -1);
0
- rb_define_method(cCommand, "quote_string", cCommand_quote_string, 1);
0
- rb_define_method(cCommand, "quote_date", cCommand_quote_date, 1);
0
- rb_define_method(cCommand, "quote_time", cCommand_quote_time, 1);
0
- rb_define_method(cCommand, "quote_datetime", cCommand_quote_date_time, 1);
0
- cResult = DRIVER_CLASS("Result", cDO_Result);
0
- cReader = DRIVER_CLASS("Reader", cDO_Reader);
0
- rb_define_method(cReader, "close", cReader_close, 0);
0
- rb_define_method(cReader, "next!", cReader_next, 0);
0
- rb_define_method(cReader, "values", cReader_values, 0);
0
- rb_define_method(cReader, "fields", cReader_fields, 0);
0
+ ID_TO_I = rb_intern("to_i");
0
+ ID_TO_F = rb_intern("to_f");
0
+ ID_TO_S = rb_intern("to_s");
0
+ ID_PARSE = rb_intern("parse");
0
+ ID_TO_TIME = rb_intern("to_time");
0
+ ID_NEW = rb_intern("new");
0
+ ID_NEW_RATIONAL = rb_intern("new!");
0
+ ID_NEW_DATE = RUBY_VERSION_CODE < 186 ? rb_intern("new0") : rb_intern("new!");
0
+ ID_CONST_GET = rb_intern("const_get");
0
+ ID_UTC = rb_intern("utc");
0
+ ID_ESCAPE_SQL = rb_intern("escape_sql");
0
+ ID_STRFTIME = rb_intern("strftime");
0
+ ID_LOGGER = rb_intern("logger");
0
+ ID_DEBUG = rb_intern("debug");
0
+ ID_LEVEL = rb_intern("level");
0
+ // Store references to a few helpful clases that aren't in Ruby Core
0
+ rb_cDate = RUBY_CLASS("Date");
0
+ rb_cDateTime = RUBY_CLASS("DateTime");
0
+ rb_cRational = RUBY_CLASS("Rational");
0
+ rb_cBigDecimal = RUBY_CLASS("BigDecimal");
0
+ rb_cCGI = RUBY_CLASS("CGI");
0
+ // Get references to the DataObjects module and its classes
0
+ mDO = CONST_GET(rb_mKernel, "DataObjects");
0
+ cDO_Quoting = CONST_GET(mDO, "Quoting");
0
+ cDO_Connection = CONST_GET(mDO, "Connection");
0
+ cDO_Command = CONST_GET(mDO, "Command");
0
+ cDO_Result = CONST_GET(mDO, "Result");
0
+ cDO_Reader = CONST_GET(mDO, "Reader");
0
+ // Top Level Module that all the classes live under
0
+ mDOMysql = rb_define_module_under(mDO, "Mysql");
0
+ eMysqlError = rb_define_class("MysqlError", rb_eStandardError);
0
+ cConnection = DRIVER_CLASS("Connection", cDO_Connection);
0
+ rb_define_method(cConnection, "initialize", cConnection_initialize, 1);
0
+ rb_define_method(cConnection, "using_socket?", cConnection_is_using_socket, 0);
0
+ rb_define_method(cConnection, "character_set", cConnection_character_set , 0);
0
+ rb_define_method(cConnection, "dispose", cConnection_dispose, 0);
0
+ cCommand = DRIVER_CLASS("Command", cDO_Command);
0
+ rb_include_module(cCommand, cDO_Quoting);
0
+ rb_define_method(cCommand, "set_types", cCommand_set_types, 1);
0
+ rb_define_method(cCommand, "execute_non_query", cCommand_execute_non_query, -1);
0
+ rb_define_method(cCommand, "execute_reader", cCommand_execute_reader, -1);
0
+ rb_define_method(cCommand, "quote_string", cCommand_quote_string, 1);
0
+ rb_define_method(cCommand, "quote_date", cCommand_quote_date, 1);
0
+ rb_define_method(cCommand, "quote_time", cCommand_quote_time, 1);
0
+ rb_define_method(cCommand, "quote_datetime", cCommand_quote_date_time, 1);
0
+ cResult = DRIVER_CLASS("Result", cDO_Result);
0
+ cReader = DRIVER_CLASS("Reader", cDO_Reader);
0
+ rb_define_method(cReader, "close", cReader_close, 0);
0
+ rb_define_method(cReader, "next!", cReader_next, 0);
0
+ rb_define_method(cReader, "values", cReader_values, 0);
0
+ rb_define_method(cReader, "fields", cReader_fields, 0);