init elowdb go-port commit

This commit is contained in:
41 changed files with 7273 additions and 0 deletions

641
examples/delete/delete.go Normal file
View File

@@ -0,0 +1,641 @@
package main
import (
"fmt"
"log"
"time"
"linedb/pkg/linedb"
)
// testDeleteOneRecordByID тестирует удаление одной записи по ID
func testDeleteOneRecordByID() {
// Создаем базу данных
db := linedb.NewLineDb(nil)
// Инициализируем базу данных
initOptions := &linedb.LineDbInitOptions{
CacheSize: 1000,
CacheTTL: 10 * time.Second,
DBFolder: "./data/test-linedb-delete",
Collections: []linedb.JSONLFileOptions{
{
CollectionName: "users",
AllocSize: 256,
IndexedFields: []string{"id", "username"},
},
},
}
if err := db.Init(true, initOptions); err != nil {
log.Printf("Failed to init database: %v", err)
return
}
defer db.Close()
// Создаем тестовые данные
user := map[string]any{
"id": 1,
"username": "test_user",
"email": "test@example.com",
"isActive": true,
}
// Вставляем данные
if err := db.Insert(user, "users", linedb.LineDbAdapterOptions{}); err != nil {
log.Printf("Failed to insert user: %v", err)
return
}
// Читаем данные
users, err := db.Read("users", linedb.LineDbAdapterOptions{})
if err != nil {
log.Printf("Failed to read users: %v", err)
return
}
fmt.Printf(" Записей до удаления: %d\n", len(users))
// Удаляем запись по ID
deleted, err := db.Delete(map[string]any{"id": 1}, "users", linedb.LineDbAdapterOptions{})
if err != nil {
log.Printf("Failed to delete user: %v", err)
return
}
fmt.Printf(" Удалено записей: %d\n", len(deleted))
// Проверяем результат
users, err = db.Read("users", linedb.LineDbAdapterOptions{})
if err != nil {
log.Printf("Failed to read users after delete: %v", err)
return
}
fmt.Printf(" Записей после удаления: %d\n", len(users))
}
// testDeleteOneRecordByTextFilter тестирует удаление одной записи по текстовому фильтру
func testDeleteOneRecordByTextFilter() {
// Создаем базу данных
db := linedb.NewLineDb(nil)
// Инициализируем базу данных
initOptions := &linedb.LineDbInitOptions{
CacheSize: 1000,
CacheTTL: 10 * time.Second,
DBFolder: "./data/test-linedb-delete",
Collections: []linedb.JSONLFileOptions{
{
CollectionName: "products",
AllocSize: 256,
IndexedFields: []string{"id", "name"},
},
},
}
if err := db.Init(true, initOptions); err != nil {
log.Printf("Failed to init database: %v", err)
return
}
defer db.Close()
// Создаем тестовые данные
product := map[string]any{
"id": 1,
"name": "Test Product",
"price": 99.99,
"category": "Electronics",
}
// Вставляем данные
if err := db.Insert(product, "products", linedb.LineDbAdapterOptions{}); err != nil {
log.Printf("Failed to insert product: %v", err)
return
}
// Читаем данные
products, err := db.Read("products", linedb.LineDbAdapterOptions{})
if err != nil {
log.Printf("Failed to read products: %v", err)
return
}
fmt.Printf(" Записей до удаления: %d\n", len(products))
// Удаляем запись по текстовому фильтру
deleted, err := db.Delete("name == 'Test Product'", "products", linedb.LineDbAdapterOptions{})
if err != nil {
log.Printf("Failed to delete product: %v", err)
return
}
fmt.Printf(" Удалено записей: %d\n", len(deleted))
// Проверяем результат
products, err = db.Read("products", linedb.LineDbAdapterOptions{})
if err != nil {
log.Printf("Failed to read products after delete: %v", err)
return
}
fmt.Printf(" Записей после удаления: %d\n", len(products))
}
// testDeleteMultipleRecordsByArray тестирует удаление нескольких записей по массиву данных
func testDeleteMultipleRecordsByArray() {
// Создаем базу данных
db := linedb.NewLineDb(nil)
// Инициализируем базу данных
initOptions := &linedb.LineDbInitOptions{
CacheSize: 1000,
CacheTTL: 10 * time.Second,
DBFolder: "./data/test-linedb-delete",
Collections: []linedb.JSONLFileOptions{
{
CollectionName: "orders",
AllocSize: 256,
IndexedFields: []string{"id", "status"},
},
},
}
if err := db.Init(true, initOptions); err != nil {
log.Printf("Failed to init database: %v", err)
return
}
defer db.Close()
// Создаем массив тестовых данных
orders := []any{
map[string]any{
"id": 1,
"status": "pending",
"amount": 100.0,
"customerId": 1,
},
map[string]any{
"id": 2,
"status": "completed",
"amount": 200.0,
"customerId": 2,
},
map[string]any{
"id": 3,
"status": "pending",
"amount": 150.0,
"customerId": 1,
},
}
// Вставляем данные
if err := db.Insert(orders, "orders", linedb.LineDbAdapterOptions{}); err != nil {
log.Printf("Failed to insert orders: %v", err)
return
}
// Читаем данные
ordersData, err := db.Read("orders", linedb.LineDbAdapterOptions{})
if err != nil {
log.Printf("Failed to read orders: %v", err)
return
}
fmt.Printf(" Записей до удаления: %d\n", len(ordersData))
// Удаляем несколько записей по массиву фильтров
deleteFilters := []any{
map[string]any{"id": 1},
map[string]any{"id": 2},
}
deleted, err := db.Delete(deleteFilters, "orders", linedb.LineDbAdapterOptions{})
if err != nil {
log.Printf("Failed to delete orders: %v", err)
return
}
fmt.Printf(" Удалено записей: %d\n", len(deleted))
// Проверяем результат
ordersData, err = db.Read("orders", linedb.LineDbAdapterOptions{})
if err != nil {
log.Printf("Failed to read orders after delete: %v", err)
return
}
fmt.Printf(" Записей после удаления: %d\n", len(ordersData))
}
// testDeleteByPartialMatch тестирует удаление записей по частичному совпадению
func testDeleteByPartialMatch() {
// Создаем базу данных
db := linedb.NewLineDb(nil)
// Инициализируем базу данных
initOptions := &linedb.LineDbInitOptions{
CacheSize: 1000,
CacheTTL: 10 * time.Second,
DBFolder: "./data/test-linedb-delete",
Collections: []linedb.JSONLFileOptions{
{
CollectionName: "customers",
AllocSize: 256,
IndexedFields: []string{"id", "name"},
},
},
}
if err := db.Init(true, initOptions); err != nil {
log.Printf("Failed to init database: %v", err)
return
}
defer db.Close()
// Создаем массив тестовых данных
customers := []any{
map[string]any{
"id": 1,
"name": "John Doe",
"email": "john@example.com",
},
map[string]any{
"id": 2,
"name": "Jane Smith",
"email": "jane@example.com",
},
map[string]any{
"id": 3,
"name": "John Smith",
"email": "john.smith@example.com",
},
}
// Вставляем данные
if err := db.Insert(customers, "customers", linedb.LineDbAdapterOptions{}); err != nil {
log.Printf("Failed to insert customers: %v", err)
return
}
// Читаем данные
customersData, err := db.Read("customers", linedb.LineDbAdapterOptions{})
if err != nil {
log.Printf("Failed to read customers: %v", err)
return
}
fmt.Printf(" Записей до удаления: %d\n", len(customersData))
// Удаляем записи по частичному совпадению
deleted, err := db.Delete(
map[string]any{"name": "John"},
"customers",
linedb.LineDbAdapterOptions{StrictCompare: false},
)
if err != nil {
log.Printf("Failed to delete customers: %v", err)
return
}
fmt.Printf(" Удалено записей с именем 'John': %d\n", len(deleted))
// Проверяем результат
customersData, err = db.Read("customers", linedb.LineDbAdapterOptions{})
if err != nil {
log.Printf("Failed to read customers after delete: %v", err)
return
}
fmt.Printf(" Записей после удаления: %d\n", len(customersData))
}
// testDeleteFromPartitionedCollections тестирует удаление из партиционированных коллекций
func testDeleteFromPartitionedCollections() {
// Создаем базу данных
db := linedb.NewLineDb(nil)
// Инициализируем базу данных с партициями
initOptions := &linedb.LineDbInitOptions{
CacheSize: 1000,
CacheTTL: 10 * time.Second,
DBFolder: "./data/test-linedb-delete",
Collections: []linedb.JSONLFileOptions{
{
CollectionName: "logs",
AllocSize: 256,
IndexedFields: []string{"id", "level"},
},
},
Partitions: []linedb.PartitionCollection{
{
CollectionName: "logs",
PartIDFnStr: "level",
},
},
}
if err := db.Init(true, initOptions); err != nil {
log.Printf("Failed to init database: %v", err)
return
}
defer db.Close()
// Создаем логи для разных уровней
logs := []any{
map[string]any{
"id": 1,
"level": "error",
"message": "Critical error occurred",
"timestamp": time.Now().Unix(),
},
map[string]any{
"id": 2,
"level": "info",
"message": "User logged in",
"timestamp": time.Now().Unix(),
},
map[string]any{
"id": 3,
"level": "error",
"message": "Another error",
"timestamp": time.Now().Unix(),
},
}
// Вставляем данные
if err := db.Insert(logs, "logs", linedb.LineDbAdapterOptions{}); err != nil {
log.Printf("Failed to insert logs: %v", err)
return
}
// Читаем данные
logsData, err := db.Read("logs", linedb.LineDbAdapterOptions{})
if err != nil {
log.Printf("Failed to read logs: %v", err)
return
}
fmt.Printf(" Записей до удаления: %d\n", len(logsData))
// Удаляем логи с уровнем 'error'
deleted, err := db.Delete(map[string]any{"level": "error"}, "logs", linedb.LineDbAdapterOptions{})
if err != nil {
log.Printf("Failed to delete error logs: %v", err)
return
}
fmt.Printf(" Удалено записей с уровнем 'error': %d\n", len(deleted))
// Проверяем результат
logsData, err = db.Read("logs", linedb.LineDbAdapterOptions{})
if err != nil {
log.Printf("Failed to read logs after delete: %v", err)
return
}
fmt.Printf(" Записей после удаления: %d\n", len(logsData))
}
// testDeleteEdgeCases тестирует граничные случаи удаления
func testDeleteEdgeCases() {
// Создаем базу данных
db := linedb.NewLineDb(nil)
// Инициализируем базу данных
initOptions := &linedb.LineDbInitOptions{
CacheSize: 1000,
CacheTTL: 10 * time.Second,
DBFolder: "./data/test-linedb-delete",
Collections: []linedb.JSONLFileOptions{
{
CollectionName: "test_data",
AllocSize: 256,
IndexedFields: []string{"id", "type"},
},
},
}
if err := db.Init(true, initOptions); err != nil {
log.Printf("Failed to init database: %v", err)
return
}
defer db.Close()
// Тест удаления несуществующей записи
fmt.Println(" Тест удаления несуществующей записи:")
deleted, err := db.Delete(map[string]any{"id": 999}, "test_data", linedb.LineDbAdapterOptions{})
if err != nil {
log.Printf("Failed to delete non-existent record: %v", err)
return
}
fmt.Printf(" Удалено несуществующих записей: %d\n", len(deleted))
// Тест удаления пустого массива
fmt.Println(" Тест удаления пустого массива:")
deleted, err = db.Delete([]any{}, "test_data", linedb.LineDbAdapterOptions{})
if err != nil {
log.Printf("Failed to delete empty array: %v", err)
return
}
fmt.Printf(" Удалено записей из пустого массива: %d\n", len(deleted))
// Тест удаления записей с разными типами ID
fmt.Println(" Тест удаления записей с разными типами ID:")
// Вставляем запись со строковым ID
stringIDData := map[string]any{
"id": "user-1",
"name": "Test String Id User",
"type": "string_id",
}
if err := db.Insert(stringIDData, "test_data", linedb.LineDbAdapterOptions{}); err != nil {
log.Printf("Failed to insert string ID data: %v", err)
return
}
// Удаляем запись со строковым ID
deleted, err = db.Delete("id == 'user-1'", "test_data", linedb.LineDbAdapterOptions{})
if err != nil {
log.Printf("Failed to delete string ID record: %v", err)
return
}
fmt.Printf(" Удалено записей со строковым ID: %d\n", len(deleted))
}
// testDeletePerformance тестирует производительность удаления
func testDeletePerformance() {
// Создаем базу данных
db := linedb.NewLineDb(nil)
// Инициализируем базу данных
initOptions := &linedb.LineDbInitOptions{
CacheSize: 10000,
CacheTTL: 10 * time.Second,
DBFolder: "./data/test-linedb-delete",
Collections: []linedb.JSONLFileOptions{
{
CollectionName: "performance_data",
AllocSize: 1024,
IndexedFields: []string{"id", "category"},
},
},
}
if err := db.Init(true, initOptions); err != nil {
log.Printf("Failed to init database: %v", err)
return
}
defer db.Close()
// Создаем большое количество записей
recordCount := 1000
fmt.Printf(" Создание %d записей для теста производительности...\n", recordCount)
largeDataArray := make([]any, recordCount)
for i := 1; i <= recordCount; i++ {
largeDataArray[i-1] = map[string]any{
"id": i,
"name": fmt.Sprintf("User %d", i),
"category": fmt.Sprintf("Category %d", (i-1)%10+1),
"value": float64(i) * 1.5,
}
}
// Вставляем данные
if err := db.Insert(largeDataArray, "performance_data", linedb.LineDbAdapterOptions{}); err != nil {
log.Printf("Failed to insert large data array: %v", err)
return
}
// Читаем данные для проверки
result, err := db.Read("performance_data", linedb.LineDbAdapterOptions{})
if err != nil {
log.Printf("Failed to read large data: %v", err)
return
}
fmt.Printf(" Записей в базе: %d\n", len(result))
// Удаляем половину записей (четные ID)
startTime := time.Now()
itemsToDelete := make([]any, recordCount/2)
for i := 0; i < recordCount/2; i++ {
itemsToDelete[i] = map[string]any{"id": (i + 1) * 2}
}
deleted, err := db.Delete(itemsToDelete, "performance_data", linedb.LineDbAdapterOptions{})
if err != nil {
log.Printf("Failed to delete large number of records: %v", err)
return
}
endTime := time.Now()
duration := endTime.Sub(startTime)
fmt.Printf(" Удалено записей: %d\n", len(deleted))
fmt.Printf(" Время выполнения: %v\n", duration)
// Проверяем результат
result, err = db.Read("performance_data", linedb.LineDbAdapterOptions{})
if err != nil {
log.Printf("Failed to read data after bulk delete: %v", err)
return
}
fmt.Printf(" Записей после массового удаления: %d\n", len(result))
}
// testDeleteMultipleCollections тестирует удаление из множественных коллекций
func testDeleteMultipleCollections() {
// Создаем базу данных
db := linedb.NewLineDb(nil)
// Инициализируем базу данных с множественными коллекциями
initOptions := &linedb.LineDbInitOptions{
CacheSize: 1000,
CacheTTL: 10 * time.Second,
DBFolder: "./data/test-linedb-delete",
Collections: []linedb.JSONLFileOptions{
{
CollectionName: "users",
AllocSize: 256,
IndexedFields: []string{"id", "username"},
},
{
CollectionName: "posts",
AllocSize: 256,
IndexedFields: []string{"id", "authorId"},
},
{
CollectionName: "comments",
AllocSize: 256,
IndexedFields: []string{"id", "postId"},
},
},
}
if err := db.Init(true, initOptions); err != nil {
log.Printf("Failed to init database: %v", err)
return
}
defer db.Close()
// Создаем данные для разных коллекций
users := []any{
map[string]any{
"id": 1,
"username": "user1",
"email": "user1@example.com",
},
map[string]any{
"id": 2,
"username": "user2",
"email": "user2@example.com",
},
}
posts := []any{
map[string]any{
"id": 1,
"title": "First Post",
"authorId": 1,
"content": "This is the first post",
},
map[string]any{
"id": 2,
"title": "Second Post",
"authorId": 2,
"content": "This is the second post",
},
}
comments := []any{
map[string]any{
"id": 1,
"postId": 1,
"content": "Great post!",
"authorId": 2,
},
map[string]any{
"id": 2,
"postId": 2,
"content": "Nice article",
"authorId": 1,
},
}
// Вставляем данные в разные коллекции
if err := db.Insert(users, "users", linedb.LineDbAdapterOptions{}); err != nil {
log.Printf("Failed to insert users: %v", err)
return
}
if err := db.Insert(posts, "posts", linedb.LineDbAdapterOptions{}); err != nil {
log.Printf("Failed to insert posts: %v", err)
return
}
if err := db.Insert(comments, "comments", linedb.LineDbAdapterOptions{}); err != nil {
log.Printf("Failed to insert comments: %v", err)
return
}
// Удаляем данные из разных коллекций
usersDeleted, _ := db.Delete(map[string]any{"id": 1}, "users", linedb.LineDbAdapterOptions{})
postsDeleted, _ := db.Delete(map[string]any{"authorId": 1}, "posts", linedb.LineDbAdapterOptions{})
commentsDeleted, _ := db.Delete(map[string]any{"postId": 1}, "comments", linedb.LineDbAdapterOptions{})
// Читаем данные из всех коллекций
usersData, _ := db.Read("users", linedb.LineDbAdapterOptions{})
postsData, _ := db.Read("posts", linedb.LineDbAdapterOptions{})
commentsData, _ := db.Read("comments", linedb.LineDbAdapterOptions{})
fmt.Printf(" Удалено пользователей: %d\n", len(usersDeleted))
fmt.Printf(" Удалено постов: %d\n", len(postsDeleted))
fmt.Printf(" Удалено комментариев: %d\n", len(commentsDeleted))
fmt.Printf(" Осталось пользователей: %d\n", len(usersData))
fmt.Printf(" Осталось постов: %d\n", len(postsData))
fmt.Printf(" Осталось комментариев: %d\n", len(commentsData))
}

