sqlc_gen_dart

Um plugin para SQLC que gera código Dart type-safe a partir de consultas SQL.

🇺🇸 English Version

🚀 Características

  • Type-safe: Gera código Dart fortemente tipado a partir de suas consultas SQL
  • Suporte a PostgreSQL e SQLite: Funciona com ambos os bancos de dados
  • Geração automática de modelos: Cria classes Dart para suas tabelas automaticamente
  • Queries prontas para uso: Métodos assíncronos com tratamento de erros incluído
  • Gerenciamento de conexão: Pool de conexões configurável para PostgreSQL
  • Exceções customizadas: SqlcException para tratamento de erros consistente
  • Suporte a tipos complexos: UUID, DateTime, tipos nullable e mais

📦 Instalação

Pré-requisitos

  1. Dart SDK 3.10.0 ou superior - Instalar Dart
  2. SQLC - Instalar SQLC

Instalando o Plugin

dart install sqlc_gen_dart

Nota: A partir do Dart 3.10.0, use dart install em vez de dart pub global activate.

🔧 Configuração

Crie um arquivo sqlc.yaml na raiz do seu projeto:

PostgreSQL

version: "2"

plugins:
  - name: dart
    process:
      cmd: sqlc-gen-dart
      format: json

sql:
  - schema: "schema.sql"
    queries: "query.sql"
    engine: "postgresql"
    codegen:
      - plugin: dart
        out: lib/db

SQLite

version: "2"

plugins:
  - name: dart
    process:
      cmd: sqlc-gen-dart
      format: json

sql:
  - schema: "schema.sql"
    queries: "query.sql"
    engine: "sqlite"
    codegen:
      - plugin: dart
        out: lib/db

📝 Uso

1. Defina seu schema SQL

schema.sql:

CREATE TABLE users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name TEXT NOT NULL,
    username TEXT UNIQUE NOT NULL,
    email TEXT UNIQUE NOT NULL,
    password TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

2. Escreva suas queries

query.sql:

-- name: GetUserById :one
SELECT * FROM users WHERE id = $1 LIMIT 1;

-- name: ListUsers :many
SELECT * FROM users ORDER BY name;

-- name: InsertUser :one
INSERT INTO users (name, username, email, password)
VALUES ($1, $2, $3, $4)
RETURNING *;

-- name: UpdateUser :exec
UPDATE users
SET name = COALESCE($2, name),
    username = COALESCE($3, username),
    email = COALESCE($4, email),
    password = COALESCE($5, password)
WHERE id = $1;

-- name: DeleteUser :exec
DELETE FROM users WHERE id = $1;

3. Gere o código

sqlc generate

4. Use o código gerado

PostgreSQL:

import 'package:your_app/db/sqlc_dart.dart';

void main() async {
  // Conecte ao banco de dados
  final db = SqlcDart('postgresql://user:password@localhost:5432/mydb');

  // Insira um usuário
  final user = await db.queries.insertUser(
    name: 'João Silva',
    username: 'joao',
    email: 'joao@example.com',
    password: 'hashed_password',
  );

  print('Usuário criado: ${user.name}');

  // Busque um usuário
  final foundUser = await db.queries.getUserById(id: user.id);
  print('Usuário encontrado: ${foundUser.email}');

  // Liste todos os usuários
  final users = await db.queries.listUsers();
  for (final u in users) {
    print('- ${u.name} (${u.username})');
  }

  // Atualize um usuário
  await db.queries.updateUser(
    id: user.id,
    name: 'João Pedro Silva',
    username: 'joao',
    email: 'joao@example.com',
    password: 'new_hashed_password',
  );

  // Delete um usuário
  await db.queries.deleteUser(id: user.id);
}

SQLite:

import 'package:your_app/db/sqlc_dart.dart';

void main() async {
  // Conecte ao banco de dados
  final db = SqlcDart('myapp.db');

  // Use as mesmas queries...
  final user = await db.queries.insertUser(
    name: 'Maria Santos',
    username: 'maria',
    email: 'maria@example.com',
    password: 'hashed_password',
  );
}

🎯 Código Gerado

O plugin gera um único arquivo sqlc_dart.dart contendo:

  • Classes de modelo: Representam suas tabelas com tipos Dart apropriados
  • Classe SqlcDart: Gerencia a conexão com o banco de dados
  • Classe Queries: Contém todos os métodos para executar suas queries
  • Classe SqlcException: Para tratamento de erros consistente
  • Tipos customizados: Como Uuid com validação

Exemplo de classe gerada:

class User {
  final Uuid id;
  final String name;
  final String username;
  final String email;
  final String password;
  final DateTime? createdAt;
  final DateTime? updatedAt;

  const User({
    required this.id,
    required this.name,
    required this.username,
    required this.email,
    required this.password,
    this.createdAt,
    this.updatedAt,
  });

  factory User.fromMap(Map<String, dynamic> map) { /* ... */ }
  Map<String, dynamic> toMap() { /* ... */ }
}

⚙️ Configuração Avançada

Pool de Conexões (PostgreSQL)

O plugin configura automaticamente um pool de conexões com valores padrão:

  • max_connection_count: 10
  • max_connection_age: 3600 segundos

Você pode personalizar via URL de conexão:

final db = SqlcDart(
  'postgresql://user:password@localhost:5432/mydb?max_connection_count=20&max_connection_age=7200'
);

🛠️ Dependências

O código gerado requer as seguintes dependências no seu pubspec.yaml:

Para PostgreSQL:

dependencies:
  postgres: ^3.0.0

Para SQLite:

dependencies:
  sqlite3: ^2.0.0

📚 Recursos Adicionais

🤝 Contribuindo

Contribuições são bem-vindas! Sinta-se à vontade para abrir issues ou pull requests.

📄 Licença

Este projeto está sob a licença MIT.

Libraries