As a Flutter developer, I've worked with various local databases like sqflite and Drift (Moor), but when I discovered ToStore, I was genuinely impressed. If you're looking for a database that combines the simplicity of NoSQL with the power of SQL-like queries and automatic schema upgrades, you're in for a treat!
🔥 Why I Chose ToStore
I was searching for a database that could:
- Handle schema upgrades automatically (without writing painful migration scripts).
- Support fluent query building (like Firestore but for local storage).
- Be easy to use with Dart & Flutter.
After testing ToStore, I found it to be exactly what I needed. Let me walk you through its features and some real-world examples.
🚀 Key Features of ToStore
1️⃣ Automatic Schema Upgrades
One of the biggest headaches when working with databases is handling schema changes. With ToStore, you just define your latest schema, and it takes care of the migrations!
final db = ToStore(
version: 2,
schemas: [
const TableSchema(
name: 'users',
primaryKey: 'id',
fields: [
FieldSchema(name: 'id', type: DataType.integer, nullable: false),
FieldSchema(name: 'username', type: DataType.text, nullable: false),
FieldSchema(name: 'email', type: DataType.text, nullable: false),
],
indexes: [
IndexSchema(fields: ['username'], unique: true),
],
),
],
);
await db.initialize();
If you later need to modify your schema, you can do this inside onUpgrade
:
onUpgrade: (db, oldVersion, newVersion) async {
if (oldVersion == 1) {
await db.updateSchema('users')
.addField("age", type: DataType.integer)
.renameField("email", "email_address");
}
}
No need to manually write SQL migration scripts! ToStore does it for you.
2️⃣ Fluent Query Builder
Unlike sqflite
, which requires raw SQL queries, ToStore makes it easy to fetch data using chained queries:
final users = await db.query('users')
.where('age', '>', 20)
.where('username', 'like', '%John%')
.orderByDesc('age')
.limit(10);
This feels much cleaner and is easy to read. If you've used Firestore before, it will feel very familiar.
3️⃣ SQL & Map-Based Queries
ToStore supports both SQL-style and Map-style queries.
✅ SQL Query
final users = await db.queryBySql(
'users',
where: 'age > 20 AND username LIKE "%John%"',
limit: 10
);
✅ Map Query
final users = await db.queryByMap(
'users',
where: {
'age': {'>=': 30},
'username': {'like': '%John%'},
},
orderBy: ['age'],
limit: 10,
);
If you're coming from a NoSQL background, map queries make it even easier.
4️⃣ Batch Operations & Indexing
For performance optimization, ToStore lets you insert multiple records at once:
await db.batchInsert('users', [
{'id': 1, 'username': 'John', 'age': 30},
{'id': 2, 'username': 'Mary', 'age': 25},
]);
Indexes are also supported for faster lookups:
const TableSchema(
name: 'users',
primaryKey: 'id',
fields: [...],
indexes: [
IndexSchema(fields: ['username'], unique: true),
],
);
🆚 ToStore vs Other Databases
Feature | ToStore | Drift (Moor) | sqflite |
---|---|---|---|
Schema Definition | ✅ JSON-like format | ✅ Annotated Dart | ❌ Manual SQL |
Auto Schema Upgrade | ✅ Automatic | ❌ Manual | ❌ Manual |
Fluent Queries | ✅ .where().limit() |
✅ .where() |
❌ Raw SQL Only |
Batch Operations | ✅ Supported | ✅ Supported | ✅ Supported |
SQL Queries | ✅ queryBySql() |
✅ customSelect() |
✅ rawQuery() |
Type Safety | ✅ (Schema-based) | ✅ (Dart types) | ❌ (Raw SQL) |
ToStore is a great alternative if you want a database that's easy to use while still being powerful.
✨ My Final Thoughts
I've been using ToStore in my Flutter projects, and I love how clean and efficient it is. If you're looking for a modern, SQL-like database with automatic schema upgrades, I highly recommend trying ToStore.
If you're using it in your projects, let me know your thoughts in the comments! 🚀