fixed parsing of quotes and of detecting rename statements
This commit is contained in:
parent
5119ea4d31
commit
e7cf488818
@ -8,10 +8,12 @@ package sql
|
|||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
renameColumnRegexp = regexp.MustCompile(`(?i)change\s+(column\s+|)([\S]+)\s+([\S]+)\s+`)
|
stripQuotesRegexp = regexp.MustCompile("('[^']*')")
|
||||||
|
renameColumnRegexp = regexp.MustCompile(`(?i)\bchange\s+(column\s+|)([\S]+)\s+([\S]+)\s+`)
|
||||||
)
|
)
|
||||||
|
|
||||||
type Parser struct {
|
type Parser struct {
|
||||||
@ -24,8 +26,44 @@ func NewParser() *Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *Parser) tokenizeAlterStatement(alterStatement string) (tokens []string, err error) {
|
||||||
|
terminatingQuote := rune(0)
|
||||||
|
f := func(c rune) bool {
|
||||||
|
switch {
|
||||||
|
case c == terminatingQuote:
|
||||||
|
terminatingQuote = rune(0)
|
||||||
|
return false
|
||||||
|
case terminatingQuote != rune(0):
|
||||||
|
return false
|
||||||
|
case c == '\'':
|
||||||
|
terminatingQuote = c
|
||||||
|
return false
|
||||||
|
case c == '(':
|
||||||
|
terminatingQuote = ')'
|
||||||
|
return false
|
||||||
|
default:
|
||||||
|
return c == ','
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens = strings.FieldsFunc(alterStatement, f)
|
||||||
|
for i := range tokens {
|
||||||
|
tokens[i] = strings.TrimSpace(tokens[i])
|
||||||
|
}
|
||||||
|
return tokens, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Parser) stripQuotesFromAlterStatement(alterStatement string) (strippedStatement string) {
|
||||||
|
strippedStatement = alterStatement
|
||||||
|
strippedStatement = stripQuotesRegexp.ReplaceAllString(strippedStatement, "''")
|
||||||
|
return strippedStatement
|
||||||
|
}
|
||||||
|
|
||||||
func (this *Parser) ParseAlterStatement(alterStatement string) (err error) {
|
func (this *Parser) ParseAlterStatement(alterStatement string) (err error) {
|
||||||
allStringSubmatch := renameColumnRegexp.FindAllStringSubmatch(alterStatement, -1)
|
alterTokens, _ := this.tokenizeAlterStatement(alterStatement)
|
||||||
|
for _, alterToken := range alterTokens {
|
||||||
|
alterToken = this.stripQuotesFromAlterStatement(alterToken)
|
||||||
|
allStringSubmatch := renameColumnRegexp.FindAllStringSubmatch(alterToken, -1)
|
||||||
for _, submatch := range allStringSubmatch {
|
for _, submatch := range allStringSubmatch {
|
||||||
if unquoted, err := strconv.Unquote(submatch[2]); err == nil {
|
if unquoted, err := strconv.Unquote(submatch[2]); err == nil {
|
||||||
submatch[2] = unquoted
|
submatch[2] = unquoted
|
||||||
@ -36,6 +74,7 @@ func (this *Parser) ParseAlterStatement(alterStatement string) (err error) {
|
|||||||
|
|
||||||
this.columnRenameMap[submatch[2]] = submatch[3]
|
this.columnRenameMap[submatch[2]] = submatch[3]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
package sql
|
package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/outbrain/golib/log"
|
"github.com/outbrain/golib/log"
|
||||||
@ -66,3 +67,53 @@ func TestParseAlterStatementNonTrivial(t *testing.T) {
|
|||||||
test.S(t).ExpectEquals(renames["f"], "fl")
|
test.S(t).ExpectEquals(renames["f"], "fl")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTokenizeAlterStatement(t *testing.T) {
|
||||||
|
parser := NewParser()
|
||||||
|
{
|
||||||
|
alterStatement := "add column t int"
|
||||||
|
tokens, _ := parser.tokenizeAlterStatement(alterStatement)
|
||||||
|
test.S(t).ExpectTrue(reflect.DeepEqual(tokens, []string{"add column t int"}))
|
||||||
|
}
|
||||||
|
{
|
||||||
|
alterStatement := "add column t int, change column i int"
|
||||||
|
tokens, _ := parser.tokenizeAlterStatement(alterStatement)
|
||||||
|
test.S(t).ExpectTrue(reflect.DeepEqual(tokens, []string{"add column t int", "change column i int"}))
|
||||||
|
}
|
||||||
|
{
|
||||||
|
alterStatement := "add column t int, change column i int 'some comment'"
|
||||||
|
tokens, _ := parser.tokenizeAlterStatement(alterStatement)
|
||||||
|
test.S(t).ExpectTrue(reflect.DeepEqual(tokens, []string{"add column t int", "change column i int 'some comment'"}))
|
||||||
|
}
|
||||||
|
{
|
||||||
|
alterStatement := "add column t int, change column i int 'some comment, with comma'"
|
||||||
|
tokens, _ := parser.tokenizeAlterStatement(alterStatement)
|
||||||
|
test.S(t).ExpectTrue(reflect.DeepEqual(tokens, []string{"add column t int", "change column i int 'some comment, with comma'"}))
|
||||||
|
}
|
||||||
|
{
|
||||||
|
alterStatement := "add column t int, add column e enum('a','b','c')"
|
||||||
|
tokens, _ := parser.tokenizeAlterStatement(alterStatement)
|
||||||
|
log.Errorf("%#v", tokens)
|
||||||
|
test.S(t).ExpectTrue(reflect.DeepEqual(tokens, []string{"add column t int", "add column e enum('a','b','c')"}))
|
||||||
|
}
|
||||||
|
{
|
||||||
|
alterStatement := "add column t int(11), add column e enum('a','b','c')"
|
||||||
|
tokens, _ := parser.tokenizeAlterStatement(alterStatement)
|
||||||
|
log.Errorf("%#v", tokens)
|
||||||
|
test.S(t).ExpectTrue(reflect.DeepEqual(tokens, []string{"add column t int(11)", "add column e enum('a','b','c')"}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStripQuotesFromAlterStatement(t *testing.T) {
|
||||||
|
parser := NewParser()
|
||||||
|
{
|
||||||
|
alterStatement := "add column e enum('a','b','c')"
|
||||||
|
strippedStatement := parser.stripQuotesFromAlterStatement(alterStatement)
|
||||||
|
test.S(t).ExpectEquals(strippedStatement, "add column e enum('','','')")
|
||||||
|
}
|
||||||
|
{
|
||||||
|
alterStatement := "change column i int 'some comment, with comma'"
|
||||||
|
strippedStatement := parser.stripQuotesFromAlterStatement(alterStatement)
|
||||||
|
test.S(t).ExpectEquals(strippedStatement, "change column i int ''")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user