Использование переменных связывания оракула с select_all в Rails - PullRequest
0 голосов
/ 10 мая 2018

Я пытаюсь воспользоваться преимуществами переменных связывания в Ruby on Rails, и для этого не нужно создавать экземпляр модели, поэтому я использую select_all вот так

ActiveRecord::Base.connection.select_all(
  'select * from users where id = :test', 
  {test: 'foo'}
)

Но я получаю эту большую старую ошибку:

ActiveRecord::StatementInvalid: OCIError: ORA-01008: not all variables bound: select * from users where id = :test
    from stmt.c:243:in oci8lib_220.so
    from /usr/local/rvm/gems/ruby-2.2.2/gems/ruby-oci8-2.2.4.1/lib/oci8/cursor.rb:127:in `exec'
    from /usr/local/rvm/gems/ruby-2.2.2/gems/activerecord-oracle_enhanced-adapter-1.4.3.61/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb:149:in `exec'
    from /usr/local/rvm/gems/ruby-2.2.2/gems/activerecord-oracle_enhanced-adapter-1.4.3.61/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb:696:in `block in exec_query'
    from /usr/local/rvm/gems/ruby-2.2.2/gems/activerecord-3.2.22.5/lib/active_record/connection_adapters/abstract_adapter.rb:280:in `block in log'
    from /usr/local/rvm/gems/ruby-2.2.2/gems/activesupport-3.2.22.5/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
    from /usr/local/rvm/gems/ruby-2.2.2/gems/activerecord-3.2.22.5/lib/active_record/connection_adapters/abstract_adapter.rb:275:in `log'
    from /usr/local/rvm/gems/ruby-2.2.2/gems/activerecord-oracle_enhanced-adapter-1.4.3.61/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb:1505:in `log'
    from /usr/local/rvm/gems/ruby-2.2.2/gems/activerecord-oracle_enhanced-adapter-1.4.3.61/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb:676:in `exec_query'
    from /usr/local/rvm/gems/ruby-2.2.2/gems/activerecord-oracle_enhanced-adapter-1.4.3.61/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb:1457:in `select'
    from /usr/local/rvm/gems/ruby-2.2.2/gems/activerecord-3.2.22.5/lib/active_record/connection_adapters/abstract/database_statements.rb:18:in `select_all'
    from /usr/local/rvm/gems/ruby-2.2.2/gems/activerecord-3.2.22.5/lib/active_record/connection_adapters/abstract/query_cache.rb:63:in `select_all'

Копаясь в коде ActiveRecord, кажется, что идет к этому методу:

def select_all(arel, name = nil, binds = [])
  select(to_sql(arel, binds), name, binds)
end

Это говорит о том, что мой binds хеш идет к аргументу name, но это меня озадачивает:

  • Что ожидается в аргументе name?
  • Похоже, binds ожидается массивом.

Как я могу использовать этот метод для использования преимуществ переменных связывания Oracle?


Редактировать: Было предложено установить name на nil и выразить мои привязки в виде массива массивов:

ActiveRecord::Base.connection.select_all(
  'select * from users where id = :test', 
  nil, 
  {test: 'foo'}.to_a
)

Я вижу эту ошибку в ответ

Could not log "sql.active_record" event. NoMethodError: undefined method `name' for :test:Symbol
ActiveRecord::StatementInvalid: NoMethodError: undefined method `type' for :test:Symbol: select * from users where id = :test

1 Ответ

0 голосов
/ 10 мая 2018

Синтаксис может быть немного странным, я думаю, name - это явное имя для подготовленного оператора, которое вы можете оставить равным nil.Массив тоже немного странный, но он допускает «неназванные» переменные связывания.

Таким образом, ваше утверждение должно выглядеть следующим образом:

ActiveRecord::Base.connection.select_all(
  'select * from users where id = :test', 
  nil, 
  {test: 'foo'}.to_a
)

В качестве альтернативы, поскольку вы используете оракул, вы также можете напрямую использовать гем ruby-oci8 (вместо обычной оболочки activerecord):см. документацию bind_param , где ActiveRecord::Base.connection.raw_connection - это соединение ruby-oci8.Не совсем уверен, если бы я посоветовал сделать это, но я хотел быть полным, и в некоторых случаях полезно, если вы можете использовать некоторые функции напрямую.

...