I built an SQLite extension (i.e. a .so library) that I want to use in my app using the SQLAlchemy. It is a Flask app, but I don't think Flask plays a role here.
The extension can be loaded from CLI and seems to work:
$ sqlite3
SQLite version 3.20.1 2017-08-24 16:21:36
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> .load ./libSqliteIcu.so
But I need to do it in my app. There is an example in the Python docs:
import sqlite3
con = sqlite3.connect(":memory:")
# enable extension loading
con.enable_load_extension(True)
# Load the fulltext search extension
con.execute("select load_extension('./fts3.so')")
But in my app I have to access the database using db
:
db = flask_sqlalchemy.SQLAlchemy()
I can rewrite the last statement to:
db.session.execute('select load_extension("./libsqliteicu.so")')
But it fails with "not authorized" error.
How can I call enable_load_extension()
or otherwise succesfully load an extension?
The great thing about SQLAlchemy is that it supports all popular database systems, including SQLite3, MySQL, PostgreSQL, Oracle, Microsoft SQL Server, etc. So let's start by creating our own wrapper library based on SQLAlchemy.
Sqlite is a database storage engine, which can be better compared with things such as MySQL, PostgreSQL, Oracle, MSSQL, etc. It is used to store and retrieve structured data from files. SQLAlchemy is a Python library that provides an object relational mapper (ORM).
In any directory where you feel comfortable create a folder and open the command line in the directory. Create a python virtual environment using the command below. Once the command is done running activate the virtual environment using the command below. Now, install Flask using pip(package installer for python).
Step 1 - Install the Flask-SQLAlchemy extension. Step 2 - You need to import the SQLAlchemy class from this module. Step 3 - Now create a Flask application object and set the URI for the database to use. Step 4 - then use the application object as a parameter to create an object of class SQLAlchemy.
After some searching and testing, and based on various sources, this works for me. That's all I can say about the code quality. I'm posting it only because it might help someone. Don't hesitate to comment if you see a problem.
from sqlalchemy.event import listen
# initialization routine
# app: this Flask application
# db: the database, see the question
db_collate = 'sk_SK.UTF-8' # Slovak language for example
def load_extension(dbapi_conn, unused):
dbapi_conn.enable_load_extension(True)
dbapi_conn.load_extension('/path/to/libSqliteIcu.so')
dbapi_conn.enable_load_extension(False)
dbapi_conn.execute("SELECT icu_load_collation(?, 'ICU_EXT_1')", (db_collate,))
with app.app_context():
listen(db.engine, 'connect', load_extension)
and usage:
from sqlalchemy.sql.expression import collate
...query.order_by(collate(Table.column, 'ICU_EXT_1'))
The name ICU_EXT_1
is fully arbitrary.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With