123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- package sqlite
- import (
- "errors"
- "fmt"
- "regexp"
- "strings"
- )
- type ddl struct {
- head string
- fields []string
- }
- func parseDDL(sql string) (*ddl, error) {
- reg := regexp.MustCompile("(?i)(CREATE TABLE [\"`]?[\\w\\d]+[\"`]?)(?: \\((.*)\\))?")
- sections := reg.FindStringSubmatch(sql)
- if sections == nil {
- return nil, errors.New("invalid DDL")
- }
- ddlHead := sections[1]
- ddlBody := sections[2]
- ddlBodyRunes := []rune(ddlBody)
- fields := []string{}
- bracketLevel := 0
- var quote rune = 0
- buf := ""
- for i := 0; i < len(ddlBodyRunes); i++ {
- c := ddlBodyRunes[i]
- var next rune = 0
- if i+1 < len(ddlBodyRunes) {
- next = ddlBodyRunes[i+1]
- }
- if c == '\'' || c == '"' || c == '`' {
- if c == next {
- // Skip escaped quote
- buf += string(c)
- i++
- } else if quote > 0 {
- quote = 0
- } else {
- quote = c
- }
- } else if quote == 0 {
- if c == '(' {
- bracketLevel++
- } else if c == ')' {
- bracketLevel--
- } else if bracketLevel == 0 {
- if c == ',' {
- fields = append(fields, strings.TrimSpace(buf))
- buf = ""
- continue
- }
- }
- }
- if bracketLevel < 0 {
- return nil, errors.New("invalid DDL, unbalanced brackets")
- }
- buf += string(c)
- }
- if bracketLevel != 0 {
- return nil, errors.New("invalid DDL, unbalanced brackets")
- }
- if buf != "" {
- fields = append(fields, strings.TrimSpace(buf))
- }
- return &ddl{head: ddlHead, fields: fields}, nil
- }
- func (d *ddl) compile() string {
- if len(d.fields) == 0 {
- return d.head
- }
- return fmt.Sprintf("%s (%s)", d.head, strings.Join(d.fields, ","))
- }
- func (d *ddl) addConstraint(name string, sql string) {
- reg := regexp.MustCompile("^CONSTRAINT [\"`]?" + regexp.QuoteMeta(name) + "[\"` ]")
- for i := 0; i < len(d.fields); i++ {
- if reg.MatchString(d.fields[i]) {
- d.fields[i] = sql
- return
- }
- }
- d.fields = append(d.fields, sql)
- }
- func (d *ddl) removeConstraint(name string) bool {
- reg := regexp.MustCompile("^CONSTRAINT [\"`]?" + regexp.QuoteMeta(name) + "[\"` ]")
- for i := 0; i < len(d.fields); i++ {
- if reg.MatchString(d.fields[i]) {
- d.fields = append(d.fields[:i], d.fields[i+1:]...)
- return true
- }
- }
- return false
- }
- func (d *ddl) hasConstraint(name string) bool {
- reg := regexp.MustCompile("^CONSTRAINT [\"`]?" + regexp.QuoteMeta(name) + "[\"` ]")
- for _, f := range d.fields {
- if reg.MatchString(f) {
- return true
- }
- }
- return false
- }
- func (d *ddl) getColumns() []string {
- res := []string{}
- for _, f := range d.fields {
- fUpper := strings.ToUpper(f)
- if strings.HasPrefix(fUpper, "PRIMARY KEY") ||
- strings.HasPrefix(fUpper, "CHECK") ||
- strings.HasPrefix(fUpper, "CONSTRAINT") {
- continue
- }
- reg := regexp.MustCompile("^[\"`]?([\\w\\d]+)[\"`]?")
- match := reg.FindStringSubmatch(f)
- if match != nil {
- res = append(res, "`"+match[1]+"`")
- }
- }
- return res
- }
|