Skip to content

nicozsd/SQLManager

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

130 Commits
 
 
 
 
 
 
 
 

Repository files navigation

SQLManager - Sistema de Gerenciamento de Banco de Dados

Sistema reutilizável para gerenciamento de conexões de banco de dados, validações de dados (EDTs e BaseEnums) e controle de tabelas e views.

Sumário

Características

  • Pool de Conexões: Gerenciamento eficiente de conexões com banco de dados
  • Transações Isoladas: Sistema de transações similar ao KNEX.js
  • Validações Extensíveis: Sistema de EDTs (Extended Data Types) com regex customizáveis
  • BaseEnums: Sistema de enumerações com validação integrada
  • Configuração Flexível: Suporte a múltiplos projetos sem modificar o Core
  • Type Safety: Validações de tipo e formato em runtime
  • Model Generator: Sistema automático de geração de modelos baseado no banco de dados
  • AutoRouter: Geração automática de endpoints RESTful para CRUD
  • Suporte a Tables e Views: Controllers para tabelas (CRUD completo) e views (leitura)

Instalação

Como Repositório Externo

pip install git+https://github.com/nicozsd/SQLManager.git

# Ou adicione ao requirements.txt
git+https://github.com/nicozsd/SQLManager.git

ATENÇÃO: O pip install executa automaticamente o gerador de modelos durante a instalação. Certifique-se de que:

  • Seu arquivo .env está configurado com as credenciais do banco de dados (variáveis: DB_SERVER, DB_DATABASE, DB_USER, DB_PASSWORD)
  • A pasta src/ existe na raiz do seu projeto
  • Todas as tabelas e views e views no banco possuem o campo RECID (tipo BIGINT)

Exemplo do arquivo .env:

DB_SERVER=localhost
DB_DATABASE=MeuBanco
DB_USER=admin
DB_PASSWORD=senha123
DB_DRIVER="DRIVER"

Se não houver .env
Utilizar os parametros diretamento no comando CMD/Powershell Parametros:

  • --server: Servidor do banco de dados.
  • --database: Banco de dados.
  • ---user: Usuário do banco de dados.
  • --password: Senha do banco de dados.
  • --driver: Driver ODBC para SQL Server (ex: 'ODBC Driver 17 for SQL Server').
python -m SQLManager._model._model_update --server xxx --database xxx --user xxx --password xxx

NOTA: O SQLManager será instalado no ambiente virtual (.venv) do seu projeto, não na pasta src/.

Passo Obrigatório: Gerar os Modelos

NOTA: Se você instalou via pip install, os modelos já foram gerados automaticamente durante a instalação. Este comando só é necessário se você quiser regenerar ou atualizar os modelos.

Após instalar, rode o gerador de modelos para criar as pastas e arquivos necessários:

python -m SQLManager._model._model_update

Esse comando irá criar (ou atualizar) automaticamente as seguintes pastas e arquivos dentro de src/model/:

  • src/model/EDTs/ → EDTs customizados (tipos de dados validados)
  • src/model/enum/ → Enums customizados (tipos enumerados)
  • src/model/tables/ → Classes de tabelas baseadas no banco
  • src/model/views/ → Classes de views baseadas no banco
  • src/model/views/ → Classes de views baseadas no banco

Importante:

  • O Enum DataType e o EDT Recid são obrigatórios e sempre serão gerados automaticamente.
  • O gerador sincroniza os campos das tabelas e views e views do banco com os arquivos Python.
  • Não edite manualmente arquivos gerados, exceto para customizações documentadas.

Importação do Pacote

Após instalar, use:

from SQLManager import connection, controller, CoreConfig
# ou
from SQLManager.connection import database_connection
from SQLManager.controller import EDTController, TableController, ViewController, TableController, ViewController

Atualizando o SQLManager

Para atualizar para a versão mais recente, execute:

pip install --upgrade --force-reinstall git+https://github.com/nicozsd/SQLManager.git

Patch Notes

Issues

Remodelagem do tableController

Issue: #1-TableController Remodel
Solution Development document

Issue: #3-AutoRoutes
Solution Development document

Issue: #4-ViewController
Solution Development document

Issue: #6-UpdateModel
Solution Development document

Versão 4.0.0 (27/02/2026)

