xref: /third_party/python/Modules/_sqlite/util.c (revision 7db96d56)
1/* util.c - various utility functions
2 *
3 * Copyright (C) 2005-2010 Gerhard Häring <gh@ghaering.de>
4 *
5 * This file is part of pysqlite.
6 *
7 * This software is provided 'as-is', without any express or implied
8 * warranty.  In no event will the authors be held liable for any damages
9 * arising from the use of this software.
10 *
11 * Permission is granted to anyone to use this software for any purpose,
12 * including commercial applications, and to alter it and redistribute it
13 * freely, subject to the following restrictions:
14 *
15 * 1. The origin of this software must not be misrepresented; you must not
16 *    claim that you wrote the original software. If you use this software
17 *    in a product, an acknowledgment in the product documentation would be
18 *    appreciated but is not required.
19 * 2. Altered source versions must be plainly marked as such, and must not be
20 *    misrepresented as being the original software.
21 * 3. This notice may not be removed or altered from any source distribution.
22 */
23
24#include "module.h"
25#include "connection.h"
26
27// Returns non-NULL if a new exception should be raised
28static PyObject *
29get_exception_class(pysqlite_state *state, int errorcode)
30{
31    switch (errorcode) {
32        case SQLITE_OK:
33            PyErr_Clear();
34            return NULL;
35        case SQLITE_INTERNAL:
36        case SQLITE_NOTFOUND:
37            return state->InternalError;
38        case SQLITE_NOMEM:
39            return PyErr_NoMemory();
40        case SQLITE_ERROR:
41        case SQLITE_PERM:
42        case SQLITE_ABORT:
43        case SQLITE_BUSY:
44        case SQLITE_LOCKED:
45        case SQLITE_READONLY:
46        case SQLITE_INTERRUPT:
47        case SQLITE_IOERR:
48        case SQLITE_FULL:
49        case SQLITE_CANTOPEN:
50        case SQLITE_PROTOCOL:
51        case SQLITE_EMPTY:
52        case SQLITE_SCHEMA:
53            return state->OperationalError;
54        case SQLITE_CORRUPT:
55            return state->DatabaseError;
56        case SQLITE_TOOBIG:
57            return state->DataError;
58        case SQLITE_CONSTRAINT:
59        case SQLITE_MISMATCH:
60            return state->IntegrityError;
61        case SQLITE_MISUSE:
62        case SQLITE_RANGE:
63            return state->InterfaceError;
64        default:
65            return state->DatabaseError;
66    }
67}
68
69static void
70raise_exception(PyObject *type, int errcode, const char *errmsg)
71{
72    PyObject *exc = NULL;
73    PyObject *args[] = { PyUnicode_FromString(errmsg), };
74    if (args[0] == NULL) {
75        goto exit;
76    }
77    exc = PyObject_Vectorcall(type, args, 1, NULL);
78    Py_DECREF(args[0]);
79    if (exc == NULL) {
80        goto exit;
81    }
82
83    PyObject *code = PyLong_FromLong(errcode);
84    if (code == NULL) {
85        goto exit;
86    }
87    int rc = PyObject_SetAttrString(exc, "sqlite_errorcode", code);
88    Py_DECREF(code);
89    if (rc < 0) {
90        goto exit;
91    }
92
93    const char *error_name = pysqlite_error_name(errcode);
94    PyObject *name;
95    if (error_name) {
96        name = PyUnicode_FromString(error_name);
97    }
98    else {
99        name = PyUnicode_InternFromString("unknown");
100    }
101    if (name == NULL) {
102        goto exit;
103    }
104    rc = PyObject_SetAttrString(exc, "sqlite_errorname", name);
105    Py_DECREF(name);
106    if (rc < 0) {
107        goto exit;
108    }
109
110    PyErr_SetObject(type, exc);
111
112exit:
113    Py_XDECREF(exc);
114}
115
116/**
117 * Checks the SQLite error code and sets the appropriate DB-API exception.
118 * Returns the error code (0 means no error occurred).
119 */
120int
121_pysqlite_seterror(pysqlite_state *state, sqlite3 *db)
122{
123    int errorcode = sqlite3_errcode(db);
124    PyObject *exc_class = get_exception_class(state, errorcode);
125    if (exc_class == NULL) {
126        // No new exception need be raised; just pass the error code
127        return errorcode;
128    }
129
130    /* Create and set the exception. */
131    int extended_errcode = sqlite3_extended_errcode(db);
132    const char *errmsg = sqlite3_errmsg(db);
133    raise_exception(exc_class, extended_errcode, errmsg);
134    return extended_errcode;
135}
136
137#ifdef WORDS_BIGENDIAN
138# define IS_LITTLE_ENDIAN 0
139#else
140# define IS_LITTLE_ENDIAN 1
141#endif
142
143sqlite_int64
144_pysqlite_long_as_int64(PyObject * py_val)
145{
146    int overflow;
147    long long value = PyLong_AsLongLongAndOverflow(py_val, &overflow);
148    if (value == -1 && PyErr_Occurred())
149        return -1;
150    if (!overflow) {
151# if SIZEOF_LONG_LONG > 8
152        if (-0x8000000000000000LL <= value && value <= 0x7FFFFFFFFFFFFFFFLL)
153# endif
154            return value;
155    }
156    else if (sizeof(value) < sizeof(sqlite_int64)) {
157        sqlite_int64 int64val;
158        if (_PyLong_AsByteArray((PyLongObject *)py_val,
159                                (unsigned char *)&int64val, sizeof(int64val),
160                                IS_LITTLE_ENDIAN, 1 /* signed */) >= 0) {
161            return int64val;
162        }
163    }
164    PyErr_SetString(PyExc_OverflowError,
165                    "Python int too large to convert to SQLite INTEGER");
166    return -1;
167}
168