Initial giu version, not very good looking, maybe prefer CharmBracelet Tea
This commit is contained in:
138
manager.go
Normal file
138
manager.go
Normal file
@@ -0,0 +1,138 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"git.pablu.de/pablu/sqv-engine/sql"
|
||||
)
|
||||
|
||||
type Manager struct {
|
||||
parser *sql.Parser
|
||||
|
||||
tables []Table
|
||||
}
|
||||
|
||||
func NewManagerFromFile(sqlTxt string) *Manager {
|
||||
return &Manager{
|
||||
parser: sql.NewParser(strings.NewReader(sqlTxt)),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Manager) Start() error {
|
||||
for {
|
||||
stmt, err := m.parser.Parse()
|
||||
if err != nil && errors.Is(err, io.EOF) {
|
||||
fmt.Println("Finished parsing")
|
||||
break
|
||||
} else if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
switch v := stmt.(type) {
|
||||
case *sql.CreateTableStatement:
|
||||
t, err := m.convertCreateTableStatementToTable(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.tables = append(m.tables, t)
|
||||
|
||||
default:
|
||||
panic("NOT IMPLEMENTED")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) Refresh(sqlTxt string) error {
|
||||
m.parser = sql.NewParser(strings.NewReader(sqlTxt))
|
||||
m.tables = make([]Table, 0)
|
||||
|
||||
return m.Start()
|
||||
}
|
||||
|
||||
func (m *Manager) GetTables() []Table {
|
||||
return m.tables
|
||||
}
|
||||
|
||||
func (m *Manager) GetTable(name string) (Table, bool) {
|
||||
index := slices.IndexFunc(m.tables, func(t Table) bool {
|
||||
return t.Name == name
|
||||
})
|
||||
|
||||
if index >= 0 {
|
||||
return m.tables[index], true
|
||||
}
|
||||
|
||||
return Table{}, false
|
||||
}
|
||||
|
||||
func (m *Manager) convertCreateTableStatementToTable(cts *sql.CreateTableStatement) (Table, error) {
|
||||
res := Table{
|
||||
Name: cts.TableName,
|
||||
Columns: make([]Column, len(cts.Columns)),
|
||||
Rows: make([]Row, 0),
|
||||
}
|
||||
|
||||
for i, column := range cts.Columns {
|
||||
flags := extrasToFlags(column.Extra)
|
||||
var ref *Column = nil
|
||||
if flags.Has(FOREIGN_KEY) {
|
||||
index := slices.IndexFunc(column.Extra, func(c string) bool {
|
||||
return strings.HasPrefix(c, "ref")
|
||||
})
|
||||
refExtra := column.Extra[index]
|
||||
refStr := strings.Split(refExtra, " ")[1]
|
||||
|
||||
s := strings.Split(refStr, ".")
|
||||
tableName := s[0]
|
||||
columnName := s[1]
|
||||
|
||||
refTable, ok := m.GetTable(tableName)
|
||||
if !ok {
|
||||
fmt.Println(m.tables)
|
||||
return Table{}, fmt.Errorf("Reference table '%v' not found", tableName)
|
||||
}
|
||||
|
||||
colIndex := slices.IndexFunc(refTable.Columns, func(c Column) bool {
|
||||
return c.Name == columnName
|
||||
})
|
||||
|
||||
ref = &refTable.Columns[colIndex]
|
||||
}
|
||||
|
||||
res.Columns[i] = Column{
|
||||
Type: column.Type,
|
||||
Name: column.Name,
|
||||
Reference: ref,
|
||||
Flags: flags,
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func extrasToFlags(extras []string) ColumnFlag {
|
||||
res := NONE
|
||||
for _, extra := range extras {
|
||||
|
||||
// This is not good
|
||||
switch strings.Split(extra, " ")[0] {
|
||||
case "PRIMARY_KEY":
|
||||
res |= PRIMARY_KEY
|
||||
case "ref":
|
||||
res |= FOREIGN_KEY
|
||||
case "NOT_NULL":
|
||||
res |= NOT_NULL
|
||||
default:
|
||||
log.Panicf("NOT IMPLEMENTED EXTRA: %v", extra)
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
Reference in New Issue
Block a user