1
0
mirror of https://github.com/MADTeacher/go_basics.git synced 2025-11-23 21:34:47 +02:00
Files
go_basics/part_5/go_database/database/table.go
2025-06-14 12:40:10 +03:00

156 lines
2.8 KiB
Go

package database
import (
"fmt"
"strconv"
"strings"
)
type Node[T IAttribute] struct {
Data T
Next *Node[T]
}
type Table[T IAttribute] struct {
head *Node[T]
tail *Node[T]
Title string
}
func NewTable[T IAttribute](title string) *Table[T] {
return &Table[T]{Title: title}
}
func (t *Table[T]) First() T {
if t.head != nil {
return t.head.Data
}
var zero T
return zero
}
func (t *Table[T]) Last() T {
if t.tail != nil {
return t.tail.Data
}
var zero T
return zero
}
func (t *Table[T]) Contains(data T) bool {
user, ok := any(data).(*User)
if !ok {
return false
}
temp := t.head
for temp != nil {
if temp.Data.Check(FieldID, strconv.Itoa(user.ID())) {
return true
}
temp = temp.Next
}
return false
}
func (t *Table[T]) Insert(data T) bool {
if t.Contains(data) {
return false
}
node := &Node[T]{Data: data}
if t.head == nil {
t.head = node
t.tail = node
} else {
t.tail.Next = node
t.tail = node
}
return true
}
func (t *Table[T]) Remove(id string) {
var prev *Node[T]
curr := t.head
for curr != nil {
if curr.Data.Check("id", id) {
if prev == nil {
t.head = curr.Next
if t.head == nil {
t.tail = nil
}
} else {
prev.Next = curr.Next
if prev.Next == nil {
t.tail = prev
}
}
return
}
prev = curr
curr = curr.Next
}
}
func (t *Table[T]) Intersect(attribute, value string,
other *Table[T]) *Table[T] {
newTable := NewTable[T](fmt.Sprintf("%s-%s", t.Title, other.Title))
for temp := t.head; temp != nil; temp = temp.Next {
if temp.Data.Check(attribute, value) {
newTable.Insert(temp.Data)
}
}
for temp := other.head; temp != nil; temp = temp.Next {
if temp.Data.Check(attribute, value) &&
!newTable.Contains(temp.Data) {
newTable.Insert(temp.Data)
}
}
return newTable
}
func (t *Table[T]) Union(other *Table[T]) *Table[T] {
newTable := NewTable[T](fmt.Sprintf("%s-%s", t.Title, other.Title))
for temp := t.head; temp != nil; temp = temp.Next {
newTable.Insert(temp.Data)
}
for temp := other.head; temp != nil; temp = temp.Next {
if !newTable.Contains(temp.Data) {
newTable.Insert(temp.Data)
}
}
return newTable
}
func (t *Table[T]) Selection(attribute, value string) *Table[T] {
newTable := NewTable[T](t.Title + "-new")
for temp := t.head; temp != nil; temp = temp.Next {
if temp.Data.Check(attribute, value) {
newTable.Insert(temp.Data)
}
}
return newTable
}
func (t *Table[T]) ForEach(action func(T)) {
for temp := t.head; temp != nil; temp = temp.Next {
action(temp.Data)
}
}
func (t *Table[T]) String() string {
var sb strings.Builder
sb.WriteString(fmt.Sprintf("%s%s%s\n", strings.Repeat("*", 10),
t.Title, strings.Repeat("*", 10)))
for temp := t.head; temp != nil; temp = temp.Next {
sb.WriteString(fmt.Sprintf("%s\n", temp.Data.String()))
}
return sb.String()
}