// Copyright 2020 The Xorm Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package schemas import ( "strings" ) // Quoter represents two quote characters type Quoter [2]string // CommonQuoter represetns a common quoter var CommonQuoter = Quoter{"`", "`"} func (q Quoter) IsEmpty() bool { return q[0] == "" && q[1] == "" } func (q Quoter) Quote(s string) string { var buf strings.Builder q.QuoteTo(&buf, s) return buf.String() } func (q Quoter) ReverseQuote(s string) string { reverseQuoter := Quoter{q[1], q[0]} return reverseQuoter.Quote(s) } // Trim removes quotes from s func (q Quoter) Trim(s string) string { if len(s) < 2 { return s } if s[0:1] == q[0] { s = s[1:] } if len(s) > 0 && s[len(s)-1:] == q[0] { return s[:len(s)-1] } return s } func (q Quoter) Join(s []string, splitter string) string { return q.Quote(strings.Join(s, q.ReverseQuote(splitter))) } func (q Quoter) QuoteTo(buf *strings.Builder, value string) { if q.IsEmpty() { buf.WriteString(value) return } prefix, suffix := q[0][0], q[1][0] lastCh := 0 // 0 prefix, 1 char, 2 suffix i := 0 for i < len(value) { // start of a token; might be already quoted if value[i] == '.' { _ = buf.WriteByte('.') lastCh = 1 i++ } else if value[i] == prefix || value[i] == '`' { // Has quotes; skip/normalize `name` to prefix+name+sufix var ch byte if value[i] == prefix { ch = suffix } else { ch = '`' } _ = buf.WriteByte(prefix) i++ lastCh = 0 for ; i < len(value) && value[i] != ch && value[i] != ' '; i++ { _ = buf.WriteByte(value[i]) lastCh = 1 } _ = buf.WriteByte(suffix) lastCh = 2 i++ } else if value[i] == ' ' { if lastCh != 2 { _ = buf.WriteByte(suffix) lastCh = 2 } // a AS b or a b for ; i < len(value); i++ { if value[i] != ' ' && value[i-1] == ' ' && (len(value) > i+1 && !strings.EqualFold(value[i:i+2], "AS")) { break } _ = buf.WriteByte(value[i]) lastCh = 1 } } else { // Requires quotes _ = buf.WriteByte(prefix) for ; i < len(value) && value[i] != '.' && value[i] != ' '; i++ { _ = buf.WriteByte(value[i]) lastCh = 1 } _ = buf.WriteByte(suffix) lastCh = 2 } } }