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

Exception handling : Desired clarifications #52

Open
hutou opened this issue Dec 20, 2019 · 3 comments
Open

Exception handling : Desired clarifications #52

hutou opened this issue Dec 20, 2019 · 3 comments

Comments

@hutou
Copy link

hutou commented Dec 20, 2019

Hi,
I am trying to understand how exceptions are handled in Crystal-sqlite3.
Given the following code :

require "sqlite3"
DBCONN = DB.connect "sqlite3://%3Amemory%3A"
begin
  DBCONN.exec "create table test ( id integer primary key, code text not null unique)"
  DBCONN.exec "insert into test(code) values('A')"
  DBCONN.exec "insert into test(code) values('A')"
rescue e
  if e.message =~ /UNIQUE constraint failed/i
    puts ("Already in database")
  else
    puts (e.message)
  end
ensure
  DBCONN.close
end

output is :

Already in database
Unhandled exception: UNIQUE constraint failed: test.code (SQLite3::Exception)
from lib/sqlite3/src/sqlite3/statement.cr:81:5 in 'check'
from lib/sqlite3/src/sqlite3/statement.cr:37:5 in 'do_close'
from lib/db/src/db/disposable.cr:11:7 in 'close'
from lib/db/src/db/connection.cr:60:38 in 'do_close'
from lib/sqlite3/src/sqlite3/connection.cr:34:5 in 'do_close'
from lib/db/src/db/disposable.cr:11:7 in 'close'
from test1a.cr:14:3 in '__crystal_main'
from /usr/lib/crystal/crystal/main.cr:97:5 in 'main_user_code'
from /usr/lib/crystal/crystal/main.cr:86:7 in 'main'
from /usr/lib/crystal/crystal/main.cr:106:3 in 'main'
from __libc_start_main
from _start
from ???

Why does Crystal tell me the exception is unhandled when the displayed message in the rescue clause "proves" it was rescued ?

I noticed that if I comment out the DBCONN.close statement, I only get the "Already in database" message, no more unhandled exception.

If however, I run the following program :

require "sqlite3"
DBCONN = DB.connect "sqlite3://%3Amemory%3A"
begin
  DBCONN.exec "create table test ( id integer primary key, code text not null unique)"
  DBCONN.exec "insert into test(code) values('A')"
  sql = "select 1 from test where code = 'Z'"
  code = DBCONN.query_one sql, as: {String}
rescue e
  puts (e.message)
ensure
  DBCONN.close
end

the output is a bare

no rows

So, no more unhandled exception and I'm somewhat puzzled : can you enlighten me on this?
Are there different "levels" of exceptions ?
I also noticed that putting the DBCONN.close in an at_exit statement produce the same "unhandled exception" for the first code snippet.

Thanks

@bcardiff
Copy link
Member

The unhandled error is triggered by the DBCONN.close that is why it is unhandled: there is no rescue to catch it.

It seems that https://github.com/crystal-lang/crystal-sqlite3/blob/master/src/sqlite3/statement.cr#L37 should not be checked according to https://stackoverflow.com/a/8391872/30948 🤔

In the second example, there is effectively no row to return (insert A, filter Z), plus there is no print of code.

Workaround to ignore the exception in DBCONN.close: DBCONN.close rescue nil

@hutou
Copy link
Author

hutou commented Dec 23, 2019

Thanks for the explanations and the workaround.

@hutou hutou closed this as completed Dec 23, 2019
@bcardiff
Copy link
Member

It’s still something that should be fixed. I will leave this open until then.

Thanks for reporting it.

@bcardiff bcardiff reopened this Dec 23, 2019
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

No branches or pull requests

2 participants