/* * Common typecasting logic that can be used or overriden by Adapters. */ extern VALUE data_objects_typecast(const char *value, long length, const VALUE type, int encoding) { #ifdef HAVE_RUBY_ENCODING_H rb_encoding *internal_encoding = rb_default_internal_encoding(); #else void *internal_encoding = NULL; #endif if (type == rb_cInteger) { return rb_cstr2inum(value, 10); } else if (type == rb_cString) { return DATA_OBJECTS_STR_NEW(value, length, encoding, internal_encoding); } else if (type == rb_cFloat) { return rb_float_new(rb_cstr_to_dbl(value, Qfalse)); } else if (type == rb_cBigDecimal) { return rb_funcall(rb_cBigDecimal, DO_ID_NEW, 1, rb_str_new(value, length)); } else if (type == rb_cDate) { return data_objects_parse_date(value); } else if (type == rb_cDateTime) { return data_objects_parse_date_time(value); } else if (type == rb_cTime) { return data_objects_parse_time(value); } else if (type == rb_cTrueClass) { return (!value || strcmp("0", value) == 0) ? Qfalse : Qtrue; } else if (type == rb_cByteArray) { return rb_funcall(rb_cByteArray, DO_ID_NEW, 1, rb_str_new(value, length)); } else if (type == rb_cClass) { return rb_funcall(mDO, rb_intern("full_const_get"), 1, rb_str_new(value, length)); } else if (type == rb_cNilClass) { return Qnil; } else { return DATA_OBJECTS_STR_NEW(value, length, encoding, internal_encoding); } }
VALUE do_postgres_cConnection_quote_string(VALUE self, VALUE string) { PGconn *db = DATA_PTR(rb_iv_get(self, "@connection")); const char *source = rb_str_ptr_readonly(string); int error = 0; long source_len = rb_str_len(string); long buffer_len = source_len * 2 + 3; // Overflow check if(buffer_len <= source_len) { rb_raise(rb_eArgError, "Input string is too large to be safely quoted"); } char *escaped; // Allocate space for the escaped version of 'string' // http://www.postgresql.org/docs/8.3/static/libpq-exec.html#LIBPQ-EXEC-ESCAPE-STRING if (!(escaped = calloc(buffer_len, sizeof(char)))) { rb_memerror(); } long quoted_length; VALUE result; // Escape 'source' using the current charset in use on the conection 'db' quoted_length = PQescapeStringConn(db, escaped + 1, source, source_len, &error); if(error) { rb_raise(eDO_DataError, "%s", PQerrorMessage(db)); } // Wrap the escaped string in single-quotes, this is DO's convention escaped[0] = escaped[quoted_length + 1] = '\''; result = DATA_OBJECTS_STR_NEW(escaped, quoted_length + 2, FIX2INT(rb_iv_get(self, "@encoding_id")), NULL); free(escaped); return result; }
VALUE do_mysql_cConnection_quote_string(VALUE self, VALUE string) { MYSQL *db = DATA_PTR(rb_iv_get(self, "@connection")); const char *source = rb_str_ptr_readonly(string); long source_len = rb_str_len(string); long buffer_len = source_len * 2 + 3; // Overflow check if(buffer_len <= source_len) { rb_raise(rb_eArgError, "Input string is too large to be safely quoted"); } // Allocate space for the escaped version of 'string'. Use + 3 allocate space for null term. // and the leading and trailing single-quotes. // Thanks to http://www.browardphp.com/mysql_manual_en/manual_MySQL_APIs.html#mysql_real_escape_string char *escaped = calloc(buffer_len, sizeof(char)); if (!escaped) { rb_memerror(); } unsigned long quoted_length; VALUE result; // Escape 'source' using the current encoding in use on the conection 'db' quoted_length = mysql_real_escape_string(db, escaped + 1, source, source_len); // Wrap the escaped string in single-quotes, this is DO's convention escaped[0] = escaped[quoted_length + 1] = '\''; // We don't want to use the internal encoding, because this needs // to go into the database in the connection encoding result = DATA_OBJECTS_STR_NEW(escaped, quoted_length + 2, FIX2INT(rb_iv_get(self, "@encoding_id")), NULL); free(escaped); return result; }
VALUE do_sqlite3_typecast(sqlite3_stmt *stmt, int i, VALUE type, int encoding) { int original_type = sqlite3_column_type(stmt, i); int length = sqlite3_column_bytes(stmt, i); if (original_type == SQLITE_NULL) { return Qnil; } #ifdef HAVE_RUBY_ENCODING_H rb_encoding *internal_encoding = rb_default_internal_encoding(); #else void *internal_encoding = NULL; #endif if (type == Qnil) { switch (original_type) { case SQLITE_INTEGER: type = rb_cInteger; break; case SQLITE_FLOAT: type = rb_cFloat; break; case SQLITE_BLOB: type = rb_cByteArray; break; default: type = rb_cString; break; } } if (type == rb_cInteger) { return LL2NUM(sqlite3_column_int64(stmt, i)); } else if (type == rb_cString) { return DATA_OBJECTS_STR_NEW((char*)sqlite3_column_text(stmt, i), length, encoding, internal_encoding); } else if (type == rb_cFloat) { return rb_float_new(sqlite3_column_double(stmt, i)); } else if (type == rb_cBigDecimal) { return rb_funcall(rb_cBigDecimal, ID_NEW, 1, rb_str_new((char*)sqlite3_column_text(stmt, i), length)); } else if (type == rb_cDate) { return data_objects_parse_date((char*)sqlite3_column_text(stmt, i)); } else if (type == rb_cDateTime) { return data_objects_parse_date_time((char*)sqlite3_column_text(stmt, i)); } else if (type == rb_cTime) { return data_objects_parse_time((char*)sqlite3_column_text(stmt, i)); } else if (type == rb_cTrueClass) { return strcmp((char*)sqlite3_column_text(stmt, i), "t") == 0 ? Qtrue : Qfalse; } else if (type == rb_cByteArray) { return rb_funcall(rb_cByteArray, ID_NEW, 1, rb_str_new((char*)sqlite3_column_blob(stmt, i), length)); } else if (type == rb_cClass) { return rb_funcall(mDO, rb_intern("full_const_get"), 1, rb_str_new((char*)sqlite3_column_text(stmt, i), length)); } else if (type == rb_cNilClass) { return Qnil; } else { return DATA_OBJECTS_STR_NEW((char*)sqlite3_column_text(stmt, i), length, encoding, internal_encoding); } }