144 lines
2.9 KiB
Go
144 lines
2.9 KiB
Go
|
package sqlgen
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"os"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
func parsePath(filePath string) (*schema, error) {
|
||
|
fileBytes, err := os.ReadFile(filePath)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return parseBytes(fileBytes)
|
||
|
}
|
||
|
|
||
|
func parseBytes(fileBytes []byte) (*schema, error) {
|
||
|
s := string(fileBytes)
|
||
|
for _, c := range []string{",", "(", ")", ";"} {
|
||
|
s = strings.ReplaceAll(s, c, " "+c+" ")
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
tokens = strings.Fields(s)
|
||
|
schema = &schema{}
|
||
|
err error
|
||
|
)
|
||
|
|
||
|
for len(tokens) > 0 {
|
||
|
switch tokens[0] {
|
||
|
case "TABLE":
|
||
|
tokens, err = parseTable(schema, tokens)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
return nil, errors.New("invalid token: " + tokens[0])
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return schema, nil
|
||
|
}
|
||
|
|
||
|
func parseTable(schema *schema, tokens []string) ([]string, error) {
|
||
|
tokens = tokens[1:]
|
||
|
if len(tokens) < 3 {
|
||
|
return tokens, errors.New("incomplete table definition")
|
||
|
}
|
||
|
if tokens[1] != "OF" {
|
||
|
return tokens, errors.New("expected OF in table definition")
|
||
|
}
|
||
|
|
||
|
table := &table{
|
||
|
Name: tokens[0],
|
||
|
Type: tokens[2],
|
||
|
}
|
||
|
schema.Tables = append(schema.Tables, table)
|
||
|
|
||
|
tokens = tokens[3:]
|
||
|
|
||
|
if len(tokens) == 0 {
|
||
|
return tokens, errors.New("missing table definition body")
|
||
|
}
|
||
|
|
||
|
for len(tokens) > 0 {
|
||
|
switch tokens[0] {
|
||
|
case "NoInsert":
|
||
|
table.NoInsert = true
|
||
|
tokens = tokens[1:]
|
||
|
case "NoUpdate":
|
||
|
table.NoUpdate = true
|
||
|
tokens = tokens[1:]
|
||
|
case "NoDelete":
|
||
|
table.NoDelete = true
|
||
|
tokens = tokens[1:]
|
||
|
case "(":
|
||
|
return parseTableBody(table, tokens[1:])
|
||
|
default:
|
||
|
return tokens, errors.New("unexpected token in table definition: " + tokens[0])
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return tokens, errors.New("incomplete table definition")
|
||
|
}
|
||
|
|
||
|
func parseTableBody(table *table, tokens []string) ([]string, error) {
|
||
|
var err error
|
||
|
|
||
|
for len(tokens) > 0 && tokens[0] != ";" {
|
||
|
tokens, err = parseTableColumn(table, tokens)
|
||
|
if err != nil {
|
||
|
return tokens, err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if len(tokens) < 1 || tokens[0] != ";" {
|
||
|
return tokens, errors.New("incomplete table column definitions")
|
||
|
}
|
||
|
|
||
|
return tokens[1:], nil
|
||
|
}
|
||
|
|
||
|
func parseTableColumn(table *table, tokens []string) ([]string, error) {
|
||
|
if len(tokens) < 2 {
|
||
|
return tokens, errors.New("incomplete column definition")
|
||
|
}
|
||
|
column := &column{
|
||
|
Name: tokens[0],
|
||
|
Type: tokens[1],
|
||
|
SqlName: tokens[0],
|
||
|
}
|
||
|
table.Columns = append(table.Columns, column)
|
||
|
|
||
|
tokens = tokens[2:]
|
||
|
for len(tokens) > 0 && tokens[0] != "," && tokens[0] != ")" {
|
||
|
switch tokens[0] {
|
||
|
case "AS":
|
||
|
if len(tokens) < 2 {
|
||
|
return tokens, errors.New("incomplete AS clause in column definition")
|
||
|
}
|
||
|
column.Name = tokens[1]
|
||
|
tokens = tokens[2:]
|
||
|
case "PK":
|
||
|
column.PK = true
|
||
|
tokens = tokens[1:]
|
||
|
case "NoInsert":
|
||
|
column.NoInsert = true
|
||
|
tokens = tokens[1:]
|
||
|
case "NoUpdate":
|
||
|
column.NoUpdate = true
|
||
|
tokens = tokens[1:]
|
||
|
default:
|
||
|
return tokens, errors.New("unexpected token in column definition: " + tokens[0])
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if len(tokens) == 0 {
|
||
|
return tokens, errors.New("incomplete column definition")
|
||
|
}
|
||
|
|
||
|
return tokens[1:], nil
|
||
|
}
|