Belle II Software development
using_databases.py
1
8from caf.database import SQLiteDB
9import pathlib
10
11# Moving over to pathlib objects has nice benefits like being able to avoid a lot of os.path.join/exists calls
12database_file = pathlib.Path("example.db")
13
14if database_file.exists():
15 print("Removing old database file")
16 # Slightly odd api for removing a file. Use rmdir() for directories
17 database_file.unlink()
18
19# The SQLiteDB is made as a context manager so it will open a connection and close it for you
20# If the database doesn't exist you need to pass in a 'schema' that describes the tables to create
21# If the database already exists, no table creation is done so you don't need to pass in a schema
22with SQLiteDB(database_file, schema={"users": ["name text primary key", "age int", "gender text", "email text"]}) as db:
23 # Database file and tables are created and committed automatically when opening
24 # Can now insert some rows
25 db.query("INSERT INTO users VALUES (?,?,?,?)", ("Tom", 25, "M", "tom@fakedomain.edu.au"))
26 db.query("INSERT INTO users VALUES (?,?,?,?)", ("Charlotte", 37, "F", "charlotte@fakedomain.edu.au"))
27 db.query("INSERT INTO users VALUES (?,?,?,?)", ("Taya", 36, "F", "taya@fakedomain.edu.au"))
28 db.query("INSERT INTO users VALUES (?,?,?,?)", ("Simon", 36, "O", "simon@fakedomain.edu.au"))
29 # Need to commit the changes using the connection object
30 db.conn.commit()
31 # Can now query for the values. It returns a cursor object which can be used to get the values
32 cursor1 = db.query("SELECT name, email FROM users WHERE gender=?", ("F"))
33 cursor2 = db.query("SELECT name, email FROM users WHERE gender=?", ("M"))
34
35 print("Returned rows:")
36
37 # You could iterate over the cursor to return each row
38 def iterate_cursor():
39 for row in cursor1:
40 print(" ", row)
41
42 # Or you could just get the first entry remaining in the statement (can be called multiple times)
43 def fetch_singles():
44 print(" ", cursor1.fetchone())
45 print(" ", cursor1.fetchone())
46 print(" ", cursor1.fetchone()) # Returns None as there are no matching rows left
47
48 # Or you could get all rows at once, this is not advised when you expect thousands of rows. But for a smaller number its fine
49 def fetch_all():
50 for row in cursor1.fetchall():
51 print(" ", row)
52
53 iterate_cursor()
54
55 # We are deliberately not using cursor2 at all. It should therefore be closed because otherwise it is an unfinished statement
56 # cursor1 doesn't need to be closed because its results were fetched, even if only one of them
57 cursor2.close()
58
59print("Database connection is now closed. It will have automatically committed any remaining changes.")
60print("Removing database file.")
61database_file.unlink()