Creating with a changeset fails with Oracle

Open
#217 12 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
35/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Stale
Tech stack
ruby, sql
Domain
databases

Research direction

Start by tracing the changeset create path and how the Oracle adapter handles Sequel's supports_returning? result. Compare the failing Oracle behavior with the working SQLite case and the documented create workaround; done means changesets can create records without requiring a returned INSERT result.

Written by the indexing model from the issue text.

Description

bug oracle

From @mrship on January 30, 2017 12:39

Using a changeset to create a record is failing for me when using Oracle, because (I think) you don't get the result of the INSERT statement back from Oracle using Sequel.

This is my code:

changeset_for_create = changeset(participant.to_hash)
  .map(:add_timestamps)
  .associate(participant.user, :users)
create(changeset_for_create(participant))

Which fails with:

2017-01-30 12:28:42 - Dry::Struct::Error - [ROM::Struct[Participant].new] :id is missing in Hash input:
	/Users/shipmana/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/dry-struct-0.1.1/lib/dry/struct/class_interface.rb:80:in `rescue in new'
	/Users/shipmana/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/dry-struct-0.1.1/lib/dry/struct/class_interface.rb:74:in `new'
	/Users/shipmana/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/transproc-1.0.0/lib/transproc/class.rb:30:in `constructor_inject'
	/Users/shipmana/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/transproc-1.0.0/lib/transproc/function.rb:47:in `call'
	/Users/shipmana/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/transproc-1.0.0/lib/transproc/function.rb:47:in `call'
	/Users/shipmana/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/transproc-1.0.0/lib/transproc/array.rb:41:in `block in map_array'
	/Users/shipmana/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/transproc-1.0.0/lib/transproc/array.rb:41:in `map'
	/Users/shipmana/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/transproc-1.0.0/lib/transproc/array.rb:41:in `map_array'
	/Users/shipmana/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/transproc-1.0.0/lib/transproc/function.rb:47:in `call'
	/Users/shipmana/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/transproc-1.0.0/lib/transproc/function.rb:47:in `call'
	/Users/shipmana/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/rom-mapper-0.5.0/lib/rom/mapper.rb:95:in `block in call'
	/Users/shipmana/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/rom-mapper-0.5.0/lib/rom/mapper.rb:95:in `each'
	/Users/shipmana/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/rom-mapper-0.5.0/lib/rom/mapper.rb:95:in `reduce'
	/Users/shipmana/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/rom-mapper-0.5.0/lib/rom/mapper.rb:95:in `call'
	/Users/shipmana/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/rom-repository-1.0.0.rc1/lib/rom/repository.rb:326:in `map_tuple'
	/Users/shipmana/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/rom-repository-1.0.0.rc1/lib/rom/repository/class_interface.rb:117:in `block in define_command_method'

This works fine with sqlite (in a test) but not with our production database of Oracle. I have had a similar issue in the past when expecting create to return a ROM::Struct but it does not with Oracle because of the issue with Sequel not using RETURNING as part of the INSERT query. As I understand it Sequel returns false for supports_returning? for Oracle.

My workaround is not to use changesets at all...

attributes = participant.to_hash.merge(user_id: participant.user.id)
create(attributes)

which is a real shame as I like the interface they provide and the convenience of the associate method and adding timestamps etc.

Can changesets be made to work without expecting a result from the underlying INSERT?

Copied from original issue: rom-rb/rom-repository#55

Dominant language
Ruby
Stars
220
Forks
97
PR merge metrics
No merged PRs in 30d

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from rom-rb/rom-sql

All issues in rom-rb/rom-sql

Similar issues

More Ruby issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.