github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/parsers/tree/update.go (about) 1 // Copyright 2021 Matrix Origin 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 tree 16 17 import ( 18 "context" 19 "strconv" 20 "strings" 21 22 "github.com/matrixorigin/matrixone/pkg/fileservice" 23 ) 24 25 // update statement 26 type Update struct { 27 statementImpl 28 Tables TableExprs 29 Exprs UpdateExprs 30 Where *Where 31 OrderBy OrderBy 32 Limit *Limit 33 With *With 34 } 35 36 func (node *Update) Format(ctx *FmtCtx) { 37 if node.With != nil { 38 node.With.Format(ctx) 39 ctx.WriteByte(' ') 40 } 41 ctx.WriteString("update") 42 if node.Tables != nil { 43 ctx.WriteByte(' ') 44 node.Tables.Format(ctx) 45 } 46 ctx.WriteString(" set") 47 if node.Exprs != nil { 48 ctx.WriteByte(' ') 49 node.Exprs.Format(ctx) 50 } 51 if node.Where != nil { 52 ctx.WriteByte(' ') 53 node.Where.Format(ctx) 54 } 55 if len(node.OrderBy) > 0 { 56 ctx.WriteByte(' ') 57 node.OrderBy.Format(ctx) 58 } 59 if node.Limit != nil { 60 ctx.WriteByte(' ') 61 node.Limit.Format(ctx) 62 } 63 } 64 65 func (node *Update) GetStatementType() string { return "Update" } 66 func (node *Update) GetQueryType() string { return QueryTypeDML } 67 68 type UpdateExprs []*UpdateExpr 69 70 func (node *UpdateExprs) Format(ctx *FmtCtx) { 71 prefix := "" 72 for _, u := range *node { 73 ctx.WriteString(prefix) 74 u.Format(ctx) 75 prefix = ", " 76 } 77 } 78 79 // the update expression. 80 type UpdateExpr struct { 81 NodeFormatter 82 Tuple bool 83 Names []*UnresolvedName 84 Expr Expr 85 } 86 87 func (node *UpdateExpr) Format(ctx *FmtCtx) { 88 prefix := "" 89 for _, n := range node.Names { 90 ctx.WriteString(prefix) 91 n.Format(ctx) 92 prefix = " " 93 } 94 ctx.WriteString(" = ") 95 if node.Expr != nil { 96 node.Expr.Format(ctx) 97 } 98 } 99 100 func NewUpdateExpr(t bool, n []*UnresolvedName, e Expr) *UpdateExpr { 101 return &UpdateExpr{ 102 Tuple: t, 103 Names: n, 104 Expr: e, 105 } 106 } 107 108 const ( 109 AUTO = "auto" 110 NOCOMPRESS = "none" 111 GZIP = "gzip" 112 GZ = "gz" // alias of gzip 113 BZIP2 = "bzip2" 114 BZ2 = "bz2" // alias for bzip2 115 FLATE = "flate" 116 LZW = "lzw" 117 ZLIB = "zlib" 118 LZ4 = "lz4" 119 ) 120 121 // load data fotmat 122 const ( 123 CSV = "csv" 124 JSONLINE = "jsonline" 125 ) 126 127 // if $format is jsonline 128 const ( 129 OBJECT = "object" 130 ARRAY = "array" 131 ) 132 133 const ( 134 S3 = 1 135 ) 136 137 type ExternParam struct { 138 // params which come from parser 139 ExParamConst 140 // params which come from internal construct 141 ExParam 142 } 143 144 type ExParamConst struct { 145 ScanType int 146 Filepath string 147 CompressType string 148 Format string 149 Option []string 150 Tail *TailParameter 151 } 152 153 type ExParam struct { 154 JsonData string 155 FileService fileservice.FileService 156 NullMap map[string]([]string) 157 S3Param *S3Parameter 158 Ctx context.Context 159 LoadFile bool 160 Local bool 161 QueryResult bool 162 SysTable bool 163 Parallel bool 164 } 165 166 type S3Parameter struct { 167 Endpoint string `json:"s3-test-endpoint"` 168 Region string `json:"s3-test-region"` 169 APIKey string `json:"s3-test-key"` 170 APISecret string `json:"s3-test-secret"` 171 Bucket string `json:"s3-test-bucket"` 172 Provider string `json:"s3-test-rovider"` 173 RoleArn string `json:"s3-test-rolearn"` 174 ExternalId string `json:"s3-test-externalid"` 175 } 176 177 type TailParameter struct { 178 //Fields 179 Fields *Fields 180 //Lines 181 Lines *Lines 182 //Ignored lines 183 IgnoredLines uint64 184 //col_name_or_user_var 185 ColumnList []LoadColumn 186 //set col_name 187 Assignments UpdateExprs 188 } 189 190 // Load data statement 191 type Load struct { 192 statementImpl 193 Local bool 194 DuplicateHandling DuplicateKey 195 Table *TableName 196 Accounts IdentifierList 197 //Partition 198 Param *ExternParam 199 } 200 201 type Import struct { 202 statementImpl 203 Local bool 204 DuplicateHandling DuplicateKey 205 Table *TableName 206 //Partition 207 Param *ExternParam 208 } 209 210 func (node *Load) Format(ctx *FmtCtx) { 211 ctx.WriteString("load data") 212 if node.Local { 213 ctx.WriteString(" local") 214 } 215 216 if len(node.Param.Option) == 0 { 217 ctx.WriteString(" infile ") 218 ctx.WriteString(node.Param.Filepath) 219 } else { 220 if node.Param.ScanType == S3 { 221 ctx.WriteString(" url s3option ") 222 } else { 223 ctx.WriteString(" infile ") 224 225 } 226 ctx.WriteString("{") 227 for i := 0; i < len(node.Param.Option); i += 2 { 228 switch strings.ToLower(node.Param.Option[i]) { 229 case "endpoint": 230 ctx.WriteString("'endpoint'='" + node.Param.Option[i+1] + "'") 231 case "region": 232 ctx.WriteString("'region'='" + node.Param.Option[i+1] + "'") 233 case "access_key_id": 234 ctx.WriteString("'access_key_id'='" + node.Param.Option[i+1] + "'") 235 case "secret_access_key": 236 ctx.WriteString("'secret_access_key'='" + node.Param.Option[i+1] + "'") 237 case "bucket": 238 ctx.WriteString("'bucket'='" + node.Param.Option[i+1] + "'") 239 case "filepath": 240 ctx.WriteString("'filepath'='" + node.Param.Option[i+1] + "'") 241 case "compression": 242 ctx.WriteString("'compression'='" + node.Param.Option[i+1] + "'") 243 case "format": 244 ctx.WriteString("'format'='" + node.Param.Option[i+1] + "'") 245 case "jsondata": 246 ctx.WriteString("'jsondata'='" + node.Param.Option[i+1] + "'") 247 } 248 if i != len(node.Param.Option)-2 { 249 ctx.WriteString(", ") 250 } 251 } 252 ctx.WriteString("}") 253 } 254 255 switch node.DuplicateHandling.(type) { 256 case *DuplicateKeyError: 257 break 258 case *DuplicateKeyIgnore: 259 ctx.WriteString(" ignore") 260 case *DuplicateKeyReplace: 261 ctx.WriteString(" replace") 262 } 263 ctx.WriteString(" into table ") 264 node.Table.Format(ctx) 265 266 if node.Accounts != nil { 267 ctx.WriteString(" accounts(") 268 node.Accounts.Format(ctx) 269 ctx.WriteByte(')') 270 } 271 272 if node.Param.Tail.Fields != nil { 273 ctx.WriteByte(' ') 274 node.Param.Tail.Fields.Format(ctx) 275 } 276 277 if node.Param.Tail.Lines != nil { 278 ctx.WriteByte(' ') 279 node.Param.Tail.Lines.Format(ctx) 280 } 281 282 if node.Param.Tail.IgnoredLines != 0 { 283 ctx.WriteString(" ignore ") 284 ctx.WriteString(strconv.FormatUint(node.Param.Tail.IgnoredLines, 10)) 285 ctx.WriteString(" lines") 286 } 287 if node.Param.Tail.ColumnList != nil { 288 prefix := " (" 289 for _, c := range node.Param.Tail.ColumnList { 290 ctx.WriteString(prefix) 291 c.Format(ctx) 292 prefix = ", " 293 } 294 ctx.WriteByte(')') 295 } 296 if node.Param.Tail.Assignments != nil { 297 ctx.WriteString(" set ") 298 node.Param.Tail.Assignments.Format(ctx) 299 } 300 } 301 302 func (node *Load) GetStatementType() string { return "Load" } 303 func (node *Load) GetQueryType() string { return QueryTypeDML } 304 305 func (node *Import) Format(ctx *FmtCtx) { 306 ctx.WriteString("import data") 307 if node.Local { 308 ctx.WriteString(" local") 309 } 310 311 if node.Param.CompressType == AUTO || node.Param.CompressType == NOCOMPRESS { 312 ctx.WriteString(" infile ") 313 ctx.WriteString(node.Param.Filepath) 314 } else { 315 ctx.WriteString(" infile ") 316 ctx.WriteString("{'filepath':'" + node.Param.Filepath + "', 'compression':'" + strings.ToLower(node.Param.CompressType) + "'}") 317 } 318 319 switch node.DuplicateHandling.(type) { 320 case *DuplicateKeyError: 321 break 322 case *DuplicateKeyIgnore: 323 ctx.WriteString(" ignore") 324 case *DuplicateKeyReplace: 325 ctx.WriteString(" replace") 326 } 327 ctx.WriteString(" into table ") 328 node.Table.Format(ctx) 329 330 if node.Param.Tail.Fields != nil { 331 ctx.WriteByte(' ') 332 node.Param.Tail.Fields.Format(ctx) 333 } 334 335 if node.Param.Tail.Lines != nil { 336 ctx.WriteByte(' ') 337 node.Param.Tail.Lines.Format(ctx) 338 } 339 340 if node.Param.Tail.IgnoredLines != 0 { 341 ctx.WriteString(" ignore ") 342 ctx.WriteString(strconv.FormatUint(node.Param.Tail.IgnoredLines, 10)) 343 ctx.WriteString(" lines") 344 } 345 if node.Param.Tail.ColumnList != nil { 346 prefix := " (" 347 for _, c := range node.Param.Tail.ColumnList { 348 ctx.WriteString(prefix) 349 c.Format(ctx) 350 prefix = ", " 351 } 352 ctx.WriteByte(')') 353 } 354 if node.Param.Tail.Assignments != nil { 355 ctx.WriteString(" set ") 356 node.Param.Tail.Assignments.Format(ctx) 357 } 358 } 359 360 func (node *Import) GetStatementType() string { return "Import" } 361 func (node *Import) GetQueryType() string { return QueryTypeDML } 362 363 type DuplicateKey interface{} 364 365 type duplicateKeyImpl struct { 366 DuplicateKey 367 } 368 369 type DuplicateKeyError struct { 370 duplicateKeyImpl 371 } 372 373 func NewDuplicateKeyError() *DuplicateKeyError { 374 return &DuplicateKeyError{} 375 } 376 377 type DuplicateKeyReplace struct { 378 duplicateKeyImpl 379 } 380 381 func NewDuplicateKeyReplace() *DuplicateKeyReplace { 382 return &DuplicateKeyReplace{} 383 } 384 385 type DuplicateKeyIgnore struct { 386 duplicateKeyImpl 387 } 388 389 func NewDuplicateKeyIgnore() *DuplicateKeyIgnore { 390 return &DuplicateKeyIgnore{} 391 } 392 393 type Fields struct { 394 Terminated string 395 Optionally bool 396 EnclosedBy byte 397 EscapedBy byte 398 } 399 400 func (node *Fields) Format(ctx *FmtCtx) { 401 ctx.WriteString("fields") 402 prefix := "" 403 if node.Terminated != "" { 404 ctx.WriteString(" terminated by ") 405 ctx.WriteStringQuote(node.Terminated) 406 prefix = " " 407 } 408 if node.Optionally { 409 ctx.WriteString(prefix) 410 ctx.WriteString("optionally enclosed by ") 411 ctx.WriteStringQuote(string(node.EnclosedBy)) 412 } else if node.EnclosedBy != 0 { 413 ctx.WriteString(prefix) 414 ctx.WriteString("enclosed by ") 415 ctx.WriteStringQuote(string(node.EnclosedBy)) 416 } 417 if node.EscapedBy != 0 { 418 ctx.WriteString(prefix) 419 ctx.WriteString("escaped by ") 420 ctx.WriteStringQuote(string(node.EscapedBy)) 421 } 422 } 423 424 func NewFields(t string, o bool, en byte, es byte) *Fields { 425 return &Fields{ 426 Terminated: t, 427 Optionally: o, 428 EnclosedBy: en, 429 EscapedBy: es, 430 } 431 } 432 433 type Lines struct { 434 StartingBy string 435 TerminatedBy string 436 } 437 438 func (node *Lines) Format(ctx *FmtCtx) { 439 ctx.WriteString("lines") 440 if node.StartingBy != "" { 441 ctx.WriteString(" starting by ") 442 ctx.WriteStringQuote(node.StartingBy) 443 } 444 if node.TerminatedBy != "" { 445 ctx.WriteString(" terminated by ") 446 ctx.WriteStringQuote(node.TerminatedBy) 447 } 448 } 449 450 func NewLines(s string, t string) *Lines { 451 return &Lines{ 452 StartingBy: s, 453 TerminatedBy: t, 454 } 455 } 456 457 // column element in load data column list 458 type LoadColumn interface { 459 NodeFormatter 460 } 461 462 type ExportParam struct { 463 // outfile flag 464 Outfile bool 465 // query id 466 QueryId string 467 // filename path 468 FilePath string 469 // Fields 470 Fields *Fields 471 // Lines 472 Lines *Lines 473 // fileSize 474 MaxFileSize uint64 475 // header flag 476 Header bool 477 ForceQuote []string 478 } 479 480 func (ep *ExportParam) Format(ctx *FmtCtx) { 481 if ep.FilePath == "" { 482 return 483 } 484 ep.format(ctx, true) 485 } 486 487 func (ep *ExportParam) format(ctx *FmtCtx, withOutfile bool) { 488 ctx.WriteString("into") 489 if withOutfile { 490 ctx.WriteString(" outfile") 491 } 492 ctx.WriteByte(' ') 493 ctx.WriteString(ep.FilePath) 494 if ep.Fields != nil { 495 ctx.WriteByte(' ') 496 ep.Fields.Format(ctx) 497 } 498 if ep.Lines != nil { 499 ctx.WriteByte(' ') 500 ep.Lines.Format(ctx) 501 } 502 ctx.WriteString(" header ") 503 if ep.Header { 504 ctx.WriteString("true") 505 } else { 506 ctx.WriteString("false") 507 } 508 if ep.MaxFileSize != 0 { 509 ctx.WriteString(" max_file_size ") 510 ctx.WriteString(strconv.FormatUint(ep.MaxFileSize, 10)) 511 } 512 if len(ep.ForceQuote) > 0 { 513 ctx.WriteString(" force_quote") 514 prefix := " " 515 for i := 0; i < len(ep.ForceQuote); i++ { 516 ctx.WriteString(prefix) 517 ctx.WriteString(ep.ForceQuote[i]) 518 prefix = ", " 519 } 520 } 521 } 522 523 var _ LoadColumn = &UnresolvedName{} 524 var _ LoadColumn = &VarExpr{}