VALUE string_spec_rb_str_conv_enc(VALUE self, VALUE str, VALUE from, VALUE to) { rb_encoding* from_enc; rb_encoding* to_enc; from_enc = rb_to_encoding(from); if(NIL_P(to)) { to_enc = 0; } else { to_enc = rb_to_encoding(to); } return rb_str_conv_enc(str, from_enc, to_enc); }
VALUE string_spec_rb_str_conv_enc_opts(VALUE self, VALUE str, VALUE from, VALUE to, VALUE ecflags, VALUE ecopts) { rb_encoding* from_enc; rb_encoding* to_enc; from_enc = rb_to_encoding(from); if(NIL_P(to)) { to_enc = 0; } else { to_enc = rb_to_encoding(to); } return rb_str_conv_enc_opts(str, from_enc, to_enc, FIX2INT(ecflags), ecopts); }
static VALUE rb_mysql_client_escape(VALUE self, VALUE str) { MYSQL * client; VALUE newStr; unsigned long newLen, oldLen; Check_Type(str, T_STRING); #ifdef HAVE_RUBY_ENCODING_H rb_encoding *default_internal_enc = rb_default_internal_encoding(); rb_encoding *conn_enc = rb_to_encoding(rb_iv_get(self, "@encoding")); // ensure the string is in the encoding the connection is expecting str = rb_str_export_to_enc(str, conn_enc); #endif oldLen = RSTRING_LEN(str); char escaped[(oldLen*2)+1]; Data_Get_Struct(self, MYSQL, client); REQUIRE_OPEN_DB(client); newLen = mysql_real_escape_string(client, escaped, StringValuePtr(str), RSTRING_LEN(str)); if (newLen == oldLen) { // no need to return a new ruby string if nothing changed return str; } else { newStr = rb_str_new(escaped, newLen); #ifdef HAVE_RUBY_ENCODING_H rb_enc_associate(newStr, conn_enc); if (default_internal_enc) { newStr = rb_str_export_to_enc(newStr, default_internal_enc); } #endif return newStr; } }
void rb_raise_mysql2_stmt_error(mysql_stmt_wrapper *stmt_wrapper) { VALUE e; GET_CLIENT(stmt_wrapper->client); VALUE rb_error_msg = rb_str_new2(mysql_stmt_error(stmt_wrapper->stmt)); VALUE rb_sql_state = rb_tainted_str_new2(mysql_stmt_sqlstate(stmt_wrapper->stmt)); #ifdef HAVE_RUBY_ENCODING_H rb_encoding *conn_enc; conn_enc = rb_to_encoding(wrapper->encoding); rb_encoding *default_internal_enc = rb_default_internal_encoding(); rb_enc_associate(rb_error_msg, conn_enc); rb_enc_associate(rb_sql_state, conn_enc); if (default_internal_enc) { rb_error_msg = rb_str_export_to_enc(rb_error_msg, default_internal_enc); rb_sql_state = rb_str_export_to_enc(rb_sql_state, default_internal_enc); } #endif e = rb_funcall(cMysql2Error, intern_new_with_args, 4, rb_error_msg, LONG2FIX(wrapper->server_version), UINT2NUM(mysql_stmt_errno(stmt_wrapper->stmt)), rb_sql_state); rb_exc_raise(e); }
static VALUE rb_mysql_client_info(VALUE self) { VALUE version, client_info; #ifdef HAVE_RUBY_ENCODING_H rb_encoding *default_internal_enc; rb_encoding *conn_enc; #endif GET_CLIENT(self); version = rb_hash_new(); #ifdef HAVE_RUBY_ENCODING_H default_internal_enc = rb_default_internal_encoding(); conn_enc = rb_to_encoding(wrapper->encoding); #endif rb_hash_aset(version, sym_id, LONG2NUM(mysql_get_client_version())); client_info = rb_str_new2(mysql_get_client_info()); #ifdef HAVE_RUBY_ENCODING_H rb_enc_associate(client_info, conn_enc); if (default_internal_enc) { client_info = rb_str_export_to_enc(client_info, default_internal_enc); } #endif rb_hash_aset(version, sym_version, client_info); return version; }
static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, int symbolize_keys) { VALUE rb_field; GET_RESULT(self); if (wrapper->fields == Qnil) { wrapper->numberOfFields = mysql_num_fields(wrapper->result); wrapper->fields = rb_ary_new2(wrapper->numberOfFields); } rb_field = rb_ary_entry(wrapper->fields, idx); if (rb_field == Qnil) { MYSQL_FIELD *field = NULL; rb_encoding *default_internal_enc = rb_default_internal_encoding(); rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding); field = mysql_fetch_field_direct(wrapper->result, idx); if (symbolize_keys) { rb_field = rb_intern3(field->name, field->name_length, rb_utf8_encoding()); rb_field = ID2SYM(rb_field); } else { rb_field = rb_str_new(field->name, field->name_length); rb_enc_associate(rb_field, conn_enc); if (default_internal_enc) { rb_field = rb_str_export_to_enc(rb_field, default_internal_enc); } } rb_ary_store(wrapper->fields, idx, rb_field); } return rb_field; }
static int enc_set_default_encoding(struct default_encoding *def, VALUE encoding, const char *name) { int overridden = FALSE; if (def->index != -2) /* Already set */ overridden = TRUE; if (NIL_P(encoding)) { def->index = -1; def->enc = 0; st_insert(enc_table.names, (st_data_t)strdup(name), (st_data_t)UNSPECIFIED_ENCODING); } else { def->index = rb_enc_to_index(rb_to_encoding(encoding)); def->enc = 0; enc_alias_internal(name, def->index); } if (def == &default_external) enc_set_filesystem_encoding(); return overridden; }
static VALUE rb_mysql_client_escape(VALUE self, VALUE str) { VALUE newStr; unsigned long newLen, oldLen; GET_CLIENT(self); REQUIRE_OPEN_DB(wrapper); Check_Type(str, T_STRING); #ifdef HAVE_RUBY_ENCODING_H rb_encoding *default_internal_enc = rb_default_internal_encoding(); rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding); // ensure the string is in the encoding the connection is expecting str = rb_str_export_to_enc(str, conn_enc); #endif oldLen = RSTRING_LEN(str); newStr = rb_str_new(0, oldLen*2+1); newLen = mysql_real_escape_string(wrapper->client, RSTRING_PTR(newStr), StringValuePtr(str), oldLen); if (newLen == oldLen) { // no need to return a new ruby string if nothing changed return str; } else { rb_str_resize(newStr, newLen); #ifdef HAVE_RUBY_ENCODING_H rb_enc_associate(newStr, conn_enc); if (default_internal_enc) { newStr = rb_str_export_to_enc(newStr, default_internal_enc); } #endif return newStr; } }
static VALUE rb_mysql_client_server_info(VALUE self) { VALUE version, server_info; #ifdef HAVE_RUBY_ENCODING_H rb_encoding *default_internal_enc; rb_encoding *conn_enc; #endif GET_CLIENT(self); REQUIRE_OPEN_DB(wrapper); #ifdef HAVE_RUBY_ENCODING_H default_internal_enc = rb_default_internal_encoding(); conn_enc = rb_to_encoding(wrapper->encoding); #endif version = rb_hash_new(); rb_hash_aset(version, sym_id, LONG2FIX(mysql_get_server_version(wrapper->client))); server_info = rb_str_new2(mysql_get_server_info(wrapper->client)); #ifdef HAVE_RUBY_ENCODING_H rb_enc_associate(server_info, conn_enc); if (default_internal_enc) { server_info = rb_str_export_to_enc(server_info, default_internal_enc); } #endif rb_hash_aset(version, sym_version, server_info); return version; }
/* * call-seq: * enc.replicate(name) -> encoding * * Returns a replicated encoding of _enc_ whose name is _name_. * The new encoding should have the same byte structure of _enc_. * If _name_ is used by another encoding, raise ArgumentError. * */ static VALUE enc_replicate(VALUE encoding, VALUE name) { return rb_enc_from_encoding_index( rb_enc_replicate(StringValueCStr(name), rb_to_encoding(encoding))); }
static VALUE rb_raise_mysql2_error(mysql_client_wrapper *wrapper) { VALUE rb_error_msg = rb_str_new2(mysql_error(wrapper->client)); VALUE rb_sql_state = rb_tainted_str_new2(mysql_sqlstate(wrapper->client)); VALUE e; #ifdef HAVE_RUBY_ENCODING_H if (wrapper->server_version < 50500) { /* MySQL < 5.5 uses mixed encoding, just call it binary. */ int err_enc = rb_ascii8bit_encindex(); rb_enc_associate_index(rb_error_msg, err_enc); rb_enc_associate_index(rb_sql_state, err_enc); } else { /* MySQL >= 5.5 uses UTF-8 errors internally and converts them to the connection encoding. */ rb_encoding *default_internal_enc = rb_default_internal_encoding(); rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding); rb_enc_associate(rb_error_msg, conn_enc); rb_enc_associate(rb_sql_state, conn_enc); if (default_internal_enc) { rb_error_msg = rb_str_export_to_enc(rb_error_msg, default_internal_enc); rb_sql_state = rb_str_export_to_enc(rb_sql_state, default_internal_enc); } } #endif e = rb_exc_new3(cMysql2Error, rb_error_msg); rb_funcall(e, intern_error_number_eql, 1, UINT2NUM(mysql_errno(wrapper->client))); rb_funcall(e, intern_sql_state_eql, 1, rb_sql_state); rb_exc_raise(e); return Qnil; }
static VALUE setup_plruby_oracle(plruby_context_t *ctx) { ub2 id; char name[OCI_NLS_MAXBUFSZ]; VALUE mPLRubyOracle; VALUE enc; chk(OCIAttrGet(ctx->envhp, OCI_HTYPE_ENV, &id, NULL, OCI_ATTR_ENV_CHARSET_ID, ctx->errhp)); OCINlsCharSetIdToName(ctx->envhp, (text*)name, sizeof(name), id); trace(ctx, 1, "before requre 'plruby_oracle'"); rb_require("plruby_oracle"); trace(ctx, 1, "before eval('PLRubyOracle')"); mPLRubyOracle = rb_eval_string("PLRubyOracle"); trace(ctx, 2, "rb_eval_string(\"PLRubyOracle\") => %p", mPLRubyOracle); trace(ctx, 1, "before PLRubyOracle.init('%s')", name); rb_funcall(mPLRubyOracle, rb_intern("init"), 1, rb_usascii_str_new2(name)); enc = rb_cv_get(mPLRubyOracle, "@@encoding"); trace(ctx, 2, "rb_cv_get(mPLRubyOracle, \"@@encoding\") => %s", StringValueCStr(enc)); oracle_encoding = rb_to_encoding(enc); trace(ctx, 2, "rb_enc_get(enc) => %s", rb_enc_name(oracle_encoding)); return Qnil; }
static void parse_options(VALUE ropts, Options copts) { struct _YesNoOpt ynos[] = { { circular_sym, &copts->circular }, { auto_define_sym, &copts->auto_define }, { symbol_keys_sym, &copts->sym_key }, { ascii_only_sym, &copts->ascii_only }, { Qnil, 0 } }; YesNoOpt o; if (rb_cHash == rb_obj_class(ropts)) { VALUE v; if (Qnil != (v = rb_hash_lookup(ropts, indent_sym))) { if (rb_cFixnum != rb_obj_class(v)) { rb_raise(rb_eArgError, ":indent must be a Fixnum.\n"); } copts->indent = NUM2INT(v); } #ifdef HAVE_RUBY_ENCODING_H if (Qnil != (v = rb_hash_lookup(ropts, encoding_sym))) { if (T_STRING == rb_type(v)) { oj_default_options.encoding = rb_enc_find(StringValuePtr(v)); } else if (rb_cEncoding == rb_obj_class(v)) { oj_default_options.encoding = rb_to_encoding(v); } else { rb_raise(rb_eArgError, ":encoding must be nil, a String, or an Encoding.\n"); } } #endif if (Qnil != (v = rb_hash_lookup(ropts, mode_sym))) { if (object_sym == v) { copts->mode = ObjectMode; } else if (strict_sym == v) { copts->mode = StrictMode; } else if (compat_sym == v) { copts->mode = CompatMode; } else if (null_sym == v) { copts->mode = NullMode; } else { rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, or :null.\n"); } } for (o = ynos; 0 != o->attr; o++) { if (Qnil != (v = rb_hash_lookup(ropts, o->sym))) { if (Qtrue == v) { *o->attr = Yes; } else if (Qfalse == v) { *o->attr = No; } else { rb_raise(rb_eArgError, "%s must be true or false.\n", rb_id2name(SYM2ID(o->sym))); } } } } }
VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql) { mysql_stmt_wrapper *stmt_wrapper; VALUE rb_stmt; #ifdef HAVE_RUBY_ENCODING_H rb_encoding *conn_enc; #endif Check_Type(sql, T_STRING); rb_stmt = Data_Make_Struct(cMysql2Statement, mysql_stmt_wrapper, rb_mysql_stmt_mark, rb_mysql_stmt_free, stmt_wrapper); { stmt_wrapper->client = rb_client; stmt_wrapper->refcount = 1; stmt_wrapper->closed = 0; stmt_wrapper->stmt = NULL; } // instantiate stmt { GET_CLIENT(rb_client); stmt_wrapper->stmt = mysql_stmt_init(wrapper->client); #ifdef HAVE_RUBY_ENCODING_H conn_enc = rb_to_encoding(wrapper->encoding); #endif } if (stmt_wrapper->stmt == NULL) { rb_raise(cMysql2Error, "Unable to initialize prepared statement: out of memory"); } // set STMT_ATTR_UPDATE_MAX_LENGTH attr { my_bool truth = 1; if (mysql_stmt_attr_set(stmt_wrapper->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &truth)) { rb_raise(cMysql2Error, "Unable to initialize prepared statement: set STMT_ATTR_UPDATE_MAX_LENGTH"); } } // call mysql_stmt_prepare w/o gvl { struct nogvl_prepare_statement_args args; args.stmt = stmt_wrapper->stmt; args.sql = sql; #ifdef HAVE_RUBY_ENCODING_H // ensure the string is in the encoding the connection is expecting args.sql = rb_str_export_to_enc(args.sql, conn_enc); #endif args.sql_ptr = RSTRING_PTR(sql); args.sql_len = RSTRING_LEN(sql); if ((VALUE)rb_thread_call_without_gvl(nogvl_prepare_statement, &args, RUBY_UBF_IO, 0) == Qfalse) { rb_raise_mysql2_stmt_error(stmt_wrapper); } } return rb_stmt; }
static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) { struct nogvl_send_query_args args; fd_set fdset; int fd, retval; int async = 0; VALUE opts; VALUE rb_async; MYSQL * client; if (rb_scan_args(argc, argv, "11", &args.sql, &opts) == 2) { if ((rb_async = rb_hash_aref(opts, sym_async)) != Qnil) { async = rb_async == Qtrue ? 1 : 0; } } Check_Type(args.sql, T_STRING); #ifdef HAVE_RUBY_ENCODING_H rb_encoding *conn_enc = rb_to_encoding(rb_iv_get(self, "@encoding")); // ensure the string is in the encoding the connection is expecting args.sql = rb_str_export_to_enc(args.sql, conn_enc); #endif Data_Get_Struct(self, MYSQL, client); REQUIRE_OPEN_DB(client); args.mysql = client; if (rb_thread_blocking_region(nogvl_send_query, &args, RUBY_UBF_IO, 0) == Qfalse) { return rb_raise_mysql2_error(client); } if (!async) { // the below code is largely from do_mysql // http://github.com/datamapper/do fd = client->net.fd; for(;;) { FD_ZERO(&fdset); FD_SET(fd, &fdset); retval = rb_thread_select(fd + 1, &fdset, NULL, NULL, NULL); if (retval < 0) { rb_sys_fail(0); } if (retval > 0) { break; } } return rb_mysql_client_async_result(self); } else { return Qnil; } }
/* call-seq: * client.query(sql, options = {}) * * Query the database with +sql+, with optional +options+. For the possible * options, see default_query_options on the Mysql2::Client class. */ static VALUE rb_query(VALUE self, VALUE sql, VALUE current) { #ifndef _WIN32 struct async_query_args async_args; #endif struct nogvl_send_query_args args; GET_CLIENT(self); REQUIRE_CONNECTED(wrapper); args.mysql = wrapper->client; (void)RB_GC_GUARD(current); Check_Type(current, T_HASH); rb_iv_set(self, "@current_query_options", current); Check_Type(sql, T_STRING); #ifdef HAVE_RUBY_ENCODING_H /* ensure the string is in the encoding the connection is expecting */ args.sql = rb_str_export_to_enc(sql, rb_to_encoding(wrapper->encoding)); #else args.sql = sql; #endif args.sql_ptr = RSTRING_PTR(args.sql); args.sql_len = RSTRING_LEN(args.sql); args.wrapper = wrapper; rb_mysql_client_set_active_thread(self); #ifndef _WIN32 rb_rescue2(do_send_query, (VALUE)&args, disconnect_and_raise, self, rb_eException, (VALUE)0); if (rb_hash_aref(current, sym_async) == Qtrue) { return Qnil; } else { async_args.fd = wrapper->client->net.fd; async_args.self = self; rb_rescue2(do_query, (VALUE)&async_args, disconnect_and_raise, self, rb_eException, (VALUE)0); return rb_mysql_client_async_result(self); } #else do_send_query(&args); /* this will just block until the result is ready */ return rb_ensure(rb_mysql_client_async_result, self, finish_and_mark_inactive, self); #endif }
static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, short int symbolize_keys) { mysql2_result_wrapper * wrapper; VALUE rb_field; GetMysql2Result(self, wrapper); if (wrapper->fields == Qnil) { wrapper->numberOfFields = mysql_num_fields(wrapper->result); wrapper->fields = rb_ary_new2(wrapper->numberOfFields); } rb_field = rb_ary_entry(wrapper->fields, idx); if (rb_field == Qnil) { MYSQL_FIELD *field = NULL; #ifdef HAVE_RUBY_ENCODING_H rb_encoding *default_internal_enc = rb_default_internal_encoding(); rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding); #endif field = mysql_fetch_field_direct(wrapper->result, idx); if (symbolize_keys) { char buf[field->name_length+1]; memcpy(buf, field->name, field->name_length); buf[field->name_length] = 0; #ifdef HAVE_RB_INTERN3 rb_field = rb_intern3(buf, field->name_length, rb_utf8_encoding()); rb_field = ID2SYM(rb_field); #else VALUE colStr; colStr = rb_str_new2(buf); rb_field = ID2SYM(rb_to_id(colStr)); #endif } else { rb_field = rb_str_new(field->name, field->name_length); #ifdef HAVE_RUBY_ENCODING_H rb_enc_associate(rb_field, conn_enc); if (default_internal_enc) { rb_field = rb_str_export_to_enc(rb_field, default_internal_enc); } #endif } rb_ary_store(wrapper->fields, idx, rb_field); } return rb_field; }
/* * call-seq: * blob.text(max_lines = -1, encoding = Encoding.default_external) -> String * * Return up to +max_lines+ of text from a blob as a +String+. * * In Ruby 1.9.x, the string is created with the given +encoding+, * defaulting to Encoding.default_external. * * In previous versions, the +encoding+ argument is dummy and has no * effect on the returned string. * * When limiting the size of the text with +max_lines+, the string is * expected to have an ASCII-compatible encoding, and is checked * for the newline +\n+ character. */ static VALUE rb_git_blob_text_GET(int argc, VALUE *argv, VALUE self) { #ifdef HAVE_RUBY_ENCODING_H rb_encoding *encoding = rb_default_external_encoding(); #endif git_blob *blob; size_t size; const char *content; VALUE rb_max_lines, rb_encoding; Data_Get_Struct(self, git_blob, blob); rb_scan_args(argc, argv, "02", &rb_max_lines, &rb_encoding); content = git_blob_rawcontent(blob); size = git_blob_rawsize(blob); if (!NIL_P(rb_max_lines)) { size_t i = 0; int lines = 0, maxlines; Check_Type(rb_max_lines, T_FIXNUM); maxlines = FIX2INT(rb_max_lines); if (maxlines >= 0) { while (i < size && lines < maxlines) { if (content[i++] == '\n') lines++; } } size = (size_t)i; } #ifdef HAVE_RUBY_ENCODING_H if (!NIL_P(rb_encoding)) { encoding = rb_to_encoding(rb_encoding); } #endif if (size == 0) return rugged_str_new("", 0, encoding); return rugged_str_new(content, size, encoding); }
static VALUE rb_mysql_client_info(RB_MYSQL_UNUSED VALUE self) { VALUE version = rb_hash_new(), client_info; #ifdef HAVE_RUBY_ENCODING_H rb_encoding *default_internal_enc = rb_default_internal_encoding(); rb_encoding *conn_enc = rb_to_encoding(rb_iv_get(self, "@encoding")); #endif rb_hash_aset(version, sym_id, LONG2NUM(mysql_get_client_version())); client_info = rb_str_new2(mysql_get_client_info()); #ifdef HAVE_RUBY_ENCODING_H rb_enc_associate(client_info, conn_enc); if (default_internal_enc) { client_info = rb_str_export_to_enc(client_info, default_internal_enc); } #endif rb_hash_aset(version, sym_version, client_info); return version; }
/* call-seq: * client.escape(string) * * Escape +string+ so that it may be used in a SQL statement. */ static VALUE rb_mysql_client_real_escape(VALUE self, VALUE str) { unsigned char *newStr; VALUE rb_str; unsigned long newLen, oldLen; #ifdef HAVE_RUBY_ENCODING_H rb_encoding *default_internal_enc; rb_encoding *conn_enc; #endif GET_CLIENT(self); REQUIRE_CONNECTED(wrapper); Check_Type(str, T_STRING); #ifdef HAVE_RUBY_ENCODING_H default_internal_enc = rb_default_internal_encoding(); conn_enc = rb_to_encoding(wrapper->encoding); /* ensure the string is in the encoding the connection is expecting */ str = rb_str_export_to_enc(str, conn_enc); #endif oldLen = RSTRING_LEN(str); newStr = xmalloc(oldLen*2+1); newLen = mysql_real_escape_string(wrapper->client, (char *)newStr, RSTRING_PTR(str), oldLen); if (newLen == oldLen) { /* no need to return a new ruby string if nothing changed */ #ifdef HAVE_RUBY_ENCODING_H if (default_internal_enc) { str = rb_str_export_to_enc(str, default_internal_enc); } #endif xfree(newStr); return str; } else { rb_str = rb_str_new((const char*)newStr, newLen); #ifdef HAVE_RUBY_ENCODING_H rb_enc_associate(rb_str, conn_enc); if (default_internal_enc) { rb_str = rb_str_export_to_enc(rb_str, default_internal_enc); } #endif xfree(newStr); return rb_str; } }
/* call-seq: stmt.fields # => array * * Returns a list of fields that will be returned by this statement. */ static VALUE fields(VALUE self) { MYSQL_FIELD *fields; MYSQL_RES *metadata; unsigned int field_count; unsigned int i; VALUE field_list; MYSQL_STMT* stmt; #ifdef HAVE_RUBY_ENCODING_H rb_encoding *default_internal_enc, *conn_enc; #endif GET_STATEMENT(self); stmt = stmt_wrapper->stmt; #ifdef HAVE_RUBY_ENCODING_H default_internal_enc = rb_default_internal_encoding(); { GET_CLIENT(stmt_wrapper->client); conn_enc = rb_to_encoding(wrapper->encoding); } #endif metadata = mysql_stmt_result_metadata(stmt); fields = mysql_fetch_fields(metadata); field_count = mysql_stmt_field_count(stmt); field_list = rb_ary_new2((long)field_count); for(i = 0; i < field_count; i++) { VALUE rb_field; rb_field = rb_str_new(fields[i].name, fields[i].name_length); #ifdef HAVE_RUBY_ENCODING_H rb_enc_associate(rb_field, conn_enc); if (default_internal_enc) { rb_field = rb_str_export_to_enc(rb_field, default_internal_enc); } #endif rb_ary_store(field_list, (long)i, rb_field); } mysql_free_result(metadata); return field_list; }
/* call-seq: SQLite3::Statement.new(db, sql) * * Create a new statement attached to the given Database instance, and which * encapsulates the given SQL text. If the text contains more than one * statement (i.e., separated by semicolons), then the #remainder property * will be set to the trailing text. */ static VALUE initialize(VALUE self, VALUE db, VALUE sql) { sqlite3RubyPtr db_ctx; sqlite3StmtRubyPtr ctx; const char *tail = NULL; int status; StringValue(sql); Data_Get_Struct(db, sqlite3Ruby, db_ctx); Data_Get_Struct(self, sqlite3StmtRuby, ctx); if(!db_ctx->db) rb_raise(rb_eArgError, "prepare called on a closed database"); #ifdef HAVE_RUBY_ENCODING_H if(!UTF8_P(sql)) { VALUE encoding = rb_funcall(db, rb_intern("encoding"), 0); rb_encoding * enc = NIL_P(encoding) ? rb_utf8_encoding() : rb_to_encoding(encoding); sql = rb_str_export_to_enc(sql, enc); } #endif status = sqlite3_prepare_v2( db_ctx->db, (const char *)StringValuePtr(sql), (int)RSTRING_LEN(sql), &ctx->st, &tail ); CHECK(db_ctx->db, status); rb_iv_set(self, "@connection", db); rb_iv_set(self, "@remainder", rb_str_new2(tail)); rb_iv_set(self, "@columns", Qnil); rb_iv_set(self, "@types", Qnil); return self; }
static VALUE rb_raise_mysql2_error(mysql_client_wrapper *wrapper) { VALUE rb_error_msg = rb_str_new2(mysql_error(wrapper->client)); VALUE rb_sql_state = rb_tainted_str_new2(mysql_sqlstate(wrapper->client)); #ifdef HAVE_RUBY_ENCODING_H rb_encoding *default_internal_enc = rb_default_internal_encoding(); rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding); rb_enc_associate(rb_error_msg, conn_enc); rb_enc_associate(rb_sql_state, conn_enc); if (default_internal_enc) { rb_error_msg = rb_str_export_to_enc(rb_error_msg, default_internal_enc); rb_sql_state = rb_str_export_to_enc(rb_sql_state, default_internal_enc); } #endif VALUE e = rb_exc_new3(cMysql2Error, rb_error_msg); rb_funcall(e, intern_error_number_eql, 1, UINT2NUM(mysql_errno(wrapper->client))); rb_funcall(e, intern_sql_state_eql, 1, rb_sql_state); rb_exc_raise(e); return Qnil; }
static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_encoding *default_internal_enc, rb_encoding *conn_enc) { // if binary flag is set, respect it's wishes if (field.flags & BINARY_FLAG && field.charsetnr == 63) { rb_enc_associate(val, binaryEncoding); } else { // lookup the encoding configured on this field VALUE new_encoding = rb_funcall(cMysql2Client, intern_encoding_from_charset_code, 1, INT2NUM(field.charsetnr)); if (new_encoding != Qnil) { // use the field encoding we were able to match rb_encoding *enc = rb_to_encoding(new_encoding); rb_enc_associate(val, enc); } else { // otherwise fall-back to the connection's encoding rb_enc_associate(val, conn_enc); } if (default_internal_enc) { val = rb_str_export_to_enc(val, default_internal_enc); } } return val; }
static VALUE rb_mysql_client_server_info(VALUE self) { MYSQL * client; VALUE version, server_info; #ifdef HAVE_RUBY_ENCODING_H rb_encoding *default_internal_enc = rb_default_internal_encoding(); rb_encoding *conn_enc = rb_to_encoding(rb_iv_get(self, "@encoding")); #endif Data_Get_Struct(self, MYSQL, client); REQUIRE_OPEN_DB(client); version = rb_hash_new(); rb_hash_aset(version, sym_id, LONG2FIX(mysql_get_server_version(client))); server_info = rb_str_new2(mysql_get_server_info(client)); #ifdef HAVE_RUBY_ENCODING_H rb_enc_associate(server_info, conn_enc); if (default_internal_enc) { server_info = rb_str_export_to_enc(server_info, default_internal_enc); } #endif rb_hash_aset(version, sym_version, server_info); return version; }
/* * call-seq: * blob.text(max_lines = -1, encoding = Encoding.default_external) -> string * * Return up to +max_lines+ of text from a blob as a +String+. * If +max_lines+ is less than 0, the full string is returned. * * The string is created with the given +encoding+, defaulting to * Encoding.default_external. * * When limiting the size of the text with +max_lines+, the string is * expected to have an ASCII-compatible encoding, and is checked * for the newline +\n+ character. */ static VALUE rb_git_blob_text_GET(int argc, VALUE *argv, VALUE self) { git_blob *blob; size_t size; const char *content; VALUE rb_max_lines, rb_encoding; Data_Get_Struct(self, git_blob, blob); rb_scan_args(argc, argv, "02", &rb_max_lines, &rb_encoding); content = git_blob_rawcontent(blob); size = git_blob_rawsize(blob); if (!NIL_P(rb_max_lines)) { size_t i = 0; int lines = 0, maxlines; Check_Type(rb_max_lines, T_FIXNUM); maxlines = FIX2INT(rb_max_lines); if (maxlines >= 0) { while (i < size && lines < maxlines) { if (content[i++] == '\n') lines++; } size = (size_t)i; } } if (!NIL_P(rb_encoding)) { return rb_enc_str_new(content, size, rb_to_encoding(rb_encoding)); } return rb_external_str_new(content, size); }
static VALUE mr_enc_set_default_external(VALUE klass, SEL sel, VALUE enc) { default_external = rb_to_encoding(enc); return (VALUE)default_external; }
static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) { #ifndef _WIN32 struct async_query_args async_args; #endif struct nogvl_send_query_args args; int async = 0; VALUE opts, defaults; #ifdef HAVE_RUBY_ENCODING_H rb_encoding *conn_enc; #endif GET_CLIENT(self); REQUIRE_OPEN_DB(wrapper); args.mysql = wrapper->client; defaults = rb_iv_get(self, "@query_options"); if (rb_scan_args(argc, argv, "11", &args.sql, &opts) == 2) { opts = rb_funcall(defaults, intern_merge, 1, opts); rb_iv_set(self, "@query_options", opts); if (rb_hash_aref(opts, sym_async) == Qtrue) { async = 1; } } else { opts = defaults; } Check_Type(args.sql, T_STRING); #ifdef HAVE_RUBY_ENCODING_H conn_enc = rb_to_encoding(wrapper->encoding); // ensure the string is in the encoding the connection is expecting args.sql = rb_str_export_to_enc(args.sql, conn_enc); #endif // see if this connection is still waiting on a result from a previous query if (wrapper->active == 0) { // mark this connection active wrapper->active = 1; } else { rb_raise(cMysql2Error, "This connection is still waiting for a result, try again once you have the result"); } args.wrapper = wrapper; rb_rescue2(do_send_query, (VALUE)&args, disconnect_and_raise, self, rb_eException, (VALUE)0); #ifndef _WIN32 if (!async) { async_args.fd = wrapper->client->net.fd; async_args.self = self; rb_rescue2(do_query, (VALUE)&async_args, disconnect_and_raise, self, rb_eException, (VALUE)0); return rb_mysql_client_async_result(self); } else { return Qnil; } #else // this will just block until the result is ready return rb_ensure(rb_mysql_client_async_result, self, finish_and_mark_inactive, self); #endif }
static VALUE rb_mysql_result_fetch_row_stmt(VALUE self, MYSQL_FIELD * fields, const result_each_args *args) { VALUE rowVal; unsigned int i = 0; #ifdef HAVE_RUBY_ENCODING_H rb_encoding *default_internal_enc; rb_encoding *conn_enc; #endif GET_RESULT(self); #ifdef HAVE_RUBY_ENCODING_H default_internal_enc = rb_default_internal_encoding(); conn_enc = rb_to_encoding(wrapper->encoding); #endif if (args->asArray) { rowVal = rb_ary_new2(wrapper->numberOfFields); } else { rowVal = rb_hash_new(); } if (wrapper->fields == Qnil) { wrapper->numberOfFields = mysql_num_fields(wrapper->result); wrapper->fields = rb_ary_new2(wrapper->numberOfFields); } if (wrapper->result_buffers == NULL) { rb_mysql_result_alloc_result_buffers(self, fields); } if (mysql_stmt_bind_result(wrapper->stmt_wrapper->stmt, wrapper->result_buffers)) { rb_raise_mysql2_stmt_error(wrapper->stmt_wrapper); } { switch((uintptr_t)rb_thread_call_without_gvl(nogvl_stmt_fetch, wrapper->stmt_wrapper->stmt, RUBY_UBF_IO, 0)) { case 0: /* success */ break; case 1: /* error */ rb_raise_mysql2_stmt_error(wrapper->stmt_wrapper); case MYSQL_NO_DATA: /* no more row */ return Qnil; case MYSQL_DATA_TRUNCATED: rb_raise(cMysql2Error, "IMPLBUG: caught MYSQL_DATA_TRUNCATED. should not come here as buffer_length is set to fields[i].max_length."); } } for (i = 0; i < wrapper->numberOfFields; i++) { VALUE field = rb_mysql_result_fetch_field(self, i, args->symbolizeKeys); VALUE val = Qnil; MYSQL_TIME *ts; if (wrapper->is_null[i]) { val = Qnil; } else { const MYSQL_BIND* const result_buffer = &wrapper->result_buffers[i]; switch(result_buffer->buffer_type) { case MYSQL_TYPE_TINY: // signed char if (args->castBool && fields[i].length == 1) { val = (*((unsigned char*)result_buffer->buffer) != 0) ? Qtrue : Qfalse; break; } if (result_buffer->is_unsigned) { val = UINT2NUM(*((unsigned char*)result_buffer->buffer)); } else { val = INT2NUM(*((signed char*)result_buffer->buffer)); } break; case MYSQL_TYPE_SHORT: // short int if (result_buffer->is_unsigned) { val = UINT2NUM(*((unsigned short int*)result_buffer->buffer)); } else { val = INT2NUM(*((short int*)result_buffer->buffer)); } break; case MYSQL_TYPE_INT24: // int case MYSQL_TYPE_LONG: // int case MYSQL_TYPE_YEAR: // int if (result_buffer->is_unsigned) { val = UINT2NUM(*((unsigned int*)result_buffer->buffer)); } else { val = INT2NUM(*((int*)result_buffer->buffer)); } break; case MYSQL_TYPE_LONGLONG: // long long int if (result_buffer->is_unsigned) { val = ULL2NUM(*((unsigned long long int*)result_buffer->buffer)); } else { val = LL2NUM(*((long long int*)result_buffer->buffer)); } break; case MYSQL_TYPE_FLOAT: // float val = rb_float_new((double)(*((float*)result_buffer->buffer))); break; case MYSQL_TYPE_DOUBLE: // double val = rb_float_new((double)(*((double*)result_buffer->buffer))); break; case MYSQL_TYPE_DATE: // MYSQL_TIME case MYSQL_TYPE_NEWDATE: // MYSQL_TIME ts = (MYSQL_TIME*)result_buffer->buffer; val = rb_funcall(cDate, intern_new, 3, INT2NUM(ts->year), INT2NUM(ts->month), INT2NUM(ts->day)); break; case MYSQL_TYPE_TIME: // MYSQL_TIME ts = (MYSQL_TIME*)result_buffer->buffer; val = rb_funcall(rb_cTime, args->db_timezone, 7, opt_time_year, opt_time_month, opt_time_month, UINT2NUM(ts->hour), UINT2NUM(ts->minute), UINT2NUM(ts->second), ULONG2NUM(ts->second_part)); if (!NIL_P(args->app_timezone)) { if (args->app_timezone == intern_local) { val = rb_funcall(val, intern_localtime, 0); } else { // utc val = rb_funcall(val, intern_utc, 0); } } break; case MYSQL_TYPE_DATETIME: // MYSQL_TIME case MYSQL_TYPE_TIMESTAMP: { // MYSQL_TIME uint64_t seconds; ts = (MYSQL_TIME*)result_buffer->buffer; seconds = (ts->year*31557600ULL) + (ts->month*2592000ULL) + (ts->day*86400ULL) + (ts->hour*3600ULL) + (ts->minute*60ULL) + ts->second; if (seconds < MYSQL2_MIN_TIME || seconds > MYSQL2_MAX_TIME) { // use DateTime instead VALUE offset = INT2NUM(0); if (args->db_timezone == intern_local) { offset = rb_funcall(cMysql2Client, intern_local_offset, 0); } val = rb_funcall(cDateTime, intern_civil, 7, UINT2NUM(ts->year), UINT2NUM(ts->month), UINT2NUM(ts->day), UINT2NUM(ts->hour), UINT2NUM(ts->minute), UINT2NUM(ts->second), offset); if (!NIL_P(args->app_timezone)) { if (args->app_timezone == intern_local) { offset = rb_funcall(cMysql2Client, intern_local_offset, 0); val = rb_funcall(val, intern_new_offset, 1, offset); } else { // utc val = rb_funcall(val, intern_new_offset, 1, opt_utc_offset); } } } else { val = rb_funcall(rb_cTime, args->db_timezone, 7, UINT2NUM(ts->year), UINT2NUM(ts->month), UINT2NUM(ts->day), UINT2NUM(ts->hour), UINT2NUM(ts->minute), UINT2NUM(ts->second), ULONG2NUM(ts->second_part)); if (!NIL_P(args->app_timezone)) { if (args->app_timezone == intern_local) { val = rb_funcall(val, intern_localtime, 0); } else { // utc val = rb_funcall(val, intern_utc, 0); } } } break; } case MYSQL_TYPE_DECIMAL: // char[] case MYSQL_TYPE_NEWDECIMAL: // char[] val = rb_funcall(cBigDecimal, intern_new, 1, rb_str_new(result_buffer->buffer, *(result_buffer->length))); break; case MYSQL_TYPE_STRING: // char[] case MYSQL_TYPE_VAR_STRING: // char[] case MYSQL_TYPE_VARCHAR: // char[] case MYSQL_TYPE_TINY_BLOB: // char[] case MYSQL_TYPE_BLOB: // char[] case MYSQL_TYPE_MEDIUM_BLOB: // char[] case MYSQL_TYPE_LONG_BLOB: // char[] case MYSQL_TYPE_BIT: // char[] case MYSQL_TYPE_SET: // char[] case MYSQL_TYPE_ENUM: // char[] case MYSQL_TYPE_GEOMETRY: // char[] default: val = rb_str_new(result_buffer->buffer, *(result_buffer->length)); #ifdef HAVE_RUBY_ENCODING_H val = mysql2_set_field_string_encoding(val, fields[i], default_internal_enc, conn_enc); #endif break; } } if (args->asArray) { rb_ary_push(rowVal, val); } else { rb_hash_aset(rowVal, field, val); } } return rowVal; }
static VALUE rb_mysql_result_fetch_row(VALUE self, MYSQL_FIELD * fields, const result_each_args *args) { VALUE rowVal; MYSQL_ROW row; unsigned int i = 0; unsigned long * fieldLengths; void * ptr; #ifdef HAVE_RUBY_ENCODING_H rb_encoding *default_internal_enc; rb_encoding *conn_enc; #endif GET_RESULT(self); #ifdef HAVE_RUBY_ENCODING_H default_internal_enc = rb_default_internal_encoding(); conn_enc = rb_to_encoding(wrapper->encoding); #endif ptr = wrapper->result; row = (MYSQL_ROW)rb_thread_call_without_gvl(nogvl_fetch_row, ptr, RUBY_UBF_IO, 0); if (row == NULL) { return Qnil; } if (args->asArray) { rowVal = rb_ary_new2(wrapper->numberOfFields); } else { rowVal = rb_hash_new(); } fieldLengths = mysql_fetch_lengths(wrapper->result); if (wrapper->fields == Qnil) { wrapper->numberOfFields = mysql_num_fields(wrapper->result); wrapper->fields = rb_ary_new2(wrapper->numberOfFields); } for (i = 0; i < wrapper->numberOfFields; i++) { VALUE field = rb_mysql_result_fetch_field(self, i, args->symbolizeKeys); if (row[i]) { VALUE val = Qnil; enum enum_field_types type = fields[i].type; if (!args->cast) { if (type == MYSQL_TYPE_NULL) { val = Qnil; } else { val = rb_str_new(row[i], fieldLengths[i]); #ifdef HAVE_RUBY_ENCODING_H val = mysql2_set_field_string_encoding(val, fields[i], default_internal_enc, conn_enc); #endif } } else { switch(type) { case MYSQL_TYPE_NULL: /* NULL-type field */ val = Qnil; break; case MYSQL_TYPE_BIT: /* BIT field (MySQL 5.0.3 and up) */ if (args->castBool && fields[i].length == 1) { val = *row[i] == 1 ? Qtrue : Qfalse; }else{ val = rb_str_new(row[i], fieldLengths[i]); } break; case MYSQL_TYPE_TINY: /* TINYINT field */ if (args->castBool && fields[i].length == 1) { val = *row[i] != '0' ? Qtrue : Qfalse; break; } case MYSQL_TYPE_SHORT: /* SMALLINT field */ case MYSQL_TYPE_LONG: /* INTEGER field */ case MYSQL_TYPE_INT24: /* MEDIUMINT field */ case MYSQL_TYPE_LONGLONG: /* BIGINT field */ case MYSQL_TYPE_YEAR: /* YEAR field */ val = rb_cstr2inum(row[i], 10); break; case MYSQL_TYPE_DECIMAL: /* DECIMAL or NUMERIC field */ case MYSQL_TYPE_NEWDECIMAL: /* Precision math DECIMAL or NUMERIC field (MySQL 5.0.3 and up) */ if (fields[i].decimals == 0) { val = rb_cstr2inum(row[i], 10); } else if (strtod(row[i], NULL) == 0.000000){ val = rb_funcall(cBigDecimal, intern_new, 1, opt_decimal_zero); }else{ val = rb_funcall(cBigDecimal, intern_new, 1, rb_str_new(row[i], fieldLengths[i])); } break; case MYSQL_TYPE_FLOAT: /* FLOAT field */ case MYSQL_TYPE_DOUBLE: { /* DOUBLE or REAL field */ double column_to_double; column_to_double = strtod(row[i], NULL); if (column_to_double == 0.000000){ val = opt_float_zero; }else{ val = rb_float_new(column_to_double); } break; } case MYSQL_TYPE_TIME: { /* TIME field */ int tokens; unsigned int hour=0, min=0, sec=0, msec=0; char msec_char[7] = {'0','0','0','0','0','0','\0'}; tokens = sscanf(row[i], "%2u:%2u:%2u.%6s", &hour, &min, &sec, msec_char); if (tokens < 3) { val = Qnil; break; } msec = msec_char_to_uint(msec_char, sizeof(msec_char)); val = rb_funcall(rb_cTime, args->db_timezone, 7, opt_time_year, opt_time_month, opt_time_month, UINT2NUM(hour), UINT2NUM(min), UINT2NUM(sec), UINT2NUM(msec)); if (!NIL_P(args->app_timezone)) { if (args->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 */ case MYSQL_TYPE_DATETIME: { /* DATETIME field */ int tokens; unsigned int year=0, month=0, day=0, hour=0, min=0, sec=0, msec=0; char msec_char[7] = {'0','0','0','0','0','0','\0'}; uint64_t seconds; tokens = sscanf(row[i], "%4u-%2u-%2u %2u:%2u:%2u.%6s", &year, &month, &day, &hour, &min, &sec, msec_char); if (tokens < 6) { /* msec might be empty */ val = Qnil; break; } seconds = (year*31557600ULL) + (month*2592000ULL) + (day*86400ULL) + (hour*3600ULL) + (min*60ULL) + sec; if (seconds == 0) { val = Qnil; } else { if (month < 1 || day < 1) { rb_raise(cMysql2Error, "Invalid date in field '%.*s': %s", fields[i].name_length, fields[i].name, row[i]); val = Qnil; } else { if (seconds < MYSQL2_MIN_TIME || seconds > MYSQL2_MAX_TIME) { /* use DateTime for larger date range, does not support microseconds */ VALUE offset = INT2NUM(0); if (args->db_timezone == intern_local) { offset = rb_funcall(cMysql2Client, intern_local_offset, 0); } val = rb_funcall(cDateTime, intern_civil, 7, UINT2NUM(year), UINT2NUM(month), UINT2NUM(day), UINT2NUM(hour), UINT2NUM(min), UINT2NUM(sec), offset); if (!NIL_P(args->app_timezone)) { if (args->app_timezone == intern_local) { offset = rb_funcall(cMysql2Client, intern_local_offset, 0); val = rb_funcall(val, intern_new_offset, 1, offset); } else { /* utc */ val = rb_funcall(val, intern_new_offset, 1, opt_utc_offset); } } } else { msec = msec_char_to_uint(msec_char, sizeof(msec_char)); val = rb_funcall(rb_cTime, args->db_timezone, 7, UINT2NUM(year), UINT2NUM(month), UINT2NUM(day), UINT2NUM(hour), UINT2NUM(min), UINT2NUM(sec), UINT2NUM(msec)); if (!NIL_P(args->app_timezone)) { if (args->app_timezone == intern_local) { val = rb_funcall(val, intern_localtime, 0); } else { /* utc */ val = rb_funcall(val, intern_utc, 0); } } } } } break; } case MYSQL_TYPE_DATE: /* DATE field */ case MYSQL_TYPE_NEWDATE: { /* Newer const used > 5.0 */ int tokens; unsigned int year=0, month=0, day=0; tokens = sscanf(row[i], "%4u-%2u-%2u", &year, &month, &day); if (tokens < 3) { val = Qnil; break; } if (year+month+day == 0) { val = Qnil; } else { if (month < 1 || day < 1) { rb_raise(cMysql2Error, "Invalid date in field '%.*s': %s", fields[i].name_length, fields[i].name, row[i]); val = Qnil; } else { val = rb_funcall(cDate, intern_new, 3, UINT2NUM(year), UINT2NUM(month), UINT2NUM(day)); } } break; } case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_VARCHAR: case MYSQL_TYPE_STRING: /* CHAR or BINARY field */ case MYSQL_TYPE_SET: /* SET field */ case MYSQL_TYPE_ENUM: /* ENUM field */ case MYSQL_TYPE_GEOMETRY: /* Spatial fielda */ default: val = rb_str_new(row[i], fieldLengths[i]); #ifdef HAVE_RUBY_ENCODING_H val = mysql2_set_field_string_encoding(val, fields[i], default_internal_enc, conn_enc); #endif break; } } if (args->asArray) { rb_ary_push(rowVal, val); } else { rb_hash_aset(rowVal, field, val); } } else { if (args->asArray) { rb_ary_push(rowVal, Qnil); } else { rb_hash_aset(rowVal, field, Qnil); } } } return rowVal; }