AutoRouter - Refatoração do Decorator:

  • ✅ Decorator _pre_handle refatorado com inspect.signature para mapeamento robusto de argumentos
  • ✅ Suporte a argumentos nomeados e posicionais
  • ✅ Injeção automática de dependências (_table, _table_config)
  • ✅ Cache de configurações de tabelas (uppercase normalizado)
  • ✅ Método _get_table_class_by_name() separado para reutilização
  • ✅ Testes unitários completos (test_AutoRouter.py)
  • ✅ Documentação expandida no Issue3_Note.md

Arquivos modificados:

  • SQLManager/controller/RouterController.py
  • SQLManager/tests/test_AutoRouter.py
  • SQLManager/__init__.py

Versão 2.0.0 (12/01/2026)

BREAKING CHANGES:

  • TableController refatorado com API fluente tipo SQLAlchemy
  • Acesso direto aos valores de campos (sem .value)
  • WHERE usando operadores nativos ao invés de dicionários
  • JOIN simplificado com .on() e operadores

NOVIDADES:

  • ViewController: Suporte completo para views de banco de dados (issue #4)
  • ViewController: Suporte completo para views de banco de dados (issue #4)
  • Operadores sobrecarregados: ==, !=, <, <=, >, >=, .in_(), .like()
  • Operadores lógicos: & (AND), | (OR)
  • Manager Pattern: SelectManager, InsertManager, UpdateManager, DeleteManager
  • Decorators de validação automática
  • Acesso contextual inteligente aos campos

MELHORIAS:

  • database_connection refatorado com managers reutilizáveis
  • _model_update com tratamento de erros não-bloqueante
  • Mensagem de segurança condicional no model update
  • CoreConfig com docstrings raw (sem warnings)
  • Remoção de comentários excessivos

COMPATIBILIDADE:

  • Python 3.8+ (testado em 3.13)
  • Breaking changes - revisar código antes de atualizar

MIGRAÇÃO v1.x → v2.0:

# ANTES (v1.x)
products.select(
    where=[{'field': 'PRICE', 'operator': '>', 'value': 100}],
    columns=['NAME'],
    options={'limit': 10}
)
nome = products.NAME.value

# DEPOIS (v2.0)
products.select().where(products.PRICE > 100).columns(products.NAME).limit(10)
nome = products.NAME  # Acesso direto

Para detalhes completos: PatchNote_2.0.md

Documentação Detalhada


Controllers - Controladoras

O SQLManager fornece duas controllers principais para gerenciamento de dados:

  • TableController: Para operações completas em tabelas (SELECT, INSERT, UPDATE, DELETE)
  • ViewController: Para operações de leitura em views (SELECT)

Para documentação detalhada das controllers (TableController, ViewController), métodos e exemplos, consulte:


Connection - Conexões

Para documentação detalhada da classe connection, métodos e exemplos, consulte:


AutoRouter - API REST

O AutoRouter é um sistema de rotas automáticas que transforma suas classes TableController em endpoints RESTful completos, eliminando a necessidade de criar controllers manuais para operações CRUD padrão.

Características principais:

  • Zero Boilerplate: Crie a tabela no banco, gere os modelos, e as rotas já existem
  • Validação Automática: EDTs e Enums são validados antes de tocar no banco
  • Filtros Avançados: Suporte nativo a operadores (_gt, _like, _lte, etc.)
  • Coleção Postman: Geração automática de documentação para testes
  • Decorator Robusto: Usa inspect.signature para mapeamento type-safe de argumentos

Arquitetura:

  • Utiliza Roteamento Dinâmico baseado em Reflexão (Introspection)
  • Padrão Front Controller para processamento centralizado
  • Convenção sobre Configuração para setup mínimo

Versão 4.0 (27/02/2026): Decorator _pre_handle refatorado com inspect.signature para mapeamento robusto de argumentos nomeados e posicionais, com injeção automática de dependências (_table, _table_config).

Documentação completa:


CoreConfig - Central de Configuração

O CoreConfig é a classe estática responsável por centralizar toda a configuração do SQLManager. Ele atua como uma ponte entre o seu projeto e o núcleo da biblioteca, permitindo definir conexões de banco de dados, regras de validação customizadas e comportamento de rotas sem modificar o código fonte do pacote.

Funcionalidades Principais

  1. Configuração de Banco de Dados: Define credenciais e driver de conexão.
  2. Registro de Regex (EDTs): Adiciona padrões de validação customizados para seus tipos de dados.
  3. Configuração do AutoRouter: Controla a geração automática de APIs REST.
  4. Carregamento Flexível: Suporta dicionários, variáveis de ambiente ou chamadas diretas.

1. Configuração do Banco de Dados

O SQLManager precisa saber como conectar ao seu banco. O CoreConfig gerencia essas credenciais globalmente.

Opção A: Via Variáveis de Ambiente (Recomendado)

O método configure busca automaticamente por variáveis de ambiente se load_from_env=True (padrão).

No seu arquivo .env:

DB_SERVER=localhost
DB_DATABASE=MeuBanco
DB_USER=sa
DB_PASSWORD=senha_segura

No seu código (ex: app.py):

from SQLManager import CoreConfig

# Carrega automaticamente do .env
CoreConfig.configure()

Opção B: Configuração Explícita

Útil se você gerencia configurações de outra forma (ex: AWS Secrets Manager).

CoreConfig.configure(
    db_server='192.168.1.10',
    db_database='ProductionDB',
    db_user='admin',
    db_password='secure_password',
    db_driver='ODBC Driver 17 for SQL Server', # Opcional (Padrão: ODBC Driver 18)
    load_from_env=False
)

2. Registro de Regex Customizados (EDTs)

O sistema de EDTs (Extended Data Types) usa Regex para validar dados. O CoreConfig permite que você registre seus próprios padrões (ex: formato de SKU, Email Corporativo) para usar em suas tabelas.

Registrando um único padrão

# Registra um padrão para código de produto (ex: PRD-1234)
CoreConfig.register_regex('ProductCode', r'^PRD-\d{4}$')

Registrando múltiplos padrões

CoreConfig.register_multiple_regex({
    'CompanyEmail': r'^[\w\.-]+@minhaempresa\.com$',
    'LicensePlate': r'^[A-Z]{3}-\d{4}$',
    'ZipCode': r'^\d{5}-\d{3}$'
})

Como usar na Tabela

class Products(TableController):
    def __init__(self, db):
        super().__init__(db)
        # Usa o ID 'ProductCode' registrado no CoreConfig
        self.SKU = EDTController('ProductCode', str)

3. Configuração do AutoRouter

O AutoRouter cria endpoints de API automaticamente. O CoreConfig define as regras de exposição.

router_config = {
    # Ativa/Desativa o sistema de rotas
    "enable_dynamic_routes": True,
    
    # Prefixo para as URLs (ex: http://localhost/api/v1/Products)
    "url_suffix": "api/v1",

    # Tabelas que NÃO devem ter rotas
    "exclude_tables": ["SysLog", "UserPasswords"],

    # Configurações por tabela
    "tables": {
        "Products": {
            "allowed_methods": ["GET", "POST"], # Apenas leitura e escrita (sem update/delete)
            
            # Configuração de Deleção Lógica (Soft Delete)
            "delete_behavior": {
                "mode": "logical",
                "field": "IS_DELETED",
                "value": 1
            }
        }
    }
}

CoreConfig.configure_router(router_config)

4. Métodos Utilitários

configure_from_dict

Configura banco, regex e router de uma vez só. Ideal para carregar de arquivos JSON ou YAML.

config_data = {
    "db_server": "localhost",
    "db_database": "TestDB",
    "custom_regex": {
        "OnlyUpper": r"^[A-Z]+$"
    },
    "router_config": {
        "enable_dynamic_routes": True
    }
}

CoreConfig.configure_from_dict(config_data)

reset

Limpa todas as configurações. Use no setUp de testes unitários para garantir um estado limpo.

def setUp(self):
    CoreConfig.reset()
    CoreConfig.configure(...)

is_configured

Verifica se o Core já foi inicializado.

if not CoreConfig.is_configured():
    raise Exception("SQLManager não foi configurado!")

Exemplos de Arquivos Gerados

Enum (src/model/enum/ItemType.py)

from SQLManager import BaseEnumController

class ItemType(BaseEnumController.Enum):
    '''
    Enumeração de tipos de item (número/texto), com label descritivo.
    '''
    NoneType    = (0, "Nenhum")    
    Service     = (1, "Serviço")
    Product     = (2, "Produto")
    RawMaterial = (3, "Matéria Prima")

Enum Obrigatório (src/model/enum/DataType.py)

from typing import Self
from SQLManager import BaseEnumController

class DataType(BaseEnumController.Enum):
    '''
    Enumeração de tipos de dados (texto/texto), com label descritivo.
    '''
    Null      : Self = ("NoneType",  "Tipo de dado Nulo")
    String    : Self = ("str",       "Tipo de dado String")
    Number    : Self = ("int",       "Tipo de dado Number")
    Float     : Self = ("float",     "Tipo de dado Float")
    Boolean   : Self = ("bool",      "Tipo de dado Boolean")
    Array     : Self = ("list",      "Tipo de dado Lista")
    Object    : Self = ("dict",      "Tipo de dado Dicionário")
    Tuple     : Self = ("tuple",     "Tipo de dado Tupla")
    Set       : Self = ("set",       "Tipo de dado Conjunto")
    Bytes     : Self = ("bytes",     "Tipo de dado Bytes")
    Function  : Self = ("function",  "Tipo de dado Função")
    Class     : Self = ("type",      "Tipo de dado Classe")
    Undefined : Self = ("undefined", "Tipo de dado Indefinido")

EDT (src/model/EDTs/ItemId.py)

from SQLManager import EDTController
from model.enum import DataType

class ItemId(EDTController):
    '''
    Identificação do item.
    Args:
        value str: Identificação do item
    '''
    def __init__(self, value: EDTController.Any_Type = ""):
        super().__init__("any", DataType.String, value, 50)        

EDT Obrigatório (src/model/EDTs/Recid.py)

from SQLManager import EDTController
from model.enum import DataType

class Recid(EDTController):
    '''
    Identificador numérico exclusivo.
    Args:
        value number: Identificador a ser validado
    '''
    def __init__(self, value: EDTController.Any_Type = 0):
        super().__init__("onlyNumbers", DataType.Number, value)        

Table (src/model/tables/Products.py)

from SQLManager import TableController, EDTController
from model import EDTPack, EnumPack

class Products(TableController):
    '''
    Tabela: Products
    args:
        db_controller: Banco de dados ou transação
    '''
    def __init__(self, db):
        super().__init__(db=db, table_name="Products")
        self.RECID = EDTPack.Recid()
        self.ITEMNAME = EDTController('any', EnumPack.dataType.String, None, 100)
        self.ITEMTYPE = EnumPack.ItemType()

View (src/model/views/ProductsView.py)

from SQLManager import ViewController, EDTController
from model import EDTPack, EnumPack

class ProductsView(ViewController):
    '''
    View: ProductsView
    args:
        db_controller: Banco de dados ou transação
    '''
    def __init__(self, db):
        super().__init__(db=db, source_name="ProductsView")
        self.RECID = EDTPack.Recid()
        self.ITEMNAME = EDTController('any', EnumPack.dataType.String, None, 100)
        self.ITEMTYPE = EnumPack.ItemType()
        self.CATEGORYNAME = EDTController('any', EnumPack.dataType.String, None, 50)

1. Configure o Core no seu projeto (OBRIGATORIO)

# app.py (na raiz do seu projeto)
import os
import dotenv
from SQLManager import CoreConfig

# Carrega .env do SEU projeto
dotenv.load_dotenv()

# Configurar o Core ANTES de usar
CoreConfig.configure(
    db_server=os.getenv('DB_SERVER'),
    db_database=os.getenv('DB_DATABASE'),
    db_user=os.getenv('DB_USER'),
    db_password=os.getenv('DB_PASSWORD')
)

2. Registre Regex Customizados (Opcional)

# Registrar validações específicas do seu projeto
CoreConfig.register_multiple_regex({
    'CompanyEmail': r'^[\w\.-]+@minhaempresa\.com\.br$',
    'ProductCode': r'^PRD-\d{6}$',
    'OrderNumber': r'^ORD-\d{8}$'
})

3. Sistema de Model Generator (Importante)

O Core INCLUI um gerador automatico de modelos (_model_update.py) que:

  • Vem junto com o Core quando instalado via pip
  • Escaneia as tabelas e views do banco de dados conectado
  • Gera automaticamente classes de modelo na pasta src/model/ do SEU projeto
  • Cria estrutura: src/model/EDTs/, src/model/enum/, src/model/tables/, src/model/views/
  • Atualiza automaticamente init.py e importacoes
  • Sincroniza campos quando tabelas/views sao alteradas no banco

Como usar o _model_update.py:

# Após instalar o Core, execute o gerador:
python -m SQLManager._model._model_update

# Ou se preferir:
python .venv/Lib/site-packages/SQLManager/_model/_model_update.py

Requisitos obrigatorios:

  • Seu projeto DEVE ter uma pasta src/ na raiz
  • O gerador criara automaticamente: src/model/EDTs/, src/model/enum/, src/model/tables/, src/model/views/
  • Todas as tabelas e views no banco DEVEM ter o campo RECID (tipo BIGINT)

IMPORTANTE - Nomenclatura: A coerencia entre nomes de campos no banco e EDTs/Enums e ESTRITAMENTE IMPORTANTE:

  • Se tem um EDT chamado ItemName, o campo no banco deve se chamar ITEMNAME
  • Se tem um Enum chamado ItemType, o campo no banco deve se chamar ITEMTYPE (tipo INT)
  • EDTs devem ser do tipo correto no banco (string = varchar/nvarchar, numeros = int/bigint/decimal)
  • Campos sem EDT correspondente usarao DataType padrao baseado no tipo SQL

Exemplo:

# EDT: src/model/EDTs/ItemName.py
class ItemName(EDTController):
    def __init__(self):
        super().__init__('any', str, limit=100)

# Banco de dados:
CREATE TABLE Products (
    RECID BIGINT PRIMARY KEY,
    ITEMNAME NVARCHAR(100),  -- Sera mapeado para ItemName EDT
    ITEMTYPE INT              -- Se existir Enum ItemType, sera mapeado
)

2. Registre Regex Customizados (Opcional)

# Registrar validações específicas do seu projeto
CoreConfig.register_multiple_regex({
    'CompanyEmail': r'^[\w\.-]+@minhaempresa\.com\.br$',
    'ProductCode': r'^PRD-\d{6}$',
    'OrderNumber': r'^ORD-\d{8}$'
})

Uso Básico

Nova API Fluente (v2.0)

from model import TablePack, ViewPack

# Instanciar tabela
products = TablePack.Products(db)

# Instanciar view
products_view = ViewPack.ProductsView(db)

# Acesso direto aos valores (sem .value)
nome = products.NAME  # Retorna string diretamente
products.NAME = "Novo Nome"  # Setter automático

# Views têm a mesma API para leitura
for item in products_view.select().where(products_view.PRICE > 100):
    print(f"{item.ITEMNAME} - Categoria: {item.CATEGORYNAME}")

# Queries com operadores nativos
products.select().where(products.PRICE > 100)
products.select().where((products.PRICE > 100) & (products.ACTIVE == 1))
products.select().where(products.NAME.like('%Notebook%'))

# JOIN simplificado
categories = TablePack.Categories(db)
for product, category in products.select().join(categories).on(products.CATEGORYID == categories.RECID):
    print(f"{product.NAME} - {category.NAME}")

# LEFT JOIN (especificando tipo)
for product, category in products.select().join(categories, 'LEFT').on(products.CATEGORYID == categories.RECID):
    print(f"{product.NAME} - {category.NAME if category.NAME else 'Sem categoria'}")

# MÚLTIPLOS JOINs (3+ tabelas)
suppliers = TablePack.Suppliers(db)
warehouses = TablePack.Warehouses(db)

for product, category, supplier, warehouse in products.select()\
    .join(categories).on(products.CATEGORYID == categories.RECID)\
    .join(suppliers, 'LEFT').on(products.SUPPLIERID == suppliers.RECID)\
    .join(warehouses, 'INNER').on(products.WAREHOUSEID == warehouses.RECID):
    print(f"{product.NAME} | {category.NAME} | {supplier.NAME} | {warehouse.NAME}")

# WHERE com campos de tabelas do JOIN
for product, category in products.select()\
    .join(categories).on(products.CATEGORYID == categories.RECID)\
    .where((products.PRICE > 100) & (category.NAME == 'Electronics')):
    print(f"{product.NAME} ({category.NAME}): R$ {product.PRICE}")

# Instâncias dos JOINs são atualizadas automaticamente
for product, category in products.select().join(categories).on(products.CATEGORYID == categories.RECID):
    # Acesso direto aos valores de ambas as tabelas
    print(f"Produto RECID: {product.RECID}, Nome: {product.NAME}")
    print(f"Categoria RECID: {category.RECID}, Nome: {category.NAME}")
    
    # Pode usar as instâncias normalmente
    if product.PRICE > 500:
        product.PRICE = product.PRICE * 0.9
        product.update()

# Acessando resultados SEM for (direto via execute)
results = products.select()\
    .join(categories).on(products.CATEGORYID == categories.RECID)\
    .execute()

# Acessar primeira linha
first_product = results[0][0]
first_category = results[0][1]
print(f"{first_product.NAME} - {first_category.NAME}")

# Separar por tabela
all_products = [r[0] for r in results]
all_categories = [r[1] for r in results]

# Via records (atualizado automaticamente)
print(f"Total: {len(products.records)}")

# Operações em massa com nova sintaxe
products.update_recordset(where=products.CATEGORY == 'Electronics', PRICE=100)
products.delete_from(where=products.ACTIVE == 0)

Conexão com Banco de Dados

from SQLManager.connection import database_connection

# Conectar (usa configuração do CoreConfig)
db = database_connection()
db.connect()

# Query simples
results = db.doQuery("SELECT * FROM Products WHERE Active = ?", (1,))
for row in results:
    print(row)

# Comando (INSERT/UPDATE/DELETE)
db.executeCommand(
    "INSERT INTO Products (Name, Price) VALUES (?, ?)",
    ('Produto Novo', 99.90)
)

# Desconectar
db.disconnect()

Transações Isoladas

# Transação com commit/rollback automático
with db.transaction() as trs:
    trs.executeCommand(
        "UPDATE Products SET Price = ? WHERE RecId = ?",
        (100.50, 123)
    )
    # Commit automático ao sair do bloco
    # Rollback automático em caso de erro

Transações com Níveis (TTS)

# Níveis de transação
db.ttsbegin()
try:
    db.executeCommand("UPDATE Table1 SET Field = ?", (value,))
    
    db.ttsbegin()  # Nível 2
    try:
        db.executeCommand("UPDATE Table2 SET Field = ?", (value,))
        db.ttscommit()  # Commit nível 2
    except:
        db.ttsabort()  # Rollback nível 2
    
    db.ttscommit()  # Commit nível 1
except:
    db.ttsabort()  # Rollback tudo

EDTs (Extended Data Types)

from SQLManager.controller import EDTController
from model import EnumPack

# EDT com regex built-in
email = EDTController('email', EnumPack.DataType.String)
email = 'user@example.com'  # Válido
print(email)  # 'user@example.com' (via __str__)

# EDT com limite de caracteres
name = EDTController('any', EnumPack.dataType.String, limit=50)
name = 'Nome do Produto'  #  Válido

# EDT com regex customizado
product_code = EDTController('ProductCode', EnumPack.dataType.String)
product_code = 'PRD-123456'  #  Válido

# Validação automática
try:
    email = 'invalid-email'  #  ValueError
except ValueError as e:
    print(f"Erro: {e}")

Regex Built-in Disponíveis

# Documentos
'cnpj'          # 00.000.000/0000-00
'cpf'           # 000.000.000-00
'cnpj_cpf'      # Aceita ambos
'cep'           # 00000-000

# Internet
'email'         # usuario@dominio.com
'url'           # https://exemplo.com
'ipv4'          # 192.168.0.1
'ipv6'          # 2001:0db8:85a3::8a2e:0370:7334

# Básicos
'onlyNumbers'   # Apenas dígitos
'onlyLetters'   # Apenas letras
'date'          # DD/MM/YYYY ou DD-MM-YYYY
'datetime'      # DD/MM/YYYY ou DD-MM-YYYY (opcionalmente com hora: HH:MM ou HH:MM:SS)
'number'        # Telefone brasileiro
'password'      # Mínimo 8 chars, letras e números

Padrões de Uso Avançados

Criando EDTs Personalizados

from SQLManager.controller import EDTController

class CompanyEmail(EDTController):
    def __init__(self):
        super().__init__(
            regextype='CompanyEmail',
            type_id=str
        )

# Usar
email = CompanyEmail()
email = 'joao@minhaempresa.com.br'

Sistema de Tables e Views (v2.0)

from model import TablePack, ViewPack

# Instanciar tabela
products = TablePack.Products(db)

# Definir valores (acesso direto, sem .value)
products.NAME  = "Produto Teste"
products.PRICE = 99.90

# Inserir
products.insert()

# Buscar com operadores nativos
for produto in products.select().where(products.NAME == "Produto Teste"):
    print(produto.NAME, produto.PRICE)

# Atualizar (valores diretos)
products.NAME = "Produto Atualizado"
products.update()

# Deletar
products.delete()

# Operações complexas
products.select().where((products.PRICE > 50) & (products.ACTIVE == 1)).order_by(products.NAME).limit(10)

# VIEWS - Apenas leitura
products_view = ViewPack.ProductsView(db)

# Select em views (mesma API que tables)
for item in products_view.select().where(products_view.CATEGORYNAME == "Electronics"):
    print(f"{item.ITEMNAME} - {item.CATEGORYNAME} - R$ {item.PRICE}")

# Views suportam todas as operações de leitura
products_view.select()\
    .where((products_view.PRICE > 100) & (products_view.ACTIVE == 1))\
    .order_by(products_view.ITEMNAME)\
    .limit(10)

Estrutura do Projeto Host

MeuProjeto/
│
├── .env                   # Suas variáveis de ambiente
├── requirements.txt       # git+https://github.com/nicozsd/SQLManager
├── app.py                 # Configurar CoreConfig aqui
│
├── src/
│   └── model/             # GERADO pelo _model_update.py do Core
│       ├── EDTs/          # EDTs customizados
│       ├── enum/          # Enums customizados
│       ├── tables/        # Tables geradas automaticamente
│       └── views/         # Views geradas automaticamente
│
└── .venv/                 # Core instalado AQUI via pip
    └── Lib/
        └── site-packages/
            └── core/
                ├── _model/
                │   └── _model_update.py  # Gerador (vem com o Core)
                ├── connection/
                ├── controller/
                └── CoreConfig.py

Configurações Avançadas

Variáveis de Ambiente (.env)

# Banco de Dados
DB_SERVER=localhost
DB_DATABASE=MeuBanco
DB_USER=admin
DB_PASSWORD=senha123
DB_DRIVER="versão ODBC"

Configuração Programática

from SQLManager import CoreConfig

# Via dicionário
config = {
    'db_server': 'localhost',
    'db_database': 'MeuDB',
    'db_user': 'admin',
    'db_password': 'senha',
    'custom_regex': {
        'CustomPattern': r'^CUSTOM-\d{6}$'
    }
}

CoreConfig.configure_from_dict(config)

# Verificar se configurado
if CoreConfig.is_configured():
    print("Core configurado!")

# Ver configuração atual
config = CoreConfig.get_db_config()
print(config)

Boas Práticas

1. Configure uma única vez no início

#  BOM: No main/app.py

from SQLManager import CoreConfig
CoreConfig.configure(load_from_env=True)

# Depois em qualquer lugar

from SQLManager.connection import database_connection
db = database_connection()  # Usa configuração do CoreConfig

2. Use transações isoladas para operações complexas

#  BOM: Transação isolada
with db.transaction() as trs:
    products.insert(trs)
    inventory.update(trs)
    # Commit/rollback automático

# EVITAR: Múltiplas operações sem transação
db.executeCommand("INSERT ...")
db.executeCommand("UPDATE ...")

3. Valide dados antes de inserir

#  BOM: Valida antes
email_edt = EDTController('email', str)
# (possui setter automatico mas pode haver um if)
if email_edt.is_valid(user_input):
    email_edt = user_input
else:
    raise ValueError("Email inválido")

#  EVITAR: Inserir sem validar
db.executeCommand("INSERT INTO Users (Email) VALUES (?)", (user_input,))

Troubleshooting

Erro: "Core não configurado"

# Solução: Configure antes de usar

from SQLManager import CoreConfig
CoreConfig.configure(load_from_env=True)

Erro: "Regex não encontrado"

# Solução: Registre o regex customizado

CoreConfig.register_regex('MeuRegex', r'^PATTERN$')

Erro de conexão com banco

# Verifique a configuração
config = CoreConfig.get_db_config()
print(config)  # Verificar se valores estão corretos

# Teste conexão manual

db = database_connection(
    _Server='localhost',
    _Database='TestDB',
    _User='admin',
    _Password='senha'
)

Nota: Este Core é projetado para ser um repositório independente. Nunca modifique arquivos do Core diretamente no projeto host. Use CoreConfig para todas as customizações.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages