From 786e0f03f8baf2c88dc173111620db2eef1040c4 Mon Sep 17 00:00:00 2001 From: GnomeZworc Date: Wed, 10 Dec 2025 20:38:51 +0100 Subject: [PATCH] start: add a first db in golang Signed-off-by: GnomeZworc --- cmd/db/main.go | 184 ++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 18 +++++ pkg/db/kv/init.go | 19 +++++ 3 files changed, 221 insertions(+) create mode 100644 cmd/db/main.go create mode 100644 pkg/db/kv/init.go diff --git a/cmd/db/main.go b/cmd/db/main.go new file mode 100644 index 0000000..fd7d09a --- /dev/null +++ b/cmd/db/main.go @@ -0,0 +1,184 @@ +package main + +import ( + "fmt" + "os" + "strings" + + "git.g3e.fr/syonad/two/pkg/db/kv" + "github.com/dgraph-io/badger/v4" +) + +var DB *badger.DB + +func CheckInDB(dbName, id string) int { + prefix := []byte(dbName + "/bash/") + key := []byte(dbName + "/bash/" + id) + + // vérifier si DB contient au moins une entrée avec ce préfixe + hasPrefix := false + + DB.View(func(txn *badger.Txn) error { + it := txn.NewIterator(badger.DefaultIteratorOptions) + defer it.Close() + it.Seek(prefix) + if it.ValidForPrefix(prefix) { + hasPrefix = true + } + return nil + }) + + if !hasPrefix { + return 1 + } + + // vérifier si la clé existe + err := DB.View(func(txn *badger.Txn) error { + _, err := txn.Get(key) + return err + }) + + if err == badger.ErrKeyNotFound { + return 2 + } + + return 0 +} + +func AddInDB(dbName string, line string) error { + // ID = partie avant le premier ';' + id := strings.Split(line, ";")[0] + key := []byte(dbName + "/bash/" + id) + + return DB.Update(func(txn *badger.Txn) error { + return txn.Set(key, []byte(line)) + }) +} + +func DeleteInDB(dbName, id string) error { + key := []byte(dbName + "/bash/" + id) + + return DB.Update(func(txn *badger.Txn) error { + return txn.Delete(key) + }) +} + +func CountInDB(dbName, id string) int { + prefix := []byte(dbName + "/bash/" + id) + count := 0 + + DB.View(func(txn *badger.Txn) error { + it := txn.NewIterator(badger.DefaultIteratorOptions) + defer it.Close() + + for it.Seek(prefix); it.ValidForPrefix(prefix); it.Next() { + count++ + } + return nil + }) + + return count +} + +func GetFromDB(dbName, id string) (string, error) { + key := []byte(dbName + "/bash/" + id) + + var result string + + err := DB.View(func(txn *badger.Txn) error { + item, err := txn.Get(key) + if err != nil { + return err + } + return item.Value(func(val []byte) error { + result = string(val) + return nil + }) + }) + + return result, err +} + +func printDB() { + err := DB.View(func(txn *badger.Txn) error { + it := txn.NewIterator(badger.DefaultIteratorOptions) + defer it.Close() + + for it.Rewind(); it.Valid(); it.Next() { + item := it.Item() + key := item.Key() + err := item.Value(func(val []byte) error { + fmt.Printf("%s:%s\n", string(key), string(val)) + return nil + }) + if err != nil { + return err + } + } + return nil + }) + + if err != nil { + fmt.Println("Error reading DB:", err) + } +} + +func main() { + DB = kv.InitDB() + defer DB.Close() + + printDB() + + if len(os.Args) < 2 { + fmt.Println("Usage: db [args...]") + return + } + + cmd := os.Args[1] + + switch cmd { + case "check_in_db": + if len(os.Args) != 4 { + fmt.Println("Usage: check_in_db ") + os.Exit(1) + } + ret := CheckInDB(os.Args[2], os.Args[3]) + os.Exit(ret) + case "add_in_db": + if len(os.Args) < 4 { + fmt.Println("Usage: add_in_db ") + os.Exit(1) + } + line := strings.Join(os.Args[3:], ";") + if err := AddInDB(os.Args[2], line); err != nil { + fmt.Println("Error:", err) + os.Exit(1) + } + case "delete_in_db": + if len(os.Args) != 4 { + fmt.Println("Usage: delete_in_db ") + os.Exit(1) + } + if err := DeleteInDB(os.Args[2], os.Args[3]); err != nil { + fmt.Println("Error:", err) + os.Exit(1) + } + case "count_in_db": + if len(os.Args) != 4 { + fmt.Println("Usage: count_in_db ") + os.Exit(1) + } + count := CountInDB(os.Args[2], os.Args[3]) + fmt.Println(count) + case "get_from_db": + if len(os.Args) != 4 { + fmt.Println("Usage: get_from_db ") + os.Exit(1) + } + line, _ := GetFromDB(os.Args[2], os.Args[3]) + fmt.Println(line) + default: + fmt.Println("Unknown command:", cmd) + os.Exit(1) + } +} diff --git a/go.mod b/go.mod index 3721544..e348de1 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,21 @@ module git.g3e.fr/syonad/two go 1.23.8 + +require ( + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/dgraph-io/badger/v4 v4.8.0 // indirect + github.com/dgraph-io/ristretto/v2 v2.2.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/google/flatbuffers v25.2.10+incompatible // indirect + github.com/klauspost/compress v1.18.0 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/otel v1.37.0 // indirect + go.opentelemetry.io/otel/metric v1.37.0 // indirect + go.opentelemetry.io/otel/trace v1.37.0 // indirect + golang.org/x/net v0.41.0 // indirect + golang.org/x/sys v0.34.0 // indirect + google.golang.org/protobuf v1.36.6 // indirect +) diff --git a/pkg/db/kv/init.go b/pkg/db/kv/init.go new file mode 100644 index 0000000..ebc2f1f --- /dev/null +++ b/pkg/db/kv/init.go @@ -0,0 +1,19 @@ +package kv + +import ( + "github.com/dgraph-io/badger/v4" +) + +func InitDB() *badger.DB { + opts := badger.DefaultOptions("./data") + opts.Logger = nil + opts.ValueLogFileSize = 10 << 20 // 10 Mo par fichier vlog + opts.NumMemtables = 1 + opts.NumLevelZeroTables = 1 + opts.NumLevelZeroTablesStall = 2 + db, err := badger.Open(opts) + if err != nil { + panic(err) + } + return db +}