gh-103015: Add entrypoint parameter to sqlite3.Connection.load_extension by erlend-aasland · Pull Request #103073 · python/cpython

bedevere-bot · GitHub

Thanks for putting this together

@erlend-aasland

, this looks awesome! Will try it out myself soon.

Re tests: Feel free to use this sample extension. I wrote it myself, also contributed to

the Datasette project

, and includes multiple entrypoints.

/*** This file implements a SQLite extension with multiple entrypoints.**** The default entrypoint, sqlite3_ext_init, has a single function "a".** The 1st alternate entrypoint, sqlite3_ext_b_init, has a single function "b".** The 2nd alternate entrypoint, sqlite3_ext_c_init, has a single function "c".**** Compiling instructions: ** https://www.sqlite.org/loadext.html#compiling_a_loadable_extension***/#include"sqlite3ext.h"SQLITE_EXTENSION_INIT1// SQL function that returns back the value supplied during sqlite3_create_function()staticvoidfunc(sqlite3_context*context, intargc, sqlite3_value**argv) { sqlite3_result_text(context, (char*) sqlite3_user_data(context), -1, SQLITE_STATIC); } // The default entrypoint, since it matches the "ext.dylib"/"ext.so" name#ifdef_WIN32 __declspec(dllexport) #endifintsqlite3_ext_init(sqlite3*db, char**pzErrMsg, constsqlite3_api_routines*pApi) { SQLITE_EXTENSION_INIT2(pApi); returnsqlite3_create_function(db, "a", 0, 0, "a", func, 0, 0); } // Alternate entrypoint #1#ifdef_WIN32 __declspec(dllexport) #endifintsqlite3_ext_b_init(sqlite3*db, char**pzErrMsg, constsqlite3_api_routines*pApi) { SQLITE_EXTENSION_INIT2(pApi); returnsqlite3_create_function(db, "b", 0, 0, "b", func, 0, 0); } // Alternate entrypoint #2#ifdef_WIN32 __declspec(dllexport) #endifintsqlite3_ext_c_init(sqlite3*db, char**pzErrMsg, constsqlite3_api_routines*pApi) { SQLITE_EXTENSION_INIT2(pApi); returnsqlite3_create_function(db, "c", 0, 0, "c", func, 0, 0); }Compiling SQLite extensions are always tricky, but it should need just something like this:

gcc ext.c -fPIC -shared -o ext.dylib With possibly -I path/to/sqlite if it's not globally installed, and only .dylib for MacOS system. For windows, change the suffx to .dll, and Linux to .so. To test that extension, it should be something like:

importsqlite3db=sqlite3.connect(":memory:"); # You can leave off the dylib/so/dll suffix, since SQLite will implicitly add it# loading without an entrypoint will resolve to the default sqlite3_ext_init entrypointdb.load_extension("./ext"); assertdb.execute("select a()").fetchone()[0] =="a"db.load_extension("./ext", "sqlite3_ext_b_init"); assertdb.execute("select b()").fetchone()[0] =="b"db.load_extension("./ext", "sqlite3_ext_c_init"); assertdb.execute("select c()").fetchone()[0] =="c"Let me know if you want some help adding an extension to the test suite!