2015-11-25 2 views
2

Привет, я недавно обрабатываю 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 
+0

Добро пожаловать в SO. Стоит добавить к вопросу точный текст исключения кодирования (с первой частью трассировки стека). Это может помочь другим увидеть, что ваш диагноз проблемы верен, а также поможет кому-то другому, имеющему аналогичную проблему, и найти сообщение об ошибке в Интернете. Кроме того, контекст вашего кода - где вы добавляете это - вы модифицируете и перекомпилируете расширение gumb-odbc? Gem, в каком методе? –

+0

Спасибо за ваш совет!Я действительно не знаком с этим :) Я уже отредактировал мой вопрос @NeilSlater – Xinjing

ответ

2

Вы можете использовать rb_enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...).

+0

Похоже, что это может помочь, но, пожалуйста, подумайте над добавлением некоторых деталей фона и объяснений, чтобы объяснить, что такое проблема OP и почему это помогает (I думает только одно или два предложения, чтобы сделать этот короткий ответ в параграфе) - информация из или ссылки на https://redmine.ruby-lang.org/issues/5650 и http://rxr.whitequark.org/mri/ source/error.C# 1792 также может помочь –

+0

Вау! Оно работает!!!! Спасибо! Кстати, на всякий случай кто-то другой мог встретить ту же проблему, эта функция еще не была реализована в ruby ​​1.9.3, кажется, что это 2.0, поэтому я просто скопировал ее определение функции в свою собственную программу и работает как шарм. – Xinjing