From b6e35b502576d148b8623a6c0a54937b195a768a Mon Sep 17 00:00:00 2001 From: Yuanjia Zhang Date: Tue, 1 Sep 2020 20:09:25 +0800 Subject: [PATCH] cherry pick #19438 to release-4.0 Signed-off-by: ti-srebot --- executor/select_into.go | 25 +++++++++++++++---------- executor/select_into_test.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/executor/select_into.go b/executor/select_into.go index 1d677a3b66bba..c4f86928737af 100644 --- a/executor/select_into.go +++ b/executor/select_into.go @@ -121,26 +121,31 @@ func (s *SelectIntoExec) dumpToOutfile() error { (encloseFlag && encloseOpt && s.considerEncloseOpt(et)) { s.lineBuf = append(s.lineBuf, encloseByte) } - switch col.GetType().EvalType() { - case types.ETInt: + switch col.GetType().Tp { + case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong: + s.lineBuf = strconv.AppendInt(s.lineBuf, row.GetInt64(j), 10) + case mysql.TypeLonglong: if mysql.HasUnsignedFlag(col.GetType().Flag) { s.lineBuf = strconv.AppendUint(s.lineBuf, row.GetUint64(j), 10) } else { s.lineBuf = strconv.AppendInt(s.lineBuf, row.GetInt64(j), 10) } - case types.ETReal: + case mysql.TypeFloat, mysql.TypeDouble: s.realBuf, s.lineBuf = DumpRealOutfile(s.realBuf, s.lineBuf, row.GetFloat64(j), col.RetType) - case types.ETDecimal: + case mysql.TypeNewDecimal: s.lineBuf = append(s.lineBuf, row.GetMyDecimal(j).String()...) - case types.ETString: + case mysql.TypeString, mysql.TypeVarString, mysql.TypeVarchar, mysql.TypeBit, + mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob, mysql.TypeBlob: s.lineBuf = append(s.lineBuf, row.GetBytes(j)...) - case types.ETDatetime: + case mysql.TypeDate, mysql.TypeDatetime, mysql.TypeTimestamp: s.lineBuf = append(s.lineBuf, row.GetTime(j).String()...) - case types.ETTimestamp: - s.lineBuf = append(s.lineBuf, row.GetTime(j).String()...) - case types.ETDuration: + case mysql.TypeDuration: s.lineBuf = append(s.lineBuf, row.GetDuration(j, col.GetType().Decimal).String()...) - case types.ETJson: + case mysql.TypeEnum: + s.lineBuf = append(s.lineBuf, row.GetEnum(j).String()...) + case mysql.TypeSet: + s.lineBuf = append(s.lineBuf, row.GetSet(j).String()...) + case mysql.TypeJSON: s.lineBuf = append(s.lineBuf, row.GetJSON(j).String()...) } if (encloseFlag && !encloseOpt) || diff --git a/executor/select_into_test.go b/executor/select_into_test.go index 18b9136a33d4b..23b42efccd144 100644 --- a/executor/select_into_test.go +++ b/executor/select_into_test.go @@ -50,6 +50,41 @@ func (s *testSuite1) TestSelectIntoFileExists(c *C) { c.Assert(strings.Contains(err.Error(), outfile), IsTrue) } +func (s *testSuite1) TestSelectIntoOutfileTypes(c *C) { + tmpDir := os.TempDir() + outfile := filepath.Join(tmpDir, "select-into-outfile.data") + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + + tk.MustExec("drop table if exists t") + tk.MustExec("CREATE TABLE `t` ( `a` bit(10) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;") + tk.MustExec("INSERT INTO `t` VALUES (_binary '\\0'), (_binary '\\1'), (_binary '\\2'), (_binary '\\3');") + tk.MustExec(fmt.Sprintf("SELECT * FROM t INTO OUTFILE %q", outfile)) + cmpAndRm("\x00\x00\n\x001\n\x002\n\x003\n", outfile, c) + + tk.MustExec("drop table if exists t") + tk.MustExec("CREATE TABLE `t` (col ENUM ('value1','value2','value3'));") + tk.MustExec("INSERT INTO t values ('value1'), ('value2');") + tk.MustExec(fmt.Sprintf("SELECT * FROM t INTO OUTFILE %q", outfile)) + cmpAndRm("value1\nvalue2\n", outfile, c) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t ( v json);") + tk.MustExec(`insert into t values ('{"id": 1, "name": "aaa"}'), ('{"id": 2, "name": "xxx"}');`) + tk.MustExec(fmt.Sprintf("SELECT * FROM t INTO OUTFILE %q", outfile)) + cmpAndRm(`{"id": 1, "name": "aaa"} +{"id": 2, "name": "xxx"} +`, outfile, c) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (v tinyint unsigned)") + tk.MustExec("insert into t values (0), (1)") + tk.MustExec(fmt.Sprintf("SELECT * FROM t INTO OUTFILE %q", outfile)) + cmpAndRm(`0 +1 +`, outfile, c) +} + func (s *testSuite1) TestSelectIntoOutfileFromTable(c *C) { tmpDir := os.TempDir() outfile := filepath.Join(tmpDir, "select-into-outfile.data")