Issue: different exception type
Author: MR-omid
State: closed
Created: 2018-02-27 10:36:31

hi
with postgres database connection, exception raised as `psycopg2.IntegrityError` but its not same as `peewee.IntegrityError` and not catchable.
it is normal to use `psycopg2.IntegrityError` in except ?
for example:
```
try:
    model.save()
except psycopg2.IntegrityError:
    raise
```

Peewee wraps database driver-specific exceptions with it's own exception types... This is done so that, regardless of what database driver you're using, you can catch the a single exception type.

So you would, theoretically, just write:

```python
try:
    model.save()
except peewee.IntegrityError:
    # do whatever.
```

thanks for your reply, but i tested and its not work.
working code:
```python
class Config(Database.model):
    attribute = TextField(unique=True)
    value = ComplexField()

    class Meta:
        db_table = 'core_config'

    @staticmethod
    def save_changes(configs=None):
        if not configs:
            configs = default_configs
        for config in configs:
            try:
                model = Config()
                model.attribute = config['attribute']
                model.value = config['value']
                model.save()
            except psycopg2.IntegrityError:
                model = Config.get(attribute=config['attribute'])
                model.value = config['value']
                model.save()
```

but this one is not catch exception:
```python
class Config(Database.model):
    attribute = TextField(unique=True)
    value = ComplexField()

    class Meta:
        db_table = 'core_config'

    @staticmethod
    def save_changes(configs=None):
        if not configs:
            configs = default_configs
        for config in configs:
            try:
                model = Config()
                model.attribute = config['attribute']
                model.value = config['value']
                model.save()
            except peewee.IntegrityError:
                model = Config.get(attribute=config['attribute'])
                model.value = config['value']
                model.save()
```

I'll see if I can replicate it. Thanks for the update.

I can't replicate the issue:

```python
import peewee


db = peewee.PostgresqlDatabase('peewee_test', user='postgres')

class Register(peewee.Model):
    value = peewee.IntegerField(unique=True)
    class Meta:
        database = db

db.create_tables([Register])

# Clear out any rows.
Register.delete().execute()

Register.create(value=1)

with db.atomic():
    try:
        Register.create(value=1)
    except peewee.IntegrityError:
        print('Integrity error caught')

db.drop_tables([Register])
```

The above code correctly prints "Integrity error caught".

my peewee version is: 2.10.2
i can't upgrade, 
for backward compatibility with custom migration.
may be problem in this version?

hey, i tested again and its worked :)
but if i set `autorollback` to false, problem will be appear.
```

Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/peewee.py", line 3830, in execute_sql
    cursor.execute(sql, params or ())
psycopg2.IntegrityError: duplicate key value violates unique constraint "core_config_attribute"
DETAIL:  Key (attribute)=(test) already exists.


During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/dpe/workspace/python/F.SystemAPI/models/Config.py", line 31, in save_changes
    model.save()
  File "/usr/local/lib/python3.5/dist-packages/playhouse/signals.py", line 69, in save
    ret = super(Model, self).save(*args, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/peewee.py", line 5170, in save
    pk_from_cursor = self.insert(**field_dict).execute()
  File "/usr/local/lib/python3.5/dist-packages/peewee.py", line 3584, in execute
    cursor = self._execute()
  File "/usr/local/lib/python3.5/dist-packages/peewee.py", line 2939, in _execute
    return self.database.execute_sql(sql, params, self.require_commit)
  File "/usr/local/lib/python3.5/dist-packages/peewee.py", line 3837, in execute_sql
    self.commit()
  File "/usr/local/lib/python3.5/dist-packages/peewee.py", line 3656, in __exit__
    reraise(new_type, new_type(*exc_args), traceback)
  File "/usr/local/lib/python3.5/dist-packages/peewee.py", line 135, in reraise
    raise value.with_traceback(tb)
  File "/usr/local/lib/python3.5/dist-packages/peewee.py", line 3830, in execute_sql
    cursor.execute(sql, params or ())
peewee.IntegrityError: duplicate key value violates unique constraint "core_config_attribute"
DETAIL:  Key (attribute)=(test) already exists.


During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/peewee.py", line 3830, in execute_sql
    cursor.execute(sql, params or ())
psycopg2.InternalError: current transaction is aborted, commands ignored until end of transaction block


During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/dpe/workspace/python/F.SystemAPI/dev.py", line 18, in <module>
    server.start()
  File "/home/dpe/workspace/python/F.SystemAPI/core/Server.py", line 36, in start
    Config.save_changes([{'attribute':'test','value':'omid'},{'attribute':'test2','value':'omid'},{'attribute':'test','value':'omid3'}])
  File "/home/dpe/workspace/python/F.SystemAPI/models/Config.py", line 35, in save_changes
    model = Config.get(attribute=config['attribute'])
  File "/usr/local/lib/python3.5/dist-packages/peewee.py", line 4988, in get
    return sq.get()
  File "/usr/local/lib/python3.5/dist-packages/peewee.py", line 3220, in get
    return next(clone.execute())
  File "/usr/local/lib/python3.5/dist-packages/peewee.py", line 3274, in execute
    self._qr = ResultWrapper(model_class, self._execute(), query_meta)
  File "/usr/local/lib/python3.5/dist-packages/peewee.py", line 2939, in _execute
    return self.database.execute_sql(sql, params, self.require_commit)
  File "/usr/local/lib/python3.5/dist-packages/peewee.py", line 3837, in execute_sql
    self.commit()
  File "/usr/local/lib/python3.5/dist-packages/peewee.py", line 3656, in __exit__
    reraise(new_type, new_type(*exc_args), traceback)
  File "/usr/local/lib/python3.5/dist-packages/peewee.py", line 135, in reraise
    raise value.with_traceback(tb)
  File "/usr/local/lib/python3.5/dist-packages/peewee.py", line 3830, in execute_sql
    cursor.execute(sql, params or ())
peewee.InternalError: current transaction is aborted, commands ignored until end of transaction block
```

If you are using Postgres, you need to take care that, if you get the connection into a bad state -- i.e., by an IntegrityError -- you need to rollback. Auto-rollback will issue the rollback automatically, but it's better, in my opinion, to manage the transaction yourself:

```python
try:
    with db.atomic():
        some_obj.save()
except peewee.IntegrityError:
    # do something else?
```