代码拉取完成,页面将自动刷新
同步操作将从 gorm/gen 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
package check
import (
"fmt"
"strings"
"gitee.com/whilew/gen/internal/model"
"gitee.com/whilew/gen/internal/parser"
)
// Clause a symbol of clause, it can be sql condition clause, if clause, where clause, set clause and else cluase
type Clause interface {
String() string
}
var (
_ Clause = new(SQLClause)
_ Clause = new(IfClause)
_ Clause = new(ElseClause)
_ Clause = new(WhereClause)
_ Clause = new(SetClause)
)
type clause struct {
VarName string
Type model.Status
}
// SQLClause sql condition clause
type SQLClause struct {
clause
Value []string
}
func (s SQLClause) String() string {
return strings.ReplaceAll(strings.Join(s.Value, "+"), `"+"`, "")
}
// IfClause if clause
type IfClause struct {
clause
Cond string
Value []Clause
Else []Clause
}
func (i IfClause) String() string {
return fmt.Sprintf("helper.IfClause(%s)", i.VarName)
}
// ElseClause else clause
type ElseClause struct {
clause
Cond string
Value []Clause
}
func (e ElseClause) String() (res string) {
condList := make([]string, len(e.Value))
for i, v := range e.Value {
condList[i] = v.String()
}
return strings.ReplaceAll(strings.Join(condList, "+"), `"+"`, "")
}
// WhereClause where clause
type WhereClause struct {
clause
Value []Clause
}
func (w WhereClause) String() string {
return fmt.Sprintf("helper.WhereClause(%s)", w.VarName)
}
// SetClause set clause
type SetClause struct {
clause
Value []Clause
}
func (w SetClause) String() string {
return fmt.Sprintf("helper.SetClause(%s)", w.VarName)
}
// Slices split sql into chunks
type Slices struct {
slices []slice
tmpl []string
currentIndex int
Names map[model.Status]int
}
// NewSlices create and initialize Slices
func NewSlices() *Slices {
return &Slices{
Names: map[model.Status]int{
model.IF: 0,
model.WHERE: 0,
model.SET: 0,
},
}
}
// Len return length of s.slices
func (s *Slices) Len() int {
return len(s.slices)
}
// Next return next slice and increase index by 1
func (s *Slices) Next() slice {
s.currentIndex++
return s.slices[s.currentIndex]
}
// SubIndex take index one step back
func (s *Slices) SubIndex() {
s.currentIndex--
}
// HasMore whether has more slice
func (s *Slices) HasMore() bool {
return s.currentIndex < len(s.slices)-1
}
// IsNull whether slice is empty
func (s *Slices) IsNull() bool {
return len(s.slices) == 0
}
// Current return current slice
func (s *Slices) Current() slice {
return s.slices[s.currentIndex]
}
// GetName ...
func (s *Slices) GetName(status model.Status) string {
switch status {
case model.IF:
defer func() { s.Names[model.IF]++ }()
return fmt.Sprintf("ifCond%d", s.Names[model.IF])
case model.WHERE:
defer func() { s.Names[model.WHERE]++ }()
return fmt.Sprintf("whereCond%d", s.Names[model.WHERE])
case model.SET:
defer func() { s.Names[model.SET]++ }()
return fmt.Sprintf("setCond%d", s.Names[model.SET])
default:
return fmt.Sprintf("Cond%d", s.currentIndex)
}
}
func (s *Slices) appendIfCond(name, cond, result string) {
s.tmpl = append(s.tmpl, fmt.Sprintf("%s = append(%s, helper.Cond{Cond: %s, Result: %s})", name, name, cond, result))
}
func (s *Slices) appendSetValue(name, result string) {
s.tmpl = append(s.tmpl, fmt.Sprintf("%s = append(%s, %s)", name, name, strings.TrimSpace(result)))
}
// CreateIf create if clause code
func (s *Slices) CreateIf(name string) {
s.tmpl = append(s.tmpl, fmt.Sprintf("%s := make([]helper.Cond, 0, 100)", name))
}
// CreateStringSet create string set
func (s *Slices) CreateStringSet(name string) {
s.tmpl = append(s.tmpl, fmt.Sprintf("%s := make([]string, 0, 100)", name))
}
// parse slice and append result to tmpl, return a Clause array
func (s *Slices) parse() ([]Clause, error) {
if s.IsNull() {
return nil, fmt.Errorf("sql is null")
}
name := "generateSQL"
res := make([]Clause, 0, s.Len())
for slice := s.Current(); ; slice = s.Next() {
s.tmpl = append(s.tmpl, "")
switch slice.Type {
case model.SQL, model.DATA, model.VARIABLE:
sqlClause := s.parseSQL(name)
res = append(res, sqlClause)
s.tmpl = append(s.tmpl, fmt.Sprintf("%s+=%s", name, sqlClause.String()))
case model.IF:
ifClause, err := s.parseIF()
if err != nil {
return nil, err
}
res = append(res, ifClause)
s.tmpl = append(s.tmpl, fmt.Sprintf("%s+=helper.IfClause(%s)", name, ifClause.VarName))
case model.WHERE:
whereClause, err := s.parseWhere()
if err != nil {
return nil, err
}
res = append(res, whereClause)
s.tmpl = append(s.tmpl, fmt.Sprintf("%s+=helper.WhereClause(%s)", name, whereClause.VarName))
case model.SET:
setClause, err := s.parseSet()
if err != nil {
return nil, err
}
res = append(res, setClause)
s.tmpl = append(s.tmpl, fmt.Sprintf("%s+=helper.SetClause(%s)", name, setClause.VarName))
case model.END:
default:
return nil, fmt.Errorf("unknow clause:%s", slice.Origin)
}
if !s.HasMore() {
break
}
}
return res, nil
}
// parseIF parse if clause
func (s *Slices) parseIF() (res IfClause, err error) {
slice := s.Current()
name := s.GetName(slice.Type)
s.CreateIf(name)
res.Type = slice.Type
res.Cond = slice.Value
res.VarName = name
cond := []string{res.Cond}
for s.HasMore() {
n := s.Next()
switch n.Type {
case model.SQL, model.DATA, model.VARIABLE:
str := s.parseSQL(name)
res.Value = append(res.Value, str)
s.appendIfCond(name, res.Cond, str.String())
case model.IF:
var ifClause IfClause
ifClause, err = s.parseIF()
if err != nil {
return
}
res.Value = append(res.Value, ifClause)
s.appendIfCond(name, res.Cond, ifClause.String())
case model.WHERE:
var whereClause WhereClause
whereClause, err = s.parseWhere()
if err != nil {
return
}
res.Value = append(res.Value, whereClause)
s.appendIfCond(name, res.Cond, whereClause.String())
case model.SET:
var setClause SetClause
setClause, err = s.parseSet()
if err != nil {
return
}
res.Value = append(res.Value, setClause)
s.appendIfCond(name, res.Cond, setClause.String())
case model.ELSEIF:
elseClause := s.parseElSE(name)
elseCond := elseClause.Cond
elseClause.Cond = fmt.Sprintf("!(%s) && %s", strings.Join(cond, " || "), elseCond)
res.Else = append(res.Else, elseClause)
s.appendIfCond(name, elseClause.Cond, elseClause.String())
cond = append(cond, elseCond)
case model.ELSE:
elseClause := s.parseElSE(name)
elseClause.Cond = fmt.Sprintf("!(%s)", strings.Join(cond, " || "))
res.Else = append(res.Else, elseClause)
s.appendIfCond(name, elseClause.Cond, elseClause.String())
case model.END:
return
default:
err = fmt.Errorf("unknow clause : %s", n.Origin)
return
}
}
if s.Current().Type == model.END {
return
}
err = fmt.Errorf("incomplete SQL,if not end")
return
}
// parseElSE parse else clause, the clause' type must be one of if, where, set, SQL condition
func (s *Slices) parseElSE(name string) (res ElseClause) {
slice := s.Current()
res.Cond = slice.Value
res.VarName = name
res.Type = slice.Type
if !s.HasMore() {
return
}
for n := s.Next(); s.HasMore(); n = s.Next() {
switch n.Type {
case model.SQL, model.DATA, model.VARIABLE:
res.Value = append(res.Value, s.parseSQL(name))
case model.IF:
ifClause, err := s.parseIF()
if err != nil {
return
}
res.Value = append(res.Value, ifClause)
case model.WHERE:
whereClause, err := s.parseWhere()
if err != nil {
return
}
res.Value = append(res.Value, whereClause)
case model.SET:
setClause, err := s.parseSet()
if err != nil {
return
}
res.Value = append(res.Value, setClause)
default:
s.SubIndex()
return
}
}
return
}
// parseWhere parse where clause, the clause' type must be one of if, SQL condition
func (s *Slices) parseWhere() (res WhereClause, err error) {
slice := s.Current()
name := s.GetName(slice.Type)
s.CreateStringSet(name)
res.VarName = name
res.Type = slice.Type
for s.HasMore() {
n := s.Next()
switch n.Type {
case model.SQL, model.DATA, model.VARIABLE:
strClause := s.parseSQL(name)
res.Value = append(res.Value, strClause)
s.appendSetValue(name, strClause.String())
case model.IF:
var ifClause IfClause
ifClause, err = s.parseIF()
if err != nil {
return
}
res.Value = append(res.Value, ifClause)
s.appendSetValue(name, ifClause.String())
case model.END:
return
default:
err = fmt.Errorf("unknow clause : %s", n.Origin)
return
}
}
if s.Current().Type == model.END {
return
}
err = fmt.Errorf("incomplete SQL,where not end")
return
}
// parseSet parse set clause, the clause' type must be one of if, SQL condition
func (s *Slices) parseSet() (res SetClause, err error) {
slice := s.Current()
name := s.GetName(slice.Type)
s.CreateStringSet(name)
res.VarName = name
res.Type = slice.Type
for s.HasMore() {
n := s.Next()
switch n.Type {
case model.SQL, model.DATA, model.VARIABLE:
strClause := s.parseSQL(name)
res.Value = append(res.Value, strClause)
s.appendSetValue(name, strClause.String())
case model.IF:
var ifClause IfClause
ifClause, err = s.parseIF()
if err != nil {
return
}
res.Value = append(res.Value, ifClause)
s.appendSetValue(name, ifClause.String())
case model.END:
return
default:
err = fmt.Errorf("unknow clause : %s", n.Origin)
return
}
}
if s.Current().Type == model.END {
return
}
err = fmt.Errorf("incomplete SQL,set not end")
return
}
// parseSQL parse sql condition, the clause' type must be one of SQL condition, VARIABLE, Data
func (s *Slices) parseSQL(name string) (res SQLClause) {
res.VarName = name
res.Type = model.SQL
for slice := s.Current(); ; slice = s.Next() {
switch slice.Type {
case model.SQL, model.VARIABLE, model.DATA:
res.Value = append(res.Value, slice.Value)
default:
s.SubIndex()
return
}
if !s.HasMore() {
return
}
}
}
// sql fragment
type fragment struct {
Type model.Status
Value string
IsArray bool
}
func checkFragment(s string, params []parser.Param) (f fragment, err error) {
digital := func(str string) string {
if isDigit(str) {
return "<integer>"
}
return str
}
f = fragment{Type: model.UNKNOWN, Value: strings.Trim(s, " ")}
str := strings.ToLower(strings.Trim(s, " "))
switch digital(str) {
case "<integer>":
f.Type = model.INT
case "&&", "||":
f.Type = model.LOGICAL
case ">", "<", ">=", "<=", "==", "!=":
f.Type = model.EXPRESSION
case "end":
f.Type = model.END
case "if":
f.Type = model.IF
case "set":
f.Type = model.SET
case "else":
f.Type = model.ELSE
case "where":
f.Type = model.WHERE
case "true", "false":
f.Type = model.BOOL
case "nil":
f.Type = model.NIL
default:
f.fragmentByParams(params)
if f.Type == model.UNKNOWN {
err = fmt.Errorf("unknow parameter: %s", s)
}
}
return
}
func (f *fragment) fragmentByParams(params []parser.Param) {
for _, param := range params {
if param.Name == f.Value {
f.IsArray = param.IsArray
switch param.Type {
case "bool":
f.Type = model.BOOL
return
case "int":
f.Type = model.INT
return
case "string":
f.Type = model.STRING
return
case "Time":
f.Type = model.TIME
default:
f.Type = model.OTHER
}
}
}
}
func splitTemplate(tmpl string, params []parser.Param) (fragList []fragment, err error) {
var buf model.SQLBuffer
var f fragment
for i := 0; !strOutrange(i, tmpl); i++ {
switch tmpl[i] {
case '"':
_ = buf.WriteByte(tmpl[i])
for i++; ; i++ {
if strOutrange(i, tmpl) {
return nil, fmt.Errorf("incomplete code:%s", tmpl)
}
_ = buf.WriteByte(tmpl[i])
if tmpl[i] == '"' && tmpl[i-1] != '\\' {
fragList = append(fragList, fragment{Type: model.STRING, Value: buf.Dump()})
break
}
}
case ' ':
if sqlClause := buf.Dump(); sqlClause != "" {
f, err = checkFragment(sqlClause, params)
if err != nil {
return nil, err
}
fragList = append(fragList, f)
}
case '>', '<', '=', '!':
if sqlClause := buf.Dump(); sqlClause != "" {
f, err = checkFragment(sqlClause, params)
if err != nil {
return nil, err
}
fragList = append(fragList, f)
}
_ = buf.WriteByte(tmpl[i])
if strOutrange(i+1, tmpl) {
return nil, fmt.Errorf("incomplete code:%s", tmpl)
}
if tmpl[i+1] == '=' {
_ = buf.WriteByte(tmpl[i+1])
i++
}
f, err = checkFragment(buf.Dump(), params)
if err != nil {
return nil, err
}
fragList = append(fragList, f)
case '&', '|':
if strOutrange(i+1, tmpl) {
return nil, fmt.Errorf("incomplete code:%s", tmpl)
}
if tmpl[i+1] == tmpl[i] {
i++
if sqlClause := buf.Dump(); sqlClause != "" {
f, err = checkFragment(sqlClause, params)
if err != nil {
return nil, err
}
fragList = append(fragList, f)
}
// write && or ||
fragList = append(fragList, fragment{
Type: model.LOGICAL,
Value: tmpl[i-1 : i+1],
})
}
default:
_ = buf.WriteByte(tmpl[i])
}
}
if sqlClause := buf.Dump(); sqlClause != "" {
f, err = checkFragment(sqlClause, params)
if err != nil {
return nil, err
}
fragList = append(fragList, f)
}
return fragList, nil
}
// check validition of clause's value
func checkTempleFragmentValid(list []fragment) error {
for i := 1; i < len(list); i++ {
switch list[i].Type {
case model.IF, model.ELSE, model.END, model.BOOL, model.LOGICAL, model.WHERE, model.SET:
continue
case model.INT, model.STRING, model.OTHER, model.TIME, model.NIL:
if i+2 < len(list) {
if isExpressionValid(list[i : i+3]) {
i += 2
} else {
return fmt.Errorf("condition type not match:%s", fragmentToString(list[i:i+3]))
}
}
default:
return fmt.Errorf("unknow fragment : %s ", list[i].Value)
}
}
return nil
}
// isExpressionValid check express valid
func isExpressionValid(expr []fragment) bool {
if len(expr) != 3 {
return false
}
if expr[1].Type != model.EXPRESSION {
return false
}
//Only arrays can be compared with nil
if expr[0].Type == model.NIL || expr[2].Type == model.NIL {
return expr[0].IsArray || expr[2].IsArray
}
return expr[0].Type == expr[2].Type
}
func fragmentToString(list []fragment) string {
var values []string
if len(list) == 0 {
return ""
}
for _, t := range list {
values = append(values, t.Value)
}
return strings.Join(values, " ")
}
func fragmentToSLice(list []fragment) (part slice, err error) {
var values []string
if len(list) == 0 {
return
}
for _, t := range list {
values = append(values, t.Value)
}
part.Origin = strings.Join(values, " ")
switch strings.ToLower(values[0]) {
case "if":
if len(values) > 1 {
part.Type = model.IF
part.Value = strings.Join(values[1:], " ")
return
}
case "else":
if len(values) == 1 {
part.Type = model.ELSE
return
} else {
if strings.ToLower(values[1]) == "if" && len(values) > 2 {
part.Value = strings.Join(values[2:], " ")
part.Type = model.ELSEIF
return
}
}
case "where":
part.Type = model.WHERE
return
case "set":
part.Type = model.SET
return
case "end":
part.Type = model.END
return
}
err = fmt.Errorf("syntax error:%s", strings.Join(values, " "))
return
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。