/* util.c - various utility functions
 *
 * Copyright (C) 2005-2010 Gerhard Häring <gh@ghaering.de>
 *
 * This file is part of pysqlite.
 *
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
 *    appreciated but is not required.
 * 2. Altered source versions must be plainly marked as such, and must not be
 *    misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 */

#include "module.h"
#include "connection.h"

int pysqlite_step(sqlite3_stmt* statement, pysqlite_Connection* connection)
{
    int rc;

    if (statement == NULL) {
        /* this is a workaround for SQLite 3.5 and later. it now apparently
         * returns NULL for "no-operation" statements */
        rc = SQLITE_OK;
    } else {
        Py_BEGIN_ALLOW_THREADS
        rc = sqlite3_step(statement);
        Py_END_ALLOW_THREADS
    }

    return rc;
}

/**
 * Checks the SQLite error code and sets the appropriate DB-API exception.
 * Returns the error code (0 means no error occurred).
 */
int _pysqlite_seterror(sqlite3* db, sqlite3_stmt* st)
{
    int errorcode;

    /* SQLite often doesn't report anything useful, unless you reset the statement first */
    if (st != NULL) {
        (void)sqlite3_reset(st);
    }

    errorcode = sqlite3_errcode(db);

    switch (errorcode)
    {
        case SQLITE_OK:
            PyErr_Clear();
            break;
        case SQLITE_INTERNAL:
        case SQLITE_NOTFOUND:
            PyErr_SetString(pysqlite_InternalError, sqlite3_errmsg(db));
            break;
        case SQLITE_NOMEM:
            (void)PyErr_NoMemory();
            break;
        case SQLITE_ERROR:
        case SQLITE_PERM:
        case SQLITE_ABORT:
        case SQLITE_BUSY:
        case SQLITE_LOCKED:
        case SQLITE_READONLY:
        case SQLITE_INTERRUPT:
        case SQLITE_IOERR:
        case SQLITE_FULL:
        case SQLITE_CANTOPEN:
        case SQLITE_PROTOCOL:
        case SQLITE_EMPTY:
        case SQLITE_SCHEMA:
            PyErr_SetString(pysqlite_OperationalError, sqlite3_errmsg(db));
            break;
        case SQLITE_CORRUPT:
            PyErr_SetString(pysqlite_DatabaseError, sqlite3_errmsg(db));
            break;
        case SQLITE_TOOBIG:
            PyErr_SetString(pysqlite_DataError, sqlite3_errmsg(db));
            break;
        case SQLITE_CONSTRAINT:
        case SQLITE_MISMATCH:
            PyErr_SetString(pysqlite_IntegrityError, sqlite3_errmsg(db));
            break;
        case SQLITE_MISUSE:
            PyErr_SetString(pysqlite_ProgrammingError, sqlite3_errmsg(db));
            break;
        default:
            PyErr_SetString(pysqlite_DatabaseError, sqlite3_errmsg(db));
            break;
    }

    return errorcode;
}

#ifdef WORDS_BIGENDIAN
# define IS_LITTLE_ENDIAN 0
#else
# define IS_LITTLE_ENDIAN 1
#endif

PyObject *
_pysqlite_long_from_int64(sqlite_int64 value)
{
# if SIZEOF_LONG_LONG < 8
    if (value > PY_LLONG_MAX || value < PY_LLONG_MIN) {
        return _PyLong_FromByteArray(&value, sizeof(value),
                                     IS_LITTLE_ENDIAN, 1 /* signed */);
    }
# endif
# if SIZEOF_LONG < SIZEOF_LONG_LONG
    if (value > LONG_MAX || value < LONG_MIN)
        return PyLong_FromLongLong(value);
# endif
    return PyLong_FromLong(Py_SAFE_DOWNCAST(value, sqlite_int64, long));
}

sqlite_int64
_pysqlite_long_as_int64(PyObject * py_val)
{
    int overflow;
    long long value = PyLong_AsLongLongAndOverflow(py_val, &overflow);
    if (value == -1 && PyErr_Occurred())
        return -1;
    if (!overflow) {
# if SIZEOF_LONG_LONG > 8
        if (-0x8000000000000000LL <= value && value <= 0x7FFFFFFFFFFFFFFFLL)
# endif
            return value;
    }
    else if (sizeof(value) < sizeof(sqlite_int64)) {
        sqlite_int64 int64val;
        if (_PyLong_AsByteArray((PyLongObject *)py_val,
                                (unsigned char *)&int64val, sizeof(int64val),
                                IS_LITTLE_ENDIAN, 1 /* signed */) >= 0) {
            return int64val;
        }
    }
    PyErr_SetString(PyExc_OverflowError,
                    "Python int too large to convert to SQLite INTEGER");
    return -1;
}