167
examples/delete/main.go Normal file
View File

@@ -0,0 +1,167 @@
package main
import (
"fmt"
"os"
"strconv"
"strings"
)
// TestData представляет тестовые данные
type TestData struct {
ID any `json:"id"`
Name string `json:"name"`
Age int `json:"age"`
Value *int `json:"value,omitempty"`
UserID int `json:"userId"`
Timestamp int64 `json:"timestamp"`
}
// TestUser представляет пользователя
type TestUser struct {
ID int `json:"id"`
Username string `json:"username"`
Password string `json:"password"`
IsActive bool `json:"isActive"`
Role string `json:"role"`
Timestamp int64 `json:"timestamp"`
}
// TestOrder представляет заказ
type TestOrder struct {
ID int `json:"id"`
UserID int `json:"userId"`
Status string `json:"status"`
Amount float64 `json:"amount"`
Timestamp int64 `json:"timestamp"`
}
func main() {
// Очищаем тестовую папку
os.RemoveAll("./data/test-linedb-delete")
fmt.Println("=== LineDb Delete Operations Demo ===")
// Получаем номера тестов из аргументов командной строки
testNumbers := parseTestNumbers()
// Выполняем тесты
if len(testNumbers) == 0 {
// Если номера не указаны, выполняем все тесты
runAllTests()
} else {
// Выполняем только указанные тесты
runSelectedTests(testNumbers)
}
fmt.Println("\n=== Все тесты завершены ===")
}
// parseTestNumbers парсит номера тестов из аргументов командной строки
func parseTestNumbers() []int {
if len(os.Args) < 2 {
return []int{}
}
// Получаем аргумент после имени программы
arg := os.Args[1]
// Проверяем, что это не флаг помощи
if arg == "-h" || arg == "--help" || arg == "help" {
printUsage()
return []int{}
}
// Разбиваем по запятой
parts := strings.Split(arg, ",")
var numbers []int
for _, part := range parts {
part = strings.TrimSpace(part)
if part == "" {
continue
}
num, err := strconv.Atoi(part)
if err != nil {
fmt.Printf("Ошибка: '%s' не является числом\n", part)
printUsage()
return []int{}
}
// Проверяем диапазон
if num < 1 || num > 8 {
fmt.Printf("Ошибка: номер теста %d должен быть от 1 до 8\n", num)
printUsage()
return []int{}
}
numbers = append(numbers, num)
}
return numbers
}
// printUsage выводит справку по использованию
func printUsage() {
fmt.Println("\nИспользование:")
fmt.Println(" go run main.go # Запустить все тесты")
fmt.Println(" go run main.go 1 # Запустить только тест 1")
fmt.Println(" go run main.go 1,3 # Запустить тесты 1 и 3")
fmt.Println(" go run main.go 2,3,4 # Запустить тесты 2, 3 и 4")
fmt.Println(" go run main.go help # Показать эту справку")
fmt.Println("\nДоступные тесты:")
fmt.Println(" 1 - Удаление одной записи по ID")
fmt.Println(" 2 - Удаление одной записи по текстовому фильтру")
fmt.Println(" 3 - Удаление нескольких записей по массиву данных")
fmt.Println(" 4 - Удаление записей по частичному совпадению")
fmt.Println(" 5 - Удаление записей из партиционированных коллекций")
fmt.Println(" 6 - Удаление записей с граничными случаями")
fmt.Println(" 7 - Удаление записей с производительностью")
fmt.Println(" 8 - Удаление записей с множественными коллекциями")
os.Exit(0)
}
// runAllTests запускает все тесты
func runAllTests() {
testDeleteOneRecordByID()
testDeleteOneRecordByTextFilter()
testDeleteMultipleRecordsByArray()
testDeleteByPartialMatch()
testDeleteFromPartitionedCollections()
testDeleteEdgeCases()
testDeletePerformance()
testDeleteMultipleCollections()
}
// runSelectedTests запускает только выбранные тесты
func runSelectedTests(numbers []int) {
for _, num := range numbers {
switch num {
case 1:
fmt.Println("1. Удаление одной записи по ID")
testDeleteOneRecordByID()
case 2:
fmt.Println("2. Удаление одной записи по текстовому фильтру")
testDeleteOneRecordByTextFilter()
case 3:
fmt.Println("3. Удаление нескольких записей по массиву данных")
testDeleteMultipleRecordsByArray()
case 4:
fmt.Println("4. Удаление записей по частичному совпадению")
testDeleteByPartialMatch()
case 5:
fmt.Println("5. Удаление записей из партиционированных коллекций")
testDeleteFromPartitionedCollections()
case 6:
fmt.Println("6. Удаление записей с граничными случаями")
testDeleteEdgeCases()
case 7:
fmt.Println("7. Удаление записей с производительностью")
testDeletePerformance()
case 8:
fmt.Println("8. Удаление записей с множественными коллекциями")
testDeleteMultipleCollections()
}
}
}