[Django/SQLite] Hoe laad ik een custom extension in Django?

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • MacNetron
  • Registratie: Januari 2014
  • Laatst online: 07-07 16:02

MacNetron

Ondertitel? Bovenavatar!

Topicstarter
Ik heb een SQLite database die ik gebruik voor een Django webapplicatie.
Buiten de Django Models voor database communicatie heb ik een aantal queries geschreven die gebruik maken van "geavanceerde" math die standaard niet in SQLite zitten, te weten SQRT en POWER.

Zelf de extension libsqlitefunctions gecompileerd en deze in een SQLite ide geladen om de queries te testen:
SQL:
1
2
SELECT load_extension('C:\dev\SQLiteStudio\plugins\libsqlitefunctions.dll')
SELECT SQRT(9)


Werkt perfect, queries gemaakt, gecheckt, juiste resultaat. Hoera.

Maar, hoe laad ik nu de extension in Django?

Python:
1
2
3
4
5
6
from django.db import connection
...
    cursor = connection.cursor()
    cursor.execute("SELECT load_extension('C:\dev\SQLiteStudio\plugins\libsqlitefunctions.dll')")
    cursor.execute("SELECT SQRT(9)")
...


Dit levert een stacktrace op:
code:
1
django.db.utils.OperationalError: not authorized


Het is dus blijkbaar niet toegestaan om de extension aan te zetten. Ik vind uiteindelijk wel een "SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION" setting, maar heb geen idee hoe ik dat dan kan zetten.

Iemand een idee hoe ik deze extension in Django kan laden?

"Sir! The people! They can't help falling in love with you!" - Civ2 Luxury Advisor

Beste antwoord (via MacNetron op 10-02-2017 10:01)


  • Z-Dragon
  • Registratie: December 2002
  • Laatst online: 16:03
Heb je al gekeken of het je zonder Django lukt, in niets meer dan een Python-shell? Ik vermoed dat dit probleem helemaal los staat van Django. Dat helpt je met zoeken.

Sla de documentatie van de sqlite3-module er eens op na, en dan met name sqlite3.Connection.enable_load_extension en sqlite3.Connection.load_extension. De eerstgenoemde stuurt de instelling aan die je zelf al had gevonden (standaard uitgeschakeld, wat je foutmelding goed te verklaren maakt). Het laden, dat je via de Cursor probeerde te doen, moet dus eveneens via de verbinding.

Andere zaken om aan te denken als het dan nog niet werkt:
  • De mogelijkheid dat je SQLite gecompileerd is zonder ondersteuning voor dynamisch laadbare uitbreidingen (zoals beschreven in een voetnoot)
  • Dat je een 32-bit DLL gebruikt voor 32-bit Python of een 64-bit DLL voor een 64-bit Python
  • Dat je in de juiste working directory zit als de DLL afhankelijkheden heeft (met os.chdir of door de DLL en de bijbehorende bestanden op een andere plaats te zetten)
Bij gebrek aan jouw eigen DLL heb ik getest met Spatialite – wellicht voor jou ook een idee om een kant en klare oplossing te gebruiken die alles heeft wat je nodig hebt en meer – en Python 3.6; geen enkel probleem.

Tot slot kun je voor het aardig eens proberen of het (deels) via Python (in plaats van de DLL) echt te traag is, door de Python-functies bruikbaar te maken in SQLite met sqlite3.Connection.create_function. Als je geen (wrappende) eigen functies schrijft, maar direct naar de ingebouwde (math.sqrt en math.pow) wijst, zou het wel eens mee kunnen vallen.

Om toch nog even terug te komen op Django: het netst zou zijn om de extra functies meteen te laden/maken wanneer er verbinding met de database wordt gemaakt. Dat kan zo. Dan hoef je nooit na te denken of die functies wel beschikbaar zijn en kun je altijd via Django in plaats van er omheen werken.

[ Voor 58% gewijzigd door Z-Dragon op 10-02-2017 15:54 ]

^ Wat hij zegt.

Alle reacties


Acties:
  • 0 Henk 'm!

  • Gonadan
  • Registratie: Februari 2004
  • Laatst online: 17:39

Gonadan

