您好我最近使用ruby-odbc处理。
根据我的逻辑,ruby-odbc引发了异常,Active Record lib应该抓住它。但是这个异常消息的编码是ASCII-8BIT,这将引发另一个编码不兼容的异常。我现在不想修改Active Record或者改用tiny_tds(现在)。
所以我想知道是否有办法可以将异常消息的编码更改为给定的编码?
我尝试在传递给rb_raise之前转换错误消息,但它不起作用。结果仍然是ASCII-8BIT。 所以我做了一些愚蠢的事情导致anystring来自ruby c扩展是所有ASCII-8BIT还是我在转换期间犯了错误? 有什么想法吗?
=================追加整个背景=============== 我修改并重新编译了基于cloudvolumes / ruby-odbc的odbc.c文件,主要是在这个函数中:
static VALUE stmt_prep_int(int argc, VALUE *argv, VALUE self, int mode)
对于以下所有句子:
rb_raise(Cerror, "%s",msg);
我换成了:
rb_odbc_raise_error(Cerror, msg);
这个新功能定义为:
static VALUE rb_odbc_raise_error(VALUE err,char * msg){
VALUE e;
VALUE vmsg = rb_str_new2(msg);
#ifdef USE_RB_ENC
rb_enc_associate_index(vmsg,rb_enc );
msg = rb_string_value_cstr(&vmsg);
#endif
e = rb_exc_new2(err,msg);
rb_exc_raise(e);
return Qnil;
}
注意,USE_RB_ENC和rb_enc(utf8)的定义来自repo:https://github.com/cloudvolumes/ruby-odbc。
将引发异常的ruby脚本如下所示:
begin
cfg = ActiveRecord::Base.connection_config
if cfg && cfg[:adapter] == "sqlserver"
ActiveRecord::Base.connection_pool.with_connection do |connection|
domain_name = ENV['USERDOMAIN']
computer_name = "#{ENV['COMPUTERNAME']}中文$"
name = "#{domain_name}\\#{computer_name}"
puts "Granting database access to #{name.encode(Encoding.locale_charmap)}"
connection.execute("CREATE LOGIN [#{name}] FROM WINDOWS")
end
else
puts "Database is not configured or is not SQL Server"
end
rescue Interrupt
raise
rescue Exception => e
#do something.
end
此脚本应引发
的例外"42000 (15401) [Microsoft][ODBC SQL Server Driver][SQL Server]Windows NT user or group 'ZHUO\APPMANAGERDEV中文$' not found. Check the name again.".
但是,当下面的 activerecord-3.2.21 / lib / active_record / connection_adapters / abstract_adater.rb 捕获到异常时,由于rails设置为utf-8且e.message具有编码ASCII-8BIT,会有一个提示:
" Exception Encoding::CompatibilityError: incompatible character encodings: ASCII-8BIT and UTF-8".
因此根本看不到原始错误消息。
def log(sql, name = "SQL", binds = [])
@instrumenter.instrument(
"sql.active_record",
:sql => sql,
:name => name,
:connection_id => object_id,
:binds => binds) { yield }
rescue Exception => e
message = "#{e.class.name}: #{e.message}: #{sql}"
@logger.debug message if @logger
exception = translate_exception(e, message)
exception.set_backtrace e.backtrace
raise exception
end
答案 0 :(得分:2)
您可以使用rb_enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
。