douglasribeiro/sqlite
0
1import os2import re3import shutil4import sqlite35import pandas as pd6import gradio as gr7 8DB_PATH = "loja.db"9EXPORT_DIR = "exports"10 11 12def _connect():13 return sqlite3.connect(DB_PATH, check_same_thread=False)14 15 16def _looks_like_select(sql: str) -> bool:17 s = (sql or "").strip().lower()18 return s.startswith(("select", "with", "pragma", "explain"))19 20 21def _safe_filename(name: str) -> str:22 name = (name or "").strip()23 if not name:24 name = "resultado"25 # remove caracteres ruins e espaços excessivos26 name = re.sub(r"[^\w\-\.]+", "_", name, flags=re.UNICODE)27 name = name.strip("._-")28 return name or "resultado"29 30 31def _save_df_to_csv(df: pd.DataFrame, filename_base: str) -> str:32 os.makedirs(EXPORT_DIR, exist_ok=True)33 base = _safe_filename(filename_base)34 csv_path = os.path.join(EXPORT_DIR, f"{base}.csv")35 df.to_csv(csv_path, index=False, encoding="utf-8-sig") # BOM ajuda no Excel36 return csv_path37 38 39def executar_sql(sql: str, salvar_csv: bool, nome_csv: str):40 sql = (sql or "").strip()41 if not sql:42 return "⚠️ Cole um comando SQL.", None, None43 44 try:45 con = _connect()46 cur = con.cursor()47 48 if _looks_like_select(sql):49 df = pd.read_sql_query(sql, con)50 con.close()51 52 csv_file = None53 if salvar_csv:54 if df is None or df.empty:55 # Ainda assim você pode preferir salvar vazio; aqui eu aviso e não gero arquivo.56 return "⚠️ Consulta executada, mas não retornou linhas (CSV não gerado).", df, None57 csv_file = _save_df_to_csv(df, nome_csv)58 59 msg = "✅ Consulta executada com sucesso."60 if csv_file:61 msg += f" CSV gerado em: {csv_file}"62 return msg, df, csv_file63 64 # Para comandos não-SELECT (DDL/DML), aceita múltiplas instruções com ;65 cur.executescript(sql)66 con.commit()67 con.close()68 return "✅ Comando executado e commit realizado.", None, None69 70 except Exception as e:71 return f"❌ Erro ao executar SQL:\n{e}", None, None72 73 74def reset_db():75 try:76 if os.path.exists(DB_PATH):77 os.remove(DB_PATH)78 # recria vazio (arquivo nasce ao conectar)79 con = _connect()80 con.close()81 return "✅ Banco resetado. Um novo 'loja.db' vazio foi criado."82 except Exception as e:83 return f"❌ Erro ao resetar DB: {e}"84 85 86def upload_db(db_file):87 if db_file is None:88 return "⚠️ Envie um arquivo .db primeiro."89 try:90 shutil.copy(db_file, DB_PATH)91 return f"✅ Banco carregado com sucesso: {DB_PATH}"92 except Exception as e:93 return f"❌ Erro ao carregar DB: {e}"94 95 96def download_db():97 if not os.path.exists(DB_PATH):98 # cria se ainda não existir99 con = _connect()100 con.close()101 return DB_PATH102 103 104with gr.Blocks(title="SQLite — Execução de SQL (loja.db)") as demo:105 gr.Markdown(106 """107# SQLite (loja.db) — Interface Gradio108Cole seus comandos SQL e execute direto no arquivo `loja.db`.109 110**Dica:** Para múltiplos comandos (ex.: vários CREATE/INSERT), separe por `;`.111 112✅ **Novo:** marque *Salvar resultado em CSV* para exportar o resultado de consultas `SELECT`.113"""114 )115 116 with gr.Tab("Executar SQL"):117 sql_in = gr.Textbox(118 label="Comando SQL",119 placeholder="Ex.: CREATE TABLE ...; ou SELECT * FROM ...;",120 lines=10,121 )122 123 with gr.Row():124 salvar_csv = gr.Checkbox(label="Salvar resultado em CSV (apenas SELECT)", value=False)125 nome_csv = gr.Textbox(126 label="Nome do CSV (sem extensão)",127 placeholder="Ex.: clientes_ativos",128 value="resultado_query",129 )130 131 run_btn = gr.Button("Executar")132 status = gr.Textbox(label="Status", lines=3)133 tabela = gr.Dataframe(label="Resultado (se houver)", interactive=False)134 135 gr.Markdown("### Download do resultado (CSV)")136 csv_file = gr.File(label="Baixar CSV gerado")137 138 run_btn.click(139 executar_sql,140 inputs=[sql_in, salvar_csv, nome_csv],141 outputs=[status, tabela, csv_file],142 )143 144 with gr.Tab("Banco de Dados (Upload/Download/Reset)"):145 gr.Markdown("### Upload de um banco existente (.db)")146 up = gr.File(label="Envie um arquivo .db", file_types=[".db"])147 up_btn = gr.Button("Carregar este DB para o app")148 up_status = gr.Textbox(label="Status", lines=2)149 up_btn.click(upload_db, inputs=up, outputs=up_status)150 151 gr.Markdown("### Download do banco atual")152 dl_btn = gr.Button("Gerar arquivo para download")153 dl_file = gr.File(label="Baixar loja.db")154 dl_btn.click(download_db, inputs=None, outputs=dl_file)155 156 gr.Markdown("### Reset (apaga e recria um loja.db vazio)")157 reset_btn = gr.Button("Resetar DB", variant="stop")158 reset_status = gr.Textbox(label="Status", lines=2)159 reset_btn.click(reset_db, inputs=None, outputs=reset_status)160 161demo.launch()