github.com/dolthub/go-mysql-server@v0.18.0/sql/plan/load_data.go (about) 1 // Copyright 2021 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package plan 16 17 import ( 18 "strings" 19 20 "github.com/dolthub/vitess/go/vt/sqlparser" 21 22 "github.com/dolthub/go-mysql-server/sql" 23 ) 24 25 type LoadData struct { 26 Local bool 27 File string 28 DestSch sql.Schema 29 ColumnNames []string 30 ResponsePacketSent bool 31 IgnoreNum int64 32 IsIgnore bool 33 IsReplace bool 34 35 Charset string 36 37 FieldsTerminatedBy string 38 FieldsEnclosedBy string 39 FieldsEnclosedByOpt bool 40 FieldsEscapedBy string 41 42 LinesStartingBy string 43 LinesTerminatedBy string 44 } 45 46 var _ sql.Node = (*LoadData)(nil) 47 var _ sql.CollationCoercible = (*LoadData)(nil) 48 49 func (l *LoadData) Resolved() bool { 50 return l.DestSch.Resolved() 51 } 52 53 func (l *LoadData) String() string { 54 pr := sql.NewTreePrinter() 55 56 _ = pr.WriteNode("LOAD DATA %s", l.File) 57 return pr.String() 58 } 59 60 func (l *LoadData) Schema() sql.Schema { 61 return l.DestSch 62 } 63 64 func (l *LoadData) Children() []sql.Node { 65 return nil 66 } 67 68 func (l *LoadData) IsReadOnly() bool { 69 return false 70 } 71 72 func (l *LoadData) SplitLines(data []byte, atEOF bool) (advance int, token []byte, err error) { 73 // Return Nothing if at end of file and no data passed. 74 if atEOF && len(data) == 0 { 75 return 0, nil, nil 76 } 77 78 // Find the index of the LINES TERMINATED BY delim. 79 if i := strings.Index(string(data), l.LinesTerminatedBy); i >= 0 { 80 return i + len(l.LinesTerminatedBy), data[0:i], nil 81 } 82 83 // If at end of file with data return the data. 84 if atEOF { 85 return len(data), data, nil 86 } 87 88 return 89 } 90 91 func (l *LoadData) WithChildren(children ...sql.Node) (sql.Node, error) { 92 if len(children) != 0 { 93 return nil, sql.ErrInvalidChildrenNumber.New(l, len(children), 0) 94 } 95 nl := *l 96 return &nl, nil 97 } 98 99 // CheckPrivileges implements the interface sql.Node. 100 func (l *LoadData) CheckPrivileges(ctx *sql.Context, opChecker sql.PrivilegedOperationChecker) bool { 101 return opChecker.UserHasPrivileges(ctx, sql.NewPrivilegedOperation(sql.PrivilegeCheckSubject{}, sql.PrivilegeType_File)) 102 } 103 104 // CollationCoercibility implements the interface sql.CollationCoercible. 105 func (*LoadData) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 106 return sql.Collation_binary, 7 107 } 108 109 func NewLoadData(local bool, file string, destSch sql.Schema, cols []string, ignoreNum int64, ignoreOrReplace string) *LoadData { 110 isReplace := ignoreOrReplace == sqlparser.ReplaceStr 111 isIgnore := ignoreOrReplace == sqlparser.IgnoreStr || (local && !isReplace) 112 return &LoadData{ 113 Local: local, 114 File: file, 115 DestSch: destSch, 116 ColumnNames: cols, 117 IgnoreNum: ignoreNum, 118 IsIgnore: isIgnore, 119 IsReplace: isReplace, 120 121 FieldsTerminatedBy: defaultFieldsTerminatedBy, 122 FieldsEnclosedBy: defaultFieldsEnclosedBy, 123 FieldsEnclosedByOpt: defaultFieldsEnclosedByOpt, 124 FieldsEscapedBy: defaultFieldsEscapedBy, 125 126 LinesStartingBy: defaultLinesStartingBy, 127 LinesTerminatedBy: defaultLinesTerminatedBy, 128 } 129 }