from fastlite import *Test Insert Operations
Setup
Note: Make sure to use fastlite’s database() here
db = database(':memory:')class People: id: int; name: strpeople = db.create(People, pk='id')Test Single Inserts
Here we test insert()
Test Cases for insert() Where Nothing Is Inserted
Test that calling insert() without any parameters doesn’t change anything, and returns nothing
people.insert(){}
Test None doesn’t change anything.
count = people.count
assert people.insert(None) == {}
assert people.count == countTest empty dict doesn’t change anything
count = people.count
assert people.insert({}) == {}
assert people.count == count# Test empty dataclass doesn't change anything
PersonDC = people.dataclass()
count = people.count
assert people.insert(PersonDC()) == {}
assert people.count == count# Test empty class instance doesn't change anything
class EmptyPerson: pass
count = people.count
assert people.insert(EmptyPerson()) == {}
assert people.count == countSingle Insert Types
Test insert with keyword argument. Result should be the inserted item.
assert people.insert(name='Alice').name == 'Alice'Test insert with dataclass
assert people.insert(People(name='Bobba')).name == 'Bobba'Test with regular class
class Student: pass
student = Student()
student.name = 'Charlo'
assert people.insert(student).name == 'Charlo'Verify count is 3
assert people.count == 3None and Empty String Handling
SQLite makes a clear distinction between NULL (represented as None in Python) and an empty string (’’). Unlike some popular Python ORMs, fastlite preserves this distinction because:
- NULL represents “unknown” or “missing” data
- Empty string represents “known to be empty”
These are semantically different concepts, and maintaining this distinction allows users to make appropriate queries (e.g. WHERE name IS NULL vs WHERE name = ''). The fact that fastlite preserves this distinction in both directions (Python->SQLite and SQLite->Python) is good database design.
Test inserting a record with name set to None
result = people.insert(name=None)
assert result.name is NoneTest with empty string
result = people.insert(name='')
assert result.name == ''assert people.get(pk_values=4).name == NoneRemember, get() is for getting single items. The following would not work here. pk_values can be a list only for tables with compound primary keys.
# people.get(pk_values=[4,5])Other Cases
Test with special characters
assert people.insert(name='O\'Connor').name == "O'Connor"
assert people.insert(name='José').name == 'José'Test id auto-increment
p1 = people.insert(name='Test1')
p2 = people.insert(name='Test2')
assert p2.id == p1.id + 1Test dict insert
assert people.insert({'name': 'Dict Test'}).name == 'Dict Test'Test that extra fields raise apsw.SqlError
from sqlite3 import OperationalErrortry:
p = people.insert(name='Extra', age=25, title='Dr')
except SQLError as e:
assert e.args[0] == 'table people has no column named age'Test Multiple Inserts
Here we test insert_all()
Test cases for insert_all() where nothing is changed
Test empty list doesn’t change anything
count = people.count
people.insert_all([])
assert people.count == countTest other empty iterables don’t change anything
count = people.count
people.insert_all(iter([])) # empty iterator
people.insert_all(set()) # empty set
people.insert_all(tuple()) # empty tuple
assert people.count == countTest that lists of None don’t change anything.
count = people.count
assert people.insert_all([None, None]) == people
assert people.result == []
assert people.count == countTest cases for insert_all() where records are inserted
Test that a list containing both None and a valid records only inserts the valid record.
count = people.count
people.insert_all([None, None, None, None, None, dict(name='Dermot')])
assert people.count == count + 1Test list of dicts
count = people.count
data = [{'name': 'Bulk1'}, {'name': 'Bulk2'}, {'name': 'Bulk3'}]
people.insert_all(data)
assert people.count == len(data) + countTest insert_all with a list of dataclass instances to insert
count = people.count
Person = people.dataclass()
data = [Person(name=f'DC{i}') for i in range(3)]
people.insert_all(data)
assert people.count == count + 3Test list of regular class instances
count = people.count
class Student:
def __init__(self, name): self.name = name
students = [Student(f'Student{i}') for i in range(3)]
people.insert_all(students)
assert people.count == count + 3Edge Cases
Test mixed types in list
count = people.count
Person = people.dataclass()
mixed_data = [
{'name': 'Dict1'},
Person(name='DC1'),
Student('Student1')
]
people.insert_all(mixed_data)
assert people.count == count + 3Test None/empty strings in bulk insert
count = people.count
null_data = [
{'name': None},
{'name': ''},
{'name': 'Regular'}
]
people.insert_all(null_data)
assert people.count == count + 3Test with special characters in bulk
count = people.count
special_data = [
{'name': "O'Brien"},
{'name': 'José'},
{'name': '张伟'}
]
res = people.insert_all(special_data)
assert people.count == count + 3Test error on invalid column
try:
people.insert_all([{'name': 'Valid'}, {'invalid_col': 'Bad'}])
except SQLError as e:
assert 'no column named invalid_col' in str(e)