#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <sqlite3.h>


#define ADD_INT_CONST(mod, name) \
    do { \
        if (PyModule_AddIntConstant((mod), #name, (name)) < 0) { \
            return NULL; \
        } \
    } while (0)

#define ADD_STR_CONST(mod, name) \
    do { \
        if (PyModule_AddStringConstant((mod), #name, (name)) < 0) { \
            return NULL; \
        } \
    } while (0)


static struct PyModuleDef moduledef = {
    PyModuleDef_HEAD_INIT,
    "cysqlite._constants",
    "sqlite3 constants",
    -1,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL
};

PyMODINIT_FUNC
PyInit__constants(void)
{
    PyObject *m = PyModule_Create(&moduledef);
    if (!m) {
        return NULL;
    }

    /* Version */
    ADD_STR_CONST(m, SQLITE_VERSION);
    ADD_INT_CONST(m, SQLITE_VERSION_NUMBER);

    /* Other sqlite constants */
    ADD_INT_CONST(m, SQLITE_OK);
    ADD_INT_CONST(m, SQLITE_ERROR);
    ADD_INT_CONST(m, SQLITE_ROW);
    ADD_INT_CONST(m, SQLITE_OK);
    ADD_INT_CONST(m, SQLITE_ERROR);
    ADD_INT_CONST(m, SQLITE_INTERNAL);
    ADD_INT_CONST(m, SQLITE_PERM);
    ADD_INT_CONST(m, SQLITE_ABORT);
    ADD_INT_CONST(m, SQLITE_BUSY);
    ADD_INT_CONST(m, SQLITE_LOCKED);
    ADD_INT_CONST(m, SQLITE_NOMEM);
    ADD_INT_CONST(m, SQLITE_READONLY);
    ADD_INT_CONST(m, SQLITE_INTERRUPT);
    ADD_INT_CONST(m, SQLITE_IOERR);
    ADD_INT_CONST(m, SQLITE_CORRUPT);
    ADD_INT_CONST(m, SQLITE_NOTFOUND);
    ADD_INT_CONST(m, SQLITE_FULL);
    ADD_INT_CONST(m, SQLITE_CANTOPEN);
    ADD_INT_CONST(m, SQLITE_PROTOCOL);
    ADD_INT_CONST(m, SQLITE_EMPTY);
    ADD_INT_CONST(m, SQLITE_SCHEMA);
    ADD_INT_CONST(m, SQLITE_TOOBIG);
    ADD_INT_CONST(m, SQLITE_CONSTRAINT);
    ADD_INT_CONST(m, SQLITE_MISMATCH);
    ADD_INT_CONST(m, SQLITE_MISUSE);
    ADD_INT_CONST(m, SQLITE_NOLFS);
    ADD_INT_CONST(m, SQLITE_AUTH);
    ADD_INT_CONST(m, SQLITE_FORMAT);
    ADD_INT_CONST(m, SQLITE_RANGE);
    ADD_INT_CONST(m, SQLITE_NOTADB);
    ADD_INT_CONST(m, SQLITE_ROW);
    ADD_INT_CONST(m, SQLITE_DONE);

    ADD_INT_CONST(m, SQLITE_STATUS_MEMORY_USED);
    ADD_INT_CONST(m, SQLITE_STATUS_PAGECACHE_USED);
    ADD_INT_CONST(m, SQLITE_STATUS_PAGECACHE_OVERFLOW);
    ADD_INT_CONST(m, SQLITE_STATUS_SCRATCH_USED);
    ADD_INT_CONST(m, SQLITE_STATUS_SCRATCH_OVERFLOW);
    ADD_INT_CONST(m, SQLITE_STATUS_MALLOC_SIZE);
    ADD_INT_CONST(m, SQLITE_STATUS_PARSER_STACK);
    ADD_INT_CONST(m, SQLITE_STATUS_PAGECACHE_SIZE);
    ADD_INT_CONST(m, SQLITE_STATUS_SCRATCH_SIZE);
    ADD_INT_CONST(m, SQLITE_STATUS_MALLOC_COUNT);
    ADD_INT_CONST(m, SQLITE_DBSTATUS_LOOKASIDE_USED);
    ADD_INT_CONST(m, SQLITE_DBSTATUS_CACHE_USED);
    ADD_INT_CONST(m, SQLITE_DBSTATUS_SCHEMA_USED);
    ADD_INT_CONST(m, SQLITE_DBSTATUS_STMT_USED);
    ADD_INT_CONST(m, SQLITE_DBSTATUS_LOOKASIDE_HIT);
    ADD_INT_CONST(m, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE);
    ADD_INT_CONST(m, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL);
    ADD_INT_CONST(m, SQLITE_DBSTATUS_CACHE_HIT);
    ADD_INT_CONST(m, SQLITE_DBSTATUS_CACHE_MISS);
    ADD_INT_CONST(m, SQLITE_DBSTATUS_CACHE_WRITE);
    ADD_INT_CONST(m, SQLITE_DBSTATUS_DEFERRED_FKS);

    ADD_INT_CONST(m, SQLITE_CREATE_INDEX);
    ADD_INT_CONST(m, SQLITE_CREATE_TABLE);
    ADD_INT_CONST(m, SQLITE_CREATE_TEMP_INDEX);
    ADD_INT_CONST(m, SQLITE_CREATE_TEMP_TABLE);
    ADD_INT_CONST(m, SQLITE_CREATE_TEMP_TRIGGER);
    ADD_INT_CONST(m, SQLITE_CREATE_TEMP_VIEW);
    ADD_INT_CONST(m, SQLITE_CREATE_TRIGGER);
    ADD_INT_CONST(m, SQLITE_CREATE_VIEW);
    ADD_INT_CONST(m, SQLITE_DELETE);
    ADD_INT_CONST(m, SQLITE_DROP_INDEX);
    ADD_INT_CONST(m, SQLITE_DROP_TABLE);
    ADD_INT_CONST(m, SQLITE_DROP_TEMP_INDEX);
    ADD_INT_CONST(m, SQLITE_DROP_TEMP_TABLE);
    ADD_INT_CONST(m, SQLITE_DROP_TEMP_TRIGGER);
    ADD_INT_CONST(m, SQLITE_DROP_TEMP_VIEW);
    ADD_INT_CONST(m, SQLITE_DROP_TRIGGER);
    ADD_INT_CONST(m, SQLITE_DROP_VIEW);
    ADD_INT_CONST(m, SQLITE_INSERT);
    ADD_INT_CONST(m, SQLITE_PRAGMA);
    ADD_INT_CONST(m, SQLITE_READ);
    ADD_INT_CONST(m, SQLITE_SELECT);
    ADD_INT_CONST(m, SQLITE_TRANSACTION);
    ADD_INT_CONST(m, SQLITE_UPDATE);
    ADD_INT_CONST(m, SQLITE_ATTACH);
    ADD_INT_CONST(m, SQLITE_DETACH);
    ADD_INT_CONST(m, SQLITE_ALTER_TABLE);
    ADD_INT_CONST(m, SQLITE_REINDEX);
    ADD_INT_CONST(m, SQLITE_ANALYZE);
    ADD_INT_CONST(m, SQLITE_CREATE_VTABLE);
    ADD_INT_CONST(m, SQLITE_DROP_VTABLE);
    ADD_INT_CONST(m, SQLITE_FUNCTION);
    ADD_INT_CONST(m, SQLITE_SAVEPOINT);
    ADD_INT_CONST(m, SQLITE_COPY);
    ADD_INT_CONST(m, SQLITE_RECURSIVE);
    ADD_INT_CONST(m, SQLITE_DENY);
    ADD_INT_CONST(m, SQLITE_IGNORE);

    ADD_INT_CONST(m, SQLITE_OPEN_READONLY);
    ADD_INT_CONST(m, SQLITE_OPEN_READWRITE);
    ADD_INT_CONST(m, SQLITE_OPEN_CREATE);
    ADD_INT_CONST(m, SQLITE_OPEN_DELETEONCLOSE);
    ADD_INT_CONST(m, SQLITE_OPEN_EXCLUSIVE);
    ADD_INT_CONST(m, SQLITE_OPEN_AUTOPROXY);
    ADD_INT_CONST(m, SQLITE_OPEN_URI);
    ADD_INT_CONST(m, SQLITE_OPEN_MEMORY);
    ADD_INT_CONST(m, SQLITE_OPEN_MAIN_DB);
    ADD_INT_CONST(m, SQLITE_OPEN_TEMP_DB);
    ADD_INT_CONST(m, SQLITE_OPEN_TRANSIENT_DB);
    ADD_INT_CONST(m, SQLITE_OPEN_MAIN_JOURNAL);
    ADD_INT_CONST(m, SQLITE_OPEN_TEMP_JOURNAL);
    ADD_INT_CONST(m, SQLITE_OPEN_SUBJOURNAL);
    ADD_INT_CONST(m, SQLITE_OPEN_MASTER_JOURNAL);
    ADD_INT_CONST(m, SQLITE_OPEN_NOMUTEX);
    ADD_INT_CONST(m, SQLITE_OPEN_FULLMUTEX);
    ADD_INT_CONST(m, SQLITE_OPEN_SHAREDCACHE);
    ADD_INT_CONST(m, SQLITE_OPEN_PRIVATECACHE);
    ADD_INT_CONST(m, SQLITE_OPEN_WAL);

    ADD_INT_CONST(m, SQLITE_LIMIT_LENGTH);
    ADD_INT_CONST(m, SQLITE_LIMIT_SQL_LENGTH);
    ADD_INT_CONST(m, SQLITE_LIMIT_COLUMN);
    ADD_INT_CONST(m, SQLITE_LIMIT_EXPR_DEPTH);
    ADD_INT_CONST(m, SQLITE_LIMIT_COMPOUND_SELECT);
    ADD_INT_CONST(m, SQLITE_LIMIT_VDBE_OP);
    ADD_INT_CONST(m, SQLITE_LIMIT_FUNCTION_ARG);
    ADD_INT_CONST(m, SQLITE_LIMIT_ATTACHED);
    ADD_INT_CONST(m, SQLITE_LIMIT_LIKE_PATTERN_LENGTH);
    ADD_INT_CONST(m, SQLITE_LIMIT_VARIABLE_NUMBER);
    ADD_INT_CONST(m, SQLITE_LIMIT_TRIGGER_DEPTH);
    ADD_INT_CONST(m, SQLITE_LIMIT_WORKER_THREADS);

    ADD_INT_CONST(m, SQLITE_TRACE_STMT);
    ADD_INT_CONST(m, SQLITE_TRACE_PROFILE);
    ADD_INT_CONST(m, SQLITE_TRACE_ROW);
    ADD_INT_CONST(m, SQLITE_TRACE_CLOSE);

    return m;
}
