Skip to content

WIP - Rails 7.2 bind issue #2422

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 9 commits into from
Closed

Conversation

andynu
Copy link
Contributor

@andynu andynu commented Jan 22, 2025

Hello. I've started out trying to update the library to use rails 7.2. I started by moving the rails pin forward to the beginning of the rails 7.2 branch ( rails 8c43b9614eab4d905894d2dd18eda061ef4c4755). I made some progress then have gotten stumped at this error:

  2) OracleEnhancedAdapter context index on single table should create single VARCHAR2 column index
     Failure/Error: @raw_cursor.bind_param(position, value)

     ActiveRecord::StatementInvalid:
       OCIError: ORA-01036: illegal variable name/number
     # stmt.c:218:in oci8lib_330.so
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/bundler/gems/ruby-oci8-725efd697f95/lib/oci8/cursor.rb:105:in `bind_param'
     # ./lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb:142:in `bind_param'
     # ./lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb:124:in `block in bind_params'
     # ./lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb:120:in `each'
     # ./lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb:120:in `bind_params'
     # ./lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb:37:in `block (2 levels) in exec_query'
     # ./lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb:287:in `block in with_retry'
     # ./lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb:443:in `with_retry'
     # ./lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb:105:in `with_retry'
     # ./lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb:286:in `with_retry'
     # ./lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb:27:in `block in exec_query'
     # /home/andy/src/rails/activesupport/lib/active_support/notifications/instrumenter.rb:58:in `instrument'
     # ./lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb:35:in `log'
     # ./lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb:23:in `exec_query'
     # /home/andy/src/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:647:in `select'
     # /home/andy/src/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:73:in `select_all'
     # /home/andy/src/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:222:in `select_all'
     # /home/andy/src/rails/activerecord/lib/active_record/querying.rb:70:in `_query_by_sql'
     # /home/andy/src/rails/activerecord/lib/active_record/relation.rb:1431:in `block (2 levels) in exec_main_query'
     # /home/andy/src/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:393:in `with_connection'
     # /home/andy/src/rails/activerecord/lib/active_record/connection_handling.rb:296:in `with_connection'
     # /home/andy/src/rails/activerecord/lib/active_record/relation.rb:1430:in `block in exec_main_query'
     # /home/andy/src/rails/activerecord/lib/active_record/relation.rb:1452:in `skip_query_cache_if_necessary'
     # /home/andy/src/rails/activerecord/lib/active_record/relation.rb:1414:in `exec_main_query'
     # /home/andy/src/rails/activerecord/lib/active_record/relation.rb:1392:in `block in exec_queries'
     # /home/andy/src/rails/activerecord/lib/active_record/relation.rb:1452:in `skip_query_cache_if_necessary'
     # /home/andy/src/rails/activerecord/lib/active_record/relation.rb:1386:in `exec_queries'
     # /home/andy/src/rails/activerecord/lib/active_record/relation.rb:1167:in `load'
     # /home/andy/src/rails/activerecord/lib/active_record/relation.rb:336:in `records'
     # /home/andy/src/rails/activerecord/lib/active_record/relation.rb:331:in `to_ary'
     # ./spec/active_record/connection_adapters/oracle_enhanced/context_index_spec.rb:99:in `block (4 levels) in <top (required)>'
     # ./spec/active_record/connection_adapters/oracle_enhanced/context_index_spec.rb:98:in `each'
     # ./spec/active_record/connection_adapters/oracle_enhanced/context_index_spec.rb:98:in `block (3 levels) in <top (required)>'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/example.rb:263:in `instance_exec'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/example.rb:263:in `block in run'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/example.rb:511:in `block in with_around_and_singleton_context_hooks'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/example.rb:468:in `block in with_around_example_hooks'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/hooks.rb:486:in `block in run'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/hooks.rb:624:in `run_around_example_hooks_for'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/hooks.rb:486:in `run'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/example.rb:468:in `with_around_example_hooks'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/example.rb:511:in `with_around_and_singleton_context_hooks'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/example.rb:259:in `run'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/example_group.rb:646:in `block in run_examples'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/example_group.rb:642:in `map'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/example_group.rb:642:in `run_examples'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/example_group.rb:607:in `run'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/example_group.rb:608:in `block in run'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/example_group.rb:608:in `map'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/example_group.rb:608:in `run'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/runner.rb:121:in `block (3 levels) in run_specs'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/runner.rb:121:in `map'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/runner.rb:121:in `block (2 levels) in run_specs'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/configuration.rb:2097:in `with_suite_hooks'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/runner.rb:116:in `block in run_specs'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/reporter.rb:74:in `report'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/runner.rb:115:in `run_specs'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/runner.rb:89:in `run'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/runner.rb:71:in `run'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/lib/rspec/core/runner.rb:45:in `invoke'
     # /home/andy/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/rspec-core-3.13.2/exe/rspec:4:in `<main>'
     # ------------------
     # --- Caused by: ---
     # OCIError:
     #   ORA-01036: illegal variable name/number
     #   stmt.c:218:in oci8lib_330.so

I've traced this through and the bound parameters are being provided to the raw cursor.

exec_query : SELECT "POSTS".* FROM "POSTS" WHERE (CONTAINS("TITLE", ?, 0) > 0) ORDER BY SCORE(0) DESC <- ["aaa"]
bind_param(1, "aaa")

It seems like the cursor may need some additional setup for the parameter to be bound. Interestingly, other tests that use similar binding of variables seem to work ok. Perhaps it has something to do with binding into a functional argument as is the case here.

I would appreciate any diagnostic suggestions.

Thank you!

@andynu andynu mentioned this pull request Jan 22, 2025
Active record wants '?' as a bind placeholder. Without this it will not
provide bind variables to exec.

Oracle requires :N style bind parameters, so it a translation is
required.

Something went wrong in the translation between rails 7.1 and rails 7.2
so that the where("CONTAINS(table.col, ?, 0) >0", term) was no longer
getting it's bind parameter translated to ':a1' like it should be.

This change drops down to AREL nodes which ensures that the contains
query is getting passed through the visitor pattern, specifically
hitting the visit_Arel_Nodes_BindParam method to convert the param to
':a1'.

I still do not understand what changed in rails, but this workaround is
effective.
@andynu
Copy link
Contributor Author

andynu commented Jan 31, 2025

Please see the cleaner pr at #2424

@andynu andynu closed this Jan 31, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant