Skip to content
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

Fix Sequel instrumentation when executing literal strings #1185

Conversation

matchbookmac
Copy link
Contributor

When instrumenting an application using the sequel integration, tracing was failing for a case like the following:

query = Sequel.lit("UPDATE foo SET bar = :wat WHERE bar = :var", wat: 2, var: 1)
db.run(query)
     Failure/Error: db.run(query)

     NoMethodError:
       undefined method `prepared_sql' for #<Sequel::SQL::PlaceholderLiteralString:0x00005585a864c0c0>
     # /usr/local/bundle/gems/ddtrace-0.40.0/lib/ddtrace/contrib/sequel/utils.rb:32:in `parse_opts'
     # /usr/local/bundle/gems/ddtrace-0.40.0/lib/ddtrace/contrib/sequel/database.rb:55:in `parse_opts'
     # /usr/local/bundle/gems/ddtrace-0.40.0/lib/ddtrace/contrib/sequel/database.rb:19:in `run'
     # ./app/distribution/create.rb:17:in `calculate'
     # ./app/distribution/create.rb:8:in `handle'
     # ./spec/distribution/create_spec.rb:31:in `block (3 levels) in <top (required)>'

When using Sequel.lit in this context, it returns a Sequel::SQL::PlaceholderLiteralString.
This object does not respond to prepared_sql, the method expected by Datadog::Contrib::Sequel::Utils.parse_opts.
To coerce a Sequel::SQL::PlaceholderLiteralString into a String, Sequel::Database#literal (Sequel::Dataset#literal) may be used.

Unfortunately, a duck-type approach for the variety of types the sql argument may take is not possible when sql is a String because #literal escapes 's:

db.literal("SELECT * FROM tbl WHERE name = 'foo'") # => "'SELECT * FROM tbl WHERE name = ''foo'''"

As such, it is necessary to check the type of sql in order to coerce it.

When instrumenting an application using the `sequel` integration, tracing was failing for a case like the following:

```ruby
db.run(
  Sequel.lit("UPDATE foo SET bar = :wat WHERE bar = :var", wat: 2, var: 1)
)
```

When using `Sequel.lit` in this context, it returns a `Sequel::SQL::PlaceholderLiteralString`.
This object does not respond to `prepared_sql`, the method expected by `Datadog::Contrib::Sequel::Utils.parse_opts`.
To coerce a `Sequel::SQL::PlaceholderLiteralString` into a `String`, `Sequel::Database#literal` (`Sequel::Dataset#literal`) may be used.

Unfortunately a duck-type approach for the variety of types the `sql` argument may take is not possible as when `sql` is a `String` because `#literal` escapes `'`s:

```ruby
db.literal("SELECT * FROM tbl WHERE name = 'foo'") # => "'SELECT * FROM tbl WHERE name = ''foo'''"
```
@matchbookmac matchbookmac requested a review from a team September 22, 2020 23:04
Copy link
Member

@marcotc marcotc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much for your contribution, @matchbookmac!
The changes look good. 👍

@marcotc marcotc added community Was opened by a community member integrations Involves tracing integrations labels Sep 23, 2020
@marcotc marcotc added this to the 0.41.0 milestone Sep 23, 2020
@marcotc
Copy link
Member

marcotc commented Sep 23, 2020

For the CI failures, I recommend you update this branch with latest master, as we have recently fixed a few CI test issues.

…sequel-instrumentation-fail-for-sql-expression
@marcotc marcotc changed the title sequel-instrumentation-fail-for-sql-expression Fix Sequel instrumentation when executing literal strings Sep 23, 2020
@marcotc marcotc merged commit 7519947 into DataDog:master Sep 23, 2020
@matchbookmac
Copy link
Contributor Author

Thanks!

@matchbookmac matchbookmac deleted the sequel-instrumentation-fail-for-sql-expression branch September 24, 2020 14:04
@ericmustin
Copy link
Contributor

👋 @matchbookmac This has been released in 0.41.0 https://github.com/DataDog/dd-trace-rb/releases/tag/v0.41.0, thanks again for the contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
community Was opened by a community member integrations Involves tracing integrations
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants