Implementa sistema de IDs curtos para pastes, substituindo hashes SHA-256. Atualiza a estrutura do banco de dados e a lógica de inserção para suportar a detecção de duplicatas. O README e a documentação de migração foram atualizados para refletir essas mudanças.
This commit is contained in:
+71
-6
@@ -7,6 +7,7 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"math/rand"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
@@ -16,7 +17,41 @@ import (
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
const shortIDLength = 7
|
||||
|
||||
// generateShortID gera um ID único de 7 caracteres
|
||||
func generateShortID() string {
|
||||
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
b := make([]byte, shortIDLength)
|
||||
for i := range b {
|
||||
b[i] = charset[rand.Intn(len(charset))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// generateUniqueShortID gera um ID único que não existe no banco
|
||||
func generateUniqueShortID(db *sql.DB) (string, error) {
|
||||
maxAttempts := 100
|
||||
for i := 0; i < maxAttempts; i++ {
|
||||
id := generateShortID()
|
||||
|
||||
// Verificar se o ID já existe
|
||||
var exists int
|
||||
err := db.QueryRow("SELECT 1 FROM pastes WHERE short_id = ? LIMIT 1", id).Scan(&exists)
|
||||
if err == sql.ErrNoRows {
|
||||
return id, nil
|
||||
}
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("não foi possível gerar um ID único após %d tentativas", maxAttempts)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Initialize random seed
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
var boltPath, sqlitePath string
|
||||
flag.StringVar(&boltPath, "bolt", "", "caminho para o arquivo BoltDB")
|
||||
flag.StringVar(&sqlitePath, "sqlite", "", "caminho para o arquivo SQLite3 de destino")
|
||||
@@ -44,8 +79,9 @@ func main() {
|
||||
// Criar tabela no SQLite3
|
||||
_, err = sqliteDB.Exec(`
|
||||
CREATE TABLE IF NOT EXISTS pastes (
|
||||
hash TEXT PRIMARY KEY,
|
||||
short_id TEXT PRIMARY KEY,
|
||||
content TEXT NOT NULL,
|
||||
content_hash TEXT NOT NULL,
|
||||
created_at INTEGER NOT NULL
|
||||
)
|
||||
`)
|
||||
@@ -53,6 +89,17 @@ func main() {
|
||||
log.Fatal("Erro ao criar tabela:", err)
|
||||
}
|
||||
|
||||
// Criar índices
|
||||
_, err = sqliteDB.Exec(`CREATE INDEX IF NOT EXISTS idx_pastes_content_hash ON pastes(content_hash)`)
|
||||
if err != nil {
|
||||
log.Fatal("Erro ao criar índice content_hash:", err)
|
||||
}
|
||||
|
||||
_, err = sqliteDB.Exec(`CREATE INDEX IF NOT EXISTS idx_pastes_created_at ON pastes(created_at)`)
|
||||
if err != nil {
|
||||
log.Fatal("Erro ao criar índice created_at:", err)
|
||||
}
|
||||
|
||||
// Iniciar transação no SQLite3
|
||||
tx, err := sqliteDB.Begin()
|
||||
if err != nil {
|
||||
@@ -60,7 +107,7 @@ func main() {
|
||||
}
|
||||
|
||||
// Preparar statement de inserção
|
||||
stmt, err := tx.Prepare("INSERT OR IGNORE INTO pastes (hash, content, created_at) VALUES (?, ?, ?)")
|
||||
stmt, err := tx.Prepare("INSERT OR IGNORE INTO pastes (short_id, content, content_hash, created_at) VALUES (?, ?, ?, ?)")
|
||||
if err != nil {
|
||||
log.Fatal("Erro ao preparar statement:", err)
|
||||
}
|
||||
@@ -68,6 +115,7 @@ func main() {
|
||||
|
||||
// Migrar dados do BoltDB para SQLite3
|
||||
count := 0
|
||||
duplicates := 0
|
||||
err = boltDB.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte("pastes"))
|
||||
if b == nil {
|
||||
@@ -79,10 +127,27 @@ func main() {
|
||||
hash := sha256.Sum256(v)
|
||||
hashStr := hex.EncodeToString(hash[:])
|
||||
|
||||
// Inserir no SQLite3
|
||||
_, err := stmt.Exec(hashStr, string(v), time.Now().Unix())
|
||||
// Verificar se já existe um paste com o mesmo conteúdo
|
||||
var existingID string
|
||||
err := sqliteDB.QueryRow("SELECT short_id FROM pastes WHERE content_hash = ? LIMIT 1", hashStr).Scan(&existingID)
|
||||
if err == nil {
|
||||
// Paste já existe, pular
|
||||
duplicates++
|
||||
return nil
|
||||
} else if err != sql.ErrNoRows {
|
||||
return fmt.Errorf("erro ao verificar duplicata: %v", err)
|
||||
}
|
||||
|
||||
// Gerar ID curto único
|
||||
shortID, err := generateUniqueShortID(sqliteDB)
|
||||
if err != nil {
|
||||
return fmt.Errorf("erro ao inserir paste %s: %v", hashStr, err)
|
||||
return fmt.Errorf("erro ao gerar ID único: %v", err)
|
||||
}
|
||||
|
||||
// Inserir no SQLite3
|
||||
_, err = stmt.Exec(shortID, string(v), hashStr, time.Now().Unix())
|
||||
if err != nil {
|
||||
return fmt.Errorf("erro ao inserir paste %s: %v", shortID, err)
|
||||
}
|
||||
|
||||
count++
|
||||
@@ -105,5 +170,5 @@ func main() {
|
||||
log.Fatal("Erro ao fazer commit:", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Migração concluída! %d pastes migrados com sucesso.\n", count)
|
||||
fmt.Printf("Migração concluída! %d pastes migrados com sucesso, %d duplicatas ignoradas.\n", count, duplicates)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user