<Guide du Rootard GeeXLab/>
SQLite3
Dernière mise à jour: 2018.12.10 par JeGX
>> Retour <<
SQLite3 est un moteur de base de données SQL très utilisé et surtout, très pratique
car il peut être embarqué dans n'importe quelle application (le célèbre navigateur Firefox utilise SQLite de manière intensive).
De plus, chaque base de données SQLite3 réside entièrement dans un simple fichier.
Pour toutes ces raisons, le support SQLite3 a été ajouté à GeeXLab depuis la version
0.22.1.
SQLite3 peut être utilisé de trois façons: soit en utilisant la librairie
gh_sqlite3
(disponible en Lua et Python), soit en utilisant
LuaSQL (intégré à GeeXLab), soit en utilisant le
module sqlite3
en Python (
#import sqlite3).
Comment Utiliser gh_sqlite3 ?
Nous allons voir comment créer une petite base de données de test stockée dans un fichier (database01.db). Cette base contient une seule table (users) avec
deux colonnes (name et age). Nous utiliserons des requêtes SQL pour manipuler la base de données.
D'abord quelques constantes:
local SQLITE_OK = 0
local SQLITE_ERROR = 1
local SQLITE_ROW = 100
local SQLITE_DONE = 101
local SQLITE_INTEGER = 1
local SQLITE_FLOAT = 2
local SQLITE_TEXT = 3
local SQLITE_BLOB = 4
Commençons par créer le fichier de la base de données (ou simplement de l'ouvrir s'il existe déjà):
local demo_dir = gh_utils.get_demo_dir()
local db_filename = demo_dir .. "database01.db"
local rc = SQLITE_OK
dbid, rc = gh_sqlite3.db_open(db_filename)
dbid est l'identifiant de la base de données que nous utiliseront dans toutes les autres fonctions de gh_sqlite3.
Créons maintenant la table users:
local sql = "DROP TABLE users"
if (gh_sqlite3.db_exec(dbid, sql) == SQLITE_ERROR) then
print("SQL error 1")
end
sql = "CREATE TABLE users (name varchar(64), age int not null)"
if (gh_sqlite3.db_exec(dbid, sql) == SQLITE_ERROR) then
print("SQL error 1")
end
Maintenant que la table users est créée, nous allons la remplir avec quelques enregistrements:
sql = "INSERT INTO users (name, age) VALUES ('toto', 12);"
if (gh_sqlite3.db_exec(dbid, sql) == SQLITE_ERROR) then
print("SQL error 2")
end
sql = "INSERT INTO users (name, age) VALUES ('John', 53);"
if (gh_sqlite3.db_exec(dbid, sql) == SQLITE_ERROR) then
print("SQL error 2")
end
sql = "INSERT INTO users (name, age) VALUES ('Viktor', 48);"
if (gh_sqlite3.db_exec(dbid, sql) == SQLITE_ERROR) then
print("SQL error 2")
end
sql = "INSERT INTO users (name, age) VALUES ('Duke', 85);"
if (gh_sqlite3.db_exec(dbid, sql) == SQLITE_ERROR) then
print("SQL error 2")
end
La base est maintenant opérationnelle. On va maintenant la lire avec une belle requête SELECT:
local sql = "SELECT * FROM users"
if (gh_sqlite3.db_prepare(dbid, sql) == SQLITE_OK) then
local num_columns = gh_sqlite3.db_get_column_count(dbid)
print("# columns: " .. num_columns)
local row = 1
rc = gh_sqlite3.db_step(dbid)
while (rc ~= SQLITE_DONE) do
if (rc == SQLITE_ROW) then
for c=0, num_columns-1 do
local type = gh_sqlite3.db_get_column_type(dbid, c)
if (type == SQLITE_TEXT) then
local v = gh_sqlite3.db_column_get_text(dbid, c)
print("Col. " .. c .. " | TEXT | " .. v)
elseif (type == SQLITE_INTEGER) then
local v = gh_sqlite3.db_column_get_int(dbid, c)
print("Col. " .. c .. " | INT | " .. v)
elseif (type == SQLITE_FLOAT) then
local v = gh_sqlite3.db_column_get_double(dbid, c)
print("Col. " .. c .. " | REAL | " .. v)
elseif (type == SQLITE_BLOB) then
local blob_ptr, blob_size = gh_sqlite3.db_column_get_blob(dbid, c)
print("Col. " .. c .. " | BLOB | " .. blob_size)
end
end
end
-- next result.
rc = gh_sqlite3.db_step(dbid)
if ((rc == SQLITE_ERROR) or (rc == SQLITE_DONE)) then
break
end
end
gh_sqlite3.db_finalize(dbid)
end
Quand la base de données n'est plus nécessaire, on peut la fermer proprement avec:
gh_sqlite3.db_close(dbid)
Le champ de type
BLOB mérite de s'y intéresser un peu plus. Un champ BLOB permet de stocker n'importe quel type de données. On peut
par exemple, y stocker le contenu d'un fichier image.
Voyons rapidement comment stocker une image .jpg dans un champ blob. Nous allons créer un table images contenant 3 champs: id, name et data.
Nous allons ensuite insérer une image jpg dans le champ blob.
local sql = "CREATE TABLE images (id INTEGER PRIMARY KEY, name varchar(64), data BLOB)"
if (gh_sqlite3.db_exec(dbid, sql) == SQLITE_ERROR) then
print("SQL error 1")
end
sql = "INSERT INTO images (name, data) VALUES (?, ?);"
if (gh_sqlite3.db_prepare(dbid, sql) == SQLITE_OK) then
local column = 1
gh_sqlite3.db_bind_text(dbid, column, "image.jpg") -- Image name
column = 2
gh_sqlite3.db_bind_blob_from_file(dbid, column, demo_dir .. "assets/image.jpg") -- Image data
rc = gh_sqlite3.db_step(dbid)
gh_sqlite3.db_finalize(dbid)
end
La fonction
db_bind_blob_from_file() fait tout le travail: elle permet très simplement de stocker le contenu de n'importe quel fichier
dans un champ blob.
On pourrait aussi utiliser les fonctions de
manipulations des buffers à la place de db_bind_blob_from_file:
sql = "INSERT INTO images (name, data) VALUES (?, ?);"
if (gh_sqlite3.db_prepare(dbid, sql) == SQLITE_OK) then
local column = 1
gh_sqlite3.db_bind_text(dbid, column, "image.jpg") -- Image name
buffer, buffer_size = gh_utils.file_buffer_create(demo_dir .. "assets/image.jpg")
column = 2
gh_sqlite3.db_bind_blob_from_buffer(dbid, column, buffer, buffer_size)
rc = gh_sqlite3.db_step(dbid)
gh_sqlite3.db_finalize(dbid)
gh_utils.file_buffer_kill(buffer)
end
On peut ensuite créer une texture à partir du champ blob précédant avec la fonction
create_from_buffer de la librairie
gh_texture:
local buffer, buffer_size = gh_sqlite3.db_column_get_blob(dbid, c)
upload_to_gpu = 1
pixel_format = U8_RGBA
texture_unit = 0
create_srv = 0 -- for d3d12.
gen_mipmaps = 1
compressed_format = ""
free_cpu_memory = 1
gh_texture.create_from_buffer(buffer, buffer_size, upload_to_gpu, pixel_format, texture_unit, create_srv, gen_mipmaps, compressed_format, free_cpu_memory)