Привет, я недавно обрабатываю ruby-odbc.Кодировка сообщения исключения расширения расширения Ruby C
Существует исключение, вызванное ruby-odbc в соответствии с моей логикой, и Active Record lib должен его поймать. Но кодировка сообщения этого исключения представляет собой ASCII-8BIT, что приведет к возникновению другого несовместимого с кодировкой исключения. Я не хочу сейчас изменять Active Record или использовать tiny_tds вместо этого (пока).
Так что я задавался вопросом, есть ли способ изменить кодировку сообщения исключения для данной кодировки?
Я попытался преобразовать сообщение об ошибке перед тем, как перейти к rb_raise, и это не сработало. В результате все равно ASCII-8BIT. Так что я делаю что-то глупое из-за того, что из-за расширения ruby c возникает аниверс, все ASCII-8BIT или я ошибался во время конверсии? Любые мысли?
================== Добавить весь фон на основе cloudvolumes/рубинового-ODBC, в основном, в этой функции:
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) происходят из репо: https://github.com/cloudvolumes/ruby-odbc.
Сценарий рубин, который сгенерирует исключение, как показано ниже:
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 ниже, поскольку рельсы установлены 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
Добро пожаловать в SO. Стоит добавить к вопросу точный текст исключения кодирования (с первой частью трассировки стека). Это может помочь другим увидеть, что ваш диагноз проблемы верен, а также поможет кому-то другому, имеющему аналогичную проблему, и найти сообщение об ошибке в Интернете. Кроме того, контекст вашего кода - где вы добавляете это - вы модифицируете и перекомпилируете расширение gumb-odbc? Gem, в каком методе? –
Спасибо за ваш совет!Я действительно не знаком с этим :) Я уже отредактировал мой вопрос @NeilSlater – Xinjing