From 8a04b78ece138b013e6f3ae6915f8cfe5603003d Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 13 Mar 2020 17:28:37 +0800 Subject: [PATCH] Fix dump/import bug --- engine.go | 11 ++++++--- engine_test.go | 53 ++++++++++++++++++++++++++++++++++++++++++ interface.go | 1 + session_schema_test.go | 9 ------- 4 files changed, 62 insertions(+), 12 deletions(-) diff --git a/engine.go b/engine.go index c6fd5c7e..b86e3739 100644 --- a/engine.go +++ b/engine.go @@ -6,7 +6,6 @@ package xorm import ( "bufio" - "bytes" "context" "database/sql" "errors" @@ -1174,12 +1173,18 @@ func (engine *Engine) Import(r io.Reader) ([]sql.Result, error) { var lastError error scanner := bufio.NewScanner(r) + var inSingleQuote bool semiColSpliter := func(data []byte, atEOF bool) (advance int, token []byte, err error) { if atEOF && len(data) == 0 { return 0, nil, nil } - if i := bytes.IndexByte(data, ';'); i >= 0 { - return i + 1, data[0:i], nil + for i, b := range data { + if b == '\'' { + inSingleQuote = !inSingleQuote + } + if !inSingleQuote && b == ';' { + return i + 1, data[0:i], nil + } } // If we're at EOF, we have a final, non-terminated line. Return it. if atEOF { diff --git a/engine_test.go b/engine_test.go index b82ee96a..183a148c 100644 --- a/engine_test.go +++ b/engine_test.go @@ -7,6 +7,9 @@ package xorm import ( "context" "fmt" + "io/ioutil" + "os" + "path/filepath" "testing" "time" @@ -64,3 +67,53 @@ func TestAutoTransaction(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, false, has) } + +func TestDump(t *testing.T) { + assert.NoError(t, prepareEngine()) + + type TestDumpStruct struct { + Id int64 + Name string + } + + assertSync(t, new(TestDumpStruct)) + + testEngine.Insert([]TestDumpStruct{ + {Name: "1"}, + {Name: "2\n"}, + {Name: "3;"}, + {Name: "4"}, + {Name: "5'"}, + }) + + fp := testEngine.Dialect().URI().DBName + ".sql" + os.Remove(fp) + assert.NoError(t, testEngine.DumpAllToFile(fp)) + + assert.NoError(t, prepareEngine()) + + _, err := testEngine.ImportFile(fp) + assert.NoError(t, err) +} + +func TestImport(t *testing.T) { + assert.NoError(t, prepareEngine()) + + var sql = "/*Generated by xorm 2020-03-13 17:13:51, from sqlite3 to SQLITE3*/" + + "CREATE TABLE IF NOT EXISTS `test_dump_struct` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NULL);" + + "INSERT INTO `test_dump_struct` (`id`, `name`) VALUES (1, '1');" + + "INSERT INTO `test_dump_struct` (`id`, `name`) VALUES (2, '2;');" + + "INSERT INTO `test_dump_struct` (`id`, `name`) VALUES (3, '3''');" + + "INSERT INTO `test_dump_struct` (`id`, `name`) VALUES (4, '4\n\n');" + + "INSERT INTO `test_dump_struct` (`id`, `name`) VALUES (5, '5\n;\n');" + + f, err := ioutil.TempFile(os.TempDir(), "dump_file.sql") + assert.NoError(t, err) + _, err = f.WriteString(sql) + assert.NoError(t, err) + info, err := f.Stat() + f.Close() + assert.NoError(t, err) + _, err = testEngine.ImportFile(filepath.Join(os.TempDir(), info.Name())) + assert.NoError(t, err) +} diff --git a/interface.go b/interface.go index be4da707..262a2cfe 100644 --- a/interface.go +++ b/interface.go @@ -92,6 +92,7 @@ type EngineInterface interface { GetTableMapper() names.Mapper GetTZDatabase() *time.Location GetTZLocation() *time.Location + ImportFile(fp string) ([]sql.Result, error) MapCacher(interface{}, caches.Cacher) error NewSession() *Session NoAutoTime() *Session diff --git a/session_schema_test.go b/session_schema_test.go index a20a1f97..37a1246b 100644 --- a/session_schema_test.go +++ b/session_schema_test.go @@ -6,7 +6,6 @@ package xorm import ( "fmt" - "os" "testing" "time" @@ -210,14 +209,6 @@ func TestCustomTableName(t *testing.T) { assert.NoError(t, testEngine.CreateTables(c)) } -func TestDump(t *testing.T) { - assert.NoError(t, prepareEngine()) - - fp := testEngine.Dialect().URI().DBName + ".sql" - os.Remove(fp) - assert.NoError(t, testEngine.DumpAllToFile(fp)) -} - type IndexOrUnique struct { Id int64 Index int `xorm:"index"`