Admin Beeld & Geluid, Harde Waren
Krijg je die fout al bij de eerste regel van het laden, of pas als je de wortel trekt? Even één voor één proberen om het zeker te weten.

Als het aan het laden ligt, kan het dan met gebruikersrechten te maken hebben?

Look for the signal in your life, not the noise.

Canon R6 | 50 f/1.8 STM | 430EX II
Sigma 85 f/1.4 Art | 100-400 Contemporary
Zeiss Distagon 21 f/2.8


Acties:
  • 0 Henk 'm!

  • MacNetron
  • Registratie: Januari 2014
  • Laatst online: 07-07 16:02

MacNetron

Ondertitel? Bovenavatar!

Topicstarter
Foutmelding treedt op bij het laden van de extension.
Het uitvoeren van de SQRT zou iets van een : "SQRT not supported" oid opleveren.

Je triggert me wel met gebruikersrechten, als in dat Django wellicht niet als dezelfde user rechten zou runnen als een ide?

"Sir! The people! They can't help falling in love with you!" - Civ2 Luxury Advisor


Acties:
  • 0 Henk 'm!

  • Gonadan
  • Registratie: Februari 2004
  • Laatst online: 17:39

Gonadan

Admin Beeld & Geluid, Harde Waren
Inderdaad, zoiets. Zelf heb ik nooit met Django gespeeld maar vaak hebben dit soort meldingen te maken met een andere usercontext of omgeving die niet hetzelfde is. Hoeft niet zo te zijn hoor, maar dat was het eerste waar ik aan dacht.

Look for the signal in your life, not the noise.

Canon R6 | 50 f/1.8 STM | 430EX II
Sigma 85 f/1.4 Art | 100-400 Contemporary
Zeiss Distagon 21 f/2.8


Acties:
  • 0 Henk 'm!

  • MacNetron
  • Registratie: Januari 2014
  • Laatst online: 07-07 16:02

MacNetron

Ondertitel? Bovenavatar!

Topicstarter
Hum, SQLite heeft out-of-the-box eigenlijk niets met gebruikersrechten.
In de settings van Django wordt bij het opbouwen van de connectie ook niets gezet van User of Password.

Ook even geprobeerd in een "cmd-prompt as administrator" te kijken of deze meer rechten heeft. Zelfde error.
Zal vanavond thuis nog even checken of op Linux hetzelfde probleem optreedt.

"Sir! The people! They can't help falling in love with you!" - Civ2 Luxury Advisor


Acties:
  • 0 Henk 'm!

  • Gonadan
  • Registratie: Februari 2004
  • Laatst online: 17:39

Gonadan

Admin Beeld & Geluid, Harde Waren
Draai je bepaalde componenten als service of binnen een webserver o.i.d.? Of is alles gewoon op jouw eigen afroep op de commandline?

Look for the signal in your life, not the noise.

Canon R6 | 50 f/1.8 STM | 430EX II
Sigma 85 f/1.4 Art | 100-400 Contemporary
Zeiss Distagon 21 f/2.8


Acties:
  • 0 Henk 'm!

  • MacNetron
  • Registratie: Januari 2014
  • Laatst online: 07-07 16:02

MacNetron

Ondertitel? Bovenavatar!

Topicstarter
Django draai je, zeker als je nog in development-mode zit, of van de command line of vanuit de ide (PyCharm in mijn geval). Dat is eigenlijk identiek aan hoe je bijvoorbeeld Tomcat kan draaien, command line of vanuit bijv. Eclipse.

python3 manage.py runserver


En dan nu het grappige aan Linux:
Python:
1
    cursor.execute("SELECT load_extension('/mnt/sdb/Stack/projects/eddb.io/sqlite/libsqlitefunctions.so')")

Jawel, onder Linux wordt de extension gewoon geladen en kan ik mijn query met SQRT en POWER gewoon uitvoeren...

Het probleem zit hem dus alleen onder windows... Jammer, want dan kan ik niet op de bank op de (Windows)tablet hieraan werken.
Gelukkig moet de "productie-server" een Raspberry Pi worden :)

"Sir! The people! They can't help falling in love with you!" - Civ2 Luxury Advisor


