File: exception.c

package info (click to toggle)
ruby-sqlite3 2.9.1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 684 kB
  • sloc: ruby: 4,827; ansic: 1,868; sh: 91; makefile: 7
file content (122 lines) | stat: -rw-r--r-- 4,014 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <sqlite3_ruby.h>

static VALUE
status2klass(int status)
{
    /* Consider only lower 8 bits, to work correctly when
       extended result codes are enabled. */
    switch (status & 0xff) {
        case SQLITE_OK:
            return Qnil;
        case SQLITE_ERROR:
            return rb_path2class("SQLite3::SQLException");
        case SQLITE_INTERNAL:
            return rb_path2class("SQLite3::InternalException");
        case SQLITE_PERM:
            return rb_path2class("SQLite3::PermissionException");
        case SQLITE_ABORT:
            return rb_path2class("SQLite3::AbortException");
        case SQLITE_BUSY:
            return rb_path2class("SQLite3::BusyException");
        case SQLITE_LOCKED:
            return rb_path2class("SQLite3::LockedException");
        case SQLITE_NOMEM:
            return rb_path2class("SQLite3::MemoryException");
        case SQLITE_READONLY:
            return rb_path2class("SQLite3::ReadOnlyException");
        case SQLITE_INTERRUPT:
            return rb_path2class("SQLite3::InterruptException");
        case SQLITE_IOERR:
            return rb_path2class("SQLite3::IOException");
        case SQLITE_CORRUPT:
            return rb_path2class("SQLite3::CorruptException");
        case SQLITE_NOTFOUND:
            return rb_path2class("SQLite3::NotFoundException");
        case SQLITE_FULL:
            return rb_path2class("SQLite3::FullException");
        case SQLITE_CANTOPEN:
            return rb_path2class("SQLite3::CantOpenException");
        case SQLITE_PROTOCOL:
            return rb_path2class("SQLite3::ProtocolException");
        case SQLITE_EMPTY:
            return rb_path2class("SQLite3::EmptyException");
        case SQLITE_SCHEMA:
            return rb_path2class("SQLite3::SchemaChangedException");
        case SQLITE_TOOBIG:
            return rb_path2class("SQLite3::TooBigException");
        case SQLITE_CONSTRAINT:
            return rb_path2class("SQLite3::ConstraintException");
        case SQLITE_MISMATCH:
            return rb_path2class("SQLite3::MismatchException");
        case SQLITE_MISUSE:
            return rb_path2class("SQLite3::MisuseException");
        case SQLITE_NOLFS:
            return rb_path2class("SQLite3::UnsupportedException");
        case SQLITE_AUTH:
            return rb_path2class("SQLite3::AuthorizationException");
        case SQLITE_FORMAT:
            return rb_path2class("SQLite3::FormatException");
        case SQLITE_RANGE:
            return rb_path2class("SQLite3::RangeException");
        case SQLITE_NOTADB:
            return rb_path2class("SQLite3::NotADatabaseException");
        default:
            return rb_path2class("SQLite3::Exception");
    }
}

void
rb_sqlite3_raise(sqlite3 *db, int status)
{
    VALUE klass = status2klass(status);
    if (NIL_P(klass)) {
        return;
    }

    VALUE exception = rb_exc_new2(klass, sqlite3_errmsg(db));
    rb_iv_set(exception, "@code", INT2FIX(status));

    rb_exc_raise(exception);
}

/*
 *  accepts a sqlite3 error message as the final argument, which will be `sqlite3_free`d
 */
void
rb_sqlite3_raise_msg(sqlite3 *db, int status, const char *msg)
{
    VALUE klass = status2klass(status);
    if (NIL_P(klass)) {
        return;
    }

    VALUE exception = rb_exc_new2(klass, msg);
    rb_iv_set(exception, "@code", INT2FIX(status));
    sqlite3_free((void *)msg);

    rb_exc_raise(exception);
}

void
rb_sqlite3_raise_with_sql(sqlite3 *db, int status, const char *sql)
{
    VALUE klass = status2klass(status);
    if (NIL_P(klass)) {
        return;
    }

    const char *error_msg = sqlite3_errmsg(db);
    int error_offset = -1;
#ifdef HAVE_SQLITE3_ERROR_OFFSET
    error_offset = sqlite3_error_offset(db);
#endif

    VALUE exception = rb_exc_new2(klass, error_msg);
    rb_iv_set(exception, "@code", INT2FIX(status));
    if (sql) {
        rb_iv_set(exception, "@sql", rb_str_new2(sql));
        rb_iv_set(exception, "@sql_offset", INT2FIX(error_offset));
    }

    rb_exc_raise(exception);
}