Acties:
  • 0 Henk 'm!

  • Merethil
  • Registratie: December 2008
  • Laatst online: 19:19
MacNetron schreef op donderdag 9 februari 2017 @ 20:31:
Django draai je, zeker als je nog in development-mode zit, of van de command line of vanuit de ide (PyCharm in mijn geval). Dat is eigenlijk identiek aan hoe je bijvoorbeeld Tomcat kan draaien, command line of vanuit bijv. Eclipse.

python3 manage.py runserver


En dan nu het grappige aan Linux:
Python:
1
    cursor.execute("SELECT load_extension('/mnt/sdb/Stack/projects/eddb.io/sqlite/libsqlitefunctions.so')")

Jawel, onder Linux wordt de extension gewoon geladen en kan ik mijn query met SQRT en POWER gewoon uitvoeren...

Het probleem zit hem dus alleen onder windows... Jammer, want dan kan ik niet op de bank op de (Windows)tablet hieraan werken.
Gelukkig moet de "productie-server" een Raspberry Pi worden :)
Waarom laat je eigenlijk je "database engine" (voor zover je daar van kan spreken bij sqlite :P) die wiskundige berekeningen doen? Python is daar voor zover ik weet veel sneller in, en het voorkomt dit soort dependency issues.

Acties:
  • 0 Henk 'm!

  • MacNetron
  • Registratie: Januari 2014
  • Laatst online: 07-07 16:02

MacNetron

Ondertitel? Bovenavatar!

Topicstarter
Merethil schreef op donderdag 9 februari 2017 @ 20:59:
[...]


Waarom laat je eigenlijk je "database engine" (voor zover je daar van kan spreken bij sqlite :P) die wiskundige berekeningen doen? Python is daar voor zover ik weet veel sneller in, en het voorkomt dit soort dependency issues.
Ik zal morgen eens een testje doen, maar ik geloof niet dat Python binnen 0.1 seconden van 20000+ star-systems uit kan zoeken wat de afstand in lichtjaar is tov. HIP87414 en van alle binnen 50 lichtjaar de prijzen van 3 bepaalde commodities op de star-stations binnen dit system ophaalt en sorteert. Dat is toch meer een database klusje :P

Zie ook Elite Dangerous forum

"Sir! The people! They can't help falling in love with you!" - Civ2 Luxury Advisor


Acties:
  • 0 Henk 'm!

  • EngineerCoding
  • Registratie: Oktober 2015
  • Laatst online: 31-12-2023
Misschien niet een directe oplossing van het probleem, maar waarom gebruik je niet gewoon een andere rdbms welke wel dit soort functies supporten. Natuurlijk spelen tradeoffs een rol, maar bij webservers is het volgens mij niet gebruikelijk om sqlite te gebruiken.

Acties:
  • 0 Henk 'm!

  • MacNetron
  • Registratie: Januari 2014
  • Laatst online: 07-07 16:02

MacNetron

Ondertitel? Bovenavatar!

Topicstarter
Omdat dat de lichtste database engine is, perfect voor de beperkte resources van een Raspberry Pi.
Daarnaast is het voor development mode ideaal, omdat er alleen een enkel bestand met de complete inhoud gedeeld hoeft te worden tussen mijn pc's/devices.
Ik heb geen client-server over verschillende computers, geen high-volume website, geen multi-concurrent-writers, en een beperkte grootte van de database. SQLite zou dus ruim voldoende moeten zijn.

"Sir! The people! They can't help falling in love with you!" - Civ2 Luxury Advisor


Acties:
  • Beste antwoord
  • +1 Henk 'm!

  • Z-Dragon
  • Registratie: December 2002
  • Laatst online: 16:03
Heb je al gekeken of het je zonder Django lukt, in niets meer dan een Python-shell? Ik vermoed dat dit probleem helemaal los staat van Django. Dat helpt je met zoeken.

Sla de documentatie van de sqlite3-module er eens op na, en dan met name sqlite3.Connection.enable_load_extension en sqlite3.Connection.load_extension. De eerstgenoemde stuurt de instelling aan die je zelf al had gevonden (standaard uitgeschakeld, wat je foutmelding goed te verklaren maakt). Het laden, dat je via de Cursor probeerde te doen, moet dus eveneens via de verbinding.

Andere zaken om aan te denken als het dan nog niet werkt:
  • De mogelijkheid dat je SQLite gecompileerd is zonder ondersteuning voor dynamisch laadbare uitbreidingen (zoals beschreven in een voetnoot)
  • Dat je een 32-bit DLL gebruikt voor 32-bit Python of een 64-bit DLL voor een 64-bit Python
  • Dat je in de juiste working directory zit als de DLL afhankelijkheden heeft (met os.chdir of door de DLL en de bijbehorende bestanden op een andere plaats te zetten)
Bij gebrek aan jouw eigen DLL heb ik getest met Spatialite – wellicht voor jou ook een idee om een kant en klare oplossing te gebruiken die alles heeft wat je nodig hebt en meer – en Python 3.6; geen enkel probleem.

Tot slot kun je voor het aardig eens proberen of het (deels) via Python (in plaats van de DLL) echt te traag is, door de Python-functies bruikbaar te maken in SQLite met sqlite3.Connection.create_function. Als je geen (wrappende) eigen functies schrijft, maar direct naar de ingebouwde (math.sqrt en math.pow) wijst, zou het wel eens mee kunnen vallen.

Om toch nog even terug te komen op Django: het netst zou zijn om de extra functies meteen te laden/maken wanneer er verbinding met de database wordt gemaakt. Dat kan zo. Dan hoef je nooit na te denken of die functies wel beschikbaar zijn en kun je altijd via Django in plaats van er omheen werken.

[ Voor 58% gewijzigd door Z-Dragon op 10-02-2017 15:54 ]

^ Wat hij zegt.


Acties:
  • 0 Henk 'm!

  • MacNetron
  • Registratie: Januari 2014
  • Laatst online: 07-07 16:02

MacNetron

Ondertitel? Bovenavatar!

Topicstarter
Z-Dragon schreef op donderdag 9 februari 2017 @ 22:33:[..]
• Dat je een 32-bit DLL gebruikt voor 32-bit Python of een 64-bit DLL voor een 64-bit Python
[..]
Met de sysinternals sigcheck gekeken en de dll die gebakken was door gcc was 32 bit. De pc met problemen is een win7 64 bit...
Een 64 bit gcc geinstalleerd, libsqlitefunctions.dll opnieuw gemaakt en jawel het werkt nu correct met enigzins aangepaste code:
Python:
1
2
3
4
5
from django.db import connection
...
    connection.connection.enable_load_extension(True)
    connection.connection.load_extension('path/to/libsqlitefunctions-64b.dll')
    connection.connection.enable_load_extension(False)

De enable_load_extension is op Windows nog steeds benodigd, want anders toch nog steeds "Not authorized" meldingen. Dit had ik gisteren op Linux niet nodig.

Zal, nu het werkt, eens kijken naar 1x uitvoeren bij eerste call. Dat heeft nu pas zin.

"Sir! The people! They can't help falling in love with you!" - Civ2 Luxury Advisor


Acties:
  • 0 Henk 'm!

  • Z-Dragon
  • Registratie: December 2002
  • Laatst online: 16:03
Onder Windows zul je SQLite gebruiken zoals deze met Python wordt meegeleverd. Linux zal 'm system-wide al hebben, en dan kunnen de standaardinstellingen anders zijn (afhankelijk van je distro etc.). Het lijkt me goed gebruik om altijd de mogelijkheid tot laden in en uit te schakelen; in het slechtste geval doet het niks en het maakt de code een stuk robuuster.

En voor de duidelijkheid: of het OS 32-bit of 64-bit is maakt uiteindelijk niet veel uit. Het gaat er om of het programma dat de DLL aanroept 32-bit of 64-bit is. Je had ook 32-bit Python op 64-bit Windows kunnen draaien en dan moet de rest ook 32-bit zijn. Maar waarschijnlijk heb je 64-bit Python = 64-bit SQLite = 64-bit SQLite-uitbreiding.

[ Voor 32% gewijzigd door Z-Dragon op 10-02-2017 15:57 ]

^ Wat hij zegt.

Pagina